v2api: fix missing size translation in Lookup
This commit is contained in:
parent
777b95f82f
commit
4572cd2103
@ -69,7 +69,13 @@ func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (ch
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fs.ToErrno(err)
|
return nil, fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create new inode and fill `out`
|
||||||
ch = n.newChild(ctx, st, out)
|
ch = n.newChild(ctx, st, out)
|
||||||
|
|
||||||
|
// Translate ciphertext size in `out.Attr.Size` to plaintext size
|
||||||
|
n.translateSize(dirfd, cName, &out.Attr)
|
||||||
|
|
||||||
return ch, 0
|
return ch, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,13 +104,9 @@ func (n *Node) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut)
|
|||||||
rn.inoMap.TranslateStat(st)
|
rn.inoMap.TranslateStat(st)
|
||||||
out.Attr.FromStat(st)
|
out.Attr.FromStat(st)
|
||||||
|
|
||||||
// Fix size
|
// Translate ciphertext size in `out.Attr.Size` to plaintext size
|
||||||
if out.IsRegular() {
|
n.translateSize(dirfd, cName, &out.Attr)
|
||||||
out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size)
|
|
||||||
} else if out.IsSymlink() {
|
|
||||||
target, _ := n.Readlink(ctx)
|
|
||||||
out.Size = uint64(len(target))
|
|
||||||
}
|
|
||||||
if rn.args.ForceOwner != nil {
|
if rn.args.ForceOwner != nil {
|
||||||
out.Owner = *rn.args.ForceOwner
|
out.Owner = *rn.args.ForceOwner
|
||||||
}
|
}
|
||||||
@ -221,21 +223,7 @@ func (n *Node) Readlink(ctx context.Context) (out []byte, errno syscall.Errno) {
|
|||||||
}
|
}
|
||||||
defer syscall.Close(dirfd)
|
defer syscall.Close(dirfd)
|
||||||
|
|
||||||
cTarget, err := syscallcompat.Readlinkat(dirfd, cName)
|
return n.readlink(dirfd, cName)
|
||||||
if err != nil {
|
|
||||||
return nil, fs.ToErrno(err)
|
|
||||||
}
|
|
||||||
rn := n.rootNode()
|
|
||||||
if rn.args.PlaintextNames {
|
|
||||||
return []byte(cTarget), 0
|
|
||||||
}
|
|
||||||
// Symlinks are encrypted like file contents (GCM) and base64-encoded
|
|
||||||
target, err := rn.decryptSymlinkTarget(cTarget)
|
|
||||||
if err != nil {
|
|
||||||
tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err)
|
|
||||||
return nil, syscall.EIO
|
|
||||||
}
|
|
||||||
return []byte(target), 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open - FUSE call. Open already-existing file.
|
// Open - FUSE call. Open already-existing file.
|
||||||
|
@ -2,10 +2,14 @@ package fusefrontend
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/hanwen/go-fuse/v2/fs"
|
"github.com/hanwen/go-fuse/v2/fs"
|
||||||
|
|
||||||
"github.com/hanwen/go-fuse/v2/fuse"
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// toFuseCtx tries to extract a fuse.Context from a generic context.Context.
|
// toFuseCtx tries to extract a fuse.Context from a generic context.Context.
|
||||||
@ -29,3 +33,33 @@ func toNode(op fs.InodeEmbedder) *Node {
|
|||||||
}
|
}
|
||||||
return op.(*Node)
|
return op.(*Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readlink reads and decrypts a symlink. Used by Readlink, Getattr, Lookup.
|
||||||
|
func (n *Node) readlink(dirfd int, cName string) (out []byte, errno syscall.Errno) {
|
||||||
|
cTarget, err := syscallcompat.Readlinkat(dirfd, cName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fs.ToErrno(err)
|
||||||
|
}
|
||||||
|
rn := n.rootNode()
|
||||||
|
if rn.args.PlaintextNames {
|
||||||
|
return []byte(cTarget), 0
|
||||||
|
}
|
||||||
|
// Symlinks are encrypted like file contents (GCM) and base64-encoded
|
||||||
|
target, err := rn.decryptSymlinkTarget(cTarget)
|
||||||
|
if err != nil {
|
||||||
|
tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err)
|
||||||
|
return nil, syscall.EIO
|
||||||
|
}
|
||||||
|
return []byte(target), 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// translateSize translates the ciphertext size in `out` into plaintext size.
|
||||||
|
func (n *Node) translateSize(dirfd int, cName string, out *fuse.Attr) {
|
||||||
|
if out.IsRegular() {
|
||||||
|
rn := n.rootNode()
|
||||||
|
out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size)
|
||||||
|
} else if out.IsSymlink() {
|
||||||
|
target, _ := n.readlink(dirfd, cName)
|
||||||
|
out.Size = uint64(len(target))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -293,3 +293,79 @@ func TestSeekData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestMd5sumMaintainers tries to repro this interesting
|
||||||
|
bug that was seen during gocryptfs v2.0 development:
|
||||||
|
|
||||||
|
$ md5sum linux-3.0/MAINTAINERS linux-3.0/MAINTAINERS linux-3.0/MAINTAINERS linux-3.0/MAINTAINERS
|
||||||
|
279b6ab0491e7532132e8f32afe6c04d linux-3.0/MAINTAINERS <-- WRONG!!!!
|
||||||
|
99cc9f0dfd86e63231b94edd43a43e02 linux-3.0/MAINTAINERS <-- correct
|
||||||
|
99cc9f0dfd86e63231b94edd43a43e02 linux-3.0/MAINTAINERS
|
||||||
|
99cc9f0dfd86e63231b94edd43a43e02 linux-3.0/MAINTAINERS
|
||||||
|
|
||||||
|
strace shows:
|
||||||
|
|
||||||
|
Bad
|
||||||
|
---
|
||||||
|
fstat(3, {st_mode=S_IFREG|0644, st_size=196745, ...}) = 0
|
||||||
|
read(3, "\n\tList of maintainers and how to"..., 32768) = 32768
|
||||||
|
read(3, "M:\tSylwester Nawrocki <s.nawrock"..., 32768) = 32768
|
||||||
|
read(3, "rs/scsi/eata*\n\nEATA ISA/EISA/PCI"..., 32768) = 32768
|
||||||
|
read(3, "F:\tDocumentation/isapnp.txt\nF:\td"..., 32768) = 32768
|
||||||
|
read(3, "hunkeey@googlemail.com>\nL:\tlinux"..., 32768) = 32768
|
||||||
|
read(3, "ach-spear3xx/\n\nSPEAR6XX MACHINE "..., 32768) = 32768
|
||||||
|
read(3, "", 32768) = 0
|
||||||
|
lseek(3, 0, SEEK_CUR) = 196608
|
||||||
|
close(3) = 0
|
||||||
|
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0
|
||||||
|
write(1, "279b6ab0491e7532132e8f32afe6c04d"..., 56279b6ab0491e7532132e8f32afe6c04d linux-3.0/MAINTAINERS
|
||||||
|
|
||||||
|
Good
|
||||||
|
----
|
||||||
|
fstat(3, {st_mode=S_IFREG|0644, st_size=195191, ...}) = 0
|
||||||
|
read(3, "\n\tList of maintainers and how to"..., 32768) = 32768
|
||||||
|
read(3, "M:\tSylwester Nawrocki <s.nawrock"..., 32768) = 32768
|
||||||
|
read(3, "rs/scsi/eata*\n\nEATA ISA/EISA/PCI"..., 32768) = 32768
|
||||||
|
read(3, "F:\tDocumentation/isapnp.txt\nF:\td"..., 32768) = 32768
|
||||||
|
read(3, "hunkeey@googlemail.com>\nL:\tlinux"..., 32768) = 32768
|
||||||
|
read(3, "ach-spear3xx/\n\nSPEAR6XX MACHINE "..., 32768) = 31351
|
||||||
|
read(3, "", 4096) = 0
|
||||||
|
lseek(3, 0, SEEK_CUR) = 195191
|
||||||
|
close(3) = 0
|
||||||
|
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0
|
||||||
|
write(1, "99cc9f0dfd86e63231b94edd43a43e02"..., 5699cc9f0dfd86e63231b94edd43a43e02 linux-3.0/MAINTAINERS
|
||||||
|
*/
|
||||||
|
func TestMd5sumMaintainers(t *testing.T) {
|
||||||
|
fn := filepath.Join(test_helpers.DefaultPlainDir, t.Name())
|
||||||
|
f, err := os.Create(fn)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Size of the MAINTAINERS file = 195191
|
||||||
|
const sizeWant = 195191
|
||||||
|
content := make([]byte, sizeWant)
|
||||||
|
_, err = f.Write(content)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
// Remount to clear the linux kernel attr cache
|
||||||
|
// (otherwise we would have to wait 2 seconds for the entry to expire)
|
||||||
|
test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
|
||||||
|
test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey")
|
||||||
|
|
||||||
|
cmd := exec.Command("md5sum", fn, fn, fn, fn)
|
||||||
|
out2, err := cmd.CombinedOutput()
|
||||||
|
out := string(out2)
|
||||||
|
|
||||||
|
// 195191 zero bytes have this md5sum
|
||||||
|
const md5Want = "b99bf6917f688068acd49126f3b1b005"
|
||||||
|
|
||||||
|
n := strings.Count(out, md5Want)
|
||||||
|
if n != 4 {
|
||||||
|
t.Errorf("found %d instead of %d instances of %q", n, 4, md5Want)
|
||||||
|
t.Logf("full output:\n%s", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user