diff mbox series

[v3,07/16] fscrypt: use an optional ino equivalent for per-extent infos

Message ID 8c40d7b6897875be8f908ca4aabf280c2f15b8d4.1691505882.git.sweettea-kernel@dorminy.me (mailing list archive)
State New, archived
Headers show
Series fscrypt: add extent encryption | expand

Commit Message

Sweet Tea Dorminy Aug. 8, 2023, 5:08 p.m. UTC
Since per-extent infos are not tied to inodes, an ino-based policy
cannot access the inode's i_ino to get the necessary information.
Instead, this adds an optional fscrypt_operation pointer to get the ino
equivalent for an extent, adds a wrapper to get the ino for an info, and
uses this wrapper everywhere where the ci's inode's i_ino is currently
accessed.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 fs/crypto/fscrypt_private.h | 18 ++++++++++++++++++
 fs/crypto/keyring.c         |  8 ++++----
 fs/crypto/keysetup.c        |  6 +++---
 include/linux/fscrypt.h     |  9 +++++++++
 4 files changed, 34 insertions(+), 7 deletions(-)

Comments

Josef Bacik Aug. 9, 2023, 6:51 p.m. UTC | #1
On Tue, Aug 08, 2023 at 01:08:24PM -0400, Sweet Tea Dorminy wrote:
> Since per-extent infos are not tied to inodes, an ino-based policy
> cannot access the inode's i_ino to get the necessary information.
> Instead, this adds an optional fscrypt_operation pointer to get the ino
> equivalent for an extent, adds a wrapper to get the ino for an info, and
> uses this wrapper everywhere where the ci's inode's i_ino is currently
> accessed.
> 
> Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
> ---
>  fs/crypto/fscrypt_private.h | 18 ++++++++++++++++++
>  fs/crypto/keyring.c         |  8 ++++----
>  fs/crypto/keysetup.c        |  6 +++---
>  include/linux/fscrypt.h     |  9 +++++++++
>  4 files changed, 34 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index 1244797cd8a9..4fe79b774f1f 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/fs/crypto/fscrypt_private.h
> @@ -332,6 +332,24 @@ static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
>  	return false;
>  }
>  
> +/**
> + * fscrypt_get_info_ino() - get the ino or ino equivalent for an info
> + *
> + * @ci: the fscrypt_info in question
> + *
> + * Return: For inode-based encryption, this will return the info's inode's ino.
> + * For extent-based encryption, this will return the extent's ino equivalent
> + * or 0 if it is not implemented.
> + */
> +static inline u64 fscrypt_get_info_ino(const struct fscrypt_info *ci)
> +{
> +	if (ci->ci_inode)
> +		return ci->ci_inode->i_ino;
> +	if (!ci->ci_sb->s_cop->get_extent_ino_equivalent)
> +		return 0;
> +	return ci->ci_sb->s_cop->get_extent_ino_equivalent(ci->ci_info_ptr);
> +}
> +
>  /* crypto.c */
>  extern struct kmem_cache *fscrypt_info_cachep;
>  int fscrypt_initialize(struct super_block *sb);
> diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
> index 7cbb1fd872ac..53e37b8a822c 100644
> --- a/fs/crypto/keyring.c
> +++ b/fs/crypto/keyring.c
> @@ -914,12 +914,12 @@ static int check_for_busy_inodes(struct super_block *sb,
>  	}
>  
>  	{
> -		/* select an example file to show for debugging purposes */
> -		struct inode *inode =
> +		/* select an example info to show for debugging purposes */
> +		struct fscrypt_info *ci =
>  			list_first_entry(&mk->mk_decrypted_inodes,
>  					 struct fscrypt_info,
> -					 ci_master_key_link)->ci_inode;
> -		ino = inode->i_ino;
> +					 ci_master_key_link);
> +		ino = fscrypt_get_info_ino(ci);
>  	}
>  	spin_unlock(&mk->mk_decrypted_inodes_lock);
>  
> diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
> index c72f9015ed35..32e62cc57708 100644
> --- a/fs/crypto/keysetup.c
> +++ b/fs/crypto/keysetup.c
> @@ -380,10 +380,10 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
>  void fscrypt_hash_inode_number(struct fscrypt_info *ci,
>  			       const struct fscrypt_master_key *mk)
>  {
> -	WARN_ON_ONCE(ci->ci_inode->i_ino == 0);
> +	WARN_ON_ONCE(fscrypt_get_info_ino(ci) == 0);
>  	WARN_ON_ONCE(!mk->mk_ino_hash_key_initialized);
>  
> -	ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
> +	ci->ci_hashed_ino = (u32)siphash_1u64(fscrypt_get_info_ino(ci),
>  					      &mk->mk_ino_hash_key);
>  }
>  
> @@ -705,7 +705,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
>  		if (res)
>  			goto out;
>  
> -		if (inode->i_ino)
> +		if (fscrypt_get_info_ino(crypt_info))
>  			fscrypt_hash_inode_number(crypt_info, mk);
>  	}
>  
> diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
> index c895b12737a1..2a64e7a71a53 100644
> --- a/include/linux/fscrypt.h
> +++ b/include/linux/fscrypt.h
> @@ -160,6 +160,15 @@ struct fscrypt_operations {
>  	void (*get_ino_and_lblk_bits)(struct super_block *sb,
>  				      int *ino_bits_ret, int *lblk_bits_ret);
>  
> +	/*
> +	 * Get the inode number equivalent for filesystems using per-extent
> +	 * encryption keys.
> +	 *
> +	 * This function only needs to be implemented if support for one of the
> +	 * FSCRYPT_POLICY_FLAG_IV_INO_* flags is needed.
> +	 */
> +	u64 (*get_extent_ino_equivalent)(struct fscrypt_info **info_ptr);
> +

I went and looked at your tree and nobody actually uses this.  I understand
wanting to add something for future expansion, but we're just sort of adding
things and hoping they'll be useful one day.  I think it's best to leave this
off and if somebody needs it they can add it later.  Thanks,

Josef
diff mbox series

Patch

diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 1244797cd8a9..4fe79b774f1f 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -332,6 +332,24 @@  static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
 	return false;
 }
 
