diff options
| -rw-r--r-- | drivers/net/pppol2tp.c | 101 |
1 files changed, 78 insertions, 23 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 04c7e5b407fd..70cfdb46aa27 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c | |||
| @@ -240,12 +240,15 @@ static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk) | |||
| 240 | if (sk == NULL) | 240 | if (sk == NULL) |
| 241 | return NULL; | 241 | return NULL; |
| 242 | 242 | ||
| 243 | sock_hold(sk); | ||
| 243 | session = (struct pppol2tp_session *)(sk->sk_user_data); | 244 | session = (struct pppol2tp_session *)(sk->sk_user_data); |
| 244 | if (session == NULL) | 245 | if (session == NULL) { |
| 245 | return NULL; | 246 | sock_put(sk); |
| 247 | goto out; | ||
| 248 | } | ||
| 246 | 249 | ||
| 247 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | 250 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); |
| 248 | 251 | out: | |
| 249 | return session; | 252 | return session; |
| 250 | } | 253 | } |
| 251 | 254 | ||
| @@ -256,12 +259,15 @@ static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk) | |||
| 256 | if (sk == NULL) | 259 | if (sk == NULL) |
| 257 | return NULL; | 260 | return NULL; |
| 258 | 261 | ||
| 262 | sock_hold(sk); | ||
| 259 | tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data); | 263 | tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data); |
| 260 | if (tunnel == NULL) | 264 | if (tunnel == NULL) { |
| 261 | return NULL; | 265 | sock_put(sk); |
| 266 | goto out; | ||
| 267 | } | ||
| 262 | 268 | ||
| 263 | BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); | 269 | BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); |
| 264 | 270 | out: | |
| 265 | return tunnel; | 271 | return tunnel; |
| 266 | } | 272 | } |
| 267 | 273 | ||
| @@ -716,12 +722,14 @@ discard: | |||
| 716 | session->stats.rx_errors++; | 722 | session->stats.rx_errors++; |
| 717 | kfree_skb(skb); | 723 | kfree_skb(skb); |
| 718 | sock_put(session->sock); | 724 | sock_put(session->sock); |
| 725 | sock_put(sock); | ||
| 719 | 726 | ||
| 720 | return 0; | 727 | return 0; |
| 721 | 728 | ||
| 722 | error: | 729 | error: |
| 723 | /* Put UDP header back */ | 730 | /* Put UDP header back */ |
| 724 | __skb_push(skb, sizeof(struct udphdr)); | 731 | __skb_push(skb, sizeof(struct udphdr)); |
| 732 | sock_put(sock); | ||
| 725 | 733 | ||
| 726 | no_tunnel: | 734 | no_tunnel: |
| 727 | return 1; | 735 | return 1; |
| @@ -745,10 +753,13 @@ static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
| 745 | "%s: received %d bytes\n", tunnel->name, skb->len); | 753 | "%s: received %d bytes\n", tunnel->name, skb->len); |
| 746 | 754 | ||
| 747 | if (pppol2tp_recv_core(sk, skb)) | 755 | if (pppol2tp_recv_core(sk, skb)) |
| 748 | goto pass_up; | 756 | goto pass_up_put; |
| 749 | 757 | ||
| 758 | sock_put(sk); | ||
| 750 | return 0; | 759 | return 0; |
| 751 | 760 | ||
| 761 | pass_up_put: | ||
| 762 | sock_put(sk); | ||
| 752 | pass_up: | 763 | pass_up: |
| 753 | return 1; | 764 | return 1; |
| 754 | } | 765 | } |
| @@ -858,7 +869,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
| 858 | 869 | ||
| 859 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 870 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
| 860 | if (tunnel == NULL) | 871 | if (tunnel == NULL) |
| 861 | goto error; | 872 | goto error_put_sess; |
| 862 | 873 | ||
| 863 | /* What header length is configured for this session? */ | 874 | /* What header length is configured for this session? */ |
| 864 | hdr_len = pppol2tp_l2tp_header_len(session); | 875 | hdr_len = pppol2tp_l2tp_header_len(session); |
| @@ -870,7 +881,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
| 870 | sizeof(ppph) + total_len, | 881 | sizeof(ppph) + total_len, |
| 871 | 0, GFP_KERNEL); | 882 | 0, GFP_KERNEL); |
| 872 | if (!skb) | 883 | if (!skb) |
| 873 | goto error; | 884 | goto error_put_sess_tun; |
| 874 | 885 | ||
| 875 | /* Reserve space for headers. */ | 886 | /* Reserve space for headers. */ |
| 876 | skb_reserve(skb, NET_SKB_PAD); | 887 | skb_reserve(skb, NET_SKB_PAD); |
| @@ -900,7 +911,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
| 900 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); | 911 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); |
| 901 | if (error < 0) { | 912 | if (error < 0) { |
| 902 | kfree_skb(skb); | 913 | kfree_skb(skb); |
| 903 | goto error; | 914 | goto error_put_sess_tun; |
| 904 | } | 915 | } |
| 905 | skb_put(skb, total_len); | 916 | skb_put(skb, total_len); |
| 906 | 917 | ||
| @@ -947,10 +958,33 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
| 947 | session->stats.tx_errors++; | 958 | session->stats.tx_errors++; |
| 948 | } | 959 | } |
| 949 | 960 | ||
| 961 | return error; | ||
| 962 | |||
| 963 | error_put_sess_tun: | ||
| 964 | sock_put(session->tunnel_sock); | ||
| 965 | error_put_sess: | ||
| 966 | sock_put(sk); | ||
| 950 | error: | 967 | error: |
| 951 | return error; | 968 | return error; |
| 952 | } | 969 | } |
| 953 | 970 | ||
| 971 | /* Automatically called when the skb is freed. | ||
| 972 | */ | ||
| 973 | static void pppol2tp_sock_wfree(struct sk_buff *skb) | ||
| 974 | { | ||
| 975 | sock_put(skb->sk); | ||
| 976 | } | ||
| 977 | |||
| 978 | /* For data skbs that we transmit, we associate with the tunnel socket | ||
| 979 | * but don't do accounting. | ||
| 980 | */ | ||
| 981 | static inline void pppol2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
| 982 | { | ||
| 983 | sock_hold(sk); | ||
| 984 | skb->sk = sk; | ||
| 985 | skb->destructor = pppol2tp_sock_wfree; | ||
| 986 | } | ||
| 987 | |||
| 954 | /* Transmit function called by generic PPP driver. Sends PPP frame | 988 | /* Transmit function called by generic PPP driver. Sends PPP frame |
| 955 | * over PPPoL2TP socket. | 989 | * over PPPoL2TP socket. |
| 956 | * | 990 | * |
| @@ -993,10 +1027,10 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 993 | 1027 | ||
| 994 | sk_tun = session->tunnel_sock; | 1028 | sk_tun = session->tunnel_sock; |
| 995 | if (sk_tun == NULL) | 1029 | if (sk_tun == NULL) |
| 996 | goto abort; | 1030 | goto abort_put_sess; |
| 997 | tunnel = pppol2tp_sock_to_tunnel(sk_tun); | 1031 | tunnel = pppol2tp_sock_to_tunnel(sk_tun); |
| 998 | if (tunnel == NULL) | 1032 | if (tunnel == NULL) |
| 999 | goto abort; | 1033 | goto abort_put_sess; |
| 1000 | 1034 | ||
| 1001 | /* What header length is configured for this session? */ | 1035 | /* What header length is configured for this session? */ |
| 1002 | hdr_len = pppol2tp_l2tp_header_len(session); | 1036 | hdr_len = pppol2tp_l2tp_header_len(session); |
| @@ -1009,7 +1043,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1009 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); | 1043 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); |
| 1010 | old_headroom = skb_headroom(skb); | 1044 | old_headroom = skb_headroom(skb); |
| 1011 | if (skb_cow_head(skb, headroom)) | 1045 | if (skb_cow_head(skb, headroom)) |
| 1012 | goto abort; | 1046 | goto abort_put_sess_tun; |
| 1013 | 1047 | ||
| 1014 | new_headroom = skb_headroom(skb); | 1048 | new_headroom = skb_headroom(skb); |
| 1015 | skb_orphan(skb); | 1049 | skb_orphan(skb); |
| @@ -1069,7 +1103,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1069 | /* Get routing info from the tunnel socket */ | 1103 | /* Get routing info from the tunnel socket */ |
| 1070 | dst_release(skb->dst); | 1104 | dst_release(skb->dst); |
| 1071 | skb->dst = dst_clone(__sk_dst_get(sk_tun)); | 1105 | skb->dst = dst_clone(__sk_dst_get(sk_tun)); |
| 1072 | skb->sk = sk_tun; | 1106 | pppol2tp_skb_set_owner_w(skb, sk_tun); |
| 1073 | 1107 | ||
| 1074 | /* Queue the packet to IP for output */ | 1108 | /* Queue the packet to IP for output */ |
| 1075 | len = skb->len; | 1109 | len = skb->len; |
| @@ -1086,8 +1120,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1086 | session->stats.tx_errors++; | 1120 | session->stats.tx_errors++; |
| 1087 | } | 1121 | } |
| 1088 | 1122 | ||
| 1123 | sock_put(sk_tun); | ||
| 1124 | sock_put(sk); | ||
| 1089 | return 1; | 1125 | return 1; |
| 1090 | 1126 | ||
| 1127 | abort_put_sess_tun: | ||
| 1128 | sock_put(sk_tun); | ||
| 1129 | abort_put_sess: | ||
| 1130 | sock_put(sk); | ||
| 1091 | abort: | 1131 | abort: |
| 1092 | /* Free the original skb */ | 1132 | /* Free the original skb */ |
| 1093 | kfree_skb(skb); | 1133 | kfree_skb(skb); |
| @@ -1191,7 +1231,7 @@ static void pppol2tp_tunnel_destruct(struct sock *sk) | |||
| 1191 | { | 1231 | { |
| 1192 | struct pppol2tp_tunnel *tunnel; | 1232 | struct pppol2tp_tunnel *tunnel; |
| 1193 | 1233 | ||
| 1194 | tunnel = pppol2tp_sock_to_tunnel(sk); | 1234 | tunnel = sk->sk_user_data; |
| 1195 | if (tunnel == NULL) | 1235 | if (tunnel == NULL) |
| 1196 | goto end; | 1236 | goto end; |
| 1197 | 1237 | ||
| @@ -1230,10 +1270,12 @@ static void pppol2tp_session_destruct(struct sock *sk) | |||
| 1230 | if (sk->sk_user_data != NULL) { | 1270 | if (sk->sk_user_data != NULL) { |
| 1231 | struct pppol2tp_tunnel *tunnel; | 1271 | struct pppol2tp_tunnel *tunnel; |
| 1232 | 1272 | ||
| 1233 | session = pppol2tp_sock_to_session(sk); | 1273 | session = sk->sk_user_data; |
| 1234 | if (session == NULL) | 1274 | if (session == NULL) |
| 1235 | goto out; | 1275 | goto out; |
| 1236 | 1276 | ||
| 1277 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | ||
| 1278 | |||
| 1237 | /* Don't use pppol2tp_sock_to_tunnel() here to | 1279 | /* Don't use pppol2tp_sock_to_tunnel() here to |
| 1238 | * get the tunnel context because the tunnel | 1280 | * get the tunnel context because the tunnel |
| 1239 | * socket might have already been closed (its | 1281 | * socket might have already been closed (its |
| @@ -1611,7 +1653,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
| 1611 | 1653 | ||
| 1612 | error = ppp_register_channel(&po->chan); | 1654 | error = ppp_register_channel(&po->chan); |
| 1613 | if (error) | 1655 | if (error) |
| 1614 | goto end; | 1656 | goto end_put_tun; |
| 1615 | 1657 | ||
| 1616 | /* This is how we get the session context from the socket. */ | 1658 | /* This is how we get the session context from the socket. */ |
| 1617 | sk->sk_user_data = session; | 1659 | sk->sk_user_data = session; |
| @@ -1631,6 +1673,8 @@ out_no_ppp: | |||
| 1631 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | 1673 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, |
| 1632 | "%s: created\n", session->name); | 1674 | "%s: created\n", session->name); |
| 1633 | 1675 | ||
| 1676 | end_put_tun: | ||
| 1677 | sock_put(tunnel_sock); | ||
| 1634 | end: | 1678 | end: |
| 1635 | release_sock(sk); | 1679 | release_sock(sk); |
| 1636 | 1680 | ||
| @@ -1678,6 +1722,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, | |||
| 1678 | *usockaddr_len = len; | 1722 | *usockaddr_len = len; |
| 1679 | 1723 | ||
| 1680 | error = 0; | 1724 | error = 0; |
| 1725 | sock_put(sock->sk); | ||
| 1681 | 1726 | ||
| 1682 | end: | 1727 | end: |
| 1683 | return error; | 1728 | return error; |
| @@ -1916,14 +1961,17 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, | |||
| 1916 | err = -EBADF; | 1961 | err = -EBADF; |
| 1917 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 1962 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
| 1918 | if (tunnel == NULL) | 1963 | if (tunnel == NULL) |
| 1919 | goto end; | 1964 | goto end_put_sess; |
| 1920 | 1965 | ||
| 1921 | err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); | 1966 | err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); |
| 1922 | goto end; | 1967 | sock_put(session->tunnel_sock); |
| 1968 | goto end_put_sess; | ||
| 1923 | } | 1969 | } |
| 1924 | 1970 | ||
| 1925 | err = pppol2tp_session_ioctl(session, cmd, arg); | 1971 | err = pppol2tp_session_ioctl(session, cmd, arg); |
| 1926 | 1972 | ||
| 1973 | end_put_sess: | ||
| 1974 | sock_put(sk); | ||
| 1927 | end: | 1975 | end: |
| 1928 | return err; | 1976 | return err; |
| 1929 | } | 1977 | } |
| @@ -2069,14 +2117,17 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | |||
| 2069 | err = -EBADF; | 2117 | err = -EBADF; |
| 2070 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 2118 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
| 2071 | if (tunnel == NULL) | 2119 | if (tunnel == NULL) |
| 2072 | goto end; | 2120 | goto end_put_sess; |
| 2073 | 2121 | ||
| 2074 | err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); | 2122 | err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); |
| 2123 | sock_put(session->tunnel_sock); | ||
| 2075 | } else | 2124 | } else |
| 2076 | err = pppol2tp_session_setsockopt(sk, session, optname, val); | 2125 | err = pppol2tp_session_setsockopt(sk, session, optname, val); |
| 2077 | 2126 | ||
| 2078 | err = 0; | 2127 | err = 0; |
| 2079 | 2128 | ||
| 2129 | end_put_sess: | ||
| 2130 | sock_put(sk); | ||
| 2080 | end: | 2131 | end: |
| 2081 | return err; | 2132 | return err; |
| 2082 | } | 2133 | } |
| @@ -2191,20 +2242,24 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, | |||
| 2191 | err = -EBADF; | 2242 | err = -EBADF; |
| 2192 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 2243 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
| 2193 | if (tunnel == NULL) | 2244 | if (tunnel == NULL) |
| 2194 | goto end; | 2245 | goto end_put_sess; |
| 2195 | 2246 | ||
| 2196 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); | 2247 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); |
| 2248 | sock_put(session->tunnel_sock); | ||
| 2197 | } else | 2249 | } else |
| 2198 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); | 2250 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); |
| 2199 | 2251 | ||
| 2200 | err = -EFAULT; | 2252 | err = -EFAULT; |
| 2201 | if (put_user(len, (int __user *) optlen)) | 2253 | if (put_user(len, (int __user *) optlen)) |
| 2202 | goto end; | 2254 | goto end_put_sess; |
| 2203 | 2255 | ||
| 2204 | if (copy_to_user((void __user *) optval, &val, len)) | 2256 | if (copy_to_user((void __user *) optval, &val, len)) |
| 2205 | goto end; | 2257 | goto end_put_sess; |
| 2206 | 2258 | ||
| 2207 | err = 0; | 2259 | err = 0; |
| 2260 | |||
| 2261 | end_put_sess: | ||
| 2262 | sock_put(sk); | ||
| 2208 | end: | 2263 | end: |
| 2209 | return err; | 2264 | return err; |
| 2210 | } | 2265 | } |
