| From 51f99126bd309daf8e405d708e4f6e7a37b6c9f4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 29 Jun 2020 09:23:49 +0800 |
| Subject: nbd: Fix memory leak in nbd_add_socket |
| |
| From: Zheng Bin <zhengbin13@huawei.com> |
| |
| [ Upstream commit 579dd91ab3a5446b148e7f179b6596b270dace46 ] |
| |
| When adding first socket to nbd, if nsock's allocation failed, the data |
| structure member "config->socks" was reallocated, but the data structure |
| member "config->num_connections" was not updated. A memory leak will occur |
| then because the function "nbd_config_put" will free "config->socks" only |
| when "config->num_connections" is not zero. |
| |
| Fixes: 03bf73c315ed ("nbd: prevent memory leak") |
| Reported-by: syzbot+934037347002901b8d2a@syzkaller.appspotmail.com |
| Signed-off-by: Zheng Bin <zhengbin13@huawei.com> |
| Reviewed-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/block/nbd.c | 25 +++++++++++++++---------- |
| 1 file changed, 15 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c |
| index 78181908f0df6..7b61d53ba050e 100644 |
| --- a/drivers/block/nbd.c |
| +++ b/drivers/block/nbd.c |
| @@ -1022,25 +1022,26 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, |
| test_bit(NBD_RT_BOUND, &config->runtime_flags))) { |
| dev_err(disk_to_dev(nbd->disk), |
| "Device being setup by another task"); |
| - sockfd_put(sock); |
| - return -EBUSY; |
| + err = -EBUSY; |
| + goto put_socket; |
| + } |
| + |
| + nsock = kzalloc(sizeof(*nsock), GFP_KERNEL); |
| + if (!nsock) { |
| + err = -ENOMEM; |
| + goto put_socket; |
| } |
| |
| socks = krealloc(config->socks, (config->num_connections + 1) * |
| sizeof(struct nbd_sock *), GFP_KERNEL); |
| if (!socks) { |
| - sockfd_put(sock); |
| - return -ENOMEM; |
| + kfree(nsock); |
| + err = -ENOMEM; |
| + goto put_socket; |
| } |
| |
| config->socks = socks; |
| |
| - nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL); |
| - if (!nsock) { |
| - sockfd_put(sock); |
| - return -ENOMEM; |
| - } |
| - |
| nsock->fallback_index = -1; |
| nsock->dead = false; |
| mutex_init(&nsock->tx_lock); |
| @@ -1052,6 +1053,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, |
| atomic_inc(&config->live_connections); |
| |
| return 0; |
| + |
| +put_socket: |
| + sockfd_put(sock); |
| + return err; |
| } |
| |
| static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) |
| -- |
| 2.25.1 |
| |