aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2015-04-05 22:19:04 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-07 15:25:55 -0400
commit7026b1ddb6b8d4e6ee33dc2bd06c0ca8746fa7ab (patch)
tree3e11ed0f186ea6066a3f7efecb88d85bc732ee51
parent1c984f8a5df085bcf35364a8a870bd4db4da4ed3 (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>
-rw-r--r--include/linux/netdevice.h14
-rw-r--r--include/linux/netfilter.h62
-rw-r--r--include/linux/netfilter_bridge.h2
-rw-r--r--include/net/dn_neigh.h6
-rw-r--r--include/net/ip.h3
-rw-r--r--include/net/ip6_route.h3
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/xfrm.h8
-rw-r--r--net/bridge/br_forward.c13
-rw-r--r--net/bridge/br_input.c16
-rw-r--r--net/bridge/br_multicast.c3
-rw-r--r--net/bridge/br_netfilter.c56
-rw-r--r--net/bridge/br_private.h6
-rw-r--r--net/bridge/br_stp_bpdu.c5
-rw-r--r--net/core/dev.c10
-rw-r--r--net/decnet/dn_neigh.c35
-rw-r--r--net/decnet/dn_nsp_in.c5
-rw-r--r--net/decnet/dn_route.c26
-rw-r--r--net/ipv4/arp.c10
-rw-r--r--net/ipv4/ip_forward.c8
-rw-r--r--net/ipv4/ip_input.c10
-rw-r--r--net/ipv4/ip_output.c45
-rw-r--r--net/ipv4/ipmr.c7
-rw-r--r--net/ipv4/raw.c4
-rw-r--r--net/ipv4/xfrm4_input.c5
-rw-r--r--net/ipv4/xfrm4_output.c12
-rw-r--r--net/ipv6/ip6_input.c11
-rw-r--r--net/ipv6/ip6_output.c33
-rw-r--r--net/ipv6/ip6mr.c7
-rw-r--r--net/ipv6/mcast.c9
-rw-r--r--net/ipv6/ndisc.c5
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c2
-rw-r--r--net/ipv6/output_core.c4
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/xfrm6_input.c3
-rw-r--r--net/ipv6/xfrm6_output.c15
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c8
-rw-r--r--net/netfilter/nf_queue.c2
-rw-r--r--net/xfrm/xfrm_output.c16
39 files changed, 277 insertions, 218 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 41bf58a2b936..45823db2efb0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2165,8 +2165,12 @@ int dev_open(struct net_device *dev);
2165int dev_close(struct net_device *dev); 2165int dev_close(struct net_device *dev);
2166int dev_close_many(struct list_head *head, bool unlink); 2166int dev_close_many(struct list_head *head, bool unlink);
2167void dev_disable_lro(struct net_device *dev); 2167void dev_disable_lro(struct net_device *dev);
2168int dev_loopback_xmit(struct sk_buff *newskb); 2168int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb);
2169int dev_queue_xmit(struct sk_buff *skb); 2169int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb);
2170static inline int dev_queue_xmit(struct sk_buff *skb)
2171{
2172 return dev_queue_xmit_sk(skb->sk, skb);
2173}
2170int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv); 2174int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
2171int register_netdevice(struct net_device *dev); 2175int register_netdevice(struct net_device *dev);
2172void unregister_netdevice_queue(struct net_device *dev, struct list_head *head); 2176void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
@@ -2927,7 +2931,11 @@ static inline void dev_consume_skb_any(struct sk_buff *skb)
2927 2931
2928int netif_rx(struct sk_buff *skb); 2932int netif_rx(struct sk_buff *skb);
2929int netif_rx_ni(struct sk_buff *skb); 2933int netif_rx_ni(struct sk_buff *skb);
2930int netif_receive_skb(struct sk_buff *skb); 2934int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb);
2935static inline int netif_receive_skb(struct sk_buff *skb)
2936{
2937 return netif_receive_skb_sk(skb->sk, skb);
2938}
2931gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); 2939gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
2932void napi_gro_flush(struct napi_struct *napi, bool flush_old); 2940void napi_gro_flush(struct napi_struct *napi, bool flush_old);
2933struct sk_buff *napi_get_frags(struct napi_struct *napi); 2941struct sk_buff *napi_get_frags(struct napi_struct *napi);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index f8f58fab2402..63560d0a8dfe 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -54,7 +54,7 @@ struct nf_hook_state {
54 struct net_device *in; 54 struct net_device *in;
55 struct net_device *out; 55 struct net_device *out;
56 struct sock *sk; 56 struct sock *sk;
57 int (*okfn)(struct sk_buff *); 57 int (*okfn)(struct sock *, struct sk_buff *);
58}; 58};
59 59
60static inline void nf_hook_state_init(struct nf_hook_state *p, 60static inline void nf_hook_state_init(struct nf_hook_state *p,
@@ -63,7 +63,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
63 struct net_device *indev, 63 struct net_device *indev,
64 struct net_device *outdev, 64 struct net_device *outdev,
65 struct sock *sk, 65 struct sock *sk,
66 int (*okfn)(struct sk_buff *)) 66 int (*okfn)(struct sock *, struct sk_buff *))
67{ 67{
68 p->hook = hook; 68 p->hook = hook;
69 p->thresh = thresh; 69 p->thresh = thresh;
@@ -156,26 +156,29 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
156 * value indicates the packet has been consumed by the hook. 156 * value indicates the packet has been consumed by the hook.
157 */ 157 */
158static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, 158static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
159 struct sock *sk,
159 struct sk_buff *skb, 160 struct sk_buff *skb,
160 struct net_device *indev, 161 struct net_device *indev,
161 struct net_device *outdev, 162 struct net_device *outdev,
162 int (*okfn)(struct sk_buff *), int thresh) 163 int (*okfn)(struct sock *, struct sk_buff *),
164 int thresh)
163{ 165{
164 if (nf_hooks_active(pf, hook)) { 166 if (nf_hooks_active(pf, hook)) {
165 struct nf_hook_state state; 167 struct nf_hook_state state;
166 168
167 nf_hook_state_init(&state, hook, thresh, pf, 169 nf_hook_state_init(&state, hook, thresh, pf,
168 indev, outdev, NULL, okfn); 170 indev, outdev, sk, okfn);
169 return nf_hook_slow(skb, &state); 171 return nf_hook_slow(skb, &state);
170 } 172 }
171 return 1; 173 return 1;
172} 174}
173 175
174static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, 176static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk,
175 struct net_device *indev, struct net_device *outdev, 177 struct sk_buff *skb, struct net_device *indev,
176 int (*okfn)(struct sk_buff *)) 178 struct net_device *outdev,
179 int (*okfn)(struct sock *, struct sk_buff *))
177{ 180{
178 return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN); 181 return nf_hook_thresh(pf, hook, sk, skb, indev, outdev, okfn, INT_MIN);
179} 182}
180 183
181/* Activate hook; either okfn or kfree_skb called, unless a hook 184/* Activate hook; either okfn or kfree_skb called, unless a hook
@@ -196,35 +199,36 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
196*/ 199*/
197 200
198static inline int 201static inline int
199NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb, 202NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk,
200 struct net_device *in, struct net_device *out, 203 struct sk_buff *skb, struct net_device *in,
201 int (*okfn)(struct sk_buff *), int thresh) 204 struct net_device *out,
205 int (*okfn)(struct sock *, struct sk_buff *), int thresh)
202{ 206{
203 int ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, thresh); 207 int ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, thresh);
204 if (ret == 1) 208 if (ret == 1)
205 ret = okfn(skb); 209 ret = okfn(sk, skb);
206 return ret; 210 return ret;
207} 211}
208 212
209static inline int 213static inline int
210NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb, 214NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk,
211 struct net_device *in, struct net_device *out, 215 struct sk_buff *skb, struct net_device *in, struct net_device *out,
212 int (*okfn)(struct sk_buff *), bool cond)