xsk: Check if a queue exists during umem setup

In the xdp_umem_assign_dev() path, the xsk code does not
check if a queue for which umem is to be created exists.
It leads to a situation where umem is not assigned to any
Tx/Rx queue of a netdevice, without notifying the stack
about an error. This affects both XDP_SKB and XDP_DRV
modes - in case of XDP_DRV_ZC, queue index is checked by
the driver.

This patch fixes xsk code, so that in both XDP_SKB and
XDP_DRV mode of AF_XDP, an error is returned when requested
queue index exceedes an existing maximum.

Fixes: c9b47cc1fa ("xsk: fix bug when trying to use both copy and zero-copy on one queue id")
Reported-by: Jakub Spizewski <jakub.spizewski@intel.com>
Signed-off-by: Krzysztof Kazimierczak <krzysztof.kazimierczak@intel.com>
Acked-by: Björn Töpel <bjorn.topel@intel.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
Krzysztof Kazimierczak 2019-01-10 20:29:02 +01:00 committed by Daniel Borkmann
parent 7939f8beec
commit cc5b5d3565

View File

@ -41,13 +41,20 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
* not know if the device has more tx queues than rx, or the opposite. * not know if the device has more tx queues than rx, or the opposite.
* This might also change during run time. * This might also change during run time.
*/ */
static void xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem, static int xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
u16 queue_id) u16 queue_id)
{ {
if (queue_id >= max_t(unsigned int,
dev->real_num_rx_queues,
dev->real_num_tx_queues))
return -EINVAL;
if (queue_id < dev->real_num_rx_queues) if (queue_id < dev->real_num_rx_queues)
dev->_rx[queue_id].umem = umem; dev->_rx[queue_id].umem = umem;
if (queue_id < dev->real_num_tx_queues) if (queue_id < dev->real_num_tx_queues)
dev->_tx[queue_id].umem = umem; dev->_tx[queue_id].umem = umem;
return 0;
} }
struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev, struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev,
@ -88,7 +95,10 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev,
goto out_rtnl_unlock; goto out_rtnl_unlock;
} }
xdp_reg_umem_at_qid(dev, umem, queue_id); err = xdp_reg_umem_at_qid(dev, umem, queue_id);
if (err)
goto out_rtnl_unlock;
umem->dev = dev; umem->dev = dev;
umem->queue_id = queue_id; umem->queue_id = queue_id;
if (force_copy) if (force_copy)