diff options
| author | David Miller <davem@davemloft.net> | 2015-04-05 22:19:04 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-04-07 15:25:55 -0400 |
| commit | 7026b1ddb6b8d4e6ee33dc2bd06c0ca8746fa7ab (patch) | |
| tree | 3e11ed0f186ea6066a3f7efecb88d85bc732ee51 /net/xfrm | |
| parent | 1c984f8a5df085bcf35364a8a870bd4db4da4ed3 (diff) | |
netfilter: Pass socket pointer down through okfn().
On the output paths in particular, we have to sometimes deal with two
socket contexts. First, and usually skb->sk, is the local socket that
generated the frame.
And second, is potentially the socket used to control a tunneling
socket, such as one the encapsulates using UDP.
We do not want to disassociate skb->sk when encapsulating in order
to fix this, because that would break socket memory accounting.
The most extreme case where this can cause huge problems is an
AF_PACKET socket transmitting over a vxlan device. We hit code
paths doing checks that assume they are dealing with an ipv4
socket, but are actually operating upon the AF_PACKET one.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_output.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 7c532856b398..fbcedbe33190 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <net/dst.h> | 19 | #include <net/dst.h> |
| 20 | #include <net/xfrm.h> | 20 | #include <net/xfrm.h> |
| 21 | 21 | ||
| 22 | static int xfrm_output2(struct sk_buff *skb); | 22 | static int xfrm_output2(struct sock *sk, struct sk_buff *skb); |
| 23 | 23 | ||
| 24 | static int xfrm_skb_check_space(struct sk_buff *skb) | 24 | static int xfrm_skb_check_space(struct sk_buff *skb) |
| 25 | { | 25 | { |
| @@ -130,7 +130,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) | |||
| 130 | return dst_output(skb); | 130 | return dst_output(skb); |
| 131 | 131 | ||
| 132 | err = nf_hook(skb_dst(skb)->ops->family, | 132 | err = nf_hook(skb_dst(skb)->ops->family, |
| 133 | NF_INET_POST_ROUTING, skb, | 133 | NF_INET_POST_ROUTING, skb->sk, skb, |
| 134 | NULL, skb_dst(skb)->dev, xfrm_output2); | 134 | NULL, skb_dst(skb)->dev, xfrm_output2); |
| 135 | if (unlikely(err != 1)) | 135 | if (unlikely(err != 1)) |
| 136 | goto out; | 136 | goto out; |
| @@ -144,12 +144,12 @@ out: | |||
| 144 | } | 144 | } |
| 145 | EXPORT_SYMBOL_GPL(xfrm_output_resume); | 145 | EXPORT_SYMBOL_GPL(xfrm_output_resume); |
| 146 | 146 | ||
| 147 | static int xfrm_output2(struct sk_buff *skb) | 147 | static int xfrm_output2(struct sock *sk, struct sk_buff *skb) |
| 148 | { | 148 | { |
| 149 | return xfrm_output_resume(skb, 1); | 149 | return xfrm_output_resume(skb, 1); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static int xfrm_output_gso(struct sk_buff *skb) | 152 | static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb) |
| 153 | { | 153 | { |
| 154 | struct sk_buff *segs; | 154 | struct sk_buff *segs; |
| 155 | 155 | ||
| @@ -165,7 +165,7 @@ static int xfrm_output_gso(struct sk_buff *skb) | |||
| 165 | int err; | 165 | int err; |
| 166 | 166 | ||
| 167 | segs->next = NULL; | 167 | segs->next = NULL; |
| 168 | err = xfrm_output2(segs); | 168 | err = xfrm_output2(sk, segs); |
| 169 | 169 | ||
| 170 | if (unlikely(err)) { | 170 | if (unlikely(err)) { |
| 171 | kfree_skb_list(nskb); | 171 | kfree_skb_list(nskb); |
| @@ -178,13 +178,13 @@ static int xfrm_output_gso(struct sk_buff *skb) | |||
| 178 | return 0; | 178 | return 0; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | int xfrm_output(struct sk_buff *skb) | 181 | int xfrm_output(struct sock *sk, struct sk_buff *skb) |
| 182 | { | 182 | { |
| 183 | struct net *net = dev_net(skb_dst(skb)->dev); | 183 | struct net *net = dev_net(skb_dst(skb)->dev); |
| 184 | int err; | 184 | int err; |
| 185 | 185 | ||
| 186 | if (skb_is_gso(skb)) | 186 | if (skb_is_gso(skb)) |
| 187 | return xfrm_output_gso(skb); | 187 | return xfrm_output_gso(sk, skb); |
| 188 | 188 | ||
| 189 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 189 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 190 | err = skb_checksum_help(skb); | 190 | err = skb_checksum_help(skb); |
| @@ -195,7 +195,7 @@ int xfrm_output(struct sk_buff *skb) | |||
| 195 | } | 195 | } |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | return xfrm_output2(skb); | 198 | return xfrm_output2(sk, skb); |
| 199 | } | 199 | } |
| 200 | EXPORT_SYMBOL_GPL(xfrm_output); | 200 | EXPORT_SYMBOL_GPL(xfrm_output); |
| 201 | 201 | ||
