Skip to content

Commit 6860b46

Browse files
woziwrtklassert
authored andcommitted
xfrm: propagate -EINPROGRESS from validate_xmit_xfrm()
validate_xmit_xfrm() returns NULL both when a packet is dropped and when it is stolen by async crypto (-EINPROGRESS from ->xmit()). Callers cannot distinguish the two cases. f53c723 ("net: Add asynchronous callbacks for xfrm on layer 2.") changed the semantics of a NULL return from "dropped" to "stolen or dropped", but __dev_queue_xmit() was not updated. On virtual/bridge interfaces (noqueue qdisc) __dev_queue_xmit() initialises rc=-ENOMEM and jumps to out: when skb is NULL, returning -ENOMEM to the caller even though the packet will be delivered correctly via xfrm_dev_resume(). Return ERR_PTR(-EINPROGRESS) from validate_xmit_xfrm() for the async case so callers can tell it apart from a real drop. Update __dev_queue_xmit() to handle ERR_PTR(-EINPROGRESS) from validate_xmit_skb() correctly. Update validate_xmit_skb_list() to use IS_ERR_OR_NULL() so that ERR_PTR(-EINPROGRESS) is not mistakenly added to the transmitted list. Fixes: f53c723 ("net: Add asynchronous callbacks for xfrm on layer 2.") Suggested-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Petr Wozniak <petr.wozniak@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
1 parent 805185b commit 6860b46

2 files changed

Lines changed: 10 additions & 4 deletions

File tree

net/core/dev.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4018,6 +4018,9 @@ static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb,
40184018
return NULL;
40194019
}
40204020

4021+
/* Returns the skb on success, NULL if dropped, or ERR_PTR(-EINPROGRESS)
4022+
* if stolen by async xfrm crypto (delivered via xfrm_dev_resume()).
4023+
*/
40214024
static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again)
40224025
{
40234026
netdev_features_t features;
@@ -4089,7 +4092,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
40894092
skb->prev = skb;
40904093

40914094
skb = validate_xmit_skb(skb, dev, again);
4092-
if (!skb)
4095+
if (IS_ERR_OR_NULL(skb))
40934096
continue;
40944097

40954098
if (!head)
@@ -4860,8 +4863,11 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)
48604863
goto recursion_alert;
48614864

48624865
skb = validate_xmit_skb(skb, dev, &again);
4863-
if (!skb)
4866+
if (IS_ERR_OR_NULL(skb)) {
4867+
if (PTR_ERR(skb) == -EINPROGRESS)
4868+
rc = NET_XMIT_SUCCESS;
48644869
goto out;
4870+
}
48654871

48664872
HARD_TX_LOCK(dev, txq, cpu);
48674873

net/xfrm/xfrm_device.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
182182
err = x->type_offload->xmit(x, skb, esp_features);
183183
if (err) {
184184
if (err == -EINPROGRESS)
185-
return NULL;
185+
return ERR_PTR(-EINPROGRESS);
186186

187187
XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
188188
kfree_skb(skb);
@@ -224,7 +224,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
224224
pskb = skb2;
225225
}
226226

227-
return skb;
227+
return skb ? skb : ERR_PTR(-EINPROGRESS);
228228
}
229229
EXPORT_SYMBOL_GPL(validate_xmit_xfrm);
230230

0 commit comments

Comments
 (0)