From f4a0004eca09d5f47ccecfbc46045bb4087022b1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 9 Dec 2023 14:36:03 -0800 Subject: [PATCH] Provide better error message when given a locked regular file Since opening an encrypted regular file that is locked fails with ENOKEY, getting the encryption policy of such a file is not possible. As a result, 'fscrypt status' and 'fscrypt lock' fail on such files. Provide a better error message that tries to explain what is going on. Resolves https://github.com/google/fscrypt/issues/393 --- cli-tests/t_lock.out | 15 +++++++++++++++ cli-tests/t_lock.sh | 11 +++++++++++ cmd/fscrypt/errors.go | 5 +++++ metadata/policy.go | 13 +++++++++++++ 4 files changed, 44 insertions(+) diff --git a/cli-tests/t_lock.out b/cli-tests/t_lock.out index d630e746..ce277130 100644 --- a/cli-tests/t_lock.out +++ b/cli-tests/t_lock.out @@ -85,3 +85,18 @@ If you want to force the directory to be locked, use: contents "MNT/dir" is now locked. cat: MNT/dir/file: No such file or directory + +# Try to operate on locked regular file +"MNT/dir" is now locked. +[ERROR] fscrypt status: cannot operate on locked regular file + "MNT/file" + +It is not possible to operate directly on a locked regular file, since the +kernel does not support this. Specify the parent directory instead. (For loose +files, any directory with the file's policy works.) +[ERROR] fscrypt unlock: cannot operate on locked regular file + "MNT/file" + +It is not possible to operate directly on a locked regular file, since the +kernel does not support this. Specify the parent directory instead. (For loose +files, any directory with the file's policy works.) diff --git a/cli-tests/t_lock.sh b/cli-tests/t_lock.sh index 9b193fdd..e5df4df6 100755 --- a/cli-tests/t_lock.sh +++ b/cli-tests/t_lock.sh @@ -52,3 +52,14 @@ _expect_failure "fscrypt lock '$dir'" cat "$dir/file" fscrypt lock --all-users "$dir" _expect_failure "cat '$dir/file'" + +_print_header "Try to operate on locked regular file" +_reset_filesystems +rm -rf "$dir" +mkdir "$dir" +echo hunter2 | fscrypt encrypt --quiet --name=prot "$dir" +echo contents > "$dir/file" +mv "$dir/file" "$MNT/file" # Make it a loose encrypted file. +fscrypt lock "$dir" +_expect_failure "fscrypt status '$MNT/file'" +_expect_failure "fscrypt unlock '$MNT/file'" diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index 1ccf544e..c4814f47 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -251,6 +251,11 @@ func getErrorSuggestions(err error) string { return `This is usually the result of a bad PAM configuration. Either correct the problem in your PAM stack, enable pam_keyinit.so, or run "keyctl link @u @s".` + case *metadata.ErrLockedRegularFile: + return `It is not possible to operate directly on a locked + regular file, since the kernel does not support this. + Specify the parent directory instead. (For loose files, + any directory with the file's policy works.)` } switch errors.Cause(err) { case crypto.ErrMlockUlimit: diff --git a/metadata/policy.go b/metadata/policy.go index 7831e53a..fe6c38f3 100644 --- a/metadata/policy.go +++ b/metadata/policy.go @@ -28,6 +28,7 @@ import ( "os" "os/user" "strconv" + "syscall" "unsafe" "github.com/pkg/errors" @@ -85,6 +86,15 @@ func (err *ErrDirectoryNotOwned) Error() string { write access to the directory.`, err.Path, owner) } +// ErrLockedRegularFile indicates that the path is a locked regular file. +type ErrLockedRegularFile struct { + Path string +} + +func (err *ErrLockedRegularFile) Error() string { + return fmt.Sprintf("cannot operate on locked regular file %q", err.Path) +} + // ErrNotEncrypted indicates that the path is not encrypted. type ErrNotEncrypted struct { Path string @@ -164,6 +174,9 @@ func buildV2PolicyData(policy *unix.FscryptPolicyV2) *PolicyData { func GetPolicy(path string) (*PolicyData, error) { file, err := os.Open(path) if err != nil { + if err.(*os.PathError).Err == syscall.ENOKEY { + return nil, &ErrLockedRegularFile{path} + } return nil, err } defer file.Close()