fortify/test/sandbox/mount.go
Ophestra f38ba7e923
All checks were successful
Test / Create distribution (push) Successful in 27s
Test / Fortify (push) Successful in 2m33s
Test / Fpkg (push) Successful in 3m26s
Test / Data race detector (push) Successful in 3m44s
Test / Flake checks (push) Successful in 53s
test/sandbox: bypass fields
A field is bypassed if it contains a single null byte. This will never appear in the text format so is safe to use.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-13 00:00:58 +09:00

147 lines
2.5 KiB
Go

package sandbox
/*
#include <stdlib.h>
#include <stdio.h>
#include <mntent.h>
const char *F_PROC_MOUNTS = "";
const char *F_SET_TYPE = "r";
*/
import "C"
import (
"fmt"
"runtime"
"sync"
"unsafe"
)
type Mntent struct {
/* name of mounted filesystem */
FSName string `json:"fsname"`
/* filesystem path prefix */
Dir string `json:"dir"`
/* mount type (see mntent.h) */
Type string `json:"type"`
/* mount options (see mntent.h) */
Opts string `json:"opts"`
/* dump frequency in days */
Freq int `json:"freq"`
/* pass number on parallel fsck */
Passno int `json:"passno"`
}
func (e *Mntent) String() string {
return fmt.Sprintf("%s %s %s %s %d %d",
e.FSName, e.Dir, e.Type, e.Opts, e.Freq, e.Passno)
}
func (e *Mntent) Is(want *Mntent) bool {
if want == nil {
return e == nil
}
return (e.FSName == want.FSName || want.FSName == "\x00") &&
(e.Dir == want.Dir || want.Dir == "\x00") &&
(e.Type == want.Type || want.Type == "\x00") &&
(e.Opts == want.Opts || want.Opts == "\x00") &&
(e.Freq == want.Freq || want.Freq == -1) &&
(e.Passno == want.Passno || want.Passno == -1)
}
func IterMounts(name string, f func(e *Mntent)) error {
m := new(mounts)
m.p = name
if err := m.open(); err != nil {
return err
}
for m.scan() {
e := new(Mntent)
m.copy(e)
f(e)
}
m.close()
return m.Err()
}
type mounts struct {
p string
f *C.FILE
mu sync.RWMutex
ent *C.struct_mntent
err error
}
func (m *mounts) open() error {
m.mu.Lock()
defer m.mu.Unlock()
if m.f != nil {
panic("open called twice")
}
if m.p == "" {
m.p = "/proc/mounts"
}
name := C.CString(m.p)
f, err := C.setmntent(name, C.F_SET_TYPE)
C.free(unsafe.Pointer(name))
if f == nil {
return err
}
m.f = f
runtime.SetFinalizer(m, (*mounts).close)
return err
}
func (m *mounts) close() {
m.mu.Lock()
defer m.mu.Unlock()
if m.f == nil {
panic("close called before open")
}
C.endmntent(m.f)
runtime.SetFinalizer(m, nil)
}
func (m *mounts) scan() bool {
m.mu.Lock()
defer m.mu.Unlock()
if m.f == nil {
panic("invalid file")
}
m.ent, m.err = C.getmntent(m.f)
return m.ent != nil
}
func (m *mounts) Err() error {
m.mu.RLock()
defer m.mu.RUnlock()
return m.err
}
func (m *mounts) copy(v *Mntent) {
m.mu.RLock()
defer m.mu.RUnlock()
if m.ent == nil {
panic("invalid entry")
}
v.FSName = C.GoString(m.ent.mnt_fsname)
v.Dir = C.GoString(m.ent.mnt_dir)
v.Type = C.GoString(m.ent.mnt_type)
v.Opts = C.GoString(m.ent.mnt_opts)
v.Freq = int(m.ent.mnt_freq)
v.Passno = int(m.ent.mnt_passno)
}