diff options
| author | Karan Kurani <karankurani3k@gmail.com> | 2026-04-13 23:32:12 +0530 |
|---|---|---|
| committer | Eric Biggers <ebiggers3@gmail.com> | 2026-04-14 23:30:23 -0700 |
| commit | 2dee71cdc2a7bccead530a42dfd10736e8de45a9 (patch) | |
| tree | e41917046ca1f9fbc8f2df748066710bd26369eb /actions | |
| parent | 298ed2a6c44cde90b4262b884169c53b8deda508 (diff) | |
recovery: add O_NOFOLLOW|O_EXCL to prevent symlink-following in recovery file creation
WriteRecoveryInstructions() opens the recovery README with os.OpenFile
using O_WRONLY|O_CREATE without O_NOFOLLOW. When fscrypt encrypt runs
as root, this allows a local attacker to place a symlink at the recovery
file path, causing root to write through the symlink and then fchown the
target file to the attacker. Adding O_EXCL|O_NOFOLLOW aligns with the
existing security pattern in filesystem.go:608 and filesystem.go:747.
Diffstat (limited to 'actions')
| -rw-r--r-- | actions/recovery.go | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/actions/recovery.go b/actions/recovery.go index 2bb8a23..3000be6 100644 --- a/actions/recovery.go +++ b/actions/recovery.go @@ -23,6 +23,7 @@ import ( "os" "strconv" + "golang.org/x/sys/unix" "google.golang.org/protobuf/proto" "github.com/google/fscrypt/crypto" @@ -91,7 +92,7 @@ func AddRecoveryPassphrase(policy *Policy, dirname string) (*crypto.Key, *Protec // passphrase in a different location if they actually need it. func WriteRecoveryInstructions(recoveryPassphrase *crypto.Key, recoveryProtector *Protector, policy *Policy, path string) error { - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL|unix.O_NOFOLLOW, 0600) if err != nil { return err } |