diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bluetooth/l2cap_sock.c | 4 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/sock.c | 3 | ||||
| -rw-r--r-- | net/bluetooth/sco.c | 5 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 9 | ||||
| -rw-r--r-- | net/bridge/br_netlink.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 1 | ||||
| -rw-r--r-- | net/core/fib_rules.c | 5 | ||||
| -rw-r--r-- | net/ipv4/tcp_minisocks.c | 1 | ||||
| -rw-r--r-- | net/ipv6/af_inet6.c | 1 | ||||
| -rw-r--r-- | net/l2tp/l2tp_core.c | 4 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 131 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 6 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 4 | ||||
| -rw-r--r-- | net/x25/af_x25.c | 40 | ||||
| -rw-r--r-- | net/x25/x25_dev.c | 6 | ||||
| -rw-r--r-- | net/x25/x25_facilities.c | 10 | ||||
| -rw-r--r-- | net/x25/x25_in.c | 43 | ||||
| -rw-r--r-- | net/x25/x25_link.c | 3 | ||||
| -rw-r--r-- | net/x25/x25_subr.c | 14 |
19 files changed, 213 insertions, 78 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61f1f623091d..e8292369cdcf 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | /* Bluetooth L2CAP sockets. */ | 27 | /* Bluetooth L2CAP sockets. */ |
| 28 | 28 | ||
| 29 | #include <linux/security.h> | ||
| 30 | |||
| 29 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
| 30 | #include <net/bluetooth/hci_core.h> | 32 | #include <net/bluetooth/hci_core.h> |
| 31 | #include <net/bluetooth/l2cap.h> | 33 | #include <net/bluetooth/l2cap.h> |
| @@ -933,6 +935,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
| 933 | chan->force_reliable = pchan->force_reliable; | 935 | chan->force_reliable = pchan->force_reliable; |
| 934 | chan->flushable = pchan->flushable; | 936 | chan->flushable = pchan->flushable; |
| 935 | chan->force_active = pchan->force_active; | 937 | chan->force_active = pchan->force_active; |
| 938 | |||
| 939 | security_sk_clone(parent, sk); | ||
| 936 | } else { | 940 | } else { |
| 937 | 941 | ||
| 938 | switch (sk->sk_type) { | 942 | switch (sk->sk_type) { |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 482722bbc7a0..5417f6127323 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/device.h> | 42 | #include <linux/device.h> |
| 43 | #include <linux/debugfs.h> | 43 | #include <linux/debugfs.h> |
| 44 | #include <linux/seq_file.h> | 44 | #include <linux/seq_file.h> |
| 45 | #include <linux/security.h> | ||
| 45 | #include <net/sock.h> | 46 | #include <net/sock.h> |
| 46 | 47 | ||
| 47 | #include <asm/system.h> | 48 | #include <asm/system.h> |
| @@ -264,6 +265,8 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent) | |||
| 264 | 265 | ||
| 265 | pi->sec_level = rfcomm_pi(parent)->sec_level; | 266 | pi->sec_level = rfcomm_pi(parent)->sec_level; |
| 266 | pi->role_switch = rfcomm_pi(parent)->role_switch; | 267 | pi->role_switch = rfcomm_pi(parent)->role_switch; |
| 268 | |||
| 269 | security_sk_clone(parent, sk); | ||
| 267 | } else { | 270 | } else { |
| 268 | pi->dlc->defer_setup = 0; | 271 | pi->dlc->defer_setup = 0; |
| 269 | 272 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8270f05e3f1f..a324b009e34b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/debugfs.h> | 41 | #include <linux/debugfs.h> |
| 42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
| 43 | #include <linux/list.h> | 43 | #include <linux/list.h> |
| 44 | #include <linux/security.h> | ||
| 44 | #include <net/sock.h> | 45 | #include <net/sock.h> |
| 45 | 46 | ||
| 46 | #include <asm/system.h> | 47 | #include <asm/system.h> |
| @@ -403,8 +404,10 @@ static void sco_sock_init(struct sock *sk, struct sock *parent) | |||
| 403 | { | 404 | { |
| 404 | BT_DBG("sk %p", sk); | 405 | BT_DBG("sk %p", sk); |
| 405 | 406 | ||
| 406 | if (parent) | 407 | if (parent) { |
| 407 | sk->sk_type = parent->sk_type; | 408 | sk->sk_type = parent->sk_type; |
| 409 | security_sk_clone(parent, sk); | ||
| 410 | } | ||
| 408 | } | 411 | } |
| 409 | 412 | ||
| 410 | static struct proto sco_proto = { | 413 | static struct proto sco_proto = { |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e73815456adf..1d420f64ff27 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -161,9 +161,10 @@ static void del_nbp(struct net_bridge_port *p) | |||
| 161 | call_rcu(&p->rcu, destroy_nbp_rcu); | 161 | call_rcu(&p->rcu, destroy_nbp_rcu); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | /* called with RTNL */ | 164 | /* Delete bridge device */ |
| 165 | static void del_br(struct net_bridge *br, struct list_head *head) | 165 | void br_dev_delete(struct net_device *dev, struct list_head *head) |
| 166 | { | 166 | { |
| 167 | struct net_bridge *br = netdev_priv(dev); | ||
| 167 | struct net_bridge_port *p, *n; | 168 | struct net_bridge_port *p, *n; |
| 168 | 169 | ||
| 169 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 170 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
| @@ -268,7 +269,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
| 268 | } | 269 | } |
| 269 | 270 | ||
| 270 | else | 271 | else |
| 271 | del_br(netdev_priv(dev), NULL); | 272 | br_dev_delete(dev, NULL); |
| 272 | 273 | ||
| 273 | rtnl_unlock(); | 274 | rtnl_unlock(); |
| 274 | return ret; | 275 | return ret; |
| @@ -449,7 +450,7 @@ void __net_exit br_net_exit(struct net *net) | |||
| 449 | rtnl_lock(); | 450 | rtnl_lock(); |
| 450 | for_each_netdev(net, dev) | 451 | for_each_netdev(net, dev) |
| 451 | if (dev->priv_flags & IFF_EBRIDGE) | 452 | if (dev->priv_flags & IFF_EBRIDGE) |
| 452 | del_br(netdev_priv(dev), &list); | 453 | br_dev_delete(dev, &list); |
| 453 | 454 | ||
| 454 | unregister_netdevice_many(&list); | 455 | unregister_netdevice_many(&list); |
| 455 | rtnl_unlock(); | 456 | rtnl_unlock(); |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 5b1ed1ba9aa7..e5f9ece3c9a0 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
| @@ -210,6 +210,7 @@ static struct rtnl_link_ops br_link_ops __read_mostly = { | |||
| 210 | .priv_size = sizeof(struct net_bridge), | 210 | .priv_size = sizeof(struct net_bridge), |
| 211 | .setup = br_dev_setup, | 211 | .setup = br_dev_setup, |
| 212 | .validate = br_validate, | 212 | .validate = br_validate, |
| 213 | .dellink = br_dev_delete, | ||
| 213 | }; | 214 | }; |
| 214 | 215 | ||
| 215 | int __init br_netlink_init(void) | 216 | int __init br_netlink_init(void) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 78cc364997d9..857a021deea9 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -294,6 +294,7 @@ static inline int br_is_root_bridge(const struct net_bridge *br) | |||
| 294 | 294 | ||
| 295 | /* br_device.c */ | 295 | /* br_device.c */ |
| 296 | extern void br_dev_setup(struct net_device *dev); | 296 | extern void br_dev_setup(struct net_device *dev); |
| 297 | extern void br_dev_delete(struct net_device *dev, struct list_head *list); | ||
| 297 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, | 298 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, |
| 298 | struct net_device *dev); | 299 | struct net_device *dev); |
| 299 | #ifdef CONFIG_NET_POLL_CONTROLLER | 300 | #ifdef CONFIG_NET_POLL_CONTROLLER |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 3231b468bb72..27071ee2a4e1 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
| @@ -475,8 +475,11 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
| 475 | 475 | ||
| 476 | list_del_rcu(&rule->list); | 476 | list_del_rcu(&rule->list); |
| 477 | 477 | ||
| 478 | if (rule->action == FR_ACT_GOTO) | 478 | if (rule->action == FR_ACT_GOTO) { |
| 479 | ops->nr_goto_rules--; | 479 | ops->nr_goto_rules--; |
| 480 | if (rtnl_dereference(rule->ctarget) == NULL) | ||
| 481 | ops->unresolved_rules--; | ||
| 482 | } | ||
| 480 | 483 | ||
| 481 | /* | 484 | /* |
| 482 | * Check if this rule is a target to any of them. If so, | 485 | * Check if this rule is a target to any of them. If so, |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index d2fe4e06b472..0ce3d06dce60 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
| @@ -328,6 +328,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
| 328 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); | 328 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); |
| 329 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); | 329 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); |
| 330 | 330 | ||
| 331 | tw->tw_transparent = inet_sk(sk)->transparent; | ||
| 331 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; | 332 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; |
| 332 | tcptw->tw_rcv_nxt = tp->rcv_nxt; | 333 | tcptw->tw_rcv_nxt = tp->rcv_nxt; |
| 333 | tcptw->tw_snd_nxt = tp->snd_nxt; | 334 | tcptw->tw_snd_nxt = tp->snd_nxt; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3b5669a2582d..d27c797f9f05 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -875,6 +875,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
| 875 | skb_reset_transport_header(skb); | 875 | skb_reset_transport_header(skb); |
| 876 | __skb_push(skb, skb_gro_offset(skb)); | 876 | __skb_push(skb, skb_gro_offset(skb)); |
| 877 | 877 | ||
| 878 | ops = rcu_dereference(inet6_protos[proto]); | ||
| 878 | if (!ops || !ops->gro_receive) | 879 | if (!ops || !ops->gro_receive) |
| 879 | goto out_unlock; | 880 | goto out_unlock; |
| 880 | 881 | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index ad4ac2601a56..34b2ddeacb67 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1045,8 +1045,10 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
| 1045 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + | 1045 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + |
| 1046 | uhlen + hdr_len; | 1046 | uhlen + hdr_len; |
| 1047 | old_headroom = skb_headroom(skb); | 1047 | old_headroom = skb_headroom(skb); |
| 1048 | if (skb_cow_head(skb, headroom)) | 1048 | if (skb_cow_head(skb, headroom)) { |
| 1049 | dev_kfree_skb(skb); | ||
| 1049 | goto abort; | 1050 | goto abort; |
| 1051 | } | ||
| 1050 | 1052 | ||
| 1051 | new_headroom = skb_headroom(skb); | 1053 | new_headroom = skb_headroom(skb); |
| 1052 | skb_orphan(skb); | 1054 | skb_orphan(skb); |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5290ac353a5e..e3be48bf4dcd 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -2283,6 +2283,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
| 2283 | struct ip_vs_service *svc; | 2283 | struct ip_vs_service *svc; |
| 2284 | struct ip_vs_dest_user *udest_compat; | 2284 | struct ip_vs_dest_user *udest_compat; |
| 2285 | struct ip_vs_dest_user_kern udest; | 2285 | struct ip_vs_dest_user_kern udest; |
| 2286 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
| 2286 | 2287 | ||
| 2287 | if (!capable(CAP_NET_ADMIN)) | 2288 | if (!capable(CAP_NET_ADMIN)) |
| 2288 | return -EPERM; | 2289 | return -EPERM; |
| @@ -2303,6 +2304,24 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
| 2303 | /* increase the module use count */ | 2304 | /* increase the module use count */ |
| 2304 | ip_vs_use_count_inc(); | 2305 | ip_vs_use_count_inc(); |
| 2305 | 2306 | ||
| 2307 | /* Handle daemons since they have another lock */ | ||
| 2308 | if (cmd == IP_VS_SO_SET_STARTDAEMON || | ||
| 2309 | cmd == IP_VS_SO_SET_STOPDAEMON) { | ||
| 2310 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
| 2311 | |||
| 2312 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) { | ||
| 2313 | ret = -ERESTARTSYS; | ||
| 2314 | goto out_dec; | ||
| 2315 | } | ||
| 2316 | if (cmd == IP_VS_SO_SET_STARTDAEMON) | ||
| 2317 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, | ||
| 2318 | dm->syncid); | ||
| 2319 | else | ||
| 2320 | ret = stop_sync_thread(net, dm->state); | ||
| 2321 | mutex_unlock(&ipvs->sync_mutex); | ||
| 2322 | goto out_dec; | ||
| 2323 | } | ||
| 2324 | |||
| 2306 | if (mutex_lock_interruptible(&__ip_vs_mutex)) { | 2325 | if (mutex_lock_interruptible(&__ip_vs_mutex)) { |
| 2307 | ret = -ERESTARTSYS; | 2326 | ret = -ERESTARTSYS; |
| 2308 | goto out_dec; | 2327 | goto out_dec; |
| @@ -2316,15 +2335,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
| 2316 | /* Set timeout values for (tcp tcpfin udp) */ | 2335 | /* Set timeout values for (tcp tcpfin udp) */ |
| 2317 | ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg); | 2336 | ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg); |
| 2318 | goto out_unlock; | 2337 | goto out_unlock; |
| 2319 | } else if (cmd == IP_VS_SO_SET_STARTDAEMON) { | ||
| 2320 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
| 2321 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, | ||
| 2322 | dm->syncid); | ||
| 2323 | goto out_unlock; | ||
| 2324 | } else if (cmd == IP_VS_SO_SET_STOPDAEMON) { | ||
| 2325 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | ||
| 2326 | ret = stop_sync_thread(net, dm->state); | ||
| 2327 | goto out_unlock; | ||
| 2328 | } | 2338 | } |
| 2329 | 2339 | ||
| 2330 | usvc_compat = (struct ip_vs_service_user *)arg; | 2340 | usvc_compat = (struct ip_vs_service_user *)arg; |
| @@ -2584,6 +2594,33 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 2584 | 2594 | ||
| 2585 | if (copy_from_user(arg, user, copylen) != 0) | 2595 | if (copy_from_user(arg, user, copylen) != 0) |
| 2586 | return -EFAULT; | 2596 | return -EFAULT; |
| 2597 | /* | ||
| 2598 | * Handle daemons first since it has its own locking | ||
| 2599 | */ | ||
| 2600 | if (cmd == IP_VS_SO_GET_DAEMON) { | ||
| 2601 | struct ip_vs_daemon_user d[2]; | ||
| 2602 | |||
| 2603 | memset(&d, 0, sizeof(d)); | ||
| 2604 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) | ||
| 2605 | return -ERESTARTSYS; | ||
| 2606 | |||
| 2607 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { | ||
| 2608 | d[0].state = IP_VS_STATE_MASTER; | ||
| 2609 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, | ||
| 2610 | sizeof(d[0].mcast_ifn)); | ||
| 2611 | d[0].syncid = ipvs->master_syncid; | ||
| 2612 | } | ||
| 2613 | if (ipvs->sync_state & IP_VS_STATE_BACKUP) { | ||
| 2614 | d[1].state = IP_VS_STATE_BACKUP; | ||
| 2615 | strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn, | ||
| 2616 | sizeof(d[1].mcast_ifn)); | ||
| 2617 | d[1].syncid = ipvs->backup_syncid; | ||
| 2618 | } | ||
| 2619 | if (copy_to_user(user, &d, sizeof(d)) != 0) | ||
| 2620 | ret = -EFAULT; | ||
| 2621 | mutex_unlock(&ipvs->sync_mutex); | ||
| 2622 | return ret; | ||
| 2623 | } | ||
| 2587 | 2624 | ||
| 2588 | if (mutex_lock_interruptible(&__ip_vs_mutex)) | 2625 | if (mutex_lock_interruptible(&__ip_vs_mutex)) |
| 2589 | return -ERESTARTSYS; | 2626 | return -ERESTARTSYS; |
| @@ -2681,28 +2718,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 2681 | } | 2718 | } |
| 2682 | break; | 2719 | break; |
| 2683 | 2720 | ||
| 2684 | case IP_VS_SO_GET_DAEMON: | ||
| 2685 | { | ||
| 2686 | struct ip_vs_daemon_user d[2]; | ||
| 2687 | |||
| 2688 | memset(&d, 0, sizeof(d)); | ||
| 2689 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { | ||
| 2690 | d[0].state = IP_VS_STATE_MASTER; | ||
| 2691 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, | ||
| 2692 | sizeof(d[0].mcast_ifn)); | ||
| 2693 | d[0].syncid = ipvs->master_syncid; | ||
| 2694 | } | ||
| 2695 | if (ipvs->sync_state & IP_VS_STATE_BACKUP) { | ||
| 2696 | d[1].state = IP_VS_STATE_BACKUP; | ||
| 2697 | strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn, | ||
| 2698 | sizeof(d[1].mcast_ifn)); | ||
| 2699 | d[1].syncid = ipvs->backup_syncid; | ||
| 2700 | } | ||
| 2701 | if (copy_to_user(user, &d, sizeof(d)) != 0) | ||
| 2702 | ret = -EFAULT; | ||
| 2703 | } | ||
| 2704 | break; | ||
| 2705 | |||
| 2706 | default: | 2721 | default: |
| 2707 | ret = -EINVAL; | 2722 | ret = -EINVAL; |
| 2708 | } | 2723 | } |
| @@ -3205,7 +3220,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | |||
| 3205 | struct net *net = skb_sknet(skb); | 3220 | struct net *net = skb_sknet(skb); |
| 3206 | struct netns_ipvs *ipvs = net_ipvs(net); | 3221 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 3207 | 3222 | ||
| 3208 | mutex_lock(&__ip_vs_mutex); | 3223 | mutex_lock(&ipvs->sync_mutex); |
| 3209 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { | 3224 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { |
| 3210 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, | 3225 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, |
| 3211 | ipvs->master_mcast_ifn, | 3226 | ipvs->master_mcast_ifn, |
| @@ -3225,7 +3240,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | |||
| 3225 | } | 3240 | } |
| 3226 | 3241 | ||
| 3227 | nla_put_failure: | 3242 | nla_put_failure: |
| 3228 | mutex_unlock(&__ip_vs_mutex); | 3243 | mutex_unlock(&ipvs->sync_mutex); |
| 3229 | 3244 | ||
| 3230 | return skb->len; | 3245 | return skb->len; |
| 3231 | } | 3246 | } |
| @@ -3271,13 +3286,9 @@ static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs) | |||
| 3271 | return ip_vs_set_timeout(net, &t); | 3286 | return ip_vs_set_timeout(net, &t); |
| 3272 | } | 3287 | } |
| 3273 | 3288 | ||
| 3274 | static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | 3289 | static int ip_vs_genl_set_daemon(struct sk_buff *skb, struct genl_info *info) |
| 3275 | { | 3290 | { |
| 3276 | struct ip_vs_service *svc = NULL; | ||
| 3277 | struct ip_vs_service_user_kern usvc; | ||
| 3278 | struct ip_vs_dest_user_kern udest; | ||
| 3279 | int ret = 0, cmd; | 3291 | int ret = 0, cmd; |
| 3280 | int need_full_svc = 0, need_full_dest = 0; | ||
| 3281 | struct net *net; | 3292 | struct net *net; |
| 3282 | struct netns_ipvs *ipvs; | 3293 | struct netns_ipvs *ipvs; |
| 3283 | 3294 | ||
| @@ -3285,19 +3296,10 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
| 3285 | ipvs = net_ipvs(net); | 3296 | ipvs = net_ipvs(net); |
| 3286 | cmd = info->genlhdr->cmd; | 3297 | cmd = info->genlhdr->cmd; |
| 3287 | 3298 | ||
| 3288 | mutex_lock(&__ip_vs_mutex); | 3299 | if (cmd == IPVS_CMD_NEW_DAEMON || cmd == IPVS_CMD_DEL_DAEMON) { |
| 3289 | |||
| 3290 | if (cmd == IPVS_CMD_FLUSH) { | ||
| 3291 | ret = ip_vs_flush(net); | ||
| 3292 | goto out; | ||
| 3293 | } else if (cmd == IPVS_CMD_SET_CONFIG) { | ||
| 3294 | ret = ip_vs_genl_set_config(net, info->attrs); | ||
| 3295 | goto out; | ||
| 3296 | } else if (cmd == IPVS_CMD_NEW_DAEMON || | ||
| 3297 | cmd == IPVS_CMD_DEL_DAEMON) { | ||
| 3298 | |||
| 3299 | struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1]; | 3300 | struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1]; |
| 3300 | 3301 | ||
| 3302 | mutex_lock(&ipvs->sync_mutex); | ||
| 3301 | if (!info->attrs[IPVS_CMD_ATTR_DAEMON] || | 3303 | if (!info->attrs[IPVS_CMD_ATTR_DAEMON] || |
| 3302 | nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX, | 3304 | nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX, |
| 3303 | info->attrs[IPVS_CMD_ATTR_DAEMON], | 3305 | info->attrs[IPVS_CMD_ATTR_DAEMON], |
| @@ -3310,6 +3312,33 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
| 3310 | ret = ip_vs_genl_new_daemon(net, daemon_attrs); | 3312 | ret = ip_vs_genl_new_daemon(net, daemon_attrs); |
| 3311 | else | 3313 | else |
| 3312 | ret = ip_vs_genl_del_daemon(net, daemon_attrs); | 3314 | ret = ip_vs_genl_del_daemon(net, daemon_attrs); |
| 3315 | out: | ||
| 3316 | mutex_unlock(&ipvs->sync_mutex); | ||
| 3317 | } | ||
| 3318 | return ret; | ||
| 3319 | } | ||
| 3320 | |||
| 3321 | static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | ||
| 3322 | { | ||
| 3323 | struct ip_vs_service *svc = NULL; | ||
| 3324 | struct ip_vs_service_user_kern usvc; | ||
| 3325 | struct ip_vs_dest_user_kern udest; | ||
| 3326 | int ret = 0, cmd; | ||
| 3327 | int need_full_svc = 0, need_full_dest = 0; | ||
| 3328 | struct net *net; | ||
| 3329 | struct netns_ipvs *ipvs; | ||
| 3330 | |||
| 3331 | net = skb_sknet(skb); | ||
| 3332 | ipvs = net_ipvs(net); | ||
| 3333 | cmd = info->genlhdr->cmd; | ||
| 3334 | |||
| 3335 | mutex_lock(&__ip_vs_mutex); | ||
| 3336 | |||
| 3337 | if (cmd == IPVS_CMD_FLUSH) { | ||
| 3338 | ret = ip_vs_flush(net); | ||
| 3339 | goto out; | ||
| 3340 | } else if (cmd == IPVS_CMD_SET_CONFIG) { | ||
| 3341 | ret = ip_vs_genl_set_config(net, info->attrs); | ||
| 3313 | goto out; | 3342 | goto out; |
| 3314 | } else if (cmd == IPVS_CMD_ZERO && | 3343 | } else if (cmd == IPVS_CMD_ZERO && |
| 3315 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { | 3344 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { |
| @@ -3536,13 +3565,13 @@ static struct genl_ops ip_vs_genl_ops[] __read_mostly = { | |||
| 3536 | .cmd = IPVS_CMD_NEW_DAEMON, | 3565 | .cmd = IPVS_CMD_NEW_DAEMON, |
| 3537 | .flags = GENL_ADMIN_PERM, | 3566 | .flags = GENL_ADMIN_PERM, |
| 3538 | .policy = ip_vs_cmd_policy, | 3567 | .policy = ip_vs_cmd_policy, |
| 3539 | .doit = ip_vs_genl_set_cmd, | 3568 | .doit = ip_vs_genl_set_daemon, |
| 3540 | }, | 3569 | }, |
| 3541 | { | 3570 | { |
| 3542 | .cmd = IPVS_CMD_DEL_DAEMON, | 3571 | .cmd = IPVS_CMD_DEL_DAEMON, |
| 3543 | .flags = GENL_ADMIN_PERM, | 3572 | .flags = GENL_ADMIN_PERM, |
| 3544 | .policy = ip_vs_cmd_policy, | 3573 | .policy = ip_vs_cmd_policy, |
| 3545 | .doit = ip_vs_genl_set_cmd, | 3574 | .doit = ip_vs_genl_set_daemon, |
| 3546 | }, | 3575 | }, |
| 3547 | { | 3576 | { |
| 3548 | .cmd = IPVS_CMD_GET_DAEMON, | 3577 | .cmd = IPVS_CMD_GET_DAEMON, |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 7ee7215b8ba0..3cdd479f9b5d 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | 61 | ||
| 62 | #define SYNC_PROTO_VER 1 /* Protocol version in header */ | 62 | #define SYNC_PROTO_VER 1 /* Protocol version in header */ |
| 63 | 63 | ||
| 64 | static struct lock_class_key __ipvs_sync_key; | ||
| 64 | /* | 65 | /* |
| 65 | * IPVS sync connection entry | 66 | * IPVS sync connection entry |
| 66 | * Version 0, i.e. original version. | 67 | * Version 0, i.e. original version. |
| @@ -1545,6 +1546,7 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) | |||
| 1545 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n", | 1546 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n", |
| 1546 | sizeof(struct ip_vs_sync_conn_v0)); | 1547 | sizeof(struct ip_vs_sync_conn_v0)); |
| 1547 | 1548 | ||
| 1549 | |||
| 1548 | if (state == IP_VS_STATE_MASTER) { | 1550 | if (state == IP_VS_STATE_MASTER) { |
| 1549 | if (ipvs->master_thread) | 1551 | if (ipvs->master_thread) |
| 1550 | return -EEXIST; | 1552 | return -EEXIST; |
| @@ -1667,6 +1669,7 @@ int __net_init ip_vs_sync_net_init(struct net *net) | |||
| 1667 | { | 1669 | { |
| 1668 | struct netns_ipvs *ipvs = net_ipvs(net); | 1670 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1669 | 1671 | ||
| 1672 | __mutex_init(&ipvs->sync_mutex, "ipvs->sync_mutex", &__ipvs_sync_key); | ||
| 1670 | INIT_LIST_HEAD(&ipvs->sync_queue); | 1673 | INIT_LIST_HEAD(&ipvs->sync_queue); |
| 1671 | spin_lock_init(&ipvs->sync_lock); | 1674 | spin_lock_init(&ipvs->sync_lock); |
| 1672 | spin_lock_init(&ipvs->sync_buff_lock); | 1675 | spin_lock_init(&ipvs->sync_buff_lock); |
| @@ -1680,7 +1683,9 @@ int __net_init ip_vs_sync_net_init(struct net *net) | |||
| 1680 | void ip_vs_sync_net_cleanup(struct net *net) | 1683 | void ip_vs_sync_net_cleanup(struct net *net) |
| 1681 | { | 1684 | { |
| 1682 | int retc; | 1685 | int retc; |
| 1686 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
| 1683 | 1687 | ||
| 1688 | mutex_lock(&ipvs->sync_mutex); | ||
| 1684 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); | 1689 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); |
| 1685 | if (retc && retc != -ESRCH) | 1690 | if (retc && retc != -ESRCH) |
| 1686 | pr_err("Failed to stop Master Daemon\n"); | 1691 | pr_err("Failed to stop Master Daemon\n"); |
| @@ -1688,4 +1693,5 @@ void ip_vs_sync_net_cleanup(struct net *net) | |||
| 1688 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | 1693 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); |
| 1689 | if (retc && retc != -ESRCH) | 1694 | if (retc && retc != -ESRCH) |
| 1690 | pr_err("Failed to stop Backup Daemon\n"); | 1695 | pr_err("Failed to stop Backup Daemon\n"); |
| 1696 | mutex_unlock(&ipvs->sync_mutex); | ||
| 1691 | } | 1697 | } |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index cf616e55ca41..d69facdd9a7a 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
| @@ -241,8 +241,8 @@ static int gre_packet(struct nf_conn *ct, | |||
| 241 | nf_ct_refresh_acct(ct, ctinfo, skb, | 241 | nf_ct_refresh_acct(ct, ctinfo, skb, |
| 242 | ct->proto.gre.stream_timeout); | 242 | ct->proto.gre.stream_timeout); |
| 243 | /* Also, more likely to be important, and not a probe. */ | 243 | /* Also, more likely to be important, and not a probe. */ |
| 244 | set_bit(IPS_ASSURED_BIT, &ct->status); | 244 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
| 245 | nf_conntrack_event_cache(IPCT_ASSURED, ct); | 245 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |
| 246 | } else | 246 | } else |
| 247 | nf_ct_refresh_acct(ct, ctinfo, skb, | 247 | nf_ct_refresh_acct(ct, ctinfo, skb, |
| 248 | ct->proto.gre.timeout); | 248 | ct->proto.gre.timeout); |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index d30615419b4d..5f03e4ea65bf 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -91,7 +91,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
| 91 | int needed; | 91 | int needed; |
| 92 | int rc; | 92 | int rc; |
| 93 | 93 | ||
| 94 | if (skb->len < 1) { | 94 | if (!pskb_may_pull(skb, 1)) { |
| 95 | /* packet has no address block */ | 95 | /* packet has no address block */ |
| 96 | rc = 0; | 96 | rc = 0; |
| 97 | goto empty; | 97 | goto empty; |
| @@ -100,7 +100,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
| 100 | len = *skb->data; | 100 | len = *skb->data; |
| 101 | needed = 1 + (len >> 4) + (len & 0x0f); | 101 | needed = 1 + (len >> 4) + (len & 0x0f); |
| 102 | 102 | ||
| 103 | if (skb->len < needed) { | 103 | if (!pskb_may_pull(skb, needed)) { |
| 104 | /* packet is too short to hold the addresses it claims | 104 | /* packet is too short to hold the addresses it claims |
| 105 | to hold */ | 105 | to hold */ |
| 106 | rc = -1; | 106 | rc = -1; |
| @@ -295,7 +295,8 @@ static struct sock *x25_find_listener(struct x25_address *addr, | |||
| 295 | * Found a listening socket, now check the incoming | 295 | * Found a listening socket, now check the incoming |
| 296 | * call user data vs this sockets call user data | 296 | * call user data vs this sockets call user data |
| 297 | */ | 297 | */ |
| 298 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { | 298 | if (x25_sk(s)->cudmatchlength > 0 && |
| 299 | skb->len >= x25_sk(s)->cudmatchlength) { | ||
| 299 | if((memcmp(x25_sk(s)->calluserdata.cuddata, | 300 | if((memcmp(x25_sk(s)->calluserdata.cuddata, |
| 300 | skb->data, | 301 | skb->data, |
| 301 | x25_sk(s)->cudmatchlength)) == 0) { | 302 | x25_sk(s)->cudmatchlength)) == 0) { |
| @@ -951,14 +952,27 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 951 | * | 952 | * |
| 952 | * Facilities length is mandatory in call request packets | 953 | * Facilities length is mandatory in call request packets |
| 953 | */ | 954 | */ |
| 954 | if (skb->len < 1) | 955 | if (!pskb_may_pull(skb, 1)) |
| 955 | goto out_clear_request; | 956 | goto out_clear_request; |
| 956 | len = skb->data[0] + 1; | 957 | len = skb->data[0] + 1; |
| 957 | if (skb->len < len) | 958 | if (!pskb_may_pull(skb, len)) |
| 958 | goto out_clear_request; | 959 | goto out_clear_request; |
| 959 | skb_pull(skb,len); | 960 | skb_pull(skb,len); |
| 960 | 961 | ||
| 961 | /* | 962 | /* |
| 963 | * Ensure that the amount of call user data is valid. | ||
| 964 | */ | ||
| 965 | if (skb->len > X25_MAX_CUD_LEN) | ||
| 966 | goto out_clear_request; | ||
| 967 | |||
| 968 | /* | ||
| 969 | * Get all the call user data so it can be used in | ||
| 970 | * x25_find_listener and skb_copy_from_linear_data up ahead. | ||
| 971 | */ | ||
| 972 | if (!pskb_may_pull(skb, skb->len)) | ||
| 973 | goto out_clear_request; | ||
| 974 | |||
| 975 | /* | ||
| 962 | * Find a listener for the particular address/cud pair. | 976 | * Find a listener for the particular address/cud pair. |
| 963 | */ | 977 | */ |
| 964 | sk = x25_find_listener(&source_addr,skb); | 978 | sk = x25_find_listener(&source_addr,skb); |
| @@ -1166,6 +1180,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1166 | * byte of the user data is the logical value of the Q Bit. | 1180 | * byte of the user data is the logical value of the Q Bit. |
| 1167 | */ | 1181 | */ |
| 1168 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1182 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
| 1183 | if (!pskb_may_pull(skb, 1)) | ||
| 1184 | goto out_kfree_skb; | ||
| 1185 | |||
| 1169 | qbit = skb->data[0]; | 1186 | qbit = skb->data[0]; |
| 1170 | skb_pull(skb, 1); | 1187 | skb_pull(skb, 1); |
| 1171 | } | 1188 | } |
| @@ -1244,7 +1261,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1244 | struct x25_sock *x25 = x25_sk(sk); | 1261 | struct x25_sock *x25 = x25_sk(sk); |
| 1245 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; | 1262 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; |
| 1246 | size_t copied; | 1263 | size_t copied; |
| 1247 | int qbit; | 1264 | int qbit, header_len = x25->neighbour->extended ? |
| 1265 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN; | ||
| 1266 | |||
| 1248 | struct sk_buff *skb; | 1267 | struct sk_buff *skb; |
| 1249 | unsigned char *asmptr; | 1268 | unsigned char *asmptr; |
| 1250 | int rc = -ENOTCONN; | 1269 | int rc = -ENOTCONN; |
| @@ -1265,6 +1284,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1265 | 1284 | ||
| 1266 | skb = skb_dequeue(&x25->interrupt_in_queue); | 1285 | skb = skb_dequeue(&x25->interrupt_in_queue); |
| 1267 | 1286 | ||
| 1287 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
| 1288 | goto out_free_dgram; | ||
| 1289 | |||
| 1268 | skb_pull(skb, X25_STD_MIN_LEN); | 1290 | skb_pull(skb, X25_STD_MIN_LEN); |
| 1269 | 1291 | ||
| 1270 | /* | 1292 | /* |
| @@ -1285,10 +1307,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1285 | if (!skb) | 1307 | if (!skb) |
| 1286 | goto out; | 1308 | goto out; |
| 1287 | 1309 | ||
| 1310 | if (!pskb_may_pull(skb, header_len)) | ||
| 1311 | goto out_free_dgram; | ||
| 1312 | |||
| 1288 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; | 1313 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; |
| 1289 | 1314 | ||
| 1290 | skb_pull(skb, x25->neighbour->extended ? | 1315 | skb_pull(skb, header_len); |
| 1291 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN); | ||
| 1292 | 1316 | ||
| 1293 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1317 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
| 1294 | asmptr = skb_push(skb, 1); | 1318 | asmptr = skb_push(skb, 1); |
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index e547ca1578c3..fa2b41888bd9 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
| @@ -32,6 +32,9 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | |||
| 32 | unsigned short frametype; | 32 | unsigned short frametype; |
| 33 | unsigned int lci; | 33 | unsigned int lci; |
| 34 | 34 | ||
| 35 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
| 36 | return 0; | ||
| 37 | |||
| 35 | frametype = skb->data[2]; | 38 | frametype = skb->data[2]; |
| 36 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 39 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 37 | 40 | ||
| @@ -115,6 +118,9 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, | |||
| 115 | goto drop; | 118 | goto drop; |
| 116 | } | 119 | } |
| 117 | 120 | ||
| 121 | if (!pskb_may_pull(skb, 1)) | ||
| 122 | return 0; | ||
| 123 | |||
| 118 | switch (skb->data[0]) { | 124 | switch (skb->data[0]) { |
| 119 | 125 | ||
| 120 | case X25_IFACE_DATA: | 126 | case X25_IFACE_DATA: |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index f77e4e75f914..36384a1fa9f2 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | 44 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, |
| 45 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 45 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
| 46 | { | 46 | { |
| 47 | unsigned char *p = skb->data; | 47 | unsigned char *p; |
| 48 | unsigned int len; | 48 | unsigned int len; |
| 49 | 49 | ||
| 50 | *vc_fac_mask = 0; | 50 | *vc_fac_mask = 0; |
| @@ -60,14 +60,16 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 60 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 60 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
| 61 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 61 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
| 62 | 62 | ||
| 63 | if (skb->len < 1) | 63 | if (!pskb_may_pull(skb, 1)) |
| 64 | return 0; | 64 | return 0; |
| 65 | 65 | ||
| 66 | len = *p++; | 66 | len = skb->data[0]; |
| 67 | 67 | ||
| 68 | if (len >= skb->len) | 68 | if (!pskb_may_pull(skb, 1 + len)) |
| 69 | return -1; | 69 | return -1; |
| 70 | 70 | ||
| 71 | p = skb->data + 1; | ||
| 72 | |||
| 71 | while (len > 0) { | 73 | while (len > 0) { |
| 72 | switch (*p & X25_FAC_CLASS_MASK) { | 74 | switch (*p & X25_FAC_CLASS_MASK) { |
| 73 | case X25_FAC_CLASS_A: | 75 | case X25_FAC_CLASS_A: |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 0b073b51b183..a49cd4ec551a 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -107,6 +107,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 107 | /* | 107 | /* |
| 108 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
| 109 | */ | 109 | */ |
| 110 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
| 111 | goto out_clear; | ||
| 110 | skb_pull(skb, X25_STD_MIN_LEN); | 112 | skb_pull(skb, X25_STD_MIN_LEN); |
| 111 | 113 | ||
| 112 | len = x25_parse_address_block(skb, &source_addr, | 114 | len = x25_parse_address_block(skb, &source_addr, |
| @@ -127,9 +129,11 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 127 | * Copy any Call User Data. | 129 | * Copy any Call User Data. |
| 128 | */ | 130 | */ |
| 129 | if (skb->len > 0) { | 131 | if (skb->len > 0) { |
| 130 | skb_copy_from_linear_data(skb, | 132 | if (skb->len > X25_MAX_CUD_LEN) |
| 131 | x25->calluserdata.cuddata, | 133 | goto out_clear; |
| 132 | skb->len); | 134 | |
| 135 | skb_copy_bits(skb, 0, x25->calluserdata.cuddata, | ||
| 136 | skb->len); | ||
| 133 | x25->calluserdata.cudlength = skb->len; | 137 | x25->calluserdata.cudlength = skb->len; |
| 134 | } | 138 | } |
| 135 | if (!sock_flag(sk, SOCK_DEAD)) | 139 | if (!sock_flag(sk, SOCK_DEAD)) |
| @@ -137,6 +141,9 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 137 | break; | 141 | break; |
| 138 | } | 142 | } |
| 139 | case X25_CLEAR_REQUEST: | 143 | case X25_CLEAR_REQUEST: |
| 144 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
| 145 | goto out_clear; | ||
| 146 | |||
| 140 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 147 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
| 141 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); | 148 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); |
| 142 | break; | 149 | break; |
| @@ -164,6 +171,9 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 164 | switch (frametype) { | 171 | switch (frametype) { |
| 165 | 172 | ||
| 166 | case X25_CLEAR_REQUEST: | 173 | case X25_CLEAR_REQUEST: |
| 174 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
| 175 | goto out_clear; | ||
| 176 | |||
| 167 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 177 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
| 168 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 178 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 169 | break; | 179 | break; |
| @@ -177,6 +187,11 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 177 | } | 187 | } |
| 178 | 188 | ||
| 179 | return 0; | 189 | return 0; |
| 190 | |||
| 191 | out_clear: | ||
| 192 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
| 193 | x25_start_t23timer(sk); | ||
| 194 | return 0; | ||
| 180 | } | 195 | } |
| 181 | 196 | ||
| 182 | /* | 197 | /* |
| @@ -206,6 +221,9 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 206 | break; | 221 | break; |
| 207 | 222 | ||
| 208 | case X25_CLEAR_REQUEST: | 223 | case X25_CLEAR_REQUEST: |
| 224 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
| 225 | goto out_clear; | ||
| 226 | |||
| 209 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 227 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
| 210 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 228 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 211 | break; | 229 | break; |
| @@ -304,6 +322,12 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 304 | } | 322 | } |
| 305 | 323 | ||
| 306 | return queued; | 324 | return queued; |
| 325 | |||
| 326 | out_clear: | ||
| 327 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
| 328 | x25->state = X25_STATE_2; | ||
| 329 | x25_start_t23timer(sk); | ||
| 330 | return 0; | ||
| 307 | } | 331 | } |
| 308 | 332 | ||
| 309 | /* | 333 | /* |
| @@ -313,13 +337,13 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 313 | */ | 337 | */ |
| 314 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 338 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
| 315 | { | 339 | { |
| 340 | struct x25_sock *x25 = x25_sk(sk); | ||
| 341 | |||
| 316 | switch (frametype) { | 342 | switch (frametype) { |
| 317 | 343 | ||
| 318 | case X25_RESET_REQUEST: | 344 | case X25_RESET_REQUEST: |
| 319 | x25_write_internal(sk, X25_RESET_CONFIRMATION); | 345 | x25_write_internal(sk, X25_RESET_CONFIRMATION); |
| 320 | case X25_RESET_CONFIRMATION: { | 346 | case X25_RESET_CONFIRMATION: { |
| 321 | struct x25_sock *x25 = x25_sk(sk); | ||
| 322 | |||
| 323 | x25_stop_timer(sk); | 347 | x25_stop_timer(sk); |
| 324 | x25->condition = 0x00; | 348 | x25->condition = 0x00; |
| 325 | x25->va = 0; | 349 | x25->va = 0; |
| @@ -331,6 +355,9 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 331 | break; | 355 | break; |
| 332 | } | 356 | } |
| 333 | case X25_CLEAR_REQUEST: | 357 | case X25_CLEAR_REQUEST: |
| 358 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
| 359 | goto out_clear; | ||
| 360 | |||
| 334 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 361 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
| 335 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 362 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 336 | break; | 363 | break; |
| @@ -340,6 +367,12 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 340 | } | 367 | } |
| 341 | 368 | ||
| 342 | return 0; | 369 | return 0; |
| 370 | |||
| 371 | out_clear: | ||
| 372 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
| 373 | x25->state = X25_STATE_2; | ||
| 374 | x25_start_t23timer(sk); | ||
| 375 | return 0; | ||
| 343 | } | 376 | } |
| 344 | 377 | ||
| 345 | /* Higher level upcall for a LAPB frame */ | 378 | /* Higher level upcall for a LAPB frame */ |
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 037958ff8eed..4acacf3c6617 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c | |||
| @@ -90,6 +90,9 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 90 | break; | 90 | break; |
| 91 | 91 | ||
| 92 | case X25_DIAGNOSTIC: | 92 | case X25_DIAGNOSTIC: |
| 93 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 4)) | ||
| 94 | break; | ||
| 95 | |||
| 93 | printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n", | 96 | printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n", |
| 94 | skb->data[3], skb->data[4], | 97 | skb->data[3], skb->data[4], |
| 95 | skb->data[5], skb->data[6]); | 98 | skb->data[5], skb->data[6]); |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 24a342ebc7f5..5170d52bfd96 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
| @@ -269,7 +269,11 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
| 269 | int *d, int *m) | 269 | int *d, int *m) |
| 270 | { | 270 | { |
| 271 | struct x25_sock *x25 = x25_sk(sk); | 271 | struct x25_sock *x25 = x25_sk(sk); |
| 272 | unsigned char *frame = skb->data; | 272 | unsigned char *frame; |
| 273 | |||
| 274 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
| 275 | return X25_ILLEGAL; | ||
| 276 | frame = skb->data; | ||
| 273 | 277 | ||
| 274 | *ns = *nr = *q = *d = *m = 0; | 278 | *ns = *nr = *q = *d = *m = 0; |
| 275 | 279 | ||
| @@ -294,6 +298,10 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
| 294 | if (frame[2] == X25_RR || | 298 | if (frame[2] == X25_RR || |
| 295 | frame[2] == X25_RNR || | 299 | frame[2] == X25_RNR || |
| 296 | frame[2] == X25_REJ) { | 300 | frame[2] == X25_REJ) { |
| 301 | if (!pskb_may_pull(skb, X25_EXT_MIN_LEN)) | ||
| 302 | return X25_ILLEGAL; | ||
| 303 | frame = skb->data; | ||
| 304 | |||
| 297 | *nr = (frame[3] >> 1) & 0x7F; | 305 | *nr = (frame[3] >> 1) & 0x7F; |
| 298 | return frame[2]; | 306 | return frame[2]; |
| 299 | } | 307 | } |
| @@ -308,6 +316,10 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, | |||
| 308 | 316 | ||
| 309 | if (x25->neighbour->extended) { | 317 | if (x25->neighbour->extended) { |
| 310 | if ((frame[2] & 0x01) == X25_DATA) { | 318 | if ((frame[2] & 0x01) == X25_DATA) { |
| 319 | if (!pskb_may_pull(skb, X25_EXT_MIN_LEN)) | ||
| 320 | return X25_ILLEGAL; | ||
| 321 | frame = skb->data; | ||
| 322 | |||
| 311 | *q = (frame[0] & X25_Q_BIT) == X25_Q_BIT; | 323 | *q = (frame[0] & X25_Q_BIT) == X25_Q_BIT; |
| 312 | *d = (frame[0] & X25_D_BIT) == X25_D_BIT; | 324 | *d = (frame[0] & X25_D_BIT) == X25_D_BIT; |
| 313 | *m = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT; | 325 | *m = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT; |
