v2api: fix Mkdir crash when using plaintextnames
This commit is contained in:
parent
b1d631d432
commit
735e2aa65b
@ -68,66 +68,76 @@ func (n *Node) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.En
|
|||||||
if rn.args.PreserveOwner {
|
if rn.args.PreserveOwner {
|
||||||
caller, _ = fuse.FromContext(ctx)
|
caller, _ = fuse.FromContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var st syscall.Stat_t
|
||||||
|
|
||||||
if rn.args.PlaintextNames {
|
if rn.args.PlaintextNames {
|
||||||
err = syscallcompat.MkdiratUser(dirfd, cName, mode, caller)
|
err = syscallcompat.MkdiratUser(dirfd, cName, mode, caller)
|
||||||
return nil, fs.ToErrno(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need write and execute permissions to create gocryptfs.diriv.
|
|
||||||
// Also, we need read permissions to open the directory (to avoid
|
|
||||||
// race-conditions between getting and setting the mode).
|
|
||||||
origMode := mode
|
|
||||||
mode = mode | 0700
|
|
||||||
|
|
||||||
// Handle long file name
|
|
||||||
if nametransform.IsLongContent(cName) {
|
|
||||||
// Create ".name"
|
|
||||||
err = rn.nameTransform.WriteLongNameAt(dirfd, cName, newPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fs.ToErrno(err)
|
return nil, fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
var ust unix.Stat_t
|
||||||
// Create directory
|
err = syscallcompat.Fstatat(dirfd, cName, &ust, unix.AT_SYMLINK_NOFOLLOW)
|
||||||
err = rn.mkdirWithIv(dirfd, cName, mode, caller)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nametransform.DeleteLongNameAt(dirfd, cName)
|
|
||||||
return nil, fs.ToErrno(err)
|
return nil, fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
st = syscallcompat.Unix2syscall(ust)
|
||||||
} else {
|
} else {
|
||||||
err = rn.mkdirWithIv(dirfd, cName, mode, caller)
|
// We need write and execute permissions to create gocryptfs.diriv.
|
||||||
|
// Also, we need read permissions to open the directory (to avoid
|
||||||
|
// race-conditions between getting and setting the mode).
|
||||||
|
origMode := mode
|
||||||
|
mode = mode | 0700
|
||||||
|
|
||||||
|
// Handle long file name
|
||||||
|
if nametransform.IsLongContent(cName) {
|
||||||
|
// Create ".name"
|
||||||
|
err = rn.nameTransform.WriteLongNameAt(dirfd, cName, newPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fs.ToErrno(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create directory
|
||||||
|
err = rn.mkdirWithIv(dirfd, cName, mode, caller)
|
||||||
|
if err != nil {
|
||||||
|
nametransform.DeleteLongNameAt(dirfd, cName)
|
||||||
|
return nil, fs.ToErrno(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = rn.mkdirWithIv(dirfd, cName, mode, caller)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fs.ToErrno(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := syscallcompat.Openat(dirfd, cName,
|
||||||
|
syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tlog.Warn.Printf("Mkdir %q: Openat failed: %v", cName, err)
|
||||||
return nil, fs.ToErrno(err)
|
return nil, fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
defer syscall.Close(fd)
|
||||||
|
|
||||||
|
err = syscall.Fstat(fd, &st)
|
||||||
|
if err != nil {
|
||||||
|
tlog.Warn.Printf("Mkdir %q: Fstat failed: %v", cName, err)
|
||||||
|
return nil, fs.ToErrno(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix permissions
|
||||||
|
if origMode != mode {
|
||||||
|
// Preserve SGID bit if it was set due to inheritance.
|
||||||
|
origMode = uint32(st.Mode&^0777) | origMode
|
||||||
|
err = syscall.Fchmod(fd, origMode)
|
||||||
|
if err != nil {
|
||||||
|
tlog.Warn.Printf("Mkdir %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := syscallcompat.Openat(dirfd, cName,
|
|
||||||
syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
|
|
||||||
if err != nil {
|
|
||||||
tlog.Warn.Printf("Mkdir %q: Openat failed: %v", cName, err)
|
|
||||||
return nil, fs.ToErrno(err)
|
|
||||||
}
|
|
||||||
defer syscall.Close(fd)
|
|
||||||
|
|
||||||
// Get unique inode number
|
|
||||||
var st syscall.Stat_t
|
|
||||||
err = syscall.Fstat(fd, &st)
|
|
||||||
if err != nil {
|
|
||||||
tlog.Warn.Printf("Mkdir %q: Fstat failed: %v", cName, err)
|
|
||||||
return nil, fs.ToErrno(err)
|
|
||||||
}
|
|
||||||
// Create child node
|
// Create child node
|
||||||
ch := n.newChild(ctx, &st, out)
|
ch := n.newChild(ctx, &st, out)
|
||||||
|
|
||||||
// Set mode
|
|
||||||
if origMode != mode {
|
|
||||||
// Preserve SGID bit if it was set due to inheritance.
|
|
||||||
origMode = uint32(st.Mode&^0777) | origMode
|
|
||||||
err = syscall.Fchmod(fd, origMode)
|
|
||||||
if err != nil {
|
|
||||||
tlog.Warn.Printf("Mkdir %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch, 0
|
return ch, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ func TestRename(t *testing.T, plainDir string) {
|
|||||||
}
|
}
|
||||||
err = syscall.Rename(file1, file2)
|
err = syscall.Rename(file1, file2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Errorf("Rename: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
syscall.Unlink(file2)
|
syscall.Unlink(file2)
|
||||||
|
Loading…
Reference in New Issue
Block a user