Re: [PATCH v2 1/4] net: tun: fix tun_xdp_one() for IFF_TUN mode
From: David Woodhouse <dwmw2@infradead.org>
Date: 2021-06-23 08:30:38
On Wed, 2021-06-23 at 11:45 +0800, Jason Wang wrote:
As replied in previous version, it would be better if we can unify similar logic in tun_get_user().
Ah sorry, I missed that the first time. Yes, that was my initial inclination too. But in the tun_get_user() case we already *have* "pi", having read it separately into a local variable; it never made it to the skb. So the cases are subtly different enough that abstracting it out didn't seem to make sense. If I try harder to unify it, I suppose it looks something like this and *might* just make the cut for "simple enough to be backported to stable kernels in a bug fix". I'll add the PI mode to my test cases and try it (as well as *actually* unifying the offending code, of course).
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c@@ -2332,10 +2332,12 @@ static int tun_xdp_one(struct tun_struct *tun, unsigned int datasize = xdp->data_end - xdp->data; struct tun_xdp_hdr *hdr = xdp->data_hard_start; struct virtio_net_hdr *gso = NULL; + struct tun_pi *pi = NULL; struct bpf_prog *xdp_prog; struct sk_buff *skb = NULL; u32 rxhash = 0, act; int buflen = hdr->buflen; + int reservelen = xdp->data - xdp->data_hard_start; int err = 0; bool skb_xdp = false; struct page *page;
@@ -2343,6 +2345,11 @@ static int tun_xdp_one(struct tun_struct *tun, if (tun->flags & IFF_VNET_HDR) gso = &hdr->gso; + if (!(tun->flags & IFF_NO_PI)) { + pi = xdp->data; + reservelen += sizeof(*pi); + } + xdp_prog = rcu_dereference(tun->xdp_prog); if (xdp_prog) { if (gso && gso->gso_type) {
@@ -2388,7 +2395,7 @@ static int tun_xdp_one(struct tun_struct *tun, goto out; } - skb_reserve(skb, xdp->data - xdp->data_hard_start); + skb_reserve(skb, reservelen); skb_put(skb, xdp->data_end - xdp->data); if (gso && virtio_net_hdr_to_skb(skb, gso, tun_is_little_endian(tun))) {
Attachments
- smime.p7s [application/x-pkcs7-signature] 5174 bytes