From 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:44:59 +0000
Subject: [PATCH] gmac get mac form eeprom

---
 kernel/fs/crypto/inline_crypt.c |  171 +++++++++++++++++++++-----------------------------------
 1 files changed, 64 insertions(+), 107 deletions(-)

diff --git a/kernel/fs/crypto/inline_crypt.c b/kernel/fs/crypto/inline_crypt.c
index 3b3a684..7df5877 100644
--- a/kernel/fs/crypto/inline_crypt.c
+++ b/kernel/fs/crypto/inline_crypt.c
@@ -16,6 +16,8 @@
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/keyslot-manager.h>
+#include <linux/sched/mm.h>
+#include <linux/slab.h>
 #include <linux/uio.h>
 
 #include "fscrypt_private.h"
@@ -69,23 +71,21 @@
 {
 	const struct inode *inode = ci->ci_inode;
 	struct super_block *sb = inode->i_sb;
-	enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
-	unsigned int dun_bytes;
-	struct request_queue **devs;
+	struct blk_crypto_config crypto_cfg;
 	int num_devs;
+	struct request_queue **devs;
 	int i;
 
 	/* The file must need contents encryption, not filenames encryption */
 	if (!S_ISREG(inode->i_mode))
 		return 0;
 
-	/* blk-crypto must implement the needed encryption algorithm */
-	if (crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
+	/* The crypto mode must have a blk-crypto counterpart */
+	if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
 		return 0;
 
 	/* The filesystem must be mounted with -o inlinecrypt */
-	if (!sb->s_cop->inline_crypt_enabled ||
-	    !sb->s_cop->inline_crypt_enabled(sb))
+	if (!(sb->s_flags & SB_INLINECRYPT))
 		return 0;
 
 	/*
@@ -102,37 +102,28 @@
 		return 0;
 
 	/*
-	 * The needed encryption settings must be supported either by
-	 * blk-crypto-fallback, or by hardware on all the filesystem's devices.
+	 * On all the filesystem's devices, blk-crypto must support the crypto
+	 * configuration that the file would use.
 	 */
-
-	if (IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) &&
-	    !is_hw_wrapped_key) {
-		ci->ci_inlinecrypt = true;
-		return 0;
-	}
-
+	crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
+	crypto_cfg.data_unit_size = sb->s_blocksize;
+	crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
+	crypto_cfg.is_hw_wrapped = is_hw_wrapped_key;
 	num_devs = fscrypt_get_num_devices(sb);
-	devs = kmalloc_array(num_devs, sizeof(*devs), GFP_NOFS);
+	devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
 	if (!devs)
 		return -ENOMEM;
-
 	fscrypt_get_devices(sb, num_devs, devs);
 
-	dun_bytes = fscrypt_get_dun_bytes(ci);
-
 	for (i = 0; i < num_devs; i++) {
-		if (!keyslot_manager_crypto_mode_supported(devs[i]->ksm,
-							   crypto_mode,
-							   dun_bytes,
-							   sb->s_blocksize,
-							   is_hw_wrapped_key))
+		if (!blk_crypto_config_supported(devs[i], &crypto_cfg))
 			goto out_free_devs;
 	}
 
 	ci->ci_inlinecrypt = true;
 out_free_devs:
 	kfree(devs);
+
 	return 0;
 }
 
@@ -145,32 +136,25 @@
 	const struct inode *inode = ci->ci_inode;
 	struct super_block *sb = inode->i_sb;
 	enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
-	unsigned int dun_bytes;
-	int num_devs;
+	int num_devs = fscrypt_get_num_devices(sb);
 	int queue_refs = 0;
 	struct fscrypt_blk_crypto_key *blk_key;
 	int err;
 	int i;
 
-	num_devs = fscrypt_get_num_devices(sb);
-	if (WARN_ON(num_devs < 1))
-		return -EINVAL;
-
-	blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_NOFS);
+	blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_KERNEL);
 	if (!blk_key)
 		return -ENOMEM;
 
 	blk_key->num_devs = num_devs;
 	fscrypt_get_devices(sb, num_devs, blk_key->devs);
 
-	dun_bytes = fscrypt_get_dun_bytes(ci);
-
 	BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE >
 		     BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
 
 	err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
-				  is_hw_wrapped, crypto_mode, dun_bytes,
-				  sb->s_blocksize);
+				  is_hw_wrapped, crypto_mode,
+				  fscrypt_get_dun_bytes(ci), sb->s_blocksize);
 	if (err) {
 		fscrypt_err(inode, "error %d initializing blk-crypto key", err);
 		goto fail;
@@ -191,10 +175,8 @@
 		}
 		queue_refs++;
 
