mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 15:18:19 +00:00
nbd: fix null-ptr-dereference while accessing 'nbd->config'
[ Upstream commit c2da049f41
]
Memory reordering may occur in nbd_genl_connect(), causing config_refs
to be set to 1 while nbd->config is still empty. Opening nbd at this
time will cause null-ptr-dereference.
T1 T2
nbd_open
nbd_get_config_unlocked
nbd_genl_connect
nbd_alloc_and_init_config
//memory reordered
refcount_set(&nbd->config_refs, 1) // 2
nbd->config
->null point
nbd->config = config // 1
Fix it by adding smp barrier to guarantee the execution sequence.
Signed-off-by: Li Nan <linan122@huawei.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Link: https://lore.kernel.org/r/20231116162316.1740402-4-linan666@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
8c15173441
commit
c34fa2d16e
1 changed files with 17 additions and 1 deletions
|
@ -397,8 +397,16 @@ static u32 req_to_nbd_cmd_type(struct request *req)
|
|||
|
||||
static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
|
||||
{
|
||||
if (refcount_inc_not_zero(&nbd->config_refs))
|
||||
if (refcount_inc_not_zero(&nbd->config_refs)) {
|
||||
/*
|
||||
* Add smp_mb__after_atomic to ensure that reading nbd->config_refs
|
||||
* and reading nbd->config is ordered. The pair is the barrier in
|
||||
* nbd_alloc_and_init_config(), avoid nbd->config_refs is set
|
||||
* before nbd->config.
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
return nbd->config;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1559,7 +1567,15 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd)
|
|||
init_waitqueue_head(&config->conn_wait);
|
||||
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
|
||||
atomic_set(&config->live_connections, 0);
|
||||
|
||||
nbd->config = config;
|
||||
/*
|
||||
* Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment,
|
||||
* its pair is the barrier in nbd_get_config_unlocked().
|
||||
* So nbd_get_config_unlocked() won't see nbd->config as null after
|
||||
* refcount_inc_not_zero() succeed.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
refcount_set(&nbd->config_refs, 1);
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue