github.com/criyle/go-sandbox@v0.10.3/pkg/memfd/memfd_linux.go (about) 1 package memfd 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 8 "golang.org/x/sys/unix" 9 ) 10 11 const createFlag = unix.MFD_CLOEXEC | unix.MFD_ALLOW_SEALING 12 const roSeal = unix.F_SEAL_SEAL | unix.F_SEAL_SHRINK | unix.F_SEAL_GROW | unix.F_SEAL_WRITE 13 14 // New creates a new memfd, caller need to close the file 15 func New(name string) (*os.File, error) { 16 fd, err := unix.MemfdCreate(name, createFlag) 17 if err != nil { 18 return nil, fmt.Errorf("memfd: memfd_create failed %v", err) 19 } 20 file := os.NewFile(uintptr(fd), name) 21 if file == nil { 22 unix.Close(fd) 23 return nil, fmt.Errorf("memfd: NewFile failed for %v", name) 24 } 25 return file, nil 26 } 27 28 // DupToMemfd reads content from reader to sealed (readonly) memfd for given name 29 func DupToMemfd(name string, reader io.Reader) (*os.File, error) { 30 file, err := New(name) 31 if err != nil { 32 return nil, fmt.Errorf("DupToMemfd: %v", err) 33 } 34 // linux syscall sendfile might be more efficient here if reader is a file 35 if _, err = file.ReadFrom(reader); err != nil { 36 file.Close() 37 return nil, fmt.Errorf("DupToMemfd: read from %v", err) 38 } 39 // make memfd readonly 40 if _, err = unix.FcntlInt(file.Fd(), unix.F_ADD_SEALS, roSeal); err != nil { 41 file.Close() 42 return nil, fmt.Errorf("DupToMemfd: memfd seal %v", err) 43 } 44 if _, err := file.Seek(0, 0); err != nil { 45 file.Close() 46 return nil, fmt.Errorf("DupToMemfd: file seek %v", err) 47 } 48 return file, nil 49 }