Skip to content

Commit 7026b1d

Browse files
committed
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 <[email protected]>
1 parent 1c984f8 commit 7026b1d

39 files changed

+277
-218
lines changed

include/linux/netdevice.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,8 +2165,12 @@ int dev_open(struct net_device *dev);
21652165
int dev_close(struct net_device *dev);
21662166
int dev_close_many(struct list_head *head, bool unlink);
21672167
void dev_disable_lro(struct net_device *dev);
2168-
int dev_loopback_xmit(struct sk_buff *newskb);
2169-
int dev_queue_xmit(struct sk_buff *skb);
2168+
int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb);
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+
}
21702174
int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
21712175
int register_netdevice(struct net_device *dev);
21722176
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)
29272931

29282932
int netif_rx(struct sk_buff *skb);
29292933
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+
}
29312939
gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
29322940
void napi_gro_flush(struct napi_struct *napi, bool flush_old);
29332941
struct sk_buff *napi_get_frags(struct napi_struct *napi);

include/linux/netfilter.h

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct nf_hook_state {
5454
struct net_device *in;
5555
struct net_device *out;
5656
struct sock *sk;
57-
int (*okfn)(struct sk_buff *);
57+
int (*okfn)(struct sock *, struct sk_buff *);
5858
};
5959

6060
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,
6363
struct net_device *indev,
6464
struct net_device *outdev,
6565
struct sock *sk,
66-
int (*okfn)(struct sk_buff *))
66+
int (*okfn)(struct sock *, struct sk_buff *))
6767
{
6868
p->hook = hook;
6969
p->thresh = thresh;
@@ -156,26 +156,29 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
156156
* value indicates the packet has been consumed by the hook.
157157
*/
158158
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
159+
struct sock *sk,
159160
struct sk_buff *skb,
160161
struct net_device *indev,
161162
struct net_device *outdev,
162-
int (*okfn)(struct sk_buff *), int thresh)
163+
int (*okfn)(struct sock *, struct sk_buff *),
164+
int thresh)
163165
{
164166
if (nf_hooks_active(pf, hook)) {
165167
struct nf_hook_state state;
166168

167169
nf_hook_state_init(&state, hook, thresh, pf,
168-
indev, outdev, NULL, okfn);
170+
indev, outdev, sk, okfn);
169171
return nf_hook_slow(skb, &state);
170172
}
171173
return 1;
172174
}
173175

174-
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
175-
struct net_device *indev, struct net_device *outdev,
176-
int (*okfn)(struct sk_buff *))
176+
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk,
177+
struct sk_buff *skb, struct net_device *indev,
178+
struct net_device *outdev,
179+
int (*okfn)(struct sock *, struct sk_buff *))
177180
{
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);
179182
}
180183

181184
/* 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,
196199
*/
197200

198201
static inline int
199-
NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb,
200-
struct net_device *in, struct net_device *out,
201-
int (*okfn)(struct sk_buff *), int thresh)
202+
NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk,
203+
struct sk_buff *skb, struct net_device *in,
204+
struct net_device *out,
205+
int (*okfn)(struct sock *, struct sk_buff *), int thresh)
202206
{
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);
204208
if (ret == 1)
205-
ret = okfn(skb);
209+
ret = okfn(sk, skb);
206210
return ret;
207211
}
208212

209213
static inline int
210-
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb,
211-
struct net_device *in, struct net_device *out,
212-
int (*okfn)(struct sk_buff *), bool cond)
214+
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk,
215+
struct sk_buff *skb, struct net_device *in, struct net_device *out,
216+
int (*okfn)(struct sock *, struct sk_buff *), bool cond)
213217
{
214218
int ret;
215219

216220
if (!cond ||
217-
((ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN)) == 1))
218-
ret = okfn(skb);
221+
((ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, INT_MIN)) == 1))
222+
ret = okfn(sk, skb);
219223
return ret;
220224
}
221225

222226
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,
224228
struct net_device *in, struct net_device *out,
225-
int (*okfn)(struct sk_buff *))
229+
int (*okfn)(struct sock *, struct sk_buff *))
226230
{
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);
228232
}
229233

