From d05c88a5d6da2d327560675a3c421d158779733b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 30 Nov 2020 23:24:28 +0100 Subject: [PATCH] fuse: Properly set uid/gid for directories In #2584 this was changed to use the uid/gid of the root node. This would be okay for the top-level directory of a snapshot, however, this change also applied to normal directories within a snapshot. This change reverts the problematic part and adds a test that directory attributes are represented correctly. --- changelog/unreleased/issue-2563 | 8 ++++++++ internal/fuse/dir.go | 7 +++++-- internal/fuse/fuse_test.go | 36 +++++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 changelog/unreleased/issue-2563 diff --git a/changelog/unreleased/issue-2563 b/changelog/unreleased/issue-2563 new file mode 100644 index 000000000..4a4063adf --- /dev/null +++ b/changelog/unreleased/issue-2563 @@ -0,0 +1,8 @@ +Bugfix: Use correct directory owner in fuse mount + +Restic 0.10.0 changed the fuse mount to always report the current user +as the owner of directories within the fuse mount, which is incorrect. +We have changed this back to use the correct owner of a directory. + +https://github.com/restic/restic/issues/2563 +https://github.com/restic/restic/pull/3141 diff --git a/internal/fuse/dir.go b/internal/fuse/dir.go index 8b217f473..c14e28d27 100644 --- a/internal/fuse/dir.go +++ b/internal/fuse/dir.go @@ -111,8 +111,11 @@ func (d *dir) Attr(ctx context.Context, a *fuse.Attr) error { debug.Log("Attr()") a.Inode = d.inode a.Mode = os.ModeDir | d.node.Mode - a.Uid = d.root.uid - a.Gid = d.root.gid + + if !d.root.cfg.OwnerIsRoot { + a.Uid = d.node.UID + a.Gid = d.node.GID + } a.Atime = d.node.AccessTime a.Ctime = d.node.ChangeTime a.Mtime = d.node.ModTime diff --git a/internal/fuse/fuse_test.go b/internal/fuse/fuse_test.go index 6a9c3aa8b..50128a9c0 100644 --- a/internal/fuse/fuse_test.go +++ b/internal/fuse/fuse_test.go @@ -187,6 +187,37 @@ func TestFuseFile(t *testing.T) { } } +func TestFuseDir(t *testing.T) { + repo, cleanup := repository.TestRepository(t) + defer cleanup() + + root := &Root{repo: repo, blobCache: newBlobCache(blobCacheSize)} + + node := &restic.Node{ + Mode: 0755, + UID: 42, + GID: 43, + AccessTime: time.Unix(1606773731, 0), + ChangeTime: time.Unix(1606773732, 0), + ModTime: time.Unix(1606773733, 0), + } + parentInode := fs.GenerateDynamicInode(0, "parent") + inode := fs.GenerateDynamicInode(1, "foo") + d, err := newDir(context.TODO(), root, inode, parentInode, node) + rtest.OK(t, err) + + // don't open the directory as that would require setting up a proper tree blob + attr := fuse.Attr{} + rtest.OK(t, d.Attr(context.TODO(), &attr)) + + rtest.Equals(t, inode, attr.Inode) + rtest.Equals(t, node.UID, attr.Uid) + rtest.Equals(t, node.GID, attr.Gid) + rtest.Equals(t, node.AccessTime, attr.Atime) + rtest.Equals(t, node.ChangeTime, attr.Ctime) + rtest.Equals(t, node.ModTime, attr.Mtime) +} + // Test top-level directories for their UID and GID. func TestTopUidGid(t *testing.T) { repo, cleanup := repository.TestRepository(t) @@ -222,8 +253,9 @@ func testTopUidGid(t *testing.T, cfg Config, repo restic.Repository, uid, gid ui snapshotdir, err := idsdir.(fs.NodeStringLookuper).Lookup(ctx, snapID) rtest.OK(t, err) + // restic.TestCreateSnapshot does not set the UID/GID thus it must be always zero err = snapshotdir.Attr(ctx, &attr) rtest.OK(t, err) - rtest.Equals(t, uid, attr.Uid) - rtest.Equals(t, gid, attr.Gid) + rtest.Equals(t, uint32(0), attr.Uid) + rtest.Equals(t, uint32(0), attr.Gid) }