Commit 288cfe78 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by David S. Miller

vhost: fix ubuf_info cleanup

vhost_net_clear_ubuf_info didn't clear ubuf_info
after kfree, this could trigger double free.
Fix this and simplify this code to make it more robust: make sure
ubuf info is always freed through vhost_net_clear_ubuf_info.
Reported-by: default avatarTommi Rantala <tt.rantala@gmail.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05c05351
...@@ -155,14 +155,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) ...@@ -155,14 +155,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
static void vhost_net_clear_ubuf_info(struct vhost_net *n) static void vhost_net_clear_ubuf_info(struct vhost_net *n)
{ {
bool zcopy;
int i; int i;
for (i = 0; i < n->dev.nvqs; ++i) { for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
zcopy = vhost_net_zcopy_mask & (0x1 << i);
if (zcopy)
kfree(n->vqs[i].ubuf_info); kfree(n->vqs[i].ubuf_info);
n->vqs[i].ubuf_info = NULL;
} }
} }
...@@ -171,7 +168,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n) ...@@ -171,7 +168,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n)
bool zcopy; bool zcopy;
int i; int i;
for (i = 0; i < n->dev.nvqs; ++i) { for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
zcopy = vhost_net_zcopy_mask & (0x1 << i); zcopy = vhost_net_zcopy_mask & (0x1 << i);
if (!zcopy) if (!zcopy)
continue; continue;
...@@ -183,12 +180,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n) ...@@ -183,12 +180,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n)
return 0; return 0;
err: err:
while (i--) { vhost_net_clear_ubuf_info(n);
zcopy = vhost_net_zcopy_mask & (0x1 << i);
if (!zcopy)
continue;
kfree(n->vqs[i].ubuf_info);
}
return -ENOMEM; return -ENOMEM;
} }
...@@ -196,12 +188,12 @@ void vhost_net_vq_reset(struct vhost_net *n) ...@@ -196,12 +188,12 @@ void vhost_net_vq_reset(struct vhost_net *n)
{ {
int i; int i;
vhost_net_clear_ubuf_info(n);
for (i = 0; i < VHOST_NET_VQ_MAX; i++) { for (i = 0; i < VHOST_NET_VQ_MAX; i++) {
n->vqs[i].done_idx = 0; n->vqs[i].done_idx = 0;
n->vqs[i].upend_idx = 0; n->vqs[i].upend_idx = 0;
n->vqs[i].ubufs = NULL; n->vqs[i].ubufs = NULL;
kfree(n->vqs[i].ubuf_info);
n->vqs[i].ubuf_info = NULL;
n->vqs[i].vhost_hlen = 0; n->vqs[i].vhost_hlen = 0;
n->vqs[i].sock_hlen = 0; n->vqs[i].sock_hlen = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment