diff options
Diffstat (limited to 'drivers/net/pppol2tp.c')
-rw-r--r-- | drivers/net/pppol2tp.c | 131 |
1 files changed, 100 insertions, 31 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 8db342f2fdc9..f9298827a76c 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 | } |
@@ -772,14 +783,18 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
772 | err = 0; | 783 | err = 0; |
773 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 784 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
774 | flags & MSG_DONTWAIT, &err); | 785 | flags & MSG_DONTWAIT, &err); |
775 | if (skb) { | 786 | if (!skb) |
776 | err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data, | 787 | goto end; |
777 | skb->len); | 788 | |
778 | if (err < 0) | 789 | if (len > skb->len) |
779 | goto do_skb_free; | 790 | len = skb->len; |
780 | err = skb->len; | 791 | else if (len < skb->len) |
781 | } | 792 | msg->msg_flags |= MSG_TRUNC; |
782 | do_skb_free: | 793 | |
794 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); | ||
795 | if (likely(err == 0)) | ||
796 | err = len; | ||
797 | |||
783 | kfree_skb(skb); | 798 | kfree_skb(skb); |
784 | end: | 799 | end: |
785 | return err; | 800 | return err; |
@@ -858,7 +873,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
858 | 873 | ||
859 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 874 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
860 | if (tunnel == NULL) | 875 | if (tunnel == NULL) |
861 | goto error; | 876 | goto error_put_sess; |
862 | 877 | ||
863 | /* What header length is configured for this session? */ | 878 | /* What header length is configured for this session? */ |
864 | hdr_len = pppol2tp_l2tp_header_len(session); | 879 | hdr_len = pppol2tp_l2tp_header_len(session); |
@@ -870,7 +885,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
870 | sizeof(ppph) + total_len, | 885 | sizeof(ppph) + total_len, |
871 | 0, GFP_KERNEL); | 886 | 0, GFP_KERNEL); |
872 | if (!skb) | 887 | if (!skb) |
873 | goto error; | 888 | goto error_put_sess_tun; |
874 | 889 | ||
875 | /* Reserve space for headers. */ | 890 | /* Reserve space for headers. */ |
876 | skb_reserve(skb, NET_SKB_PAD); | 891 | skb_reserve(skb, NET_SKB_PAD); |
@@ -900,7 +915,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
900 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); | 915 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); |
901 | if (error < 0) { | 916 | if (error < 0) { |
902 | kfree_skb(skb); | 917 | kfree_skb(skb); |
903 | goto error; | 918 | goto error_put_sess_tun; |
904 | } | 919 | } |
905 | skb_put(skb, total_len); | 920 | skb_put(skb, total_len); |
906 | 921 | ||
@@ -947,10 +962,33 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
947 | session->stats.tx_errors++; | 962 | session->stats.tx_errors++; |
948 | } | 963 | } |
949 | 964 | ||
965 | return error; | ||
966 | |||
967 | error_put_sess_tun: | ||
968 | sock_put(session->tunnel_sock); | ||
969 | error_put_sess: | ||
970 | sock_put(sk); | ||
950 | error: | 971 | error: |
951 | return error; | 972 | return error; |
952 | } | 973 | } |
953 | 974 | ||
975 | /* Automatically called when the skb is freed. | ||
976 | */ | ||
977 | static void pppol2tp_sock_wfree(struct sk_buff *skb) | ||
978 | { | ||
979 | sock_put(skb->sk); | ||
980 | } | ||
981 | |||
982 | /* For data skbs that we transmit, we associate with the tunnel socket | ||
983 | * but don't do accounting. | ||
984 | */ | ||
985 | static inline void pppol2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
986 | { | ||
987 | sock_hold(sk); | ||
988 | skb->sk = sk; | ||
989 | skb->destructor = pppol2tp_sock_wfree; | ||
990 | } | ||
991 | |||
954 | /* Transmit function called by generic PPP driver. Sends PPP frame | 992 | /* Transmit function called by generic PPP driver. Sends PPP frame |
955 | * over PPPoL2TP socket. | 993 | * over PPPoL2TP socket. |
956 | * | 994 | * |
@@ -993,10 +1031,10 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
993 | 1031 | ||
994 | sk_tun = session->tunnel_sock; | 1032 | sk_tun = session->tunnel_sock; |
995 | if (sk_tun == NULL) | 1033 | if (sk_tun == NULL) |
996 | goto abort; | 1034 | goto abort_put_sess; |
997 | tunnel = pppol2tp_sock_to_tunnel(sk_tun); | 1035 | tunnel = pppol2tp_sock_to_tunnel(sk_tun); |
998 | if (tunnel == NULL) | 1036 | if (tunnel == NULL) |
999 | goto abort; | 1037 | goto abort_put_sess; |
1000 | 1038 | ||
1001 | /* What header length is configured for this session? */ | 1039 | /* What header length is configured for this session? */ |
1002 | hdr_len = pppol2tp_l2tp_header_len(session); | 1040 | hdr_len = pppol2tp_l2tp_header_len(session); |
@@ -1009,7 +1047,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1009 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); | 1047 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); |
1010 | old_headroom = skb_headroom(skb); | 1048 | old_headroom = skb_headroom(skb); |
1011 | if (skb_cow_head(skb, headroom)) | 1049 | if (skb_cow_head(skb, headroom)) |
1012 | goto abort; | 1050 | goto abort_put_sess_tun; |
1013 | 1051 | ||
1014 | new_headroom = skb_headroom(skb); | 1052 | new_headroom = skb_headroom(skb); |
1015 | skb_orphan(skb); | 1053 | skb_orphan(skb); |
@@ -1069,7 +1107,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1069 | /* Get routing info from the tunnel socket */ | 1107 | /* Get routing info from the tunnel socket */ |
1070 | dst_release(skb->dst); | 1108 | dst_release(skb->dst); |
1071 | skb->dst = dst_clone(__sk_dst_get(sk_tun)); | 1109 | skb->dst = dst_clone(__sk_dst_get(sk_tun)); |
1072 | skb->sk = sk_tun; | 1110 | pppol2tp_skb_set_owner_w(skb, sk_tun); |
1073 | 1111 | ||
1074 | /* Queue the packet to IP for output */ | 1112 | /* Queue the packet to IP for output */ |
1075 | len = skb->len; | 1113 | len = skb->len; |
@@ -1086,8 +1124,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1086 | session->stats.tx_errors++; | 1124 | session->stats.tx_errors++; |
1087 | } | 1125 | } |
1088 | 1126 | ||
1127 | sock_put(sk_tun); | ||
1128 | sock_put(sk); | ||
1089 | return 1; | 1129 | return 1; |
1090 | 1130 | ||
1131 | abort_put_sess_tun: | ||
1132 | sock_put(sk_tun); | ||
1133 | abort_put_sess: | ||
1134 | sock_put(sk); | ||
1091 | abort: | 1135 | abort: |
1092 | /* Free the original skb */ | 1136 | /* Free the original skb */ |
1093 | kfree_skb(skb); | 1137 | kfree_skb(skb); |
@@ -1191,7 +1235,7 @@ static void pppol2tp_tunnel_destruct(struct sock *sk) | |||
1191 | { | 1235 | { |
1192 | struct pppol2tp_tunnel *tunnel; | 1236 | struct pppol2tp_tunnel *tunnel; |
1193 | 1237 | ||
1194 | tunnel = pppol2tp_sock_to_tunnel(sk); | 1238 | tunnel = sk->sk_user_data; |
1195 | if (tunnel == NULL) | 1239 | if (tunnel == NULL) |
1196 | goto end; | 1240 | goto end; |
1197 | 1241 | ||
@@ -1230,10 +1274,12 @@ static void pppol2tp_session_destruct(struct sock *sk) | |||
1230 | if (sk->sk_user_data != NULL) { | 1274 | if (sk->sk_user_data != NULL) { |
1231 | struct pppol2tp_tunnel *tunnel; | 1275 | struct pppol2tp_tunnel *tunnel; |
1232 | 1276 | ||
1233 | session = pppol2tp_sock_to_session(sk); | 1277 | session = sk->sk_user_data; |
1234 | if (session == NULL) | 1278 | if (session == NULL) |
1235 | goto out; | 1279 | goto out; |
1236 | 1280 | ||
1281 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | ||
1282 | |||
1237 | /* Don't use pppol2tp_sock_to_tunnel() here to | 1283 | /* Don't use pppol2tp_sock_to_tunnel() here to |
1238 | * get the tunnel context because the tunnel | 1284 | * get the tunnel context because the tunnel |
1239 | * socket might have already been closed (its | 1285 | * socket might have already been closed (its |
@@ -1279,6 +1325,7 @@ out: | |||
1279 | static int pppol2tp_release(struct socket *sock) | 1325 | static int pppol2tp_release(struct socket *sock) |
1280 | { | 1326 | { |
1281 | struct sock *sk = sock->sk; | 1327 | struct sock *sk = sock->sk; |
1328 | struct pppol2tp_session *session; | ||
1282 | int error; | 1329 | int error; |
1283 | 1330 | ||
1284 | if (!sk) | 1331 | if (!sk) |
@@ -1296,9 +1343,18 @@ static int pppol2tp_release(struct socket *sock) | |||
1296 | sock_orphan(sk); | 1343 | sock_orphan(sk); |
1297 | sock->sk = NULL; | 1344 | sock->sk = NULL; |
1298 | 1345 | ||
1346 | session = pppol2tp_sock_to_session(sk); | ||
1347 | |||
1299 | /* Purge any queued data */ | 1348 | /* Purge any queued data */ |
1300 | skb_queue_purge(&sk->sk_receive_queue); | 1349 | skb_queue_purge(&sk->sk_receive_queue); |
1301 | skb_queue_purge(&sk->sk_write_queue); | 1350 | skb_queue_purge(&sk->sk_write_queue); |
1351 | if (session != NULL) { | ||
1352 | struct sk_buff *skb; | ||
1353 | while ((skb = skb_dequeue(&session->reorder_q))) { | ||
1354 | kfree_skb(skb); | ||
1355 | sock_put(sk); | ||
1356 | } | ||
1357 | } | ||
1302 | 1358 | ||
1303 | release_sock(sk); | 1359 | release_sock(sk); |
1304 | 1360 | ||
@@ -1601,7 +1657,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
1601 | 1657 | ||
1602 | error = ppp_register_channel(&po->chan); | 1658 | error = ppp_register_channel(&po->chan); |
1603 | if (error) | 1659 | if (error) |
1604 | goto end; | 1660 | goto end_put_tun; |
1605 | 1661 | ||
1606 | /* This is how we get the session context from the socket. */ | 1662 | /* This is how we get the session context from the socket. */ |
1607 | sk->sk_user_data = session; | 1663 | sk->sk_user_data = session; |
@@ -1621,6 +1677,8 @@ out_no_ppp: | |||
1621 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | 1677 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, |
1622 | "%s: created\n", session->name); | 1678 | "%s: created\n", session->name); |
1623 | 1679 | ||
1680 | end_put_tun: | ||
1681 | sock_put(tunnel_sock); | ||
1624 | end: | 1682 | end: |
1625 | release_sock(sk); | 1683 | release_sock(sk); |
1626 | 1684 | ||
@@ -1668,6 +1726,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1668 | *usockaddr_len = len; | 1726 | *usockaddr_len = len; |
1669 | 1727 | ||
1670 | error = 0; | 1728 | error = 0; |
1729 | sock_put(sock->sk); | ||
1671 | 1730 | ||
1672 | end: | 1731 | end: |
1673 | return error; | 1732 | return error; |
@@ -1906,14 +1965,17 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, | |||
1906 | err = -EBADF; | 1965 | err = -EBADF; |
1907 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 1966 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
1908 | if (tunnel == NULL) | 1967 | if (tunnel == NULL) |
1909 | goto end; | 1968 | goto end_put_sess; |
1910 | 1969 | ||
1911 | err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); | 1970 | err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); |
1912 | goto end; | 1971 | sock_put(session->tunnel_sock); |
1972 | goto end_put_sess; | ||
1913 | } | 1973 | } |
1914 | 1974 | ||
1915 | err = pppol2tp_session_ioctl(session, cmd, arg); | 1975 | err = pppol2tp_session_ioctl(session, cmd, arg); |
1916 | 1976 | ||
1977 | end_put_sess: | ||
1978 | sock_put(sk); | ||
1917 | end: | 1979 | end: |
1918 | return err; | 1980 | return err; |
1919 | } | 1981 | } |
@@ -2059,14 +2121,17 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | |||
2059 | err = -EBADF; | 2121 | err = -EBADF; |
2060 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 2122 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
2061 | if (tunnel == NULL) | 2123 | if (tunnel == NULL) |
2062 | goto end; | 2124 | goto end_put_sess; |
2063 | 2125 | ||
2064 | err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); | 2126 | err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); |
2127 | sock_put(session->tunnel_sock); | ||
2065 | } else | 2128 | } else |
2066 | err = pppol2tp_session_setsockopt(sk, session, optname, val); | 2129 | err = pppol2tp_session_setsockopt(sk, session, optname, val); |
2067 | 2130 | ||
2068 | err = 0; | 2131 | err = 0; |
2069 | 2132 | ||
2133 | end_put_sess: | ||
2134 | sock_put(sk); | ||
2070 | end: | 2135 | end: |
2071 | return err; | 2136 | return err; |
2072 | } | 2137 | } |
@@ -2181,20 +2246,24 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, | |||
2181 | err = -EBADF; | 2246 | err = -EBADF; |
2182 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); | 2247 | tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); |
2183 | if (tunnel == NULL) | 2248 | if (tunnel == NULL) |
2184 | goto end; | 2249 | goto end_put_sess; |
2185 | 2250 | ||
2186 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); | 2251 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); |
2252 | sock_put(session->tunnel_sock); | ||
2187 | } else | 2253 | } else |
2188 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); | 2254 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); |
2189 | 2255 | ||
2190 | err = -EFAULT; | 2256 | err = -EFAULT; |
2191 | if (put_user(len, (int __user *) optlen)) | 2257 | if (put_user(len, (int __user *) optlen)) |
2192 | goto end; | 2258 | goto end_put_sess; |
2193 | 2259 | ||
2194 | if (copy_to_user((void __user *) optval, &val, len)) | 2260 | if (copy_to_user((void __user *) optval, &val, len)) |
2195 | goto end; | 2261 | goto end_put_sess; |
2196 | 2262 | ||
2197 | err = 0; | 2263 | err = 0; |
2264 | |||
2265 | end_put_sess: | ||
2266 | sock_put(sk); | ||
2198 | end: | 2267 | end: |
2199 | return err; | 2268 | return err; |
2200 | } | 2269 | } |