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/xfrm_output.c | |
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/xfrm_output.c')
-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 | ||