From 6697ffd6e213828ff4cd873cd1d104877096a230 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 18 Oct 2020 21:05:44 +0200 Subject: fusefronted: reject GETXATTR "security.capability" Unless we are mounted with -suid, we can reject these requests, and gain back some lost speed. Closes https://github.com/rfjakob/gocryptfs/issues/515 --- Documentation/performance.txt | 3 ++- internal/fusefrontend/args.go | 5 +++++ internal/fusefrontend/node_xattr.go | 13 +++++++++++++ internal/syscallcompat/mem.prof | Bin 0 -> 902 bytes internal/syscallcompat/mem2.prof | Bin 0 -> 1015 bytes internal/syscallcompat/new.txt | 6 ++++++ internal/syscallcompat/old.txt | 6 ++++++ internal/syscallcompat/prof | Bin 0 -> 6499 bytes internal/syscallcompat/prof2 | Bin 0 -> 5831 bytes mount.go | 1 + 10 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 internal/syscallcompat/mem.prof create mode 100644 internal/syscallcompat/mem2.prof create mode 100644 internal/syscallcompat/new.txt create mode 100644 internal/syscallcompat/old.txt create mode 100644 internal/syscallcompat/prof create mode 100644 internal/syscallcompat/prof2 diff --git a/Documentation/performance.txt b/Documentation/performance.txt index 4fa2fd9..a724632 100644 --- a/Documentation/performance.txt +++ b/Documentation/performance.txt @@ -64,7 +64,8 @@ v1.7.1 577 1100 8.3 4.2 0.9 2.0 go1.14.2, Linux 5. v1.7.1-60-gb23f77c 472 1100 12.7 4.2 0.8 2.0 v1.8.0 410 1000 17.5 6.7 5.4 7.8 go1.15.3, Linux 5.8.13 v2.0-beta1 387 1100 36.2 14.4 12.8 19.3 - +v2.0-beta1-5-gc943ed3 417 1000 30.4 12.7 9.9 16.4 +v2.0-beta1-6 529 1100 17.5 9.0 3.6 9.0 Results for EncFS for comparison (benchmark.bash -encfs): diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index 646d6c4..f822650 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -39,4 +39,9 @@ type Args struct { // ExcludeFrom is a list of files from which to read exclusion patterns // (with wildcard syntax) ExcludeFrom []string + // Suid is true if the filesystem has been mounted with the "-suid" flag. + // If it is false, we can ignore the GETXATTR "security.capability" calls, + // which are a performance problem for writes. See + // https://github.com/rfjakob/gocryptfs/issues/515 for details. + Suid bool } diff --git a/internal/fusefrontend/node_xattr.go b/internal/fusefrontend/node_xattr.go index de40915..cbc5804 100644 --- a/internal/fusefrontend/node_xattr.go +++ b/internal/fusefrontend/node_xattr.go @@ -18,11 +18,24 @@ var xattrNameIV = []byte("xattr_name_iv_xx") // encrypted original name. var xattrStorePrefix = "user.gocryptfs." +// We get one read of this xattr for each write - +// see https://github.com/rfjakob/gocryptfs/issues/515 for details. +var xattrCapability = "security.capability" + // GetXAttr - FUSE call. Reads the value of extended attribute "attr". // // This function is symlink-safe through Fgetxattr. func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { rn := n.rootNode() + // If we are not mounted with -suid, reading the capability xattr does not + // make a lot of sense, so reject the request and gain a massive speedup. + // See https://github.com/rfjakob/gocryptfs/issues/515 . + if !rn.args.Suid && attr == xattrCapability { + // Returning EOPNOTSUPP is what we did till + // ca9e912a28b901387e1dbb85f6c531119f2d5ef2 "fusefrontend: drop xattr user namespace restriction" + // and it did not cause trouble. Seems cleaner than saying ENODATA. + return 0, syscall.EOPNOTSUPP + } cAttr := rn.encryptXattrName(attr) cData, errno := n.getXAttr(cAttr) if errno != 0 { diff --git a/internal/syscallcompat/mem.prof b/internal/syscallcompat/mem.prof new file mode 100644 index 0000000..052fcc6 Binary files /dev/null and b/internal/syscallcompat/mem.prof differ diff --git a/internal/syscallcompat/mem2.prof b/internal/syscallcompat/mem2.prof new file mode 100644 index 0000000..e0f73aa Binary files /dev/null and b/internal/syscallcompat/mem2.prof differ diff --git a/internal/syscallcompat/new.txt b/internal/syscallcompat/new.txt new file mode 100644 index 0000000..df3a0ea --- /dev/null +++ b/internal/syscallcompat/new.txt @@ -0,0 +1,6 @@ +goos: linux +goarch: amd64 +pkg: github.com/rfjakob/gocryptfs/internal/syscallcompat +BenchmarkLgetxattr-4 594607 1799 ns/op +PASS +ok github.com/rfjakob/gocryptfs/internal/syscallcompat 1.108s diff --git a/internal/syscallcompat/old.txt b/internal/syscallcompat/old.txt new file mode 100644 index 0000000..0020b27 --- /dev/null +++ b/internal/syscallcompat/old.txt @@ -0,0 +1,6 @@ +goos: linux +goarch: amd64 +pkg: github.com/rfjakob/gocryptfs/internal/syscallcompat +BenchmarkLgetxattr-4 77743 15183 ns/op +PASS +ok github.com/rfjakob/gocryptfs/internal/syscallcompat 1.360s diff --git a/internal/syscallcompat/prof b/internal/syscallcompat/prof new file mode 100644 index 0000000..4eb4f40 Binary files /dev/null and b/internal/syscallcompat/prof differ diff --git a/internal/syscallcompat/prof2 b/internal/syscallcompat/prof2 new file mode 100644 index 0000000..54fad10 Binary files /dev/null and b/internal/syscallcompat/prof2 differ diff --git a/mount.go b/mount.go index f02bc21..39f3f3c 100644 --- a/mount.go +++ b/mount.go @@ -266,6 +266,7 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f Exclude: args.exclude, ExcludeWildcard: args.excludeWildcard, ExcludeFrom: args.excludeFrom, + Suid: args.suid, } // confFile is nil when "-zerokey" or "-masterkey" was used if confFile != nil { -- cgit v1.2.3