Skip to content

Commit 6013d56

Browse files
authored
added -noxattr flag which ignores all xattr operations (#987)
* added -noxattr flag which ignores all xattr operations
1 parent c9cf6f1 commit 6013d56

File tree

9 files changed

+43
-3
lines changed

9 files changed

+43
-3
lines changed

cli_args.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type argContainer struct {
3131
longnames, allow_other, reverse, aessiv, nonempty, raw64,
3232
noprealloc, speed, hkdf, serialize_reads, hh, info,
3333
sharedstorage, fsck, one_file_system, deterministic_names,
34-
xchacha bool
34+
xchacha, noxattr bool
3535
// Mount options with opposites
3636
dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool
3737
masterkey, mountpoint, cipherdir, cpuprofile,
@@ -188,6 +188,7 @@ func parseCliOpts(osArgs []string) (args argContainer) {
188188
flagSet.BoolVar(&args.one_file_system, "one-file-system", false, "Don't cross filesystem boundaries")
189189
flagSet.BoolVar(&args.deterministic_names, "deterministic-names", false, "Disable diriv file name randomisation")
190190
flagSet.BoolVar(&args.xchacha, "xchacha", false, "Use XChaCha20-Poly1305 file content encryption")
191+
flagSet.BoolVar(&args.noxattr, "noxattr", false, "Disable extended attribute operations")
191192

192193
// Mount options with opposites
193194
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")

internal/fusefrontend/args.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@ type Args struct {
5151
OneFileSystem bool
5252
// DeterministicNames disables gocryptfs.diriv files
5353
DeterministicNames bool
54+
// NoXattr disables extended attribute operations
55+
NoXattr bool
5456
}

internal/fusefrontend/node_xattr.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func isAcl(attr string) bool {
3232
// This function is symlink-safe through Fgetxattr.
3333
func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
3434
rn := n.rootNode()
35+
// If -noxattr is enabled, return ENOATTR for all getxattr calls
36+
if rn.args.NoXattr {
37+
return 0, noSuchAttributeError
38+
}
3539
// If we are not mounted with -suid, reading the capability xattr does not
3640
// make a lot of sense, so reject the request and gain a massive speedup.
3741
// See https://github.com/rfjakob/gocryptfs/issues/515 .
@@ -77,6 +81,10 @@ func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32,
7781
// This function is symlink-safe through Fsetxattr.
7882
func (n *Node) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
7983
rn := n.rootNode()
84+
// If -noxattr is enabled, fail all setxattr calls
85+
if rn.args.NoXattr {
86+
return syscall.EOPNOTSUPP
87+
}
8088
flags = uint32(filterXattrSetFlags(int(flags)))
8189

8290
// ACLs are passed through without encryption
@@ -102,6 +110,10 @@ func (n *Node) Setxattr(ctx context.Context, attr string, data []byte, flags uin
102110
// This function is symlink-safe through Fremovexattr.
103111
func (n *Node) Removexattr(ctx context.Context, attr string) syscall.Errno {
104112
rn := n.rootNode()
113+
// If -noxattr is enabled, fail all removexattr calls
114+
if rn.args.NoXattr {
115+
return syscall.EOPNOTSUPP
116+
}
105117

106118
// ACLs are passed through without encryption
107119
if isAcl(attr) {
@@ -119,11 +131,15 @@ func (n *Node) Removexattr(ctx context.Context, attr string) syscall.Errno {
119131
//
120132
// This function is symlink-safe through Flistxattr.
121133
func (n *Node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
134+
rn := n.rootNode()
135+
// If -noxattr is enabled, return zero results for listxattr
136+
if rn.args.NoXattr {
137+
return 0, 0
138+
}
122139
cNames, errno := n.listXAttr()
123140
if errno != 0 {
124141
return 0, errno
125142
}
126-
rn := n.rootNode()
127143
var buf bytes.Buffer
128144
for _, curName := range cNames {
129145
// ACLs are passed through without encryption

internal/fusefrontend/node_xattr_darwin.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
1212
)
1313

14+
// On Darwin, ENOATTR is returned when an attribute is not found.
15+
const noSuchAttributeError = syscall.ENOATTR
16+
1417
// On Darwin we have to unset XATTR_NOSECURITY 0x0008
1518
func filterXattrSetFlags(flags int) int {
1619
// See https://opensource.apple.com/source/xnu/xnu-1504.15.3/bsd/sys/xattr.h.auto.html

internal/fusefrontend/node_xattr_linux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import (
1212
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
1313
)
1414

15+
// On Linux, ENODATA is returned when an attribute is not found.
16+
const noSuchAttributeError = syscall.ENODATA
17+
1518
func filterXattrSetFlags(flags int) int {
1619
return flags
1720
}

internal/fusefrontend_reverse/node_xattr.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ func isAcl(attr string) bool {
2525
// This function is symlink-safe through Fgetxattr.
2626
func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
2727
rn := n.rootNode()
28+
// If -noxattr is enabled, return ENOATTR for all getxattr calls
29+
if rn.args.NoXattr {
30+
return 0, noSuchAttributeError
31+
}
2832
var data []byte
2933
// ACLs are passed through without encryption
3034
if isAcl(attr) {
@@ -56,11 +60,15 @@ func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32,
5660
//
5761
// This function is symlink-safe through Flistxattr.
5862
func (n *Node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
63+
rn := n.rootNode()
64+
// If -noxattr is enabled, return zero results for listxattr
65+
if rn.args.NoXattr {
66+
return 0, 0
67+
}
5968
pNames, errno := n.listXAttr()
6069
if errno != 0 {
6170
return 0, errno
6271
}
63-
rn := n.rootNode()
6472
var buf bytes.Buffer
6573
for _, pName := range pNames {
6674
// ACLs are passed through without encryption

internal/fusefrontend_reverse/node_xattr_darwin.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
99
)
1010

11+
// On Darwin, ENOATTR is returned when an attribute is not found.
12+
const noSuchAttributeError = syscall.ENOATTR
13+
1114
func (n *Node) getXAttr(cAttr string) (out []byte, errno syscall.Errno) {
1215
d, errno := n.prepareAtSyscall("")
1316
if errno != 0 {

internal/fusefrontend_reverse/node_xattr_linux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import (
99
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
1010
)
1111

12+
// On Linux, ENODATA is returned when an attribute is not found.
13+
const noSuchAttributeError = syscall.ENODATA
14+
1215
func (n *Node) getXAttr(cAttr string) (out []byte, errno syscall.Errno) {
1316
d, errno := n.prepareAtSyscall("")
1417
if errno != 0 {

mount.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
284284
SharedStorage: args.sharedstorage,
285285
OneFileSystem: args.one_file_system,
286286
DeterministicNames: args.deterministic_names,
287+
NoXattr: args.noxattr,
287288
}
288289
// confFile is nil when "-zerokey" or "-masterkey" was used
289290
if confFile != nil {

0 commit comments

Comments
 (0)