230234
/* Call setsockopt() */
@@ -324,19 +328,21 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
324328
}
325329

326330
#else /* !CONFIG_NETFILTER */
327-
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
328-
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
331+
#define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb)
332+
#define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb)
329333
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
334+
struct sock *sk,
330335
struct sk_buff *skb,
331336
struct net_device *indev,
332337
struct net_device *outdev,
333-
int (*okfn)(struct sk_buff *), int thresh)
338+
int (*okfn)(struct sock *sk, struct sk_buff *), int thresh)
334339
{
335-
return okfn(skb);
340+
return okfn(sk, skb);
336341
}
337-
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
338-
struct net_device *indev, struct net_device *outdev,
339-
int (*okfn)(struct sk_buff *))
342+
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk,
343+
struct sk_buff *skb, struct net_device *indev,
344+
struct net_device *outdev,
345+
int (*okfn)(struct sock *, struct sk_buff *))
340346
{
341347
return 1;
342348
}

include/linux/netfilter_bridge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
3030
return 0;
3131
}
3232

33-
int br_handle_frame_finish(struct sk_buff *skb);
33+
int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb);
3434

3535
static inline void br_drop_fake_rtable(struct sk_buff *skb)
3636
{

include/net/dn_neigh.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ struct dn_neigh {
1818

1919
void dn_neigh_init(void);
2020
void dn_neigh_cleanup(void);
21-
int dn_neigh_router_hello(struct sk_buff *skb);
22-
int dn_neigh_endnode_hello(struct sk_buff *skb);
21+
int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb);
22+
int dn_neigh_endnode_hello(struct sock *sk, struct sk_buff *skb);
2323
void dn_neigh_pointopoint_hello(struct sk_buff *skb);
2424
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
25-
int dn_to_neigh_output(struct sk_buff *skb);
25+
int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb);
2626

2727
extern struct neigh_table dn_neigh_table;
2828

include/net/ip.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ int ip_local_deliver(struct sk_buff *skb);
108108
int ip_mr_input(struct sk_buff *skb);
109109
int ip_output(struct sock *sk, struct sk_buff *skb);
110110
int ip_mc_output(struct sock *sk, struct sk_buff *skb);
111-
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
111+
int ip_fragment(struct sock *sk, struct sk_buff *skb,
112+
int (*output)(struct sock *, struct sk_buff *));
112113
int ip_do_nat(struct sk_buff *skb);
113114
void ip_send_check(struct iphdr *ip);
114115
int __ip_local_out(struct sk_buff *skb);

include/net/ip6_route.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
170170
return rt->rt6i_flags & RTF_ANYCAST;
171171
}
172172

173-
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
173+
int ip6_fragment(struct sock *sk, struct sk_buff *skb,
174+
int (*output)(struct sock *, struct sk_buff *));
174175

175176
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
176177
{

include/net/ipv6.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ static inline u8 ip6_tclass(__be32 flowinfo)
769769
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev,
770770
struct packet_type *pt, struct net_device *orig_dev);
771771

772-
int ip6_rcv_finish(struct sk_buff *skb);
772+
int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb);
773773

774774
/*
775775
* upper-layer output functions

include/net/xfrm.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ struct xfrm_state_afinfo {
332332
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
333333
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
334334
int (*output)(struct sock *sk, struct sk_buff *skb);
335-
int (*output_finish)(struct sk_buff *skb);
335+
int (*output_finish)(struct sock *sk, struct sk_buff *skb);
336336
int (*extract_input)(struct xfrm_state *x,
337337
struct sk_buff *skb);
338338
int (*extract_output)(struct xfrm_state *x,
@@ -1503,7 +1503,7 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
15031503
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
15041504
int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
15051505
int xfrm_output_resume(struct sk_buff *skb, int err);
1506-
int xfrm_output(struct sk_buff *skb);
1506+
int xfrm_output(struct sock *sk, struct sk_buff *skb);
15071507
int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
15081508
void xfrm_local_error(struct sk_buff *skb, int mtu);
15091509
int xfrm4_extract_header(struct sk_buff *skb);
@@ -1524,7 +1524,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
15241524
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
15251525
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
15261526
int xfrm4_output(struct sock *sk, struct sk_buff *skb);
1527-
int xfrm4_output_finish(struct sk_buff *skb);
1527+
int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb);
15281528
int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
15291529
int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
15301530
int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char protocol);
@@ -1549,7 +1549,7 @@ __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
15491549
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
15501550
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
15511551
int xfrm6_output(struct sock *sk, struct sk_buff *skb);
1552-
int xfrm6_output_finish(struct sk_buff *skb);
1552+
int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb);
15531553
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
15541554
u8 **prevhdr);
15551555

net/bridge/br_forward.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
3535
p->state == BR_STATE_FORWARDING;
3636
}
3737

38-
int br_dev_queue_push_xmit(struct sk_buff *skb)
38+
int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb)
3939
{
4040
if (!is_skb_forwardable(skb->dev, skb)) {
4141
kfree_skb(skb);
@@ -49,9 +49,10 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
4949
}
5050
EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
5151

52-
int br_forward_finish(struct sk_buff *skb)
52+
int br_forward_finish(struct sock *sk, struct sk_buff *skb)
5353
{
54-
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
54+
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, sk, skb,
55+
NULL, skb->dev,
5556
br_dev_queue_push_xmit);
5657

5758
}
@@ -75,7 +76,8 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
7576
return;
7677
}
7778

78-
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
79+
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, NULL, skb,
80+
NULL, skb->dev,
7981
br_forward_finish);
8082
}
8183

@@ -96,7 +98,8 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
9698
skb->dev = to->dev;
9799
skb_forward_csum(skb);
98100

99-
NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
101+
NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, NULL, skb,
102+
indev, skb->dev,
100103
br_forward_finish);
101104
}
102105

net/bridge/br_input.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ static int br_pass_frame_up(struct sk_buff *skb)
5555
if (!skb)
5656
return NET_RX_DROP;
5757

58-
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
59-
netif_receive_skb);
58+
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb,
59+
indev, NULL,
60+
netif_receive_skb_sk);
6061
}
6162

6263
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
@@ -119,7 +120,7 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
119120
}
120121

121122
/* note: already called with rcu_read_lock */
122-
int br_handle_frame_finish(struct sk_buff *skb)
123+
int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb)
123124
{
124125
const unsigned char *dest = eth_hdr(skb)->h_dest;
125126
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
@@ -207,7 +208,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
207208
EXPORT_SYMBOL_GPL(br_handle_frame_finish);
208209

209210
/* note: already called with rcu_read_lock */
210-
static int br_handle_local_finish(struct sk_buff *skb)
211+
static int br_handle_local_finish(struct sock *sk, struct sk_buff *skb)
211212
{
212213
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
213214
u16 vid = 0;
@@ -277,8 +278,8 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
277278
}
278279

279280
/* Deliver packet to local host only */
280-
if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
281-
NULL, br_handle_local_finish)) {
281+
if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb,
282+
skb->dev, NULL, br_handle_local_finish)) {
282283
return RX_HANDLER_CONSUMED; /* consumed by filter */
283284
} else {
284285
*pskb = skb;
@@ -302,7 +303,8 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
302303
if (ether_addr_equal(p->br->dev->dev_addr, dest))
303304
skb->pkt_type = PACKET_HOST;
304305

305-
NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
306+
NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, NULL, skb,
307+
skb->dev, NULL,
306308
br_handle_frame_finish);
307309
break;
308310
default:

net/bridge/br_multicast.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,8 @@ static void __br_multicast_send_query(struct net_bridge *br,
814814

815815
if (port) {
816816
skb->dev = port->dev;
817-
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
817+
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, NULL, skb,
818+
NULL, skb->dev,
818819
br_dev_queue_push_xmit);
819820
} else {
820821
br_multicast_select_own_querier(br, ip, skb);

0 commit comments

Comments
 (0)