diff options
author | Sebastian Lackner | 2019-01-12 21:19:23 +0100 |
---|---|---|
committer | Sebastian Lackner | 2019-01-12 21:20:16 +0100 |
commit | 1fbe7798cf879d80cfbd755b05bdadae24bc5519 (patch) | |
tree | 43fdd12317feaebd3fa8d318ba09a9fce60d2d1f | |
parent | a525e33eaa59c6561653a5fc40e5c4d5a9a3184b (diff) |
fusefrontend: -allow_other: Use MknodatUser in Mknod FUSE call.
Instead of manually adjusting the user and mode after creating the
device file, adjust effective permissions and let the kernel deal
with it.
Related to https://github.com/rfjakob/gocryptfs/issues/338.
-rw-r--r-- | internal/fusefrontend/fs.go | 21 | ||||
-rw-r--r-- | internal/syscallcompat/sys_darwin.go | 5 | ||||
-rw-r--r-- | internal/syscallcompat/sys_linux.go | 22 |
3 files changed, 34 insertions, 14 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 2c6ac5a..9637acf 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -319,6 +319,10 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context) return fuse.ToStatus(err) } defer syscall.Close(dirfd) + // Make sure context is nil if we don't want to preserve the owner + if !fs.args.PreserveOwner { + context = nil + } // Create ".name" file to store long file name (except in PlaintextNames mode) if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) { err = fs.nameTransform.WriteLongNameAt(dirfd, cName, path) @@ -326,26 +330,15 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context) return fuse.ToStatus(err) } // Create "gocryptfs.longfile." device node - err = syscallcompat.Mknodat(dirfd, cName, mode, int(dev)) + err = syscallcompat.MknodatUser(dirfd, cName, mode, int(dev), context) if err != nil { nametransform.DeleteLongNameAt(dirfd, cName) } } else { // Create regular device node - err = syscallcompat.Mknodat(dirfd, cName, mode, int(dev)) - } - if err != nil { - return fuse.ToStatus(err) - } - // Set owner - if fs.args.PreserveOwner { - err = syscallcompat.Fchownat(dirfd, cName, int(context.Owner.Uid), - int(context.Owner.Gid), unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - tlog.Warn.Printf("Mknod: Fchownat failed: %v", err) - } + err = syscallcompat.MknodatUser(dirfd, cName, mode, int(dev), context) } - return fuse.OK + return fuse.ToStatus(err) } // Truncate - FUSE call. Truncates a file. diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go index 3c431b9..c9f3ad7 100644 --- a/internal/syscallcompat/sys_darwin.go +++ b/internal/syscallcompat/sys_darwin.go @@ -63,6 +63,11 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { return emulateMknodat(dirfd, path, mode, dev) } +func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) { + // FIXME: take into account context.Owner + return Mknodat(dirfd, path, mode, dev) +} + func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { return emulateFchmodat(dirfd, path, mode, flags) } diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go index a431195..cf747b1 100644 --- a/internal/syscallcompat/sys_linux.go +++ b/internal/syscallcompat/sys_linux.go @@ -113,6 +113,28 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { return syscall.Mknodat(dirfd, path, mode, dev) } +// MknodatUser runs the Mknodat syscall in the context of a different user. +func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) { + if context != nil { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err = syscall.Setregid(-1, int(context.Owner.Gid)) + if err != nil { + return err + } + defer syscall.Setregid(-1, 0) + + err = syscall.Setreuid(-1, int(context.Owner.Uid)) + if err != nil { + return err + } + defer syscall.Setreuid(-1, 0) + } + + return Mknodat(dirfd, path, mode, dev) +} + // Dup3 wraps the Dup3 syscall. We want to use Dup3 rather than Dup2 because Dup2 // is not implemented on arm64. func Dup3(oldfd int, newfd int, flags int) (err error) { |