]> git.apps.os.sepia.ceph.com Git - fscrypt.git/commitdiff
fsync set policy ioctls
authorMarcel Lauhoff <marcel.lauhoff@suse.com>
Fri, 12 Aug 2022 12:45:29 +0000 (14:45 +0200)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 23 Aug 2022 16:35:43 +0000 (09:35 -0700)
Split policyIoctl into setPolicyIoctl and getPolicyIoctl. Add a
os.Sync() call to setPolicyIoctl.

Policy ioctls are not necessary durable on return. For example, on
ext4 (ref: fs/ext4/crypto.c: ext4_set_context) they are not. This may
lead to a filesystem containing fscrypt metadata (in .fscrypt), but
without the policy applied on an encrypted directory.

Example:
Snapshotting a mounted ext4 filesystem on Ceph RBD right after
setting the policy. While subject to timing, with high probability the
snapshot will not have the policy set. Calling fsync fixes this.

Signed-off-by: Marcel Lauhoff <marcel.lauhoff@suse.com>
metadata/policy.go
metadata/policy_test.go

index e218a0814d7b1ab0adfe06e188f65e80c353acd9..7831e53a669c11ad2d19f31402d55e8f24f93fff 100644 (file)
@@ -94,7 +94,7 @@ func (err *ErrNotEncrypted) Error() string {
        return fmt.Sprintf("file or directory %q is not encrypted", err.Path)
 }
 
-func policyIoctl(file *os.File, request uintptr, arg unsafe.Pointer) error {
+func getPolicyIoctl(file *os.File, request uintptr, arg unsafe.Pointer) error {
        _, _, errno := unix.Syscall(unix.SYS_IOCTL, file.Fd(), request, uintptr(arg))
        if errno == 0 {
                return nil
@@ -102,6 +102,19 @@ func policyIoctl(file *os.File, request uintptr, arg unsafe.Pointer) error {
        return errno
 }
 
+func setPolicy(file *os.File, arg unsafe.Pointer) error {
+       _, _, errno := unix.Syscall(unix.SYS_IOCTL, file.Fd(), unix.FS_IOC_SET_ENCRYPTION_POLICY, uintptr(arg))
+       if errno != 0 {
+               return errno
+       }
+
+       if err := file.Sync(); err != nil {
+               return err
+       }
+
+       return nil
+}
+
 // Maps EncryptionOptions.Padding <-> FSCRYPT_POLICY_FLAGS
 var (
        paddingArray = []int64{4, 8, 16, 32}
@@ -159,10 +172,10 @@ func GetPolicy(path string) (*PolicyData, error) {
        var arg unix.FscryptGetPolicyExArg
        arg.Size = uint64(unsafe.Sizeof(arg.Policy))
        policyPtr := util.Ptr(arg.Policy[:])
-       err = policyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY_EX, unsafe.Pointer(&arg))
+       err = getPolicyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY_EX, unsafe.Pointer(&arg))
        if err == unix.ENOTTY {
                // Fall back to the old version of the ioctl. This works for v1 policies only.
-               err = policyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY, policyPtr)
+               err = getPolicyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY, policyPtr)
                arg.Size = uint64(unsafe.Sizeof(unix.FscryptPolicyV1{}))
        }
        switch err {
@@ -235,7 +248,7 @@ func setV1Policy(file *os.File, options *EncryptionOptions, descriptorBytes []by
        }
        copy(policy.Master_key_descriptor[:], descriptorBytes)
 
-       return policyIoctl(file, unix.FS_IOC_SET_ENCRYPTION_POLICY, unsafe.Pointer(&policy))
+       return setPolicy(file, unsafe.Pointer(&policy))
 }
 
 func setV2Policy(file *os.File, options *EncryptionOptions, descriptorBytes []byte) error {
@@ -252,7 +265,7 @@ func setV2Policy(file *os.File, options *EncryptionOptions, descriptorBytes []by
        }
        copy(policy.Master_key_identifier[:], descriptorBytes)
 
-       return policyIoctl(file, unix.FS_IOC_SET_ENCRYPTION_POLICY, unsafe.Pointer(&policy))
+       return setPolicy(file, unsafe.Pointer(&policy))
 }
 
 // SetPolicy sets up the specified directory to be encrypted with the specified
@@ -332,7 +345,7 @@ func CheckSupport(path string) error {
                Flags:                     math.MaxUint8,
        }
 
-       err = policyIoctl(file, unix.FS_IOC_SET_ENCRYPTION_POLICY, unsafe.Pointer(&badPolicy))
+       err = setPolicy(file, unsafe.Pointer(&badPolicy))
        switch err {
        case nil:
                log.Panicf(`FS_IOC_SET_ENCRYPTION_POLICY succeeded when it should have failed.
index 7fe2841168314e24bda296855c4bd2d5ff527ff2..7856ed3d91e3f8b7bfd31285a205497be449b4a5 100644 (file)
@@ -186,7 +186,7 @@ func requireV2PolicySupport(t *testing.T, directory string) {
        }
        defer file.Close()
 
-       err = policyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY_EX, nil)
+       err = getPolicyIoctl(file, unix.FS_IOC_GET_ENCRYPTION_POLICY_EX, nil)
        if err == ErrEncryptionNotSupported {
                t.Skip("No support for v2 encryption policies, skipping test")
        }