aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@suse.com>2018-09-25 04:13:01 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-25 13:39:34 -0400
commit22f9cde3401077ea450b69bf9b0bba373e12e454 (patch)
tree7c51fbb18bf4a47ede96817e964cffd7c3953014
parent780e83c259fc33e8959fed8dfdad17e378d72b62 (diff)
xen-netback: validate queue numbers in xenvif_set_hash_mapping()
Checking them before the grant copy means nothing as to the validity of the incoming request. As we shouldn't make the new data live before having validated it, introduce a second instance of the mapping array. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/xen-netback/common.h3
-rw-r--r--drivers/net/xen-netback/hash.c20
-rw-r--r--drivers/net/xen-netback/interface.c3
3 files changed, 18 insertions, 8 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index a46a1e94505d..936c0b3e0ba2 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -241,8 +241,9 @@ struct xenvif_hash_cache {
241struct xenvif_hash { 241struct xenvif_hash {
242 unsigned int alg; 242 unsigned int alg;
243 u32 flags; 243 u32 flags;
244 bool mapping_sel;
244 u8 key[XEN_NETBK_MAX_HASH_KEY_SIZE]; 245 u8 key[XEN_NETBK_MAX_HASH_KEY_SIZE];
245 u32 mapping[XEN_NETBK_MAX_HASH_MAPPING_SIZE]; 246 u32 mapping[2][XEN_NETBK_MAX_HASH_MAPPING_SIZE];
246 unsigned int size; 247 unsigned int size;
247 struct xenvif_hash_cache cache; 248 struct xenvif_hash_cache cache;
248}; 249};
diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c
index 3b6fb5b3bdb2..dc9841ea2fff 100644
--- a/drivers/net/xen-netback/hash.c
+++ b/drivers/net/xen-netback/hash.c
@@ -324,7 +324,8 @@ u32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size)
324 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; 324 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
325 325
326 vif->hash.size = size; 326 vif->hash.size = size;
327 memset(vif->hash.mapping, 0, sizeof(u32) * size); 327 memset(vif->hash.mapping[vif->hash.mapping_sel], 0,
328 sizeof(u32) * size);
328 329
329 return XEN_NETIF_CTRL_STATUS_SUCCESS; 330 return XEN_NETIF_CTRL_STATUS_SUCCESS;
330} 331}
@@ -332,7 +333,7 @@ u32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size)
332u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, 333u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len,
333 u32 off) 334 u32 off)
334{ 335{
335 u32 *mapping = vif->hash.mapping; 336 u32 *mapping = vif->hash.mapping[!vif->hash.mapping_sel];
336 struct gnttab_copy copy_op = { 337 struct gnttab_copy copy_op = {
337 .source.u.ref = gref, 338 .source.u.ref = gref,
338 .source.domid = vif->domid, 339 .source.domid = vif->domid,
@@ -348,9 +349,8 @@ u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len,
348 copy_op.dest.u.gmfn = virt_to_gfn(mapping + off); 349 copy_op.dest.u.gmfn = virt_to_gfn(mapping + off);
349 copy_op.dest.offset = xen_offset_in_page(mapping + off); 350 copy_op.dest.offset = xen_offset_in_page(mapping + off);
350 351
351 while (len-- != 0) 352 memcpy(mapping, vif->hash.mapping[vif->hash.mapping_sel],
352 if (mapping[off++] >= vif->num_queues) 353 vif->hash.size * sizeof(*mapping));
353 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
354 354
355 if (copy_op.len != 0) { 355 if (copy_op.len != 0) {
356 gnttab_batch_copy(&copy_op, 1); 356 gnttab_batch_copy(&copy_op, 1);
@@ -359,6 +359,12 @@ u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len,
359 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; 359 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
360 } 360 }
361 361
362 while (len-- != 0)
363 if (mapping[off++] >= vif->num_queues)
364 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
365
366 vif->hash.mapping_sel = !vif->hash.mapping_sel;
367
362 return XEN_NETIF_CTRL_STATUS_SUCCESS; 368 return XEN_NETIF_CTRL_STATUS_SUCCESS;
363} 369}
364 370
@@ -410,6 +416,8 @@ void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m)
410 } 416 }
411 417
412 if (vif->hash.size != 0) { 418 if (vif->hash.size != 0) {
419 const u32 *mapping = vif->hash.mapping[vif->hash.mapping_sel];
420
413 seq_puts(m, "\nHash Mapping:\n"); 421 seq_puts(m, "\nHash Mapping:\n");
414 422
415 for (i = 0; i < vif->hash.size; ) { 423 for (i = 0; i < vif->hash.size; ) {
@@ -422,7 +430,7 @@ void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m)
422 seq_printf(m, "[%4u - %4u]: ", i, i + n - 1); 430 seq_printf(m, "[%4u - %4u]: ", i, i + n - 1);
423 431
424 for (j = 0; j < n; j++, i++) 432 for (j = 0; j < n; j++, i++)
425 seq_printf(m, "%4u ", vif->hash.mapping[i]); 433 seq_printf(m, "%4u ", mapping[i]);
426 434
427 seq_puts(m, "\n"); 435 seq_puts(m, "\n");
428 } 436 }
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 92274c237200..f6ae23fc3f6b 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -162,7 +162,8 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
162 if (size == 0) 162 if (size == 0)
163 return skb_get_hash_raw(skb) % dev->real_num_tx_queues; 163 return skb_get_hash_raw(skb) % dev->real_num_tx_queues;
164 164
165 return vif->hash.mapping[skb_get_hash_raw(skb) % size]; 165 return vif->hash.mapping[vif->hash.mapping_sel]
166 [skb_get_hash_raw(skb) % size];
166} 167}
167 168
168static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) 169static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)