提交 749eccf1 编写于 作者: Y Yu Kuai 提交者: Zhong Jinghua

nbd: fix null-ptr-dereference while accessing 'nbd->config'

Offering: HULK
hulk inclusion
category: bugfix
bugzilla: 188902, https://gitee.com/openeuler/kernel/issues/I7EENU

----------------------------------------

nbd->config = config and refcount_set(&nbd->config_refs, 1) in
nbd_genl_connect may be out of order, causing config_refs to be set to 1
first, and then nbd_open accessing nbd->config reports a null pointer
reference.
   T1                      T2
vfs_open
  do_dentry_open
    blkdev_open
      blkdev_get
        __blkdev_get
          nbd_open
           nbd_get_config_unlocked
                        genl_rcv_msg
                          genl_family_rcv_msg
                            genl_family_rcv_msg_doit
                              nbd_genl_connect
                                nbd_alloc_and_init_config
                                  // out of order execution
                                  refcount_set(&nbd->config_refs, 1); // 2
             nbd->config
             // null point
                                  nbd->config = config; // 1

Fix it by adding a cpu memory barrier to guarantee sequential execution.
Signed-off-by: NYu Kuai <yukuai3@huawei.com>
Signed-off-by: NZhong Jinghua <zhongjinghua@huawei.com>
上级 77d63b9a
...@@ -391,8 +391,16 @@ static u32 req_to_nbd_cmd_type(struct request *req) ...@@ -391,8 +391,16 @@ static u32 req_to_nbd_cmd_type(struct request *req)
static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd) 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 nbd->config;
}
return NULL; return NULL;
} }
...@@ -1563,7 +1571,15 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd) ...@@ -1563,7 +1571,15 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd)
init_waitqueue_head(&config->conn_wait); init_waitqueue_head(&config->conn_wait);
config->blksize = NBD_DEF_BLKSIZE; config->blksize = NBD_DEF_BLKSIZE;
atomic_set(&config->live_connections, 0); atomic_set(&config->live_connections, 0);
nbd->config = config; 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); refcount_set(&nbd->config_refs, 1);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册