-		err = blk_crypto_start_using_mode(crypto_mode, dun_bytes,
-						  sb->s_blocksize,
-						  is_hw_wrapped,
-						  blk_key->devs[i]);
+		err = blk_crypto_start_using_key(&blk_key->base,
+						 blk_key->devs[i]);
 		if (err) {
 			fscrypt_err(inode,
 				    "error %d starting to use blk-crypto", err);
@@ -213,7 +195,7 @@
 fail:
 	for (i = 0; i < queue_refs; i++)
 		blk_put_queue(blk_key->devs[i]);
-	kzfree(blk_key);
+	kfree_sensitive(blk_key);
 	return err;
 }
 
@@ -227,7 +209,7 @@
 			blk_crypto_evict_key(blk_key->devs[i], &blk_key->base);
 			blk_put_queue(blk_key->devs[i]);
 		}
-		kzfree(blk_key);
+		kfree_sensitive(blk_key);
 	}
 }
 
@@ -238,46 +220,19 @@
 {
 	struct request_queue *q;
 
-	q = sb->s_bdev->bd_queue;
+	q = bdev_get_queue(sb->s_bdev);
 	if (!q->ksm)
 		return -EOPNOTSUPP;
 
-	return keyslot_manager_derive_raw_secret(q->ksm,
-						 wrapped_key, wrapped_key_size,
-						 raw_secret, raw_secret_size);
+	return blk_ksm_derive_raw_secret(q->ksm, wrapped_key, wrapped_key_size,
+					 raw_secret, raw_secret_size);
 }
 
-/**
- * fscrypt_inode_uses_inline_crypto - test whether an inode uses inline
- *				      encryption
- * @inode: an inode
- *
- * Return: true if the inode requires file contents encryption and if the
- *	   encryption should be done in the block layer via blk-crypto rather
- *	   than in the filesystem layer.
- */
-bool fscrypt_inode_uses_inline_crypto(const struct inode *inode)
+bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
 {
-	return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) &&
-		inode->i_crypt_info->ci_inlinecrypt;
+	return inode->i_crypt_info->ci_inlinecrypt;
 }
-EXPORT_SYMBOL_GPL(fscrypt_inode_uses_inline_crypto);
-
-/**
- * fscrypt_inode_uses_fs_layer_crypto - test whether an inode uses fs-layer
- *					encryption
- * @inode: an inode
- *
- * Return: true if the inode requires file contents encryption and if the
- *	   encryption should be done in the filesystem layer rather than in the
- *	   block layer via blk-crypto.
- */
-bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode)
-{
-	return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) &&
-		!inode->i_crypt_info->ci_inlinecrypt;
-}
-EXPORT_SYMBOL_GPL(fscrypt_inode_uses_fs_layer_crypto);
+EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
 
 static void fscrypt_generate_dun(const struct fscrypt_info *ci, u64 lblk_num,
 				 u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE])
@@ -294,7 +249,7 @@
 }
 
 /**
- * fscrypt_set_bio_crypt_ctx - prepare a file contents bio for inline encryption
+ * fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto
  * @bio: a bio which will eventually be submitted to the file
  * @inode: the file's inode
  * @first_lblk: the first file logical block number in the I/O
@@ -314,7 +269,7 @@
 void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
 			       u64 first_lblk, gfp_t gfp_mask)
 {
-	const struct fscrypt_info *ci = inode->i_crypt_info;
+	const struct fscrypt_info *ci;
 	u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
 
 	if (fscrypt_inode_should_skip_dm_default_key(inode))
@@ -322,9 +277,10 @@
 
 	if (!fscrypt_inode_uses_inline_crypto(inode))
 		return;
+	ci = inode->i_crypt_info;
 
 	fscrypt_generate_dun(ci, first_lblk, dun);
-	bio_crypt_set_ctx(bio, &ci->ci_key.blk_key->base, dun, gfp_mask);
+	bio_crypt_set_ctx(bio, &ci->ci_enc_key.blk_key->base, dun, gfp_mask);
 }
 EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
 
@@ -353,8 +309,8 @@
 }
 
 /**
- * fscrypt_set_bio_crypt_ctx_bh - prepare a file contents bio for inline
- *				  encryption
+ * fscrypt_set_bio_crypt_ctx_bh() - prepare a file contents bio for inline
+ *				    crypto
  * @bio: a bio which will eventually be submitted to the file
  * @first_bh: the first buffer_head for which I/O will be submitted
  * @gfp_mask: memory allocation flags
@@ -363,8 +319,8 @@
  * of an inode and block number directly.
  */
 void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
