Open /dev/nbdX first, the config_refs will be 1 and the pointers in nbd_device are still null. Disconnect /dev/nbdX, then reference a null recv_workq. The protection by config_refs in nbd_genl_disconnect is useless. To fix it, just add a check for a non null task_recv in nbd_genl_disconnect. Signed-off-by: Sun Ke <sunke32@xxxxxxxxxx> --- v1 -> v2: Add an omitted mutex_unlock. v2 -> v3: Add nbd->config_lock, suggested by Josef. --- drivers/block/nbd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index b4607dd96185..870b3fd0c101 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -2008,12 +2008,20 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) index); return -EINVAL; } + mutex_lock(&nbd->config_lock); if (!refcount_inc_not_zero(&nbd->refs)) { + mutex_unlock(&nbd->config_lock); mutex_unlock(&nbd_index_mutex); printk(KERN_ERR "nbd: device at index %d is going down\n", index); return -EINVAL; } + if (!nbd->recv_workq) { + mutex_unlock(&nbd->config_lock); + mutex_unlock(&nbd_index_mutex); + return -EINVAL; + } + mutex_unlock(&nbd->config_lock); mutex_unlock(&nbd_index_mutex); if (!refcount_inc_not_zero(&nbd->config_refs)) { nbd_put(nbd); -- 2.17.2