Commit 288cfe78c8173f35c7a94f06859f60b3693d828a
Committed by
David S. Miller
1 parent
05c0535194
Exists in
master
and in
20 other branches
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: Tommi Rantala <tt.rantala@gmail.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 7 additions and 15 deletions Side-by-side Diff
drivers/vhost/net.c
... | ... | @@ -155,14 +155,11 @@ |
155 | 155 | |
156 | 156 | static void vhost_net_clear_ubuf_info(struct vhost_net *n) |
157 | 157 | { |
158 | - | |
159 | - bool zcopy; | |
160 | 158 | int i; |
161 | 159 | |
162 | - for (i = 0; i < n->dev.nvqs; ++i) { | |
163 | - zcopy = vhost_net_zcopy_mask & (0x1 << i); | |
164 | - if (zcopy) | |
165 | - kfree(n->vqs[i].ubuf_info); | |
160 | + for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { | |
161 | + kfree(n->vqs[i].ubuf_info); | |
162 | + n->vqs[i].ubuf_info = NULL; | |
166 | 163 | } |
167 | 164 | } |
168 | 165 | |
... | ... | @@ -171,7 +168,7 @@ |
171 | 168 | bool zcopy; |
172 | 169 | int i; |
173 | 170 | |
174 | - for (i = 0; i < n->dev.nvqs; ++i) { | |
171 | + for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { | |
175 | 172 | zcopy = vhost_net_zcopy_mask & (0x1 << i); |
176 | 173 | if (!zcopy) |
177 | 174 | continue; |
... | ... | @@ -183,12 +180,7 @@ |
183 | 180 | return 0; |
184 | 181 | |
185 | 182 | err: |
186 | - while (i--) { | |
187 | - zcopy = vhost_net_zcopy_mask & (0x1 << i); | |
188 | - if (!zcopy) | |
189 | - continue; | |
190 | - kfree(n->vqs[i].ubuf_info); | |
191 | - } | |
183 | + vhost_net_clear_ubuf_info(n); | |
192 | 184 | return -ENOMEM; |
193 | 185 | } |
194 | 186 | |
195 | 187 | |
... | ... | @@ -196,12 +188,12 @@ |
196 | 188 | { |
197 | 189 | int i; |
198 | 190 | |
191 | + vhost_net_clear_ubuf_info(n); | |
192 | + | |
199 | 193 | for (i = 0; i < VHOST_NET_VQ_MAX; i++) { |
200 | 194 | n->vqs[i].done_idx = 0; |
201 | 195 | n->vqs[i].upend_idx = 0; |
202 | 196 | n->vqs[i].ubufs = NULL; |
203 | - kfree(n->vqs[i].ubuf_info); | |
204 | - n->vqs[i].ubuf_info = NULL; | |
205 | 197 | n->vqs[i].vhost_hlen = 0; |
206 | 198 | n->vqs[i].sock_hlen = 0; |
207 | 199 | } |