-				 const struct buffer_head *first_bh,
-				 gfp_t gfp_mask)
+				  const struct buffer_head *first_bh,
+				  gfp_t gfp_mask)
 {
 	const struct inode *inode;
 	u64 first_lblk;
@@ -375,14 +331,14 @@
 EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
 
 /**
- * fscrypt_mergeable_bio - test whether data can be added to a bio
+ * fscrypt_mergeable_bio() - test whether data can be added to a bio
  * @bio: the bio being built up
  * @inode: the inode for the next part of the I/O
  * @next_lblk: the next file logical block number in the I/O
  *
  * When building a bio which may contain data which should undergo inline
  * encryption (or decryption) via fscrypt, filesystems should call this function
- * to ensure that the resulting bio contains only logically contiguous data.
+ * to ensure that the resulting bio contains only contiguous data unit numbers.
  * This will return false if the next part of the I/O cannot be merged with the
  * bio because either the encryption key would be different or the encryption
  * data unit numbers would be discontiguous.
@@ -413,7 +369,7 @@
 	 * uses the same pointer.  I.e., there's currently no need to support
 	 * merging requests where the keys are the same but the pointers differ.
 	 */
-	if (bc->bc_key != &inode->i_crypt_info->ci_key.blk_key->base)
+	if (bc->bc_key != &inode->i_crypt_info->ci_enc_key.blk_key->base)
 		return false;
 
 	fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
@@ -422,7 +378,7 @@
 EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
 
 /**
- * fscrypt_mergeable_bio_bh - test whether data can be added to a bio
+ * fscrypt_mergeable_bio_bh() - test whether data can be added to a bio
  * @bio: the bio being built up
  * @next_bh: the next buffer_head for which I/O will be submitted
  *
@@ -478,42 +434,43 @@
 EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
 
 /**
- * fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs
+ * fscrypt_limit_io_blocks() - limit I/O blocks to avoid discontiguous DUNs
  * @inode: the file on which I/O is being done
- * @pos: the file position (in bytes) at which the I/O is being done
- * @nr_pages: the number of pages we want to submit starting at @pos
+ * @lblk: the block at which the I/O is being started from
+ * @nr_blocks: the number of blocks we want to submit starting at @pos
  *
- * For direct I/O: limit the number of pages that will be submitted in the bio
- * targeting @pos, in order to avoid crossing a data unit number (DUN)
- * discontinuity.  This is only needed for certain IV generation methods.
+ * Determine the limit to the number of blocks that can be submitted in the bio
+ * targeting @pos without causing a data unit number (DUN) discontinuity.
  *
- * Return: the actual number of pages that can be submitted
+ * This is normally just @nr_blocks, as normally the DUNs just increment along
+ * with the logical blocks.  (Or the file is not encrypted.)
+ *
+ * In rare cases, fscrypt can be using an IV generation method that allows the
+ * DUN to wrap around within logically continuous blocks, and that wraparound
+ * will occur.  If this happens, a value less than @nr_blocks will be returned
+ * so that the wraparound doesn't occur in the middle of the bio.
+ *
+ * Return: the actual number of blocks that can be submitted
  */
-int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages)
+u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
 {
 	const struct fscrypt_info *ci = inode->i_crypt_info;
 	u32 dun;
 
 	if (!fscrypt_inode_uses_inline_crypto(inode))
-		return nr_pages;
+		return nr_blocks;
 
-	if (nr_pages <= 1)
-		return nr_pages;
+	if (nr_blocks <= 1)
+		return nr_blocks;
 
 	if (!(fscrypt_policy_flags(&ci->ci_policy) &
 	      FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
-		return nr_pages;
-
-	/*
-	 * fscrypt_select_encryption_impl() ensures that block_size == PAGE_SIZE
-	 * when using FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32.
-	 */
-	if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE))
-		return 1;
+		return nr_blocks;
 
 	/* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */
 
-	dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits);
+	dun = ci->ci_hashed_ino + lblk;
 
-	return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun);
+	return min_t(u64, nr_blocks, (u64)U32_MAX + 1 - dun);
 }
+EXPORT_SYMBOL_GPL(fscrypt_limit_io_blocks);

--
Gitblit v1.6.2