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.
This commit is contained in:
Sebastian Lackner 2019-01-12 21:19:23 +01:00
parent a525e33eaa
commit 1fbe7798cf
3 changed files with 34 additions and 14 deletions

View File

@ -319,6 +319,10 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context)
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
defer syscall.Close(dirfd) 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) // Create ".name" file to store long file name (except in PlaintextNames mode)
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) { if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
err = fs.nameTransform.WriteLongNameAt(dirfd, cName, path) 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) return fuse.ToStatus(err)
} }
// Create "gocryptfs.longfile." device node // 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 { if err != nil {
nametransform.DeleteLongNameAt(dirfd, cName) nametransform.DeleteLongNameAt(dirfd, cName)
} }
} else { } else {
// Create regular device node // Create regular device node
err = syscallcompat.Mknodat(dirfd, cName, mode, int(dev)) err = syscallcompat.MknodatUser(dirfd, cName, mode, int(dev), context)
} }
if err != nil { return fuse.ToStatus(err)
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)
}
}
return fuse.OK
} }
// Truncate - FUSE call. Truncates a file. // Truncate - FUSE call. Truncates a file.

View File

@ -63,6 +63,11 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
return emulateMknodat(dirfd, path, mode, dev) 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) { func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
return emulateFchmodat(dirfd, path, mode, flags) return emulateFchmodat(dirfd, path, mode, flags)
} }

View File

@ -113,6 +113,28 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
return syscall.Mknodat(dirfd, path, mode, dev) 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 // Dup3 wraps the Dup3 syscall. We want to use Dup3 rather than Dup2 because Dup2
// is not implemented on arm64. // is not implemented on arm64.
func Dup3(oldfd int, newfd int, flags int) (err error) { func Dup3(oldfd int, newfd int, flags int) (err error) {