Skip to content

Commit c2da049

Browse files
Li Nanaxboe
authored andcommitted
nbd: fix null-ptr-dereference while accessing 'nbd->config'
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 <[email protected]> Reviewed-by: Josef Bacik <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 3123ac7 commit c2da049

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

drivers/block/nbd.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,16 @@ static u32 req_to_nbd_cmd_type(struct request *req)
397397

398398
static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
399399
{
400-
if (refcount_inc_not_zero(&nbd->config_refs))
400+
if (refcount_inc_not_zero(&nbd->config_refs)) {
401+
/*
402+
* Add smp_mb__after_atomic to ensure that reading nbd->config_refs
403+
* and reading nbd->config is ordered. The pair is the barrier in
404+
* nbd_alloc_and_init_config(), avoid nbd->config_refs is set
405+
* before nbd->config.
406+
*/
407+
smp_mb__after_atomic();
401408
return nbd->config;
409+
}
402410

403411
return NULL;
404412
}
@@ -1559,7 +1567,15 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd)
15591567
init_waitqueue_head(&config->conn_wait);
15601568
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
15611569
atomic_set(&config->live_connections, 0);
1570+
15621571
nbd->config = config;
1572+
/*
1573+
* Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment,
1574+
* its pair is the barrier in nbd_get_config_unlocked().
1575+
* So nbd_get_config_unlocked() won't see nbd->config as null after
1576+
* refcount_inc_not_zero() succeed.
1577+
*/
1578+
smp_mb__before_atomic();
15631579
refcount_set(&nbd->config_refs, 1);
15641580

15651581
return 0;

0 commit comments

Comments
 (0)