aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2020-11-07 14:20:45 -0800
committerEric Biggers <ebiggers3@gmail.com>2020-11-07 14:49:02 -0800
commitb68d603854bb38f59e77963d61ca25d92b945589 (patch)
treeddf9d51d6afe99e1a9c3334906d364d297df4f6b /cmd
parent9dde51ae5a9f18a81292d4a8431e81b3869dee62 (diff)
cmd/fscrypt: fix isDirUnlockedHeuristic() on latest kernels
On an "incompletely locked" directory, isDirUnlockedHeuristic() is supposed to return true, but on Linux v5.10-rc1 and later it returns false since now creating a subdirectory fails rather than succeeds. This change was intentional, so make isDirUnlockedHeuristic() apply a second heuristic too: also return true if any filenames in the directory don't appear to be valid no-key names. This fixes cli-tests/t_v1_encrypt on Linux v5.10-rc1 and later.
Diffstat (limited to 'cmd')
-rw-r--r--cmd/fscrypt/commands.go37
1 files changed, 35 insertions, 2 deletions
diff --git a/cmd/fscrypt/commands.go b/cmd/fscrypt/commands.go
index 7c12356..e6c8ecc 100644
--- a/cmd/fscrypt/commands.go
+++ b/cmd/fscrypt/commands.go
@@ -25,6 +25,7 @@ import (
"log"
"os"
"path/filepath"
+ "strings"
"github.com/pkg/errors"
"github.com/urfave/cli"
@@ -532,8 +533,25 @@ func lockAction(c *cli.Context) error {
return nil
}
-// isDirUnlockedHeuristic returns true if we can create a subdirectory of the
-// given directory and therefore it is definitely still unlocked. It returns
+func isPossibleNoKeyName(filename string) bool {
+ // No-key names are at least 22 bytes long, since they are
+ // base64-encoded and ciphertext filenames are at least 16 bytes.
+ if len(filename) < 22 {
+ return false
+ }
+ // No-key names contain only base64 characters and underscore.
+ validChars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,_"
+ for _, char := range filename {
+ if !strings.ContainsRune(validChars, char) {
+ return false
+ }
+ }
+ return true
+}
+
+// isDirUnlockedHeuristic returns true if the directory is definitely still
+// unlocked. This is the case if we can create a subdirectory or if the
+// directory contains filenames that aren't valid no-key names. It returns
// false if the directory is probably locked (though it could also be unlocked).
//
// This is only useful if the directory's policy uses the user keyring, since
@@ -544,6 +562,21 @@ func isDirUnlockedHeuristic(dirPath string) bool {
os.Remove(subdirPath)
return true
}
+ dir, err := os.Open(dirPath)
+ if err != nil {
+ return false
+ }
+ defer dir.Close()
+
+ names, err := dir.Readdirnames(-1)
+ if err != nil {
+ return false
+ }
+ for _, name := range names {
+ if !isPossibleNoKeyName(name) {
+ return true
+ }
+ }
return false
}