Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fscrypt: stop holding extra request_queue references

Now that the fscrypt_master_key lifetime has been reworked to not be
subject to the quirks of the keyrings subsystem, blk_crypto_evict_key()
no longer gets called after the filesystem has already been unmounted.
Therefore, there is no longer any need to hold extra references to the
filesystem's request_queue(s). (And these references didn't always do
their intended job anyway, as pinning a request_queue doesn't
necessarily pin the corresponding blk_crypto_profile.)

Stop taking these extra references. Instead, just pass the super_block
to fscrypt_destroy_inline_crypt_key(), and use it to get the list of
block devices the key needs to be evicted from.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20220901193208.138056-3-ebiggers@kernel.org

+65 -61
+7 -4
fs/crypto/fscrypt_private.h
··· 184 184 struct fscrypt_prepared_key { 185 185 struct crypto_skcipher *tfm; 186 186 #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT 187 - struct fscrypt_blk_crypto_key *blk_key; 187 + struct blk_crypto_key *blk_key; 188 188 #endif 189 189 }; 190 190 ··· 344 344 const u8 *raw_key, 345 345 const struct fscrypt_info *ci); 346 346 347 - void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key); 347 + void fscrypt_destroy_inline_crypt_key(struct super_block *sb, 348 + struct fscrypt_prepared_key *prep_key); 348 349 349 350 /* 350 351 * Check whether the crypto transform or blk-crypto key has been allocated in ··· 391 390 } 392 391 393 392 static inline void 394 - fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key) 393 + fscrypt_destroy_inline_crypt_key(struct super_block *sb, 394 + struct fscrypt_prepared_key *prep_key) 395 395 { 396 396 } 397 397 ··· 602 600 int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, 603 601 const u8 *raw_key, const struct fscrypt_info *ci); 604 602 605 - void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key); 603 + void fscrypt_destroy_prepared_key(struct super_block *sb, 604 + struct fscrypt_prepared_key *prep_key); 606 605 607 606 int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key); 608 607
+44 -50
fs/crypto/inline_crypt.c
··· 21 21 22 22 #include "fscrypt_private.h" 23 23 24 - struct fscrypt_blk_crypto_key { 25 - struct blk_crypto_key base; 26 - int num_devs; 27 - struct request_queue *devs[]; 28 - }; 29 - 30 24 static int fscrypt_get_num_devices(struct super_block *sb) 31 25 { 32 26 if (sb->s_cop->get_num_devices) ··· 156 162 const struct inode *inode = ci->ci_inode; 157 163 struct super_block *sb = inode->i_sb; 158 164 enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode; 159 - int num_devs = fscrypt_get_num_devices(sb); 160 - int queue_refs = 0; 161 - struct fscrypt_blk_crypto_key *blk_key; 165 + struct blk_crypto_key *blk_key; 166 + struct request_queue **devs; 167 + unsigned int num_devs; 168 + unsigned int i; 162 169 int err; 163 - int i; 164 170 165 - blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_KERNEL); 171 + blk_key = kmalloc(sizeof(*blk_key), GFP_KERNEL); 166 172 if (!blk_key) 167 173 return -ENOMEM; 168 174 169 - blk_key->num_devs = num_devs; 170 - fscrypt_get_devices(sb, num_devs, blk_key->devs); 171 - 172 - err = blk_crypto_init_key(&blk_key->base, raw_key, crypto_mode, 175 + err = blk_crypto_init_key(blk_key, raw_key, crypto_mode, 173 176 fscrypt_get_dun_bytes(ci), sb->s_blocksize); 174 177 if (err) { 175 178 fscrypt_err(inode, "error %d initializing blk-crypto key", err); 176 179 goto fail; 177 180 } 178 181 179 - /* 180 - * We have to start using blk-crypto on all the filesystem's devices. 181 - * We also have to save all the request_queue's for later so that the 182 - * key can be evicted from them. This is needed because some keys 183 - * aren't destroyed until after the filesystem was already unmounted 184 - * (namely, the per-mode keys in struct fscrypt_master_key). 185 - */ 186 - for (i = 0; i < num_devs; i++) { 187 - if (!blk_get_queue(blk_key->devs[i])) { 188 - fscrypt_err(inode, "couldn't get request_queue"); 189 - err = -EAGAIN; 190 - goto fail; 191 - } 192 - queue_refs++; 193 - 194 - err = blk_crypto_start_using_key(&blk_key->base, 195 - blk_key->devs[i]); 196 - if (err) { 197 - fscrypt_err(inode, 198 - "error %d starting to use blk-crypto", err); 199 - goto fail; 200 - } 182 + /* Start using blk-crypto on all the filesystem's block devices. */ 183 + num_devs = fscrypt_get_num_devices(sb); 184 + devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL); 185 + if (!devs) { 186 + err = -ENOMEM; 187 + goto fail; 201 188 } 189 + fscrypt_get_devices(sb, num_devs, devs); 190 + for (i = 0; i < num_devs; i++) { 191 + err = blk_crypto_start_using_key(blk_key, devs[i]); 192 + if (err) 193 + break; 194 + } 195 + kfree(devs); 196 + if (err) { 197 + fscrypt_err(inode, "error %d starting to use blk-crypto", err); 198 + goto fail; 199 + } 200 + 202 201 /* 203 202 * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared(). 204 203 * I.e., here we publish ->blk_key with a RELEASE barrier so that ··· 202 215 return 0; 203 216 204 217 fail: 205 - for (i = 0; i < queue_refs; i++) 206 - blk_put_queue(blk_key->devs[i]); 207 218 kfree_sensitive(blk_key); 208 219 return err; 209 220 } 210 221 211 - void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key) 222 + void fscrypt_destroy_inline_crypt_key(struct super_block *sb, 223 + struct fscrypt_prepared_key *prep_key) 212 224 { 213 - struct fscrypt_blk_crypto_key *blk_key = prep_key->blk_key; 214 - int i; 225 + struct blk_crypto_key *blk_key = prep_key->blk_key; 226 + struct request_queue **devs; 227 + unsigned int num_devs; 228 + unsigned int i; 215 229 216 - if (blk_key) { 217 - for (i = 0; i < blk_key->num_devs; i++) { 218 - blk_crypto_evict_key(blk_key->devs[i], &blk_key->base); 219 - blk_put_queue(blk_key->devs[i]); 220 - } 221 - kfree_sensitive(blk_key); 230 + if (!blk_key) 231 + return; 232 + 233 + /* Evict the key from all the filesystem's block devices. */ 234 + num_devs = fscrypt_get_num_devices(sb); 235 + devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL); 236 + if (devs) { 237 + fscrypt_get_devices(sb, num_devs, devs); 238 + for (i = 0; i < num_devs; i++) 239 + blk_crypto_evict_key(devs[i], blk_key); 240 + kfree(devs); 222 241 } 242 + kfree_sensitive(blk_key); 223 243 } 224 244 225 245 bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) ··· 276 282 ci = inode->i_crypt_info; 277 283 278 284 fscrypt_generate_dun(ci, first_lblk, dun); 279 - bio_crypt_set_ctx(bio, &ci->ci_enc_key.blk_key->base, dun, gfp_mask); 285 + bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask); 280 286 } 281 287 EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); 282 288 ··· 363 369 * uses the same pointer. I.e., there's currently no need to support 364 370 * merging requests where the keys are the same but the pointers differ. 365 371 */ 366 - if (bc->bc_key != &inode->i_crypt_info->ci_enc_key.blk_key->base) 372 + if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key) 367 373 return false; 368 374 369 375 fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
+6 -3
fs/crypto/keyring.c
··· 105 105 WARN_ON(!list_empty(&mk->mk_decrypted_inodes)); 106 106 107 107 for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { 108 - fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]); 109 - fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]); 110 - fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]); 108 + fscrypt_destroy_prepared_key( 109 + sb, &mk->mk_direct_keys[i]); 110 + fscrypt_destroy_prepared_key( 111 + sb, &mk->mk_iv_ino_lblk_64_keys[i]); 112 + fscrypt_destroy_prepared_key( 113 + sb, &mk->mk_iv_ino_lblk_32_keys[i]); 111 114 } 112 115 memzero_explicit(&mk->mk_ino_hash_key, 113 116 sizeof(mk->mk_ino_hash_key));
+5 -3
fs/crypto/keysetup.c
··· 154 154 } 155 155 156 156 /* Destroy a crypto transform object and/or blk-crypto key. */ 157 - void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key) 157 + void fscrypt_destroy_prepared_key(struct super_block *sb, 158 + struct fscrypt_prepared_key *prep_key) 158 159 { 159 160 crypto_free_skcipher(prep_key->tfm); 160 - fscrypt_destroy_inline_crypt_key(prep_key); 161 + fscrypt_destroy_inline_crypt_key(sb, prep_key); 161 162 memzero_explicit(prep_key, sizeof(*prep_key)); 162 163 } 163 164 ··· 495 494 if (ci->ci_direct_key) 496 495 fscrypt_put_direct_key(ci->ci_direct_key); 497 496 else if (ci->ci_owns_key) 498 - fscrypt_destroy_prepared_key(&ci->ci_enc_key); 497 + fscrypt_destroy_prepared_key(ci->ci_inode->i_sb, 498 + &ci->ci_enc_key); 499 499 500 500 mk = ci->ci_master_key; 501 501 if (mk) {
+3 -1
fs/crypto/keysetup_v1.c
··· 143 143 144 144 /* Master key referenced by DIRECT_KEY policy */ 145 145 struct fscrypt_direct_key { 146 + struct super_block *dk_sb; 146 147 struct hlist_node dk_node; 147 148 refcount_t dk_refcount; 148 149 const struct fscrypt_mode *dk_mode; ··· 155 154 static void free_direct_key(struct fscrypt_direct_key *dk) 156 155 { 157 156 if (dk) { 158 - fscrypt_destroy_prepared_key(&dk->dk_key); 157 + fscrypt_destroy_prepared_key(dk->dk_sb, &dk->dk_key); 159 158 kfree_sensitive(dk); 160 159 } 161 160 } ··· 232 231 dk = kzalloc(sizeof(*dk), GFP_KERNEL); 233 232 if (!dk) 234 233 return ERR_PTR(-ENOMEM); 234 + dk->dk_sb = ci->ci_inode->i_sb; 235 235 refcount_set(&dk->dk_refcount, 1); 236 236 dk->dk_mode = ci->ci_mode; 237 237 err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci);