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 /include/linux | |
| 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 'include/linux')
| -rw-r--r-- | include/linux/netdevice.h | 14 | ||||
| -rw-r--r-- | include/linux/netfilter.h | 62 | ||||
| -rw-r--r-- | include/linux/netfilter_bridge.h | 2 |
3 files changed, 46 insertions, 32 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); | |||
| 2165 | int dev_close(struct net_device *dev); | 2165 | int dev_close(struct net_device *dev); |
| 2166 | int dev_close_many(struct list_head *head, bool unlink); | 2166 | int dev_close_many(struct list_head *head, bool unlink); |
| 2167 | void dev_disable_lro(struct net_device *dev); | 2167 | void dev_disable_lro(struct net_device *dev); |
| 2168 | int dev_loopback_xmit(struct sk_buff *newskb); | 2168 | int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb); |
| 2169 | int dev_queue_xmit(struct sk_buff *skb); | 2169 | int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb); |
| 2170 | static inline int dev_queue_xmit(struct sk_buff *skb) | ||
| 2171 | { | ||
| 2172 | return dev_queue_xmit_sk(skb->sk, skb); | ||
| 2173 | } | ||
| 2170 | int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv); | 2174 | int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv); |
| 2171 | int register_netdevice(struct net_device *dev); | 2175 | int register_netdevice(struct net_device *dev); |
| 2172 | void unregister_netdevice_queue(struct net_device *dev, struct list_head *head); | 2176 | void 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 | ||
| 2928 | int netif_rx(struct sk_buff *skb); | 2932 | int netif_rx(struct sk_buff *skb); |
| 2929 | int netif_rx_ni(struct sk_buff *skb); | 2933 | int netif_rx_ni(struct sk_buff *skb); |
| 2930 | int netif_receive_skb(struct sk_buff *skb); | 2934 | int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb); |
| 2935 | static inline int netif_receive_skb(struct sk_buff *skb) | ||
| 2936 | { | ||
| 2937 | return netif_receive_skb_sk(skb->sk, skb); | ||
| 2938 | } | ||
| 2931 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); | 2939 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); |
| 2932 | void napi_gro_flush(struct napi_struct *napi, bool flush_old); | 2940 | void napi_gro_flush(struct napi_struct *napi, bool flush_old); |
| 2933 | struct sk_buff *napi_get_frags(struct napi_struct *napi); | 2941 | struct 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 | ||
| 60 | static inline void nf_hook_state_init(struct nf_hook_state *p, | 60 | static 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 | */ |
| 158 | static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, | 158 | static 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 | ||
| 174 | static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, | 176 | static 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 | ||
| 198 | static inline int | 201 | static inline int |
| 199 | NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb, | 202 | NF_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 | ||
| 209 | static inline int | 213 | static inline int |
| 210 | NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb, | 214 | NF_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) | 216 | int (*okfn)(struct sock *, struct sk_buff *), bool cond) |
| 213 | { | 217 | { |
| 214 | int ret; | 218 | int ret; |
| 215 | 219 | ||
| 216 | if (!cond || | 220 | if (!cond || |
| 217 | ((ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN)) == 1)) | 221 | ((ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, INT_MIN)) == 1)) |
| 218 | ret = okfn(skb); | 222 | ret = okfn(sk, skb); |
| 219 | return ret; | 223 | return ret; |
| 220 | } | 224 | } |
| 221 | 225 | ||
| 222 | static inline int | 226 | static inline int |
| 223 | NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb, | 227 | NF_HOOK(uint8_t pf, unsigned int hook, struct sock *sk, struct sk_buff *skb, |
| 224 | struct net_device *in, struct net_device *out, | 228 | struct net_device *in, struct net_device *out, |
| 225 | int (*okfn)(struct sk_buff *)) | 229 | int (*okfn)(struct sock *, struct sk_buff *)) |
| 226 | { | 230 | { |
| 227 | return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN); | 231 | return NF_HOOK_THRESH(pf, hook, sk, skb, in, out, okfn, INT_MIN); |
| 228 | } | 232 | } |
| 229 | 233 | ||
| 230 | /* Call setsockopt() */ | 234 | /* Call setsockopt() */ |
| @@ -324,19 +328,21 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) | |||
| 324 | } | 328 | } |
| 325 | 329 | ||
| 326 | #else /* !CONFIG_NETFILTER */ | 330 | #else /* !CONFIG_NETFILTER */ |
| 327 | #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) | 331 | #define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb) |
| 328 | #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) | 332 | #define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb) |
| 329 | static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, | 333 | static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, |
| 334 | struct sock *sk, | ||
| 330 | struct sk_buff *skb, | 335 | struct sk_buff *skb, |
| 331 | struct net_device *indev, | 336 | struct net_device *indev, |
| 332 | struct net_device *outdev, | 337 | struct net_device *outdev, |
| 333 | int (*okfn)(struct sk_buff *), int thresh) | 338 | int (*okfn)(struct sock *sk, struct sk_buff *), int thresh) |
| 334 | { | 339 | { |
| 335 | return okfn(skb); | 340 | return okfn(sk, skb); |
| 336 | } | 341 | } |
| 337 | static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, | 342 | static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, |
| 338 | struct net_device *indev, struct net_device *outdev, | 343 | struct sk_buff *skb, struct net_device *indev, |
| 339 | int (*okfn)(struct sk_buff *)) | 344 | struct net_device *outdev, |
| 345 | int (*okfn)(struct sock *, struct sk_buff *)) | ||
| 340 | { | 346 | { |
| 341 | return 1; | 347 | return 1; |
| 342 | } | 348 | } |
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 2734977199ca..5fc0a0fe244b 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h | |||
| @@ -30,7 +30,7 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) | |||
| 30 | return 0; | 30 | return 0; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | int br_handle_frame_finish(struct sk_buff *skb); | 33 | int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb); |
| 34 | 34 | ||
| 35 | static inline void br_drop_fake_rtable(struct sk_buff *skb) | 35 | static inline void br_drop_fake_rtable(struct sk_buff *skb) |
| 36 | { | 36 | { |
