diff options
| author | Jakob Unterwurzacher | 2021-05-08 17:17:08 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2021-05-15 17:58:37 +0200 | 
| commit | 86d8336b43418c028c34c37f06fcbd43ab0d44a1 (patch) | |
| tree | 571dfa970a43938587496ac63b95a17060c8df80 | |
| parent | a91ad29d362e8cb5348766da637202ac8905b9f2 (diff) | |
Add -acl flag to enable ACL enforcement
With test to verify that it actually works this
time: Run "make root_test".
Depends-on: https://github.com/rfjakob/gocryptfs/issues/536
Fixes: https://github.com/rfjakob/gocryptfs/issues/536
| -rw-r--r-- | cli_args.go | 3 | ||||
| -rw-r--r-- | mount.go | 3 | ||||
| -rw-r--r-- | tests/root_test/root_test.go | 82 | 
3 files changed, 87 insertions, 1 deletions
| diff --git a/cli_args.go b/cli_args.go index 8451083..7743120 100644 --- a/cli_args.go +++ b/cli_args.go @@ -30,7 +30,7 @@ type argContainer struct {  	noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,  	sharedstorage, devrandom, fsck bool  	// Mount options with opposites -	dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache bool +	dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool  	masterkey, mountpoint, cipherdir, cpuprofile,  	memprofile, ko, ctlsock, fsname, force_owner, trace, fido2 string  	// -extpass, -badname, -passfile can be passed multiple times @@ -180,6 +180,7 @@ func parseCliOpts() (args argContainer) {  	flagSet.BoolVar(&args.rw, "rw", false, "Mount the filesystem read-write")  	flagSet.BoolVar(&args.ro, "ro", false, "Mount the filesystem read-only")  	flagSet.BoolVar(&args.kernel_cache, "kernel_cache", false, "Enable the FUSE kernel_cache option") +	flagSet.BoolVar(&args.acl, "acl", false, "Enforce ACLs")  	flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")  	flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file") @@ -396,6 +396,9 @@ func initGoFuse(rootNode fs.InodeEmbedder, args *argContainer) *fuse.Server {  		// Make the kernel check the file permissions for us  		mOpts.Options = append(mOpts.Options, "default_permissions")  	} +	if args.acl { +		mOpts.EnableAcl = true +	}  	if args.forcedecode {  		tlog.Info.Printf(tlog.ColorYellow + "THE OPTION \"-forcedecode\" IS ACTIVE. GOCRYPTFS WILL RETURN CORRUPT DATA!" +  			tlog.ColorReset) diff --git a/tests/root_test/root_test.go b/tests/root_test/root_test.go index 9a22add..8547e4e 100644 --- a/tests/root_test/root_test.go +++ b/tests/root_test/root_test.go @@ -137,6 +137,7 @@ func writeTillFull(t *testing.T, path string) (int, syscall.Errno) {  	return sz, 0  } +// TestDiskFull needs root permissions because it creates a loop disk  func TestDiskFull(t *testing.T) {  	if os.Getuid() != 0 {  		t.Skip("must run as root") @@ -229,3 +230,84 @@ func TestDiskFull(t *testing.T) {  		t.Fail()  	}  } + +func TestAcl(t *testing.T) { +	if os.Getuid() != 0 { +		t.Skip("must run as root") +	} +	cDir := test_helpers.InitFS(t) +	os.Chmod(cDir, 0755) +	pDir := cDir + ".mnt" +	test_helpers.MountOrFatal(t, cDir, pDir, "-allow_other", "-acl", "-extpass=echo test") +	defer test_helpers.UnmountPanic(pDir) + +	f1 := pDir + "/f1" +	if err := ioutil.WriteFile(f1, []byte("hello world\n"), 000); err != nil { +		t.Fatal(err) +	} + +	openUser1234 := func(rwMode int) error { +		return asUser(1234, 1234, nil, func() error { +			fd, err := syscall.Open(f1, rwMode, 0) +			if err != nil { +				return err +			} +			defer syscall.Close(fd) +			buf := make([]byte, 100) +			if rwMode == syscall.O_RDONLY || rwMode == syscall.O_RDWR { +				_, err = syscall.Read(fd, buf) +				if err != nil { +					return err +				} +			} +			if rwMode == syscall.O_WRONLY || rwMode == syscall.O_RDWR { +				_, err = syscall.Write(fd, buf) +				if err != nil { +					return err +				} +			} +			return err +		}) +	} + +	dumpAcl := func() { +		out, err := exec.Command("getfacl", f1).CombinedOutput() +		if err != nil { +			t.Fatal(err) +		} +		t.Log(string(out)) +	} + +	if err := openUser1234(syscall.O_RDONLY); err == nil { +		t.Error("this should have failed") +		dumpAcl() +	} + +	// Allow read +	out, err := exec.Command("setfacl", "-m", "u:1234:r", f1).CombinedOutput() +	if err != nil { +		t.Fatal(string(out)) +	} +	if err := openUser1234(syscall.O_RDONLY); err != nil { +		t.Errorf("O_RDONLY should have worked, but got error: %v", err) +		dumpAcl() +	} +	if err := openUser1234(syscall.O_WRONLY); err == nil { +		t.Error("O_WRONLY should have failed") +		dumpAcl() +	} + +	// Allow write +	out, err = exec.Command("setfacl", "-m", "u:1234:w", f1).CombinedOutput() +	if err != nil { +		t.Fatal(string(out)) +	} +	if err := openUser1234(syscall.O_WRONLY); err != nil { +		t.Errorf("O_WRONLY should have worked, but got error: %v", err) +		dumpAcl() +	} +	if err := openUser1234(syscall.O_RDONLY); err == nil { +		t.Error("O_RDONLY should have failed") +		dumpAcl() +	} +} | 