+/**
+ * fscrypt_get_info_ino() - get the ino or ino equivalent for an info
+ *
+ * @ci: the fscrypt_info in question
+ *
+ * Return: For inode-based encryption, this will return the info's inode's ino.
+ * For extent-based encryption, this will return the extent's ino equivalent
+ * or 0 if it is not implemented.
+ */
+static inline u64 fscrypt_get_info_ino(const struct fscrypt_info *ci)
+{
+	if (ci->ci_inode)
+		return ci->ci_inode->i_ino;
+	if (!ci->ci_sb->s_cop->get_extent_ino_equivalent)
+		return 0;
+	return ci->ci_sb->s_cop->get_extent_ino_equivalent(ci->ci_info_ptr);
+}
+
 /* crypto.c */
 extern struct kmem_cache *fscrypt_info_cachep;
 int fscrypt_initialize(struct super_block *sb);
diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
index 7cbb1fd872ac..53e37b8a822c 100644
--- a/fs/crypto/keyring.c
+++ b/fs/crypto/keyring.c
@@ -914,12 +914,12 @@  static int check_for_busy_inodes(struct super_block *sb,
 	}
 
 	{
-		/* select an example file to show for debugging purposes */
-		struct inode *inode =
+		/* select an example info to show for debugging purposes */
+		struct fscrypt_info *ci =
 			list_first_entry(&mk->mk_decrypted_inodes,
 					 struct fscrypt_info,
-					 ci_master_key_link)->ci_inode;
-		ino = inode->i_ino;
+					 ci_master_key_link);
+		ino = fscrypt_get_info_ino(ci);
 	}
 	spin_unlock(&mk->mk_decrypted_inodes_lock);
 
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index c72f9015ed35..32e62cc57708 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -380,10 +380,10 @@  int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
 void fscrypt_hash_inode_number(struct fscrypt_info *ci,
 			       const struct fscrypt_master_key *mk)
 {
-	WARN_ON_ONCE(ci->ci_inode->i_ino == 0);
+	WARN_ON_ONCE(fscrypt_get_info_ino(ci) == 0);
 	WARN_ON_ONCE(!mk->mk_ino_hash_key_initialized);
 
-	ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
+	ci->ci_hashed_ino = (u32)siphash_1u64(fscrypt_get_info_ino(ci),
 					      &mk->mk_ino_hash_key);
 }
 
@@ -705,7 +705,7 @@  fscrypt_setup_encryption_info(struct inode *inode,
 		if (res)
 			goto out;
 
-		if (inode->i_ino)
+		if (fscrypt_get_info_ino(crypt_info))
 			fscrypt_hash_inode_number(crypt_info, mk);
 	}
 
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index c895b12737a1..2a64e7a71a53 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -160,6 +160,15 @@  struct fscrypt_operations {
 	void (*get_ino_and_lblk_bits)(struct super_block *sb,
 				      int *ino_bits_ret, int *lblk_bits_ret);
 
+	/*
+	 * Get the inode number equivalent for filesystems using per-extent
+	 * encryption keys.
+	 *
+	 * This function only needs to be implemented if support for one of the
+	 * FSCRYPT_POLICY_FLAG_IV_INO_* flags is needed.
+	 */
+	u64 (*get_extent_ino_equivalent)(struct fscrypt_info **info_ptr);
+
 	/*
 	 * Return an array of pointers to the block devices to which the
 	 * filesystem may write encrypted file contents, NULL if the filesystem