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/decnet | |
| 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/decnet')
| -rw-r--r-- | net/decnet/dn_neigh.c | 35 | ||||
| -rw-r--r-- | net/decnet/dn_nsp_in.c | 5 | ||||
| -rw-r--r-- | net/decnet/dn_route.c | 26 |
3 files changed, 37 insertions, 29 deletions
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index be1f08cdad29..4507b188fc51 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
| @@ -194,7 +194,7 @@ static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 194 | return err; | 194 | return err; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static int dn_neigh_output_packet(struct sk_buff *skb) | 197 | static int dn_neigh_output_packet(struct sock *sk, struct sk_buff *skb) |
| 198 | { | 198 | { |
| 199 | struct dst_entry *dst = skb_dst(skb); | 199 | struct dst_entry *dst = skb_dst(skb); |
| 200 | struct dn_route *rt = (struct dn_route *)dst; | 200 | struct dn_route *rt = (struct dn_route *)dst; |
| @@ -206,7 +206,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb) | |||
| 206 | /* | 206 | /* |
| 207 | * For talking to broadcast devices: Ethernet & PPP | 207 | * For talking to broadcast devices: Ethernet & PPP |
| 208 | */ | 208 | */ |
| 209 | static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) | 209 | static int dn_long_output(struct neighbour *neigh, struct sock *sk, |
| 210 | struct sk_buff *skb) | ||
| 210 | { | 211 | { |
| 211 | struct net_device *dev = neigh->dev; | 212 | struct net_device *dev = neigh->dev; |
| 212 | int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; | 213 | int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; |
| @@ -245,14 +246,15 @@ static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 245 | 246 | ||
| 246 | skb_reset_network_header(skb); | 247 | skb_reset_network_header(skb); |
| 247 | 248 | ||
| 248 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, | 249 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, |
| 249 | neigh->dev, dn_neigh_output_packet); | 250 | NULL, neigh->dev, dn_neigh_output_packet); |
| 250 | } | 251 | } |
| 251 | 252 | ||
| 252 | /* | 253 | /* |
| 253 | * For talking to pointopoint and multidrop devices: DDCMP and X.25 | 254 | * For talking to pointopoint and multidrop devices: DDCMP and X.25 |
| 254 | */ | 255 | */ |
| 255 | static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) | 256 | static int dn_short_output(struct neighbour *neigh, struct sock *sk, |
| 257 | struct sk_buff *skb) | ||
| 256 | { | 258 | { |
| 257 | struct net_device *dev = neigh->dev; | 259 | struct net_device *dev = neigh->dev; |
| 258 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; | 260 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; |
| @@ -284,8 +286,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 284 | 286 | ||
| 285 | skb_reset_network_header(skb); | 287 | skb_reset_network_header(skb); |
| 286 | 288 | ||
| 287 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, | 289 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, |
| 288 | neigh->dev, dn_neigh_output_packet); | 290 | NULL, neigh->dev, dn_neigh_output_packet); |
| 289 | } | 291 | } |
| 290 | 292 | ||
| 291 | /* | 293 | /* |
| @@ -293,7 +295,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 293 | * Phase 3 output is the same as short output, execpt that | 295 | * Phase 3 output is the same as short output, execpt that |
| 294 | * it clears the area bits before transmission. | 296 | * it clears the area bits before transmission. |
| 295 | */ | 297 | */ |
| 296 | static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) | 298 | static int dn_phase3_output(struct neighbour *neigh, struct sock *sk, |
| 299 | struct sk_buff *skb) | ||
| 297 | { | 300 | { |
| 298 | struct net_device *dev = neigh->dev; | 301 | struct net_device *dev = neigh->dev; |
| 299 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; | 302 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; |
| @@ -324,11 +327,11 @@ static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 324 | 327 | ||
| 325 | skb_reset_network_header(skb); | 328 | skb_reset_network_header(skb); |
| 326 | 329 | ||
| 327 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, | 330 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, |
| 328 | neigh->dev, dn_neigh_output_packet); | 331 | NULL, neigh->dev, dn_neigh_output_packet); |
| 329 | } | 332 | } |
| 330 | 333 | ||
| 331 | int dn_to_neigh_output(struct sk_buff *skb) | 334 | int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb) |
| 332 | { | 335 | { |
| 333 | struct dst_entry *dst = skb_dst(skb); | 336 | struct dst_entry *dst = skb_dst(skb); |
| 334 | struct dn_route *rt = (struct dn_route *) dst; | 337 | struct dn_route *rt = (struct dn_route *) dst; |
| @@ -347,11 +350,11 @@ int dn_to_neigh_output(struct sk_buff *skb) | |||
| 347 | rcu_read_unlock(); | 350 | rcu_read_unlock(); |
| 348 | 351 | ||
| 349 | if (dn->flags & DN_NDFLAG_P3) | 352 | if (dn->flags & DN_NDFLAG_P3) |
| 350 | return dn_phase3_output(neigh, skb); | 353 | return dn_phase3_output(neigh, sk, skb); |
| 351 | if (use_long) | 354 | if (use_long) |
| 352 | return dn_long_output(neigh, skb); | 355 | return dn_long_output(neigh, sk, skb); |
| 353 | else | 356 | else |
| 354 | return dn_short_output(neigh, skb); | 357 | return dn_short_output(neigh, sk, skb); |
| 355 | } | 358 | } |
| 356 | 359 | ||
| 357 | /* | 360 | /* |
| @@ -372,7 +375,7 @@ void dn_neigh_pointopoint_hello(struct sk_buff *skb) | |||
| 372 | /* | 375 | /* |
| 373 | * Ethernet router hello message received | 376 | * Ethernet router hello message received |
| 374 | */ | 377 | */ |
| 375 | int dn_neigh_router_hello(struct sk_buff *skb) | 378 | int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb) |
| 376 | { | 379 | { |
| 377 | struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data; | 380 | struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data; |
| 378 | 381 | ||
| @@ -434,7 +437,7 @@ int dn_neigh_router_hello(struct sk_buff *skb) | |||
| 434 | /* | 437 | /* |
| 435 | * Endnode hello message received | 438 | * Endnode hello message received |
| 436 | */ | 439 | */ |
| 437 | int dn_neigh_endnode_hello(struct sk_buff *skb) | 440 | int dn_neigh_endnode_hello(struct sock *sk, struct sk_buff *skb) |
| 438 | { | 441 | { |
| 439 | struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; | 442 | struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; |
| 440 | struct neighbour *neigh; | 443 | struct neighbour *neigh; |
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index fe5f01485d33..a321eac9fd0c 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c | |||
| @@ -714,7 +714,7 @@ out: | |||
| 714 | return ret; | 714 | return ret; |
| 715 | } | 715 | } |
| 716 | 716 | ||
| 717 | static int dn_nsp_rx_packet(struct sk_buff *skb) | 717 | static int dn_nsp_rx_packet(struct sock *sk2, struct sk_buff *skb) |
| 718 | { | 718 | { |
| 719 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | 719 | struct dn_skb_cb *cb = DN_SKB_CB(skb); |
| 720 | struct sock *sk = NULL; | 720 | struct sock *sk = NULL; |
| @@ -814,7 +814,8 @@ free_out: | |||
| 814 | 814 | ||
| 815 | int dn_nsp_rx(struct sk_buff *skb) | 815 | int dn_nsp_rx(struct sk_buff *skb) |
| 816 | { | 816 | { |
| 817 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN, skb, skb->dev, NULL, | 817 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN, NULL, skb, |
| 818 | skb->dev, NULL, | ||
| 818 | dn_nsp_rx_packet); | 819 | dn_nsp_rx_packet); |
| 819 | } | 820 | } |
| 820 | 821 | ||
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 9ab0c4ba297f..03227ffd19ce 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
| @@ -512,7 +512,7 @@ static int dn_return_long(struct sk_buff *skb) | |||
| 512 | * | 512 | * |
| 513 | * Returns: result of input function if route is found, error code otherwise | 513 | * Returns: result of input function if route is found, error code otherwise |
| 514 | */ | 514 | */ |
| 515 | static int dn_route_rx_packet(struct sk_buff *skb) | 515 | static int dn_route_rx_packet(struct sock *sk, struct sk_buff *skb) |
| 516 | { | 516 | { |
| 517 | struct dn_skb_cb *cb; | 517 | struct dn_skb_cb *cb; |
| 518 | int err; | 518 | int err; |
| @@ -573,7 +573,8 @@ static int dn_route_rx_long(struct sk_buff *skb) | |||
| 573 | ptr++; | 573 | ptr++; |
| 574 | cb->hops = *ptr++; /* Visit Count */ | 574 | cb->hops = *ptr++; /* Visit Count */ |
| 575 | 575 | ||
| 576 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, | 576 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, NULL, skb, |
| 577 | skb->dev, NULL, | ||
| 577 | dn_route_rx_packet); | 578 | dn_route_rx_packet); |
| 578 | 579 | ||
| 579 | drop_it: | 580 | drop_it: |
| @@ -600,7 +601,8 @@ static int dn_route_rx_short(struct sk_buff *skb) | |||
| 600 | ptr += 2; | 601 | ptr += 2; |
| 601 | cb->hops = *ptr & 0x3f; | 602 | cb->hops = *ptr & 0x3f; |
| 602 | 603 | ||
| 603 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, | 604 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, NULL, skb, |
| 605 | skb->dev, NULL, | ||
| 604 | dn_route_rx_packet); | 606 | dn_route_rx_packet); |
| 605 | 607 | ||
| 606 | drop_it: | 608 | drop_it: |
| @@ -608,7 +610,7 @@ drop_it: | |||
| 608 | return NET_RX_DROP; | 610 | return NET_RX_DROP; |
| 609 | } | 611 | } |
| 610 | 612 | ||
| 611 | static int dn_route_discard(struct sk_buff *skb) | 613 | static int dn_route_discard(struct sock *sk, struct sk_buff *skb) |
| 612 | { | 614 | { |
| 613 | /* | 615 | /* |
| 614 | * I know we drop the packet here, but thats considered success in | 616 | * I know we drop the packet here, but thats considered success in |
| @@ -618,7 +620,7 @@ static int dn_route_discard(struct sk_buff *skb) | |||
| 618 | return NET_RX_SUCCESS; | 620 | return NET_RX_SUCCESS; |
| 619 | } | 621 | } |
| 620 | 622 | ||
| 621 | static int dn_route_ptp_hello(struct sk_buff *skb) | 623 | static int dn_route_ptp_hello(struct sock *sk, struct sk_buff *skb) |
| 622 | { | 624 | { |
| 623 | dn_dev_hello(skb); | 625 | dn_dev_hello(skb); |
| 624 | dn_neigh_pointopoint_hello(skb); | 626 | dn_neigh_pointopoint_hello(skb); |
| @@ -704,22 +706,22 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type | |||
| 704 | switch (flags & DN_RT_CNTL_MSK) { | 706 | switch (flags & DN_RT_CNTL_MSK) { |
| 705 | case DN_RT_PKT_HELO: | 707 | case DN_RT_PKT_HELO: |
| 706 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, | 708 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
| 707 | skb, skb->dev, NULL, | 709 | NULL, skb, skb->dev, NULL, |
| 708 | dn_route_ptp_hello); | 710 | dn_route_ptp_hello); |
| 709 | 711 | ||
| 710 | case DN_RT_PKT_L1RT: | 712 | case DN_RT_PKT_L1RT: |
| 711 | case DN_RT_PKT_L2RT: | 713 | case DN_RT_PKT_L2RT: |
| 712 | return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE, | 714 | return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE, |
| 713 | skb, skb->dev, NULL, | 715 | NULL, skb, skb->dev, NULL, |
| 714 | dn_route_discard); | 716 | dn_route_discard); |
| 715 | case DN_RT_PKT_ERTH: | 717 | case DN_RT_PKT_ERTH: |
| 716 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, | 718 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
| 717 | skb, skb->dev, NULL, | 719 | NULL, skb, skb->dev, NULL, |
| 718 | dn_neigh_router_hello); | 720 | dn_neigh_router_hello); |
| 719 | 721 | ||
| 720 | case DN_RT_PKT_EEDH: | 722 | case DN_RT_PKT_EEDH: |
| 721 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, | 723 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
| 722 | skb, skb->dev, NULL, | 724 | NULL, skb, skb->dev, NULL, |
| 723 | dn_neigh_endnode_hello); | 725 | dn_neigh_endnode_hello); |
| 724 | } | 726 | } |
| 725 | } else { | 727 | } else { |
| @@ -768,7 +770,8 @@ static int dn_output(struct sock *sk, struct sk_buff *skb) | |||
| 768 | cb->rt_flags |= DN_RT_F_IE; | 770 | cb->rt_flags |= DN_RT_F_IE; |
| 769 | cb->hops = 0; | 771 | cb->hops = 0; |
| 770 | 772 | ||
| 771 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev, | 773 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, sk, skb, |
| 774 | NULL, dev, | ||
| 772 | dn_to_neigh_output); | 775 | dn_to_neigh_output); |
| 773 | 776 | ||
| 774 | error: | 777 | error: |
| @@ -816,7 +819,8 @@ static int dn_forward(struct sk_buff *skb) | |||
| 816 | if (rt->rt_flags & RTCF_DOREDIRECT) | 819 | if (rt->rt_flags & RTCF_DOREDIRECT) |
| 817 | cb->rt_flags |= DN_RT_F_IE; | 820 | cb->rt_flags |= DN_RT_F_IE; |
| 818 | 821 | ||
| 819 | return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev, | 822 | return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, NULL, skb, |
| 823 | dev, skb->dev, | ||
| 820 | dn_to_neigh_output); | 824 | dn_to_neigh_output); |
| 821 | 825 | ||
| 822 | drop: | 826 | drop: |
