]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
fscrypt: new helper function - fscrypt_prepare_setattr()
authorEric Biggers <ebiggers@google.com>
Mon, 9 Oct 2017 19:15:44 +0000 (12:15 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 18 Oct 2017 23:52:39 +0000 (19:52 -0400)
Introduce a helper function for filesystems to call when processing
->setattr() on a possibly-encrypted inode.  It handles enforcing that an
encrypted file can only be truncated if its encryption key is available.

Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
include/linux/fscrypt.h

index 2327859c8cd265c6b8c178343eaa788c19275c1b..53437bfdfcbcadc83d78e9b62616fa5a8296c3cd 100644 (file)
@@ -265,4 +265,29 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
        return 0;
 }
 
+/**
+ * fscrypt_prepare_setattr - prepare to change a possibly-encrypted inode's attributes
+ * @dentry: dentry through which the inode is being changed
+ * @attr: attributes to change
+ *
+ * Prepare for ->setattr() on a possibly-encrypted inode.  On an encrypted file,
+ * most attribute changes are allowed even without the encryption key.  However,
+ * without the encryption key we do have to forbid truncates.  This is needed
+ * because the size being truncated to may not be a multiple of the filesystem
+ * block size, and in that case we'd have to decrypt the final block, zero the
+ * portion past i_size, and re-encrypt it.  (We *could* allow truncating to a
+ * filesystem block boundary, but it's simpler to just forbid all truncates ---
+ * and we already forbid all other contents modifications without the key.)
+ *
+ * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
+ * if a problem occurred while setting up the encryption key.
+ */
+static inline int fscrypt_prepare_setattr(struct dentry *dentry,
+                                         struct iattr *attr)
+{
+       if (attr->ia_valid & ATTR_SIZE)
+               return fscrypt_require_key(d_inode(dentry));
+       return 0;
+}
+
 #endif /* _LINUX_FSCRYPT_H */