Merge release-20200810.0-68-g633570462 (automated)
This commit is contained in:
commit
2e9d7f0d73
|
@ -167,7 +167,7 @@ func (s *Statx) MarshalUnsafe(dst []byte) {
|
|||
|
||||
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
|
||||
func (s *Statx) UnmarshalUnsafe(src []byte) {
|
||||
if s.Mtime.Packed() && s.Atime.Packed() && s.Btime.Packed() && s.Ctime.Packed() {
|
||||
if s.Atime.Packed() && s.Btime.Packed() && s.Ctime.Packed() && s.Mtime.Packed() {
|
||||
safecopy.CopyOut(unsafe.Pointer(s), src)
|
||||
} else {
|
||||
// Type Statx doesn't have a packed layout in memory, fallback to UnmarshalBytes.
|
||||
|
@ -632,7 +632,7 @@ func (f *FUSEHeaderIn) Packed() bool {
|
|||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
func (f *FUSEHeaderIn) MarshalUnsafe(dst []byte) {
|
||||
if f.Opcode.Packed() && f.Unique.Packed() {
|
||||
if f.Unique.Packed() && f.Opcode.Packed() {
|
||||
safecopy.CopyIn(dst, unsafe.Pointer(f))
|
||||
} else {
|
||||
// Type FUSEHeaderIn doesn't have a packed layout in memory, fallback to MarshalBytes.
|
||||
|
@ -2208,12 +2208,12 @@ func (i *IPTIP) UnmarshalBytes(src []byte) {
|
|||
// Packed implements marshal.Marshallable.Packed.
|
||||
//go:nosplit
|
||||
func (i *IPTIP) Packed() bool {
|
||||
return i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed()
|
||||
return i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed()
|
||||
}
|
||||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
func (i *IPTIP) MarshalUnsafe(dst []byte) {
|
||||
if i.SrcMask.Packed() && i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() {
|
||||
if i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() {
|
||||
safecopy.CopyIn(dst, unsafe.Pointer(i))
|
||||
} else {
|
||||
// Type IPTIP doesn't have a packed layout in memory, fallback to MarshalBytes.
|
||||
|
@ -2290,7 +2290,7 @@ func (i *IPTIP) CopyIn(task marshal.Task, addr usermem.Addr) (int, error) {
|
|||
|
||||
// WriteTo implements io.WriterTo.WriteTo.
|
||||
func (i *IPTIP) WriteTo(w io.Writer) (int64, error) {
|
||||
if !i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() {
|
||||
if !i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
// Type IPTIP doesn't have a packed layout in memory, fall back to MarshalBytes.
|
||||
buf := make([]byte, i.SizeBytes())
|
||||
i.MarshalBytes(buf)
|
||||
|
@ -2999,7 +2999,7 @@ func (i *IP6TEntry) UnmarshalBytes(src []byte) {
|
|||
// Packed implements marshal.Marshallable.Packed.
|
||||
//go:nosplit
|
||||
func (i *IP6TEntry) Packed() bool {
|
||||
return i.Counters.Packed() && i.IPv6.Packed()
|
||||
return i.IPv6.Packed() && i.Counters.Packed()
|
||||
}
|
||||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
|
@ -3196,12 +3196,12 @@ func (i *IP6TIP) UnmarshalBytes(src []byte) {
|
|||
// Packed implements marshal.Marshallable.Packed.
|
||||
//go:nosplit
|
||||
func (i *IP6TIP) Packed() bool {
|
||||
return i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed()
|
||||
return i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() && i.Src.Packed()
|
||||
}
|
||||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
func (i *IP6TIP) MarshalUnsafe(dst []byte) {
|
||||
if i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
if i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() && i.Src.Packed() {
|
||||
safecopy.CopyIn(dst, unsafe.Pointer(i))
|
||||
} else {
|
||||
// Type IP6TIP doesn't have a packed layout in memory, fallback to MarshalBytes.
|
||||
|
@ -3211,7 +3211,7 @@ func (i *IP6TIP) MarshalUnsafe(dst []byte) {
|
|||
|
||||
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
|
||||
func (i *IP6TIP) UnmarshalUnsafe(src []byte) {
|
||||
if i.SrcMask.Packed() && i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() {
|
||||
if i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
safecopy.CopyOut(unsafe.Pointer(i), src)
|
||||
} else {
|
||||
// Type IP6TIP doesn't have a packed layout in memory, fallback to UnmarshalBytes.
|
||||
|
@ -3222,7 +3222,7 @@ func (i *IP6TIP) UnmarshalUnsafe(src []byte) {
|
|||
// CopyOutN implements marshal.Marshallable.CopyOutN.
|
||||
//go:nosplit
|
||||
func (i *IP6TIP) CopyOutN(task marshal.Task, addr usermem.Addr, limit int) (int, error) {
|
||||
if !i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
if !i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() {
|
||||
// Type IP6TIP doesn't have a packed layout in memory, fall back to MarshalBytes.
|
||||
buf := task.CopyScratchBuffer(i.SizeBytes()) // escapes: okay.
|
||||
i.MarshalBytes(buf) // escapes: fallback.
|
||||
|
@ -3252,7 +3252,7 @@ func (i *IP6TIP) CopyOut(task marshal.Task, addr usermem.Addr) (int, error) {
|
|||
// CopyIn implements marshal.Marshallable.CopyIn.
|
||||
//go:nosplit
|
||||
func (i *IP6TIP) CopyIn(task marshal.Task, addr usermem.Addr) (int, error) {
|
||||
if !i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
if !i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() {
|
||||
// Type IP6TIP doesn't have a packed layout in memory, fall back to UnmarshalBytes.
|
||||
buf := task.CopyScratchBuffer(i.SizeBytes()) // escapes: okay.
|
||||
length, err := task.CopyInBytes(addr, buf) // escapes: okay.
|
||||
|
@ -3278,7 +3278,7 @@ func (i *IP6TIP) CopyIn(task marshal.Task, addr usermem.Addr) (int, error) {
|
|||
|
||||
// WriteTo implements io.WriterTo.WriteTo.
|
||||
func (i *IP6TIP) WriteTo(w io.Writer) (int64, error) {
|
||||
if !i.DstMask.Packed() && i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() {
|
||||
if !i.Src.Packed() && i.Dst.Packed() && i.SrcMask.Packed() && i.DstMask.Packed() {
|
||||
// Type IP6TIP doesn't have a packed layout in memory, fall back to MarshalBytes.
|
||||
buf := make([]byte, i.SizeBytes())
|
||||
i.MarshalBytes(buf)
|
||||
|
|
|
@ -82,7 +82,7 @@ type createSyntheticOpts struct {
|
|||
// Preconditions: d.dirMu must be locked. d.isDir(). d does not already contain
|
||||
// a child with the given name.
|
||||
func (d *dentry) createSyntheticChildLocked(opts *createSyntheticOpts) {
|
||||
d2 := &dentry{
|
||||
child := &dentry{
|
||||
refs: 1, // held by d
|
||||
fs: d.fs,
|
||||
ino: d.fs.nextSyntheticIno(),
|
||||
|
@ -97,16 +97,16 @@ func (d *dentry) createSyntheticChildLocked(opts *createSyntheticOpts) {
|
|||
case linux.S_IFDIR:
|
||||
// Nothing else needs to be done.
|
||||
case linux.S_IFSOCK:
|
||||
d2.endpoint = opts.endpoint
|
||||
child.endpoint = opts.endpoint
|
||||
case linux.S_IFIFO:
|
||||
d2.pipe = opts.pipe
|
||||
child.pipe = opts.pipe
|
||||
default:
|
||||
panic(fmt.Sprintf("failed to create synthetic file of unrecognized type: %v", opts.mode.FileType()))
|
||||
}
|
||||
d2.pf.dentry = d2
|
||||
d2.vfsd.Init(d2)
|
||||
child.pf.dentry = child
|
||||
child.vfsd.Init(child)
|
||||
|
||||
d.cacheNewChildLocked(d2, opts.name)
|
||||
d.cacheNewChildLocked(child, opts.name)
|
||||
d.syntheticChildren++
|
||||
}
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ func (fs *filesystem) resolveLocked(ctx context.Context, rp *vfs.ResolvingPath,
|
|||
//
|
||||
// Preconditions: !rp.Done(). For the final path component in rp,
|
||||
// !rp.ShouldFollowSymlink().
|
||||
func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir bool, createInRemoteDir func(parent *dentry, name string) error, createInSyntheticDir func(parent *dentry, name string) error) error {
|
||||
func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir bool, createInRemoteDir func(parent *dentry, name string, ds **[]*dentry) error, createInSyntheticDir func(parent *dentry, name string) error) error {
|
||||
var ds *[]*dentry
|
||||
fs.renameMu.RLock()
|
||||
defer fs.renameMuRUnlockAndCheckCaching(ctx, &ds)
|
||||
|
@ -399,7 +399,7 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir
|
|||
// RPC will fail with EEXIST like we would have. If the RPC succeeds, and a
|
||||
// stale dentry exists, the dentry will fail revalidation next time it's
|
||||
// used.
|
||||
if err := createInRemoteDir(parent, name); err != nil {
|
||||
if err := createInRemoteDir(parent, name, &ds); err != nil {
|
||||
return err
|
||||
}
|
||||
ev := linux.IN_CREATE
|
||||
|
@ -414,7 +414,7 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir
|
|||
}
|
||||
// No cached dentry exists; however, there might still be an existing file
|
||||
// at name. As above, we attempt the file creation RPC anyway.
|
||||
if err := createInRemoteDir(parent, name); err != nil {
|
||||
if err := createInRemoteDir(parent, name, &ds); err != nil {
|
||||
return err
|
||||
}
|
||||
if child, ok := parent.children[name]; ok && child == nil {
|
||||
|
@ -721,7 +721,7 @@ func (fs *filesystem) GetParentDentryAt(ctx context.Context, rp *vfs.ResolvingPa
|
|||
|
||||
// LinkAt implements vfs.FilesystemImpl.LinkAt.
|
||||
func (fs *filesystem) LinkAt(ctx context.Context, rp *vfs.ResolvingPath, vd vfs.VirtualDentry) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, childName string) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, childName string, _ **[]*dentry) error {
|
||||
if rp.Mount() != vd.Mount() {
|
||||
return syserror.EXDEV
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ func (fs *filesystem) LinkAt(ctx context.Context, rp *vfs.ResolvingPath, vd vfs.
|
|||
// MkdirAt implements vfs.FilesystemImpl.MkdirAt.
|
||||
func (fs *filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.MkdirOptions) error {
|
||||
creds := rp.Credentials()
|
||||
return fs.doCreateAt(ctx, rp, true /* dir */, func(parent *dentry, name string) error {
|
||||
return fs.doCreateAt(ctx, rp, true /* dir */, func(parent *dentry, name string, _ **[]*dentry) error {
|
||||
if _, err := parent.file.mkdir(ctx, name, (p9.FileMode)(opts.Mode), (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID)); err != nil {
|
||||
if !opts.ForSyntheticMountpoint || err == syserror.EEXIST {
|
||||
return err
|
||||
|
@ -789,34 +789,49 @@ func (fs *filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
|
|||
|
||||
// MknodAt implements vfs.FilesystemImpl.MknodAt.
|
||||
func (fs *filesystem) MknodAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.MknodOptions) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, name string) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, name string, ds **[]*dentry) error {
|
||||
creds := rp.Credentials()
|
||||
_, err := parent.file.mknod(ctx, name, (p9.FileMode)(opts.Mode), opts.DevMajor, opts.DevMinor, (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
|
||||
// If the gofer does not allow creating a socket or pipe, create a
|
||||
// synthetic one, i.e. one that is kept entirely in memory.
|
||||
if err == syserror.EPERM {
|
||||
switch opts.Mode.FileType() {
|
||||
case linux.S_IFSOCK:
|
||||
parent.createSyntheticChildLocked(&createSyntheticOpts{
|
||||
name: name,
|
||||
mode: opts.Mode,
|
||||
kuid: creds.EffectiveKUID,
|
||||
kgid: creds.EffectiveKGID,
|
||||
endpoint: opts.Endpoint,
|
||||
})
|
||||
return nil
|
||||
case linux.S_IFIFO:
|
||||
parent.createSyntheticChildLocked(&createSyntheticOpts{
|
||||
name: name,
|
||||
mode: opts.Mode,
|
||||
kuid: creds.EffectiveKUID,
|
||||
kgid: creds.EffectiveKGID,
|
||||
pipe: pipe.NewVFSPipe(true /* isNamed */, pipe.DefaultPipeSize, usermem.PageSize),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
if err != syserror.EPERM {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
|
||||
// EPERM means that gofer does not allow creating a socket or pipe. Fallback
|
||||
// to creating a synthetic one, i.e. one that is kept entirely in memory.
|
||||
|
||||
// Check that we're not overriding an existing file with a synthetic one.
|
||||
_, err = fs.stepLocked(ctx, rp, parent, true, ds)
|
||||
switch {
|
||||
case err == nil:
|
||||
// Step succeeded, another file exists.
|
||||
return syserror.EEXIST
|
||||
case err != syserror.ENOENT:
|
||||
// Unexpected error.
|
||||
return err
|
||||
}
|
||||
|
||||
switch opts.Mode.FileType() {
|
||||
case linux.S_IFSOCK:
|
||||
parent.createSyntheticChildLocked(&createSyntheticOpts{
|
||||
name: name,
|
||||
mode: opts.Mode,
|
||||
kuid: creds.EffectiveKUID,
|
||||
kgid: creds.EffectiveKGID,
|
||||
endpoint: opts.Endpoint,
|
||||
})
|
||||
return nil
|
||||
case linux.S_IFIFO:
|
||||
parent.createSyntheticChildLocked(&createSyntheticOpts{
|
||||
name: name,
|
||||
mode: opts.Mode,
|
||||
kuid: creds.EffectiveKUID,
|
||||
kgid: creds.EffectiveKGID,
|
||||
pipe: pipe.NewVFSPipe(true /* isNamed */, pipe.DefaultPipeSize, usermem.PageSize),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
// Retain error from gofer if synthetic file cannot be created internally.
|
||||
return syserror.EPERM
|
||||
}, nil)
|
||||
}
|
||||
|
||||
|
@ -1452,7 +1467,7 @@ func (fs *filesystem) StatFSAt(ctx context.Context, rp *vfs.ResolvingPath) (linu
|
|||
|
||||
// SymlinkAt implements vfs.FilesystemImpl.SymlinkAt.
|
||||
func (fs *filesystem) SymlinkAt(ctx context.Context, rp *vfs.ResolvingPath, target string) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, name string) error {
|
||||
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, name string, _ **[]*dentry) error {
|
||||
creds := rp.Credentials()
|
||||
_, err := parent.file.symlink(ctx, target, name, (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
|
||||
return err
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package tmpfs
|
||||
|
||||
import (
|
||||
refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
|
||||
)
|
||||
|
||||
// ownerType is used to customize logging. Note that we use a pointer to T so
|
||||
|
|
|
@ -3,11 +3,11 @@ package ring0
|
|||
import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform/ring0/pagetables"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"fmt"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Useful bits.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package unix
|
||||
|
||||
import (
|
||||
refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
|
||||
)
|
||||
|
||||
// ownerType is used to customize logging. Note that we use a pointer to T so
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
|
@ -45,7 +44,7 @@ const (
|
|||
// modes to ensure an unopened/closed file fails all mode checks.
|
||||
invalidMode = p9.OpenFlags(math.MaxUint32)
|
||||
|
||||
openFlags = syscall.O_NOFOLLOW | syscall.O_CLOEXEC
|
||||
openFlags = unix.O_NOFOLLOW | unix.O_CLOEXEC
|
||||
|
||||
allowedOpenFlags = unix.O_TRUNC
|
||||
)
|
||||
|
@ -125,7 +124,7 @@ func (a *attachPoint) Attach() (p9.File, error) {
|
|||
}
|
||||
|
||||
// makeQID returns a unique QID for the given stat buffer.
|
||||
func (a *attachPoint) makeQID(stat syscall.Stat_t) p9.QID {
|
||||
func (a *attachPoint) makeQID(stat unix.Stat_t) p9.QID {
|
||||
a.deviceMu.Lock()
|
||||
defer a.deviceMu.Unlock()
|
||||
|
||||
|
@ -156,9 +155,7 @@ func (a *attachPoint) makeQID(stat syscall.Stat_t) p9.QID {
|
|||
// localFile implements p9.File wrapping a local file. The underlying file
|
||||
// is opened during Walk() and stored in 'file' to be used with other
|
||||
// operations. The file is opened as readonly, unless it's a symlink or there is
|
||||
// no read access, which requires O_PATH. 'file' is dup'ed when Walk(nil) is
|
||||
// called to clone the file. This reduces the number of walks that need to be
|
||||
// done by the host file system when files are reused.
|
||||
// no read access, which requires O_PATH.
|
||||
//
|
||||
// The file may be reopened if the requested mode in Open() is not a subset of
|
||||
// current mode. Consequently, 'file' could have a mode wider than requested and
|
||||
|
@ -170,11 +167,28 @@ func (a *attachPoint) makeQID(stat syscall.Stat_t) p9.QID {
|
|||
// performance with 'overlay2' storage driver. overlay2 eagerly copies the
|
||||
// entire file up when it's opened in write mode, and would perform badly when
|
||||
// multiple files are only being opened for read (esp. startup).
|
||||
//
|
||||
// File operations must use "at" functions whenever possible:
|
||||
// * Local operations must use AT_EMPTY_PATH:
|
||||
// fchownat(fd, "", AT_EMPTY_PATH, ...), instead of chown(fullpath, ...)
|
||||
// * Creation operations must use (fd + name):
|
||||
// mkdirat(fd, name, ...), instead of mkdir(fullpath, ...)
|
||||
//
|
||||
// Apart from being faster, it also adds another layer of defense against
|
||||
// symlink attacks (note that O_NOFOLLOW applies only to the last element in
|
||||
// the path).
|
||||
//
|
||||
// The few exceptions where it cannot be done are: utimensat on symlinks, and
|
||||
// Connect() for the socket address.
|
||||
type localFile struct {
|
||||
// attachPoint is the attachPoint that serves this localFile.
|
||||
attachPoint *attachPoint
|
||||
|
||||
// hostPath will be safely updated by the Renamed hook.
|
||||
// hostPath is the full path to the host file. It can be used for logging and
|
||||
// the few cases where full path is required to operation the host file. In
|
||||
// all other cases, use "file" directly.
|
||||
//
|
||||
// Note: it's safely updated by the Renamed hook.
|
||||
hostPath string
|
||||
|
||||
// file is opened when localFile is created and it's never nil. It may be
|
||||
|
@ -191,7 +205,7 @@ type localFile struct {
|
|||
mode p9.OpenFlags
|
||||
|
||||
// fileType for this file. It is equivalent to:
|
||||
// syscall.Stat_t.Mode & syscall.S_IFMT
|
||||
// unix.Stat_t.Mode & unix.S_IFMT
|
||||
fileType uint32
|
||||
|
||||
qid p9.QID
|
||||
|
@ -211,7 +225,7 @@ var procSelfFD *fd.FD
|
|||
// OpenProcSelfFD opens the /proc/self/fd directory, which will be used to
|
||||
// reopen file descriptors.
|
||||
func OpenProcSelfFD() error {
|
||||
d, err := syscall.Open("/proc/self/fd", syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
|
||||
d, err := unix.Open("/proc/self/fd", unix.O_RDONLY|unix.O_DIRECTORY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening /proc/self/fd: %v", err)
|
||||
}
|
||||
|
@ -220,7 +234,7 @@ func OpenProcSelfFD() error {
|
|||
}
|
||||
|
||||
func reopenProcFd(f *fd.FD, mode int) (*fd.FD, error) {
|
||||
d, err := syscall.Openat(int(procSelfFD.FD()), strconv.Itoa(f.FD()), mode&^syscall.O_NOFOLLOW, 0)
|
||||
d, err := unix.Openat(int(procSelfFD.FD()), strconv.Itoa(f.FD()), mode&^unix.O_NOFOLLOW, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -229,17 +243,17 @@ func reopenProcFd(f *fd.FD, mode int) (*fd.FD, error) {
|
|||
}
|
||||
|
||||
func openAnyFileFromParent(parent *localFile, name string) (*fd.FD, string, bool, error) {
|
||||
path := path.Join(parent.hostPath, name)
|
||||
f, readable, err := openAnyFile(path, func(mode int) (*fd.FD, error) {
|
||||
pathDebug := path.Join(parent.hostPath, name)
|
||||
f, readable, err := openAnyFile(pathDebug, func(mode int) (*fd.FD, error) {
|
||||
return fd.OpenAt(parent.file, name, openFlags|mode, 0)
|
||||
})
|
||||
return f, path, readable, err
|
||||
return f, pathDebug, readable, err
|
||||
}
|
||||
|
||||
// openAnyFile attempts to open the file in O_RDONLY and if it fails fallsback
|
||||
// openAnyFile attempts to open the file in O_RDONLY. If it fails, falls back
|
||||
// to O_PATH. 'path' is used for logging messages only. 'fn' is what does the
|
||||
// actual file open and is customizable by the caller.
|
||||
func openAnyFile(path string, fn func(mode int) (*fd.FD, error)) (*fd.FD, bool, error) {
|
||||
func openAnyFile(pathDebug string, fn func(mode int) (*fd.FD, error)) (*fd.FD, bool, error) {
|
||||
// Attempt to open file in the following mode in order:
|
||||
// 1. RDONLY | NONBLOCK: for all files, directories, ro mounts, FIFOs.
|
||||
// Use non-blocking to prevent getting stuck inside open(2) for
|
||||
|
@ -250,7 +264,7 @@ func openAnyFile(path string, fn func(mode int) (*fd.FD, error)) (*fd.FD, bool,
|
|||
readable bool
|
||||
}{
|
||||
{
|
||||
mode: syscall.O_RDONLY | syscall.O_NONBLOCK,
|
||||
mode: unix.O_RDONLY | unix.O_NONBLOCK,
|
||||
readable: true,
|
||||
},
|
||||
{
|
||||
|
@ -268,36 +282,36 @@ func openAnyFile(path string, fn func(mode int) (*fd.FD, error)) (*fd.FD, bool,
|
|||
return file, option.readable, nil
|
||||
}
|
||||
switch e := extractErrno(err); e {
|
||||
case syscall.ENOENT:
|
||||
case unix.ENOENT:
|
||||
// File doesn't exist, no point in retrying.
|
||||
return nil, false, e
|
||||
}
|
||||
// File failed to open. Try again with next mode, preserving 'err' in case
|
||||
// this was the last attempt.
|
||||
log.Debugf("Attempt %d to open file failed, mode: %#x, path: %q, err: %v", i, openFlags|option.mode, path, err)
|
||||
log.Debugf("Attempt %d to open file failed, mode: %#x, path: %q, err: %v", i, openFlags|option.mode, pathDebug, err)
|
||||
}
|
||||
// All attempts to open file have failed, return the last error.
|
||||
log.Debugf("Failed to open file, path: %q, err: %v", path, err)
|
||||
log.Debugf("Failed to open file, path: %q, err: %v", pathDebug, err)
|
||||
return nil, false, extractErrno(err)
|
||||
}
|
||||
|
||||
func checkSupportedFileType(stat syscall.Stat_t, permitSocket bool) error {
|
||||
switch stat.Mode & syscall.S_IFMT {
|
||||
case syscall.S_IFREG, syscall.S_IFDIR, syscall.S_IFLNK:
|
||||
func checkSupportedFileType(stat unix.Stat_t, permitSocket bool) error {
|
||||
switch stat.Mode & unix.S_IFMT {
|
||||
case unix.S_IFREG, unix.S_IFDIR, unix.S_IFLNK:
|
||||
return nil
|
||||
|
||||
case syscall.S_IFSOCK:
|
||||
case unix.S_IFSOCK:
|
||||
if !permitSocket {
|
||||
return syscall.EPERM
|
||||
return unix.EPERM
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return syscall.EPERM
|
||||
return unix.EPERM
|
||||
}
|
||||
}
|
||||
|
||||
func newLocalFile(a *attachPoint, file *fd.FD, path string, readable bool, stat syscall.Stat_t) (*localFile, error) {
|
||||
func newLocalFile(a *attachPoint, file *fd.FD, path string, readable bool, stat unix.Stat_t) (*localFile, error) {
|
||||
if err := checkSupportedFileType(stat, a.conf.HostUDS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -307,7 +321,7 @@ func newLocalFile(a *attachPoint, file *fd.FD, path string, readable bool, stat
|
|||
hostPath: path,
|
||||
file: file,
|
||||
mode: invalidMode,
|
||||
fileType: stat.Mode & syscall.S_IFMT,
|
||||
fileType: stat.Mode & unix.S_IFMT,
|
||||
qid: a.makeQID(stat),
|
||||
controlReadable: readable,
|
||||
}, nil
|
||||
|
@ -317,7 +331,7 @@ func newLocalFile(a *attachPoint, file *fd.FD, path string, readable bool, stat
|
|||
// non-blocking. If anything fails, returns nil. It's better to have a file
|
||||
// without host FD, than to fail the operation.
|
||||
func newFDMaybe(file *fd.FD) *fd.FD {
|
||||
dupFD, err := syscall.Dup(file.FD())
|
||||
dupFD, err := unix.Dup(file.FD())
|
||||
// Technically, the runtime may call the finalizer on file as soon as
|
||||
// FD() returns.
|
||||
runtime.KeepAlive(file)
|
||||
|
@ -327,31 +341,23 @@ func newFDMaybe(file *fd.FD) *fd.FD {
|
|||
dup := fd.New(dupFD)
|
||||
|
||||
// fd is blocking; non-blocking is required.
|
||||
if err := syscall.SetNonblock(dup.FD(), true); err != nil {
|
||||
if err := unix.SetNonblock(dup.FD(), true); err != nil {
|
||||
_ = dup.Close()
|
||||
return nil
|
||||
}
|
||||
return dup
|
||||
}
|
||||
|
||||
func fstat(fd int) (syscall.Stat_t, error) {
|
||||
var stat syscall.Stat_t
|
||||
if err := syscall.Fstat(fd, &stat); err != nil {
|
||||
return syscall.Stat_t{}, err
|
||||
}
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
func stat(path string) (syscall.Stat_t, error) {
|
||||
var stat syscall.Stat_t
|
||||
if err := syscall.Stat(path, &stat); err != nil {
|
||||
return syscall.Stat_t{}, err
|
||||
func fstat(fd int) (unix.Stat_t, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Fstat(fd, &stat); err != nil {
|
||||
return unix.Stat_t{}, err
|
||||
}
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
func fchown(fd int, uid p9.UID, gid p9.GID) error {
|
||||
return syscall.Fchownat(fd, "", int(uid), int(gid), linux.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW)
|
||||
return unix.Fchownat(fd, "", int(uid), int(gid), linux.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
// Open implements p9.File.
|
||||
|
@ -377,7 +383,7 @@ func (l *localFile) Open(flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
|
|||
// name_to_handle_at and open_by_handle_at aren't supported by overlay2.
|
||||
log.Debugf("Open reopening file, flags: %v, %q", flags, l.hostPath)
|
||||
var err error
|
||||
osFlags := flags.OSFlags() & (syscall.O_ACCMODE | allowedOpenFlags)
|
||||
osFlags := flags.OSFlags() & (unix.O_ACCMODE | allowedOpenFlags)
|
||||
newFile, err = reopenProcFd(l.file, openFlags|osFlags)
|
||||
if err != nil {
|
||||
return nil, p9.QID{}, 0, extractErrno(err)
|
||||
|
@ -385,7 +391,7 @@ func (l *localFile) Open(flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
|
|||
}
|
||||
|
||||
var fd *fd.FD
|
||||
if l.fileType == syscall.S_IFREG {
|
||||
if l.fileType == unix.S_IFREG {
|
||||
// Donate FD for regular files only.
|
||||
fd = newFDMaybe(newFile)
|
||||
}
|
||||
|
@ -408,7 +414,7 @@ func (l *localFile) Create(name string, p9Flags p9.OpenFlags, perm p9.FileMode,
|
|||
}
|
||||
|
||||
// Set file creation flags, plus allowed open flags from caller.
|
||||
osFlags := openFlags | syscall.O_CREAT | syscall.O_EXCL
|
||||
osFlags := openFlags | unix.O_CREAT | unix.O_EXCL
|
||||
osFlags |= p9Flags.OSFlags() & allowedOpenFlags
|
||||
|
||||
// 'file' may be used for other operations (e.g. Walk), so read access is
|
||||
|
@ -416,9 +422,9 @@ func (l *localFile) Create(name string, p9Flags p9.OpenFlags, perm p9.FileMode,
|
|||
// than needed for each particular case.
|
||||
mode := p9Flags & p9.OpenFlagsModeMask
|
||||
if mode == p9.WriteOnly {
|
||||
osFlags |= syscall.O_RDWR
|
||||
osFlags |= unix.O_RDWR
|
||||
} else {
|
||||
osFlags |= mode.OSFlags() & unix.O_ACCMODE
|
||||
osFlags |= mode.OSFlags()
|
||||
}
|
||||
|
||||
child, err := fd.OpenAt(l.file, name, osFlags, uint32(perm.Permissions()))
|
||||
|
@ -428,7 +434,7 @@ func (l *localFile) Create(name string, p9Flags p9.OpenFlags, perm p9.FileMode,
|
|||
cu := cleanup.Make(func() {
|
||||
_ = child.Close()
|
||||
// Best effort attempt to remove the file in case of failure.
|
||||
if err := syscall.Unlinkat(l.file.FD(), name); err != nil {
|
||||
if err := unix.Unlinkat(l.file.FD(), name, 0); err != nil {
|
||||
log.Warningf("error unlinking file %q after failure: %v", path.Join(l.hostPath, name), err)
|
||||
}
|
||||
})
|
||||
|
@ -447,7 +453,7 @@ func (l *localFile) Create(name string, p9Flags p9.OpenFlags, perm p9.FileMode,
|
|||
hostPath: path.Join(l.hostPath, name),
|
||||
file: child,
|
||||
mode: mode,
|
||||
fileType: syscall.S_IFREG,
|
||||
fileType: unix.S_IFREG,
|
||||
qid: l.attachPoint.makeQID(stat),
|
||||
}
|
||||
|
||||
|
@ -461,7 +467,7 @@ func (l *localFile) Mkdir(name string, perm p9.FileMode, uid p9.UID, gid p9.GID)
|
|||
return p9.QID{}, err
|
||||
}
|
||||
|
||||
if err := syscall.Mkdirat(l.file.FD(), name, uint32(perm.Permissions())); err != nil {
|
||||
if err := unix.Mkdirat(l.file.FD(), name, uint32(perm.Permissions())); err != nil {
|
||||
return p9.QID{}, extractErrno(err)
|
||||
}
|
||||
cu := cleanup.Make(func() {
|
||||
|
@ -473,7 +479,7 @@ func (l *localFile) Mkdir(name string, perm p9.FileMode, uid p9.UID, gid p9.GID)
|
|||
defer cu.Clean()
|
||||
|
||||
// Open directory to change ownership and stat it.
|
||||
flags := syscall.O_DIRECTORY | syscall.O_RDONLY | openFlags
|
||||
flags := unix.O_DIRECTORY | unix.O_RDONLY | openFlags
|
||||
f, err := fd.OpenAt(l.file, name, flags, 0)
|
||||
if err != nil {
|
||||
return p9.QID{}, extractErrno(err)
|
||||
|
@ -508,20 +514,20 @@ func (l *localFile) WalkGetAttr(names []string) ([]p9.QID, p9.File, p9.AttrMask,
|
|||
return qids, file, mask, attr, nil
|
||||
}
|
||||
|
||||
func (l *localFile) walk(names []string) ([]p9.QID, p9.File, syscall.Stat_t, error) {
|
||||
func (l *localFile) walk(names []string) ([]p9.QID, p9.File, unix.Stat_t, error) {
|
||||
// Duplicate current file if 'names' is empty.
|
||||
if len(names) == 0 {
|
||||
newFile, readable, err := openAnyFile(l.hostPath, func(mode int) (*fd.FD, error) {
|
||||
return reopenProcFd(l.file, openFlags|mode)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, syscall.Stat_t{}, extractErrno(err)
|
||||
return nil, nil, unix.Stat_t{}, extractErrno(err)
|
||||
}
|
||||
|
||||
stat, err := fstat(newFile.FD())
|
||||
if err != nil {
|
||||
_ = newFile.Close()
|
||||
return nil, nil, syscall.Stat_t{}, extractErrno(err)
|
||||
return nil, nil, unix.Stat_t{}, extractErrno(err)
|
||||
}
|
||||
|
||||
c := &localFile{
|
||||
|
@ -537,7 +543,7 @@ func (l *localFile) walk(names []string) ([]p9.QID, p9.File, syscall.Stat_t, err
|
|||
}
|
||||
|
||||
var qids []p9.QID
|
||||
var lastStat syscall.Stat_t
|
||||
var lastStat unix.Stat_t
|
||||
last := l
|
||||
for _, name := range names {
|
||||
f, path, readable, err := openAnyFileFromParent(last, name)
|
||||
|
@ -545,17 +551,17 @@ func (l *localFile) walk(names []string) ([]p9.QID, p9.File, syscall.Stat_t, err
|
|||
_ = last.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, syscall.Stat_t{}, extractErrno(err)
|
||||
return nil, nil, unix.Stat_t{}, extractErrno(err)
|
||||
}
|
||||
lastStat, err = fstat(f.FD())
|
||||
if err != nil {
|
||||
_ = f.Close()
|
||||
return nil, nil, syscall.Stat_t{}, extractErrno(err)
|
||||
return nil, nil, unix.Stat_t{}, extractErrno(err)
|
||||
}
|
||||
c, err := newLocalFile(last.attachPoint, f, path, readable, lastStat)
|
||||
if err != nil {
|
||||
_ = f.Close()
|
||||
return nil, nil, syscall.Stat_t{}, extractErrno(err)
|
||||
return nil, nil, unix.Stat_t{}, extractErrno(err)
|
||||
}
|
||||
|
||||
qids = append(qids, c.qid)
|
||||
|
@ -566,8 +572,8 @@ func (l *localFile) walk(names []string) ([]p9.QID, p9.File, syscall.Stat_t, err
|
|||
|
||||
// StatFS implements p9.File.
|
||||
func (l *localFile) StatFS() (p9.FSStat, error) {
|
||||
var s syscall.Statfs_t
|
||||
if err := syscall.Fstatfs(l.file.FD(), &s); err != nil {
|
||||
var s unix.Statfs_t
|
||||
if err := unix.Fstatfs(l.file.FD(), &s); err != nil {
|
||||
return p9.FSStat{}, extractErrno(err)
|
||||
}
|
||||
|
||||
|
@ -587,9 +593,9 @@ func (l *localFile) StatFS() (p9.FSStat, error) {
|
|||
// FSync implements p9.File.
|
||||
func (l *localFile) FSync() error {
|
||||
if !l.isOpen() {
|
||||
return syscall.EBADF
|
||||
return unix.EBADF
|
||||
}
|
||||
if err := syscall.Fsync(l.file.FD()); err != nil {
|
||||
if err := unix.Fsync(l.file.FD()); err != nil {
|
||||
return extractErrno(err)
|
||||
}
|
||||
return nil
|
||||
|
@ -605,7 +611,7 @@ func (l *localFile) GetAttr(_ p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error)
|
|||
return l.qid, mask, attr, nil
|
||||
}
|
||||
|
||||
func (l *localFile) fillAttr(stat syscall.Stat_t) (p9.AttrMask, p9.Attr) {
|
||||
func (l *localFile) fillAttr(stat unix.Stat_t) (p9.AttrMask, p9.Attr) {
|
||||
attr := p9.Attr{
|
||||
Mode: p9.FileMode(stat.Mode),
|
||||
UID: p9.UID(stat.Uid),
|
||||
|
@ -665,13 +671,13 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
|
|||
// consistent result that is not attribute dependent.
|
||||
if !valid.IsSubsetOf(allowed) {
|
||||
log.Warningf("SetAttr() failed for %q, mask: %v", l.hostPath, valid)
|
||||
return syscall.EPERM
|
||||
return unix.EPERM
|
||||
}
|
||||
|
||||
// Check if it's possible to use cached file, or if another one needs to be
|
||||
// opened for write.
|
||||
f := l.file
|
||||
if l.fileType == syscall.S_IFREG && l.mode != p9.WriteOnly && l.mode != p9.ReadWrite {
|
||||
if l.fileType == unix.S_IFREG && l.mode != p9.WriteOnly && l.mode != p9.ReadWrite {
|
||||
var err error
|
||||
f, err = reopenProcFd(l.file, openFlags|os.O_WRONLY)
|
||||
if err != nil {
|
||||
|
@ -692,21 +698,21 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
|
|||
// over another.
|
||||
var err error
|
||||
if valid.Permissions {
|
||||
if cerr := syscall.Fchmod(f.FD(), uint32(attr.Permissions)); cerr != nil {
|
||||
if cerr := unix.Fchmod(f.FD(), uint32(attr.Permissions)); cerr != nil {
|
||||
log.Debugf("SetAttr fchmod failed %q, err: %v", l.hostPath, cerr)
|
||||
err = extractErrno(cerr)
|
||||
}
|
||||
}
|
||||
|
||||
if valid.Size {
|
||||
if terr := syscall.Ftruncate(f.FD(), int64(attr.Size)); terr != nil {
|
||||
if terr := unix.Ftruncate(f.FD(), int64(attr.Size)); terr != nil {
|
||||
log.Debugf("SetAttr ftruncate failed %q, err: %v", l.hostPath, terr)
|
||||
err = extractErrno(terr)
|
||||
}
|
||||
}
|
||||
|
||||
if valid.ATime || valid.MTime {
|
||||
utimes := [2]syscall.Timespec{
|
||||
utimes := [2]unix.Timespec{
|
||||
{Sec: 0, Nsec: linux.UTIME_OMIT},
|
||||
{Sec: 0, Nsec: linux.UTIME_OMIT},
|
||||
}
|
||||
|
@ -727,15 +733,15 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
|
|||
}
|
||||
}
|
||||
|
||||
if l.fileType == syscall.S_IFLNK {
|
||||
if l.fileType == unix.S_IFLNK {
|
||||
// utimensat operates different that other syscalls. To operate on a
|
||||
// symlink it *requires* AT_SYMLINK_NOFOLLOW with dirFD and a non-empty
|
||||
// name.
|
||||
parent, err := syscall.Open(path.Dir(l.hostPath), openFlags|unix.O_PATH, 0)
|
||||
parent, err := unix.Open(path.Dir(l.hostPath), openFlags|unix.O_PATH, 0)
|
||||
if err != nil {
|
||||
return extractErrno(err)
|
||||
}
|
||||
defer syscall.Close(parent)
|
||||
defer unix.Close(parent)
|
||||
|
||||
if terr := utimensat(parent, path.Base(l.hostPath), utimes, linux.AT_SYMLINK_NOFOLLOW); terr != nil {
|
||||
log.Debugf("SetAttr utimens failed %q, err: %v", l.hostPath, terr)
|
||||
|
@ -760,7 +766,7 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
|
|||
if valid.GID {
|
||||
gid = int(attr.GID)
|
||||
}
|
||||
if oerr := syscall.Fchownat(f.FD(), "", uid, gid, linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW); oerr != nil {
|
||||
if oerr := unix.Fchownat(f.FD(), "", uid, gid, linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW); oerr != nil {
|
||||
log.Debugf("SetAttr fchownat failed %q, err: %v", l.hostPath, oerr)
|
||||
err = extractErrno(oerr)
|
||||
}
|
||||
|
@ -770,28 +776,28 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
|
|||
}
|
||||
|
||||
func (*localFile) GetXattr(string, uint64) (string, error) {
|
||||
return "", syscall.EOPNOTSUPP
|
||||
return "", unix.EOPNOTSUPP
|
||||
}
|
||||
|
||||
func (*localFile) SetXattr(string, string, uint32) error {
|
||||
return syscall.EOPNOTSUPP
|
||||
return unix.EOPNOTSUPP
|
||||
}
|
||||
|
||||
func (*localFile) ListXattr(uint64) (map[string]struct{}, error) {
|
||||
return nil, syscall.EOPNOTSUPP
|
||||
return nil, unix.EOPNOTSUPP
|
||||
}
|
||||
|
||||
func (*localFile) RemoveXattr(string) error {
|
||||
return syscall.EOPNOTSUPP
|
||||
return unix.EOPNOTSUPP
|
||||
}
|
||||
|
||||
// Allocate implements p9.File.
|
||||
func (l *localFile) Allocate(mode p9.AllocateMode, offset, length uint64) error {
|
||||
if !l.isOpen() {
|
||||
return syscall.EBADF
|
||||
return unix.EBADF
|
||||
}
|
||||
|
||||
if err := syscall.Fallocate(l.file.FD(), mode.ToLinux(), int64(offset), int64(length)); err != nil {
|
||||
if err := unix.Fallocate(l.file.FD(), mode.ToLinux(), int64(offset), int64(length)); err != nil {
|
||||
return extractErrno(err)
|
||||
}
|
||||
return nil
|
||||
|
@ -818,10 +824,10 @@ func (l *localFile) RenameAt(oldName string, directory p9.File, newName string)
|
|||
// ReadAt implements p9.File.
|
||||
func (l *localFile) ReadAt(p []byte, offset uint64) (int, error) {
|
||||
if l.mode != p9.ReadOnly && l.mode != p9.ReadWrite {
|
||||
return 0, syscall.EBADF
|
||||
return 0, unix.EBADF
|
||||
}
|
||||
if !l.isOpen() {
|
||||
return 0, syscall.EBADF
|
||||
return 0, unix.EBADF
|
||||
}
|
||||
|
||||
r, err := l.file.ReadAt(p, int64(offset))
|
||||
|
@ -836,10 +842,10 @@ func (l *localFile) ReadAt(p []byte, offset uint64) (int, error) {
|
|||
// WriteAt implements p9.File.
|
||||
func (l *localFile) WriteAt(p []byte, offset uint64) (int, error) {
|
||||
if l.mode != p9.WriteOnly && l.mode != p9.ReadWrite {
|
||||
return 0, syscall.EBADF
|
||||
return 0, unix.EBADF
|
||||
}
|
||||
if !l.isOpen() {
|
||||
return 0, syscall.EBADF
|
||||
return 0, unix.EBADF
|
||||
}
|
||||
|
||||
w, err := l.file.WriteAt(p, int64(offset))
|
||||
|
@ -860,7 +866,7 @@ func (l *localFile) Symlink(target, newName string, uid p9.UID, gid p9.GID) (p9.
|
|||
}
|
||||
cu := cleanup.Make(func() {
|
||||
// Best effort attempt to remove the symlink in case of failure.
|
||||
if err := syscall.Unlinkat(l.file.FD(), newName); err != nil {
|
||||
if err := unix.Unlinkat(l.file.FD(), newName, 0); err != nil {
|
||||
log.Warningf("error unlinking file %q after failure: %v", path.Join(l.hostPath, newName), err)
|
||||
}
|
||||
})
|
||||
|
@ -899,34 +905,46 @@ func (l *localFile) Link(target p9.File, newName string) error {
|
|||
}
|
||||
|
||||
// Mknod implements p9.File.
|
||||
func (l *localFile) Mknod(name string, mode p9.FileMode, _ uint32, _ uint32, _ p9.UID, _ p9.GID) (p9.QID, error) {
|
||||
func (l *localFile) Mknod(name string, mode p9.FileMode, _ uint32, _ uint32, uid p9.UID, gid p9.GID) (p9.QID, error) {
|
||||
if err := l.checkROMount(); err != nil {
|
||||
return p9.QID{}, err
|
||||
}
|
||||
|
||||
hostPath := path.Join(l.hostPath, name)
|
||||
|
||||
// Return EEXIST if the file already exists.
|
||||
if _, err := stat(hostPath); err == nil {
|
||||
return p9.QID{}, syscall.EEXIST
|
||||
}
|
||||
|
||||
// From mknod(2) man page:
|
||||
// "EPERM: [...] if the filesystem containing pathname does not support
|
||||
// the type of node requested."
|
||||
if mode.FileType() != p9.ModeRegular {
|
||||
return p9.QID{}, syscall.EPERM
|
||||
return p9.QID{}, unix.EPERM
|
||||
}
|
||||
|
||||
// Allow Mknod to create regular files.
|
||||
if err := syscall.Mknod(hostPath, uint32(mode), 0); err != nil {
|
||||
if err := unix.Mknodat(l.file.FD(), name, uint32(mode), 0); err != nil {
|
||||
return p9.QID{}, err
|
||||
}
|
||||
cu := cleanup.Make(func() {
|
||||
// Best effort attempt to remove the file in case of failure.
|
||||
if err := unix.Unlinkat(l.file.FD(), name, 0); err != nil {
|
||||
log.Warningf("error unlinking file %q after failure: %v", path.Join(l.hostPath, name), err)
|
||||
}
|
||||
})
|
||||
defer cu.Clean()
|
||||
|
||||
stat, err := stat(hostPath)
|
||||
// Open file to change ownership and stat it.
|
||||
child, err := fd.OpenAt(l.file, name, unix.O_PATH|openFlags, 0)
|
||||
if err != nil {
|
||||
return p9.QID{}, extractErrno(err)
|
||||
}
|
||||
defer child.Close()
|
||||
|
||||
if err := fchown(child.FD(), uid, gid); err != nil {
|
||||
return p9.QID{}, extractErrno(err)
|
||||
}
|
||||
stat, err := fstat(child.FD())
|
||||
if err != nil {
|
||||
return p9.QID{}, extractErrno(err)
|
||||
}
|
||||
|
||||
cu.Release()
|
||||
return l.attachPoint.makeQID(stat), nil
|
||||
}
|
||||
|
||||
|
@ -945,10 +963,10 @@ func (l *localFile) UnlinkAt(name string, flags uint32) error {
|
|||
// Readdir implements p9.File.
|
||||
func (l *localFile) Readdir(offset uint64, count uint32) ([]p9.Dirent, error) {
|
||||
if l.mode != p9.ReadOnly && l.mode != p9.ReadWrite {
|
||||
return nil, syscall.EBADF
|
||||
return nil, unix.EBADF
|
||||
}
|
||||
if !l.isOpen() {
|
||||
return nil, syscall.EBADF
|
||||
return nil, unix.EBADF
|
||||
}
|
||||
|
||||
// Readdirnames is a cursor over directories, so seek back to 0 to ensure it's
|
||||
|
@ -965,7 +983,7 @@ func (l *localFile) Readdir(offset uint64, count uint32) ([]p9.Dirent, error) {
|
|||
// which causes the directory stream to resynchronize with the directory's
|
||||
// current contents).
|
||||
if l.lastDirentOffset != offset || offset == 0 {
|
||||
if _, err := syscall.Seek(l.file.FD(), 0, 0); err != nil {
|
||||
if _, err := unix.Seek(l.file.FD(), 0, 0); err != nil {
|
||||
return nil, extractErrno(err)
|
||||
}
|
||||
skip = offset
|
||||
|
@ -998,7 +1016,7 @@ func (l *localFile) readDirent(f int, offset uint64, count uint32, skip uint64)
|
|||
|
||||
end := offset + uint64(count)
|
||||
for offset < end {
|
||||
dirSize, err := syscall.ReadDirent(f, direntsBuf)
|
||||
dirSize, err := unix.ReadDirent(f, direntsBuf)
|
||||
if err != nil {
|
||||
return dirents, err
|
||||
}
|
||||
|
@ -1007,7 +1025,7 @@ func (l *localFile) readDirent(f int, offset uint64, count uint32, skip uint64)
|
|||
}
|
||||
|
||||
names := names[:0]
|
||||
_, _, names = syscall.ParseDirent(direntsBuf[:dirSize], -1, names)
|
||||
_, _, names = unix.ParseDirent(direntsBuf[:dirSize], -1, names)
|
||||
|
||||
// Skip over entries that the caller is not interested in.
|
||||
if skip > 0 {
|
||||
|
@ -1052,7 +1070,7 @@ func (l *localFile) Readlink() (string, error) {
|
|||
return string(b[:n]), nil
|
||||
}
|
||||
}
|
||||
return "", syscall.ENOMEM
|
||||
return "", unix.ENOMEM
|
||||
}
|
||||
|
||||
// Flush implements p9.File.
|
||||
|
@ -1063,7 +1081,7 @@ func (l *localFile) Flush() error {
|
|||
// Connect implements p9.File.
|
||||
func (l *localFile) Connect(flags p9.ConnectFlags) (*fd.FD, error) {
|
||||
if !l.attachPoint.conf.HostUDS {
|
||||
return nil, syscall.ECONNREFUSED
|
||||
return nil, unix.ECONNREFUSED
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/1003): Due to different app vs replacement
|
||||
|
@ -1071,34 +1089,34 @@ func (l *localFile) Connect(flags p9.ConnectFlags) (*fd.FD, error) {
|
|||
// fit f.path in our sockaddr. We'd need to redirect through a shorter
|
||||
// path in order to actually connect to this socket.
|
||||
if len(l.hostPath) > linux.UnixPathMax {
|
||||
return nil, syscall.ECONNREFUSED
|
||||
return nil, unix.ECONNREFUSED
|
||||
}
|
||||
|
||||
var stype int
|
||||
switch flags {
|
||||
case p9.StreamSocket:
|
||||
stype = syscall.SOCK_STREAM
|
||||
stype = unix.SOCK_STREAM
|
||||
case p9.DgramSocket:
|
||||
stype = syscall.SOCK_DGRAM
|
||||
stype = unix.SOCK_DGRAM
|
||||
case p9.SeqpacketSocket:
|
||||
stype = syscall.SOCK_SEQPACKET
|
||||
stype = unix.SOCK_SEQPACKET
|
||||
default:
|
||||
return nil, syscall.ENXIO
|
||||
return nil, unix.ENXIO
|
||||
}
|
||||
|
||||
f, err := syscall.Socket(syscall.AF_UNIX, stype, 0)
|
||||
f, err := unix.Socket(unix.AF_UNIX, stype, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := syscall.SetNonblock(f, true); err != nil {
|
||||
_ = syscall.Close(f)
|
||||
if err := unix.SetNonblock(f, true); err != nil {
|
||||
_ = unix.Close(f)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sa := syscall.SockaddrUnix{Name: l.hostPath}
|
||||
if err := syscall.Connect(f, &sa); err != nil {
|
||||
_ = syscall.Close(f)
|
||||
sa := unix.SockaddrUnix{Name: l.hostPath}
|
||||
if err := unix.Connect(f, &sa); err != nil {
|
||||
_ = unix.Close(f)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1141,7 @@ func (l *localFile) Renamed(newDir p9.File, newName string) {
|
|||
}
|
||||
|
||||
// extractErrno tries to determine the errno.
|
||||
func extractErrno(err error) syscall.Errno {
|
||||
func extractErrno(err error) unix.Errno {
|
||||
if err == nil {
|
||||
// This should never happen. The likely result will be that
|
||||
// some user gets the frustrating "error: SUCCESS" message.
|
||||
|
@ -1133,18 +1151,18 @@ func extractErrno(err error) syscall.Errno {
|
|||
|
||||
switch err {
|
||||
case os.ErrNotExist:
|
||||
return syscall.ENOENT
|
||||
return unix.ENOENT
|
||||
case os.ErrExist:
|
||||
return syscall.EEXIST
|
||||
return unix.EEXIST
|
||||
case os.ErrPermission:
|
||||
return syscall.EACCES
|
||||
return unix.EACCES
|
||||
case os.ErrInvalid:
|
||||
return syscall.EINVAL
|
||||
return unix.EINVAL
|
||||
}
|
||||
|
||||
// See if it's an errno or a common wrapped error.
|
||||
switch e := err.(type) {
|
||||
case syscall.Errno:
|
||||
case unix.Errno:
|
||||
return e
|
||||
case *os.PathError:
|
||||
return extractErrno(e.Err)
|
||||
|
@ -1156,7 +1174,7 @@ func extractErrno(err error) syscall.Errno {
|
|||
|
||||
// Fall back to EIO.
|
||||
log.Debugf("Unknown error: %v, defaulting to EIO", err)
|
||||
return syscall.EIO
|
||||
return unix.EIO
|
||||
}
|
||||
|
||||
func (l *localFile) checkROMount() error {
|
||||
|
@ -1164,7 +1182,7 @@ func (l *localFile) checkROMount() error {
|
|||
if conf.PanicOnWrite {
|
||||
panic("attempt to write to RO mount")
|
||||
}
|
||||
return syscall.EROFS
|
||||
return unix.EROFS
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,25 +17,25 @@
|
|||
package fsgofer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
)
|
||||
|
||||
func statAt(dirFd int, name string) (syscall.Stat_t, error) {
|
||||
nameBytes, err := syscall.BytePtrFromString(name)
|
||||
func statAt(dirFd int, name string) (unix.Stat_t, error) {
|
||||
nameBytes, err := unix.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return syscall.Stat_t{}, err
|
||||
return unix.Stat_t{}, err
|
||||
}
|
||||
namePtr := unsafe.Pointer(nameBytes)
|
||||
|
||||
var stat syscall.Stat_t
|
||||
var stat unix.Stat_t
|
||||
statPtr := unsafe.Pointer(&stat)
|
||||
|
||||
if _, _, errno := syscall.Syscall6(
|
||||
syscall.SYS_NEWFSTATAT,
|
||||
if _, _, errno := unix.Syscall6(
|
||||
unix.SYS_NEWFSTATAT,
|
||||
uintptr(dirFd),
|
||||
uintptr(namePtr),
|
||||
uintptr(statPtr),
|
||||
|
@ -43,7 +43,7 @@ func statAt(dirFd int, name string) (syscall.Stat_t, error) {
|
|||
0,
|
||||
0); errno != 0 {
|
||||
|
||||
return syscall.Stat_t{}, syserr.FromHost(errno).ToError()
|
||||
return unix.Stat_t{}, syserr.FromHost(errno).ToError()
|
||||
}
|
||||
return stat, nil
|
||||
}
|
||||
|
|
|
@ -17,25 +17,25 @@
|
|||
package fsgofer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
)
|
||||
|
||||
func statAt(dirFd int, name string) (syscall.Stat_t, error) {
|
||||
nameBytes, err := syscall.BytePtrFromString(name)
|
||||
func statAt(dirFd int, name string) (unix.Stat_t, error) {
|
||||
nameBytes, err := unix.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return syscall.Stat_t{}, err
|
||||
return unix.Stat_t{}, err
|
||||
}
|
||||
namePtr := unsafe.Pointer(nameBytes)
|
||||
|
||||
var stat syscall.Stat_t
|
||||
var stat unix.Stat_t
|
||||
statPtr := unsafe.Pointer(&stat)
|
||||
|
||||
if _, _, errno := syscall.Syscall6(
|
||||
syscall.SYS_FSTATAT,
|
||||
if _, _, errno := unix.Syscall6(
|
||||
unix.SYS_FSTATAT,
|
||||
uintptr(dirFd),
|
||||
uintptr(namePtr),
|
||||
uintptr(statPtr),
|
||||
|
@ -43,7 +43,7 @@ func statAt(dirFd int, name string) (syscall.Stat_t, error) {
|
|||
0,
|
||||
0); errno != 0 {
|
||||
|
||||
return syscall.Stat_t{}, syserr.FromHost(errno).ToError()
|
||||
return unix.Stat_t{}, syserr.FromHost(errno).ToError()
|
||||
}
|
||||
return stat, nil
|
||||
}
|
||||
|
|
|
@ -15,18 +15,18 @@
|
|||
package fsgofer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
)
|
||||
|
||||
func utimensat(dirFd int, name string, times [2]syscall.Timespec, flags int) error {
|
||||
func utimensat(dirFd int, name string, times [2]unix.Timespec, flags int) error {
|
||||
// utimensat(2) doesn't accept empty name, instead name must be nil to make it
|
||||
// operate directly on 'dirFd' unlike other *at syscalls.
|
||||
var namePtr unsafe.Pointer
|
||||
if name != "" {
|
||||
nameBytes, err := syscall.BytePtrFromString(name)
|
||||
nameBytes, err := unix.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ func utimensat(dirFd int, name string, times [2]syscall.Timespec, flags int) err
|
|||
|
||||
timesPtr := unsafe.Pointer(×[0])
|
||||
|
||||
if _, _, errno := syscall.Syscall6(
|
||||
syscall.SYS_UTIMENSAT,
|
||||
if _, _, errno := unix.Syscall6(
|
||||
unix.SYS_UTIMENSAT,
|
||||
uintptr(dirFd),
|
||||
uintptr(namePtr),
|
||||
uintptr(timesPtr),
|
||||
|
@ -52,7 +52,7 @@ func utimensat(dirFd int, name string, times [2]syscall.Timespec, flags int) err
|
|||
func renameat(oldDirFD int, oldName string, newDirFD int, newName string) error {
|
||||
var oldNamePtr unsafe.Pointer
|
||||
if oldName != "" {
|
||||
nameBytes, err := syscall.BytePtrFromString(oldName)
|
||||
nameBytes, err := unix.BytePtrFromString(oldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -60,15 +60,15 @@ func renameat(oldDirFD int, oldName string, newDirFD int, newName string) error
|
|||
}
|
||||
var newNamePtr unsafe.Pointer
|
||||
if newName != "" {
|
||||
nameBytes, err := syscall.BytePtrFromString(newName)
|
||||
nameBytes, err := unix.BytePtrFromString(newName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newNamePtr = unsafe.Pointer(nameBytes)
|
||||
}
|
||||
|
||||
if _, _, errno := syscall.Syscall6(
|
||||
syscall.SYS_RENAMEAT,
|
||||
if _, _, errno := unix.Syscall6(
|
||||
unix.SYS_RENAMEAT,
|
||||
uintptr(oldDirFD),
|
||||
uintptr(oldNamePtr),
|
||||
uintptr(newDirFD),
|
||||
|
|
Loading…
Reference in New Issue