Commit 7b380192 authored by Sabrina Dubroca's avatar Sabrina Dubroca Committed by Steffen Klassert

xfrm: introduce xfrm_trans_queue_net

This will be used by TCP encapsulation to write packets to the encap
socket without holding the user socket's lock. Without this reinjection,
we're already holding the lock of the user socket, and then try to lock
the encap socket as well when we enqueue the encrypted packet.

While at it, add a BUILD_BUG_ON like we usually do for skb->cb, since
it's missing for struct xfrm_trans_cb.
Co-developed-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent b50b0580
...@@ -1547,6 +1547,9 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); ...@@ -1547,6 +1547,9 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
int xfrm_init_state(struct xfrm_state *x); int xfrm_init_state(struct xfrm_state *x);
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type); int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
int xfrm_input_resume(struct sk_buff *skb, int nexthdr); int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
int (*finish)(struct net *, struct sock *,
struct sk_buff *));
int xfrm_trans_queue(struct sk_buff *skb, int xfrm_trans_queue(struct sk_buff *skb,
int (*finish)(struct net *, struct sock *, int (*finish)(struct net *, struct sock *,
struct sk_buff *)); struct sk_buff *));
......
...@@ -36,6 +36,7 @@ struct xfrm_trans_cb { ...@@ -36,6 +36,7 @@ struct xfrm_trans_cb {
#endif #endif
} header; } header;
int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb); int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb);
struct net *net;
}; };
#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0])) #define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
...@@ -766,10 +767,11 @@ static void xfrm_trans_reinject(unsigned long data) ...@@ -766,10 +767,11 @@ static void xfrm_trans_reinject(unsigned long data)
skb_queue_splice_init(&trans->queue, &queue); skb_queue_splice_init(&trans->queue, &queue);
while ((skb = __skb_dequeue(&queue))) while ((skb = __skb_dequeue(&queue)))
XFRM_TRANS_SKB_CB(skb)->finish(dev_net(skb->dev), NULL, skb); XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net,
NULL, skb);
} }
int xfrm_trans_queue(struct sk_buff *skb, int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
int (*finish)(struct net *, struct sock *, int (*finish)(struct net *, struct sock *,
struct sk_buff *)) struct sk_buff *))
{ {
...@@ -780,11 +782,22 @@ int xfrm_trans_queue(struct sk_buff *skb, ...@@ -780,11 +782,22 @@ int xfrm_trans_queue(struct sk_buff *skb,
if (skb_queue_len(&trans->queue) >= netdev_max_backlog) if (skb_queue_len(&trans->queue) >= netdev_max_backlog)
return -ENOBUFS; return -ENOBUFS;
BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb));
XFRM_TRANS_SKB_CB(skb)->finish = finish; XFRM_TRANS_SKB_CB(skb)->finish = finish;
XFRM_TRANS_SKB_CB(skb)->net = net;
__skb_queue_tail(&trans->queue, skb); __skb_queue_tail(&trans->queue, skb);
tasklet_schedule(&trans->tasklet); tasklet_schedule(&trans->tasklet);
return 0; return 0;
} }
EXPORT_SYMBOL(xfrm_trans_queue_net);
int xfrm_trans_queue(struct sk_buff *skb,
int (*finish)(struct net *, struct sock *,
struct sk_buff *))
{
return xfrm_trans_queue_net(dev_net(skb->dev), skb, finish);
}
EXPORT_SYMBOL(xfrm_trans_queue); EXPORT_SYMBOL(xfrm_trans_queue);
void __init xfrm_input_init(void) void __init xfrm_input_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment