2019-06-01 11:08:42 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2015-12-04 00:01:51 +03:00
/*
* Copyright ( C ) 2012 Red Hat , Inc .
* Copyright ( C ) 2015 Google , Inc .
*
* Author : Mikulas Patocka < mpatocka @ redhat . com >
*
* Based on Chromium dm - verity driver ( C ) 2011 The Chromium OS Authors
*/
# ifndef DM_VERITY_H
# define DM_VERITY_H
2018-03-15 23:02:31 +03:00
# include <linux/dm-bufio.h>
2015-12-04 00:01:51 +03:00
# include <linux/device-mapper.h>
2022-07-22 12:38:23 +03:00
# include <linux/interrupt.h>
2015-12-04 00:01:51 +03:00
# include <crypto/hash.h>
# define DM_VERITY_MAX_LEVELS 63
enum verity_mode {
DM_VERITY_MODE_EIO ,
DM_VERITY_MODE_LOGGING ,
2020-06-18 09:56:50 +03:00
DM_VERITY_MODE_RESTART ,
DM_VERITY_MODE_PANIC
2015-12-04 00:01:51 +03:00
} ;
enum verity_block_type {
DM_VERITY_BLOCK_TYPE_DATA ,
DM_VERITY_BLOCK_TYPE_METADATA
} ;
2015-12-03 17:26:30 +03:00
struct dm_verity_fec ;
2015-12-04 00:01:51 +03:00
struct dm_verity {
struct dm_dev * data_dev ;
struct dm_dev * hash_dev ;
struct dm_target * ti ;
struct dm_bufio_client * bufio ;
char * alg_name ;
2017-02-19 15:46:07 +03:00
struct crypto_ahash * tfm ;
2015-12-04 00:01:51 +03:00
u8 * root_digest ; /* digest of the root block */
u8 * salt ; /* salt: its size is salt_size */
2015-12-03 17:26:31 +03:00
u8 * zero_digest ; /* digest for a zero block */
2023-01-25 23:14:58 +03:00
unsigned int salt_size ;
2015-12-04 00:01:51 +03:00
sector_t data_start ; /* data offset in 512-byte sectors */
sector_t hash_start ; /* hash start in blocks */
sector_t data_blocks ; /* the number of data blocks */
sector_t hash_blocks ; /* the number of hash blocks */
unsigned char data_dev_block_bits ; /* log2(data blocksize) */
unsigned char hash_dev_block_bits ; /* log2(hash blocksize) */
unsigned char hash_per_block_bits ; /* log2(hashes in hash block) */
unsigned char levels ; /* the number of tree levels */
unsigned char version ;
2022-07-22 12:38:23 +03:00
bool hash_failed : 1 ; /* set if hash of any block failed */
bool use_tasklet : 1 ; /* try to verify in tasklet before work-queue */
2023-01-25 23:14:58 +03:00
unsigned int digest_size ; /* digest size for the current hash algorithm */
2017-02-19 15:46:07 +03:00
unsigned int ahash_reqsize ; /* the size of temporary space for crypto */
2015-12-04 00:01:51 +03:00
enum verity_mode mode ; /* mode for handling verification errors */
2023-01-25 23:14:58 +03:00
unsigned int corrupted_errs ; /* Number of errors for corrupted blocks */
2015-12-04 00:01:51 +03:00
struct workqueue_struct * verify_wq ;
/* starting blocks for each tree level. 0 is the lowest level. */
sector_t hash_level_block [ DM_VERITY_MAX_LEVELS ] ;
2015-12-03 17:26:30 +03:00
struct dm_verity_fec * fec ; /* forward error correction */
2018-03-23 04:18:04 +03:00
unsigned long * validated_blocks ; /* bitset blocks validated */
2019-07-18 03:46:15 +03:00
char * signature_key_desc ; /* signature keyring reference */
2015-12-04 00:01:51 +03:00
} ;
struct dm_verity_io {
struct dm_verity * v ;
/* original value of bio->bi_end_io */
bio_end_io_t * orig_bi_end_io ;
sector_t block ;
2023-01-25 23:14:58 +03:00
unsigned int n_blocks ;
2022-07-22 12:38:23 +03:00
bool in_tasklet ;
2015-12-04 00:01:51 +03:00
struct bvec_iter iter ;
struct work_struct work ;
/*
* Three variably - size fields follow this struct :
*
2017-02-19 15:46:07 +03:00
* u8 hash_req [ v - > ahash_reqsize ] ;
2015-12-04 00:01:51 +03:00
* u8 real_digest [ v - > digest_size ] ;
* u8 want_digest [ v - > digest_size ] ;
*
2017-02-19 15:46:07 +03:00
* To access them use : verity_io_hash_req ( ) , verity_io_real_digest ( )
2015-12-04 00:01:51 +03:00
* and verity_io_want_digest ( ) .
*/
} ;
2017-02-19 15:46:07 +03:00
static inline struct ahash_request * verity_io_hash_req ( struct dm_verity * v ,
2015-12-04 00:01:51 +03:00
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( struct ahash_request * ) ( io + 1 ) ;
2015-12-04 00:01:51 +03:00
}
static inline u8 * verity_io_real_digest ( struct dm_verity * v ,
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( u8 * ) ( io + 1 ) + v - > ahash_reqsize ;
2015-12-04 00:01:51 +03:00
}
static inline u8 * verity_io_want_digest ( struct dm_verity * v ,
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( u8 * ) ( io + 1 ) + v - > ahash_reqsize + v - > digest_size ;
2015-12-04 00:01:51 +03:00
}
2015-12-04 00:30:36 +03:00
extern int verity_for_bv_block ( struct dm_verity * v , struct dm_verity_io * io ,
struct bvec_iter * iter ,
int ( * process ) ( struct dm_verity * v ,
struct dm_verity_io * io ,
u8 * data , size_t len ) ) ;
2017-02-19 15:46:07 +03:00
extern int verity_hash ( struct dm_verity * v , struct ahash_request * req ,
dm-verity: don't use blocking calls from tasklets
The commit 5721d4e5a9cd enhanced dm-verity, so that it can verify blocks
from tasklets rather than from workqueues. This reportedly improves
performance significantly.
However, dm-verity was using the flag CRYPTO_TFM_REQ_MAY_SLEEP from
tasklets which resulted in warnings about sleeping function being called
from non-sleeping context.
BUG: sleeping function called from invalid context at crypto/internal.h:206
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 14, name: ksoftirqd/0
preempt_count: 100, expected: 0
RCU nest depth: 0, expected: 0
CPU: 0 PID: 14 Comm: ksoftirqd/0 Tainted: G W 6.7.0-rc1 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x32/0x50
__might_resched+0x110/0x160
crypto_hash_walk_done+0x54/0xb0
shash_ahash_update+0x51/0x60
verity_hash_update.isra.0+0x4a/0x130 [dm_verity]
verity_verify_io+0x165/0x550 [dm_verity]
? free_unref_page+0xdf/0x170
? psi_group_change+0x113/0x390
verity_tasklet+0xd/0x70 [dm_verity]
tasklet_action_common.isra.0+0xb3/0xc0
__do_softirq+0xaf/0x1ec
? smpboot_thread_fn+0x1d/0x200
? sort_range+0x20/0x20
run_ksoftirqd+0x15/0x30
smpboot_thread_fn+0xed/0x200
kthread+0xdc/0x110
? kthread_complete_and_exit+0x20/0x20
ret_from_fork+0x28/0x40
? kthread_complete_and_exit+0x20/0x20
ret_from_fork_asm+0x11/0x20
</TASK>
This commit fixes dm-verity so that it doesn't use the flags
CRYPTO_TFM_REQ_MAY_SLEEP and CRYPTO_TFM_REQ_MAY_BACKLOG from tasklets. The
crypto API would do GFP_ATOMIC allocation instead, it could return -ENOMEM
and we catch -ENOMEM in verity_tasklet and requeue the request to the
workqueue.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org # v6.0+
Fixes: 5721d4e5a9cd ("dm verity: Add optional "try_verify_in_tasklet" feature")
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
2023-11-17 20:37:25 +03:00
const u8 * data , size_t len , u8 * digest , bool may_sleep ) ;
2015-12-04 00:01:51 +03:00
extern int verity_hash_for_block ( struct dm_verity * v , struct dm_verity_io * io ,
2015-12-03 17:26:31 +03:00
sector_t block , u8 * digest , bool * is_zero ) ;
2015-12-04 00:01:51 +03:00
2022-06-27 18:35:24 +03:00
extern bool dm_is_verity_target ( struct dm_target * ti ) ;
2022-09-07 23:30:58 +03:00
extern int dm_verity_get_mode ( struct dm_target * ti ) ;
2022-06-27 18:35:24 +03:00
extern int dm_verity_get_root_digest ( struct dm_target * ti , u8 * * root_digest ,
unsigned int * digest_size ) ;
2015-12-04 00:01:51 +03:00
# endif /* DM_VERITY_H */