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:
parent
1fbe7798cf
commit
efc280330c
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user