Skip to content

Commit f7306ac

Browse files
igsilyaborkmann
authored andcommitted
xsk: Honor SO_BINDTODEVICE on bind
Initial creation of an AF_XDP socket requires CAP_NET_RAW capability. A privileged process might create the socket and pass it to a non-privileged process for later use. However, that process will be able to bind the socket to any network interface. Even though it will not be able to receive any traffic without modification of the BPF map, the situation is not ideal. Sockets already have a mechanism that can be used to restrict what interface they can be attached to. That is SO_BINDTODEVICE. To change the SO_BINDTODEVICE binding the process will need CAP_NET_RAW. Make xsk_bind() honor the SO_BINDTODEVICE in order to allow safer workflow when non-privileged process is using AF_XDP. The intended workflow is following: 1. First process creates a bare socket with socket(AF_XDP, ...). 2. First process loads the XSK program to the interface. 3. First process adds the socket fd to a BPF map. 4. First process ties socket fd to a particular interface using SO_BINDTODEVICE. 5. First process sends socket fd to a second process. 6. Second process allocates UMEM. 7. Second process binds socket to the interface with bind(...). 8. Second process sends/receives the traffic. All the steps above are possible today if the first process is privileged and the second one has sufficient RLIMIT_MEMLOCK and no capabilities. However, the second process will be able to bind the socket to any interface it wants on step 7 and send traffic from it. With the proposed change, the second process will be able to bind the socket only to a specific interface chosen by the first process at step 4. Fixes: 965a990 ("xsk: add support for bind for Rx") Signed-off-by: Ilya Maximets <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Magnus Karlsson <[email protected]> Acked-by: John Fastabend <[email protected]> Acked-by: Jason Wang <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 3de4d22 commit f7306ac

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

Documentation/networking/af_xdp.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,15 @@ start N bytes into the buffer leaving the first N bytes for the
433433
application to use. The final option is the flags field, but it will
434434
be dealt with in separate sections for each UMEM flag.
435435

436+
SO_BINDTODEVICE setsockopt
437+
--------------------------
438+
439+
This is a generic SOL_SOCKET option that can be used to tie AF_XDP
440+
socket to a particular network interface. It is useful when a socket
441+
is created by a privileged process and passed to a non-privileged one.
442+
Once the option is set, kernel will refuse attempts to bind that socket
443+
to a different interface. Updating the value requires CAP_NET_RAW.
444+
436445
XDP_STATISTICS getsockopt
437446
-------------------------
438447

net/xdp/xsk.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
886886
struct sock *sk = sock->sk;
887887
struct xdp_sock *xs = xdp_sk(sk);
888888
struct net_device *dev;
889+
int bound_dev_if;
889890
u32 flags, qid;
890891
int err = 0;
891892

@@ -899,6 +900,10 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
899900
XDP_USE_NEED_WAKEUP))
900901
return -EINVAL;
901902

903+
bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
904+
if (bound_dev_if && bound_dev_if != sxdp->sxdp_ifindex)
905+
return -EINVAL;
906+
902907
rtnl_lock();
903908
mutex_lock(&xs->mutex);
904909
if (xs->state != XSK_READY) {

0 commit comments

Comments
 (0)