diff mbox series

[v5,03/52] fscrypt: add a fscrypt_inode_open helper

Message ID 4a372419c3fe6ad425e1b124c342a054e9d6db23.1706116485.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series btrfs: add fscrypt support | expand

Commit Message

Josef Bacik Jan. 24, 2024, 5:18 p.m. UTC
We have fscrypt_file_open() which is meant to be called on files being
opened so that their key is loaded when we start reading data from them.

However for btrfs send we are opening the inode directly without a filp,
so we need a different helper to make sure we can load the fscrypt
context for the inode before reading its contents.

We need a different helper as opposed to simply using
fscrypt_has_permitted_context() directly because of '-o
test_dummy_encryption', which allows for encrypted files to be created
with !IS_ENCRYPTED set on the directory (the root directory in this
case).  fscrypt_file_open() already does the appropriate check where it
simply doesn't call fscrypt_has_permitted_context() if the parent
directory isn't marked with IS_ENCRYPTED in order to facilitate this
invariant when using '-o test_dummy_encryption'.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/crypto/hooks.c       | 46 +++++++++++++++++++++++++++++++----------
 include/linux/fscrypt.h |  8 +++++++
 2 files changed, 43 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 52504dd478d3..6b4291d5eb44 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -7,6 +7,38 @@ 
 
 #include "fscrypt_private.h"
 
+/**
+ * __fscrypt_file_open() - prepare for filesystem-internal access to a
+ *			   possibly-encrypted regular file
+ * @dir: the inode for the directory via which the file is being accessed
+ * @inode: the inode being "opened"
+ *
+ * This is like fscrypt_file_open(), but instead of taking the 'struct file'
+ * being opened it takes the parent directory explicitly.  This is intended for
+ * use cases such as "send/receive" which involve the filesystem accessing file
+ * contents without setting up a 'struct file'.
+ *
+ * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
+ */
+int __fscrypt_file_open(struct inode *dir, struct inode *inode)
+{
+	int err;
+
+	err = fscrypt_require_key(inode);
+	if (err)
+		return err;
+
+	if (IS_ENCRYPTED(dir) &&
+	    !fscrypt_has_permitted_context(dir, inode)) {
+		fscrypt_warn(inode,
+			     "Inconsistent encryption context (parent directory: %lu)",
+			     dir->i_ino);
+		err = -EPERM;
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(__fscrypt_file_open);
+
 /**
  * fscrypt_file_open() - prepare to open a possibly-encrypted regular file
  * @inode: the inode being opened
@@ -32,18 +64,10 @@  int fscrypt_file_open(struct inode *inode, struct file *filp)
 	int err;
 	struct dentry *dir;
 
-	err = fscrypt_require_key(inode);
-	if (err)
-		return err;
-
 	dir = dget_parent(file_dentry(filp));
-	if (IS_ENCRYPTED(d_inode(dir)) &&
-	    !fscrypt_has_permitted_context(d_inode(dir), inode)) {
-		fscrypt_warn(inode,
-			     "Inconsistent encryption context (parent directory: %lu)",
-			     d_inode(dir)->i_ino);
-		err = -EPERM;
-	}
+
+	err = __fscrypt_file_open(d_inode(dir), inode);
+
 	dput(dir);
 	return err;
 }
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 4b3916d76dc7..22211f87e7be 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -393,6 +393,7 @@  int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
 
 /* hooks.c */
 int fscrypt_file_open(struct inode *inode, struct file *filp);
+int __fscrypt_file_open(struct inode *dir, struct inode *inode);
 int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
 			   struct dentry *dentry);
 int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -737,6 +738,13 @@  static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+static inline int __fscrypt_file_open(struct inode *dir, struct inode *inode)
+{
+	if (IS_ENCRYPTED(inode))
+		return -EOPNOTSUPP;
+	return 0;
+}
+
 static inline int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
 					 struct dentry *dentry)
 {