fusefrontend: -allow_other: Use SymlinkatUser in Symlink FUSE call.

Instead of manually adjusting the user after creating the symlink,
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:22:52 +01:00
parent 1fbe7798cf
commit efc280330c
3 changed files with 34 additions and 14 deletions

View File

@ -483,6 +483,10 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co
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
}
cTarget := target
if !fs.args.PlaintextNames {
// Symlinks are encrypted like file contents (GCM) and base64-encoded
@ -495,26 +499,15 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co
return fuse.ToStatus(err)
}
// Create "gocryptfs.longfile." symlink
err = syscallcompat.Symlinkat(cTarget, dirfd, cName)
err = syscallcompat.SymlinkatUser(cTarget, dirfd, cName, context)
if err != nil {
nametransform.DeleteLongNameAt(dirfd, cName)
}
} else {
// Create symlink
err = syscallcompat.Symlinkat(cTarget, dirfd, cName)
err = syscallcompat.SymlinkatUser(cTarget, dirfd, cName, context)
}
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("Symlink: Fchownat failed: %v", err)
}
}
return fuse.OK
return fuse.ToStatus(err)
}
// Rename - FUSE call.

View File

@ -80,6 +80,11 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
return emulateSymlinkat(oldpath, newdirfd, newpath)
}
func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.Context) (err error) {
// FIXME: take into account context.Owner
return Symlinkat(oldpath, newdirfd, newpath)
}
func Mkdirat(dirfd int, path string, mode uint32) (err error) {
return emulateMkdirat(dirfd, path, mode)
}

View File

@ -197,6 +197,28 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
return unix.Symlinkat(oldpath, newdirfd, newpath)
}
// SymlinkatUser runs the Symlinkat syscall in the context of a different user.
func SymlinkatUser(oldpath string, newdirfd int, newpath string, 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 Symlinkat(oldpath, newdirfd, newpath)
}
// Mkdirat syscall.
func Mkdirat(dirfd int, path string, mode uint32) (err error) {
return syscall.Mkdirat(dirfd, path, mode)