diff options
Diffstat (limited to 'net/x25')
-rw-r--r-- | net/x25/af_x25.c | 179 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 36 | ||||
-rw-r--r-- | net/x25/x25_forward.c | 4 | ||||
-rw-r--r-- | net/x25/x25_in.c | 12 | ||||
-rw-r--r-- | net/x25/x25_link.c | 12 | ||||
-rw-r--r-- | net/x25/x25_out.c | 7 |
6 files changed, 135 insertions, 115 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 5e86d4e97dce..4680b1e4c79c 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
41 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/smp_lock.h> | ||
44 | #include <linux/timer.h> | 43 | #include <linux/timer.h> |
45 | #include <linux/string.h> | 44 | #include <linux/string.h> |
46 | #include <linux/net.h> | 45 | #include <linux/net.h> |
@@ -432,15 +431,6 @@ void x25_destroy_socket_from_timer(struct sock *sk) | |||
432 | sock_put(sk); | 431 | sock_put(sk); |
433 | } | 432 | } |
434 | 433 | ||
435 | static void x25_destroy_socket(struct sock *sk) | ||
436 | { | ||
437 | sock_hold(sk); | ||
438 | lock_sock(sk); | ||
439 | __x25_destroy_socket(sk); | ||
440 | release_sock(sk); | ||
441 | sock_put(sk); | ||
442 | } | ||
443 | |||
444 | /* | 434 | /* |
445 | * Handling for system calls applied via the various interfaces to a | 435 | * Handling for system calls applied via the various interfaces to a |
446 | * X.25 socket object. | 436 | * X.25 socket object. |
@@ -507,14 +497,14 @@ static int x25_listen(struct socket *sock, int backlog) | |||
507 | struct sock *sk = sock->sk; | 497 | struct sock *sk = sock->sk; |
508 | int rc = -EOPNOTSUPP; | 498 | int rc = -EOPNOTSUPP; |
509 | 499 | ||
510 | lock_kernel(); | 500 | lock_sock(sk); |
511 | if (sk->sk_state != TCP_LISTEN) { | 501 | if (sk->sk_state != TCP_LISTEN) { |
512 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); | 502 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); |
513 | sk->sk_max_ack_backlog = backlog; | 503 | sk->sk_max_ack_backlog = backlog; |
514 | sk->sk_state = TCP_LISTEN; | 504 | sk->sk_state = TCP_LISTEN; |
515 | rc = 0; | 505 | rc = 0; |
516 | } | 506 | } |
517 | unlock_kernel(); | 507 | release_sock(sk); |
518 | 508 | ||
519 | return rc; | 509 | return rc; |
520 | } | 510 | } |
@@ -647,18 +637,19 @@ static int x25_release(struct socket *sock) | |||
647 | struct sock *sk = sock->sk; | 637 | struct sock *sk = sock->sk; |
648 | struct x25_sock *x25; | 638 | struct x25_sock *x25; |
649 | 639 | ||
650 | lock_kernel(); | ||
651 | if (!sk) | 640 | if (!sk) |
652 | goto out; | 641 | return 0; |
653 | 642 | ||
654 | x25 = x25_sk(sk); | 643 | x25 = x25_sk(sk); |
655 | 644 | ||
645 | sock_hold(sk); | ||
646 | lock_sock(sk); | ||
656 | switch (x25->state) { | 647 | switch (x25->state) { |
657 | 648 | ||
658 | case X25_STATE_0: | 649 | case X25_STATE_0: |
659 | case X25_STATE_2: | 650 | case X25_STATE_2: |
660 | x25_disconnect(sk, 0, 0, 0); | 651 | x25_disconnect(sk, 0, 0, 0); |
661 | x25_destroy_socket(sk); | 652 | __x25_destroy_socket(sk); |
662 | goto out; | 653 | goto out; |
663 | 654 | ||
664 | case X25_STATE_1: | 655 | case X25_STATE_1: |
@@ -678,7 +669,8 @@ static int x25_release(struct socket *sock) | |||
678 | 669 | ||
679 | sock_orphan(sk); | 670 | sock_orphan(sk); |
680 | out: | 671 | out: |
681 | unlock_kernel(); | 672 | release_sock(sk); |
673 | sock_put(sk); | ||
682 | return 0; | 674 | return 0; |
683 | } | 675 | } |
684 | 676 | ||
@@ -688,7 +680,6 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
688 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; | 680 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; |
689 | int len, i, rc = 0; | 681 | int len, i, rc = 0; |
690 | 682 | ||
691 | lock_kernel(); | ||
692 | if (!sock_flag(sk, SOCK_ZAPPED) || | 683 | if (!sock_flag(sk, SOCK_ZAPPED) || |
693 | addr_len != sizeof(struct sockaddr_x25) || | 684 | addr_len != sizeof(struct sockaddr_x25) || |
694 | addr->sx25_family != AF_X25) { | 685 | addr->sx25_family != AF_X25) { |
@@ -704,12 +695,13 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
704 | } | 695 | } |
705 | } | 696 | } |
706 | 697 | ||
698 | lock_sock(sk); | ||
707 | x25_sk(sk)->source_addr = addr->sx25_addr; | 699 | x25_sk(sk)->source_addr = addr->sx25_addr; |
708 | x25_insert_socket(sk); | 700 | x25_insert_socket(sk); |
709 | sock_reset_flag(sk, SOCK_ZAPPED); | 701 | sock_reset_flag(sk, SOCK_ZAPPED); |
702 | release_sock(sk); | ||
710 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); | 703 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); |
711 | out: | 704 | out: |
712 | unlock_kernel(); | ||
713 | return rc; | 705 | return rc; |
714 | } | 706 | } |
715 | 707 | ||
@@ -751,7 +743,6 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, | |||
751 | struct x25_route *rt; | 743 | struct x25_route *rt; |
752 | int rc = 0; | 744 | int rc = 0; |
753 | 745 | ||
754 | lock_kernel(); | ||
755 | lock_sock(sk); | 746 | lock_sock(sk); |
756 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 747 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
757 | sock->state = SS_CONNECTED; | 748 | sock->state = SS_CONNECTED; |
@@ -829,7 +820,6 @@ out_put_route: | |||
829 | x25_route_put(rt); | 820 | x25_route_put(rt); |
830 | out: | 821 | out: |
831 | release_sock(sk); | 822 | release_sock(sk); |
832 | unlock_kernel(); | ||
833 | return rc; | 823 | return rc; |
834 | } | 824 | } |
835 | 825 | ||
@@ -869,8 +859,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
869 | struct sk_buff *skb; | 859 | struct sk_buff *skb; |
870 | int rc = -EINVAL; | 860 | int rc = -EINVAL; |
871 | 861 | ||
872 | lock_kernel(); | 862 | if (!sk) |
873 | if (!sk || sk->sk_state != TCP_LISTEN) | ||
874 | goto out; | 863 | goto out; |
875 | 864 | ||
876 | rc = -EOPNOTSUPP; | 865 | rc = -EOPNOTSUPP; |
@@ -878,6 +867,10 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
878 | goto out; | 867 | goto out; |
879 | 868 | ||
880 | lock_sock(sk); | 869 | lock_sock(sk); |
870 | rc = -EINVAL; | ||
871 | if (sk->sk_state != TCP_LISTEN) | ||
872 | goto out2; | ||
873 | |||
881 | rc = x25_wait_for_data(sk, sk->sk_rcvtimeo); | 874 | rc = x25_wait_for_data(sk, sk->sk_rcvtimeo); |
882 | if (rc) | 875 | if (rc) |
883 | goto out2; | 876 | goto out2; |
@@ -897,7 +890,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
897 | out2: | 890 | out2: |
898 | release_sock(sk); | 891 | release_sock(sk); |
899 | out: | 892 | out: |
900 | unlock_kernel(); | ||
901 | return rc; | 893 | return rc; |
902 | } | 894 | } |
903 | 895 | ||
@@ -909,7 +901,6 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
909 | struct x25_sock *x25 = x25_sk(sk); | 901 | struct x25_sock *x25 = x25_sk(sk); |
910 | int rc = 0; | 902 | int rc = 0; |
911 | 903 | ||
912 | lock_kernel(); | ||
913 | if (peer) { | 904 | if (peer) { |
914 | if (sk->sk_state != TCP_ESTABLISHED) { | 905 | if (sk->sk_state != TCP_ESTABLISHED) { |
915 | rc = -ENOTCONN; | 906 | rc = -ENOTCONN; |
@@ -923,19 +914,6 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
923 | *uaddr_len = sizeof(*sx25); | 914 | *uaddr_len = sizeof(*sx25); |
924 | 915 | ||
925 | out: | 916 | out: |
926 | unlock_kernel(); | ||
927 | return rc; | ||
928 | } | ||
929 | |||
930 | static unsigned int x25_datagram_poll(struct file *file, struct socket *sock, | ||
931 | poll_table *wait) | ||
932 | { | ||
933 | int rc; | ||
934 | |||
935 | lock_kernel(); | ||
936 | rc = datagram_poll(file, sock, wait); | ||
937 | unlock_kernel(); | ||
938 | |||
939 | return rc; | 917 | return rc; |
940 | } | 918 | } |
941 | 919 | ||
@@ -1099,7 +1077,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1099 | size_t size; | 1077 | size_t size; |
1100 | int qbit = 0, rc = -EINVAL; | 1078 | int qbit = 0, rc = -EINVAL; |
1101 | 1079 | ||
1102 | lock_kernel(); | 1080 | lock_sock(sk); |
1103 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) | 1081 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) |
1104 | goto out; | 1082 | goto out; |
1105 | 1083 | ||
@@ -1162,7 +1140,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1162 | 1140 | ||
1163 | size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN; | 1141 | size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN; |
1164 | 1142 | ||
1143 | release_sock(sk); | ||
1165 | skb = sock_alloc_send_skb(sk, size, noblock, &rc); | 1144 | skb = sock_alloc_send_skb(sk, size, noblock, &rc); |
1145 | lock_sock(sk); | ||
1166 | if (!skb) | 1146 | if (!skb) |
1167 | goto out; | 1147 | goto out; |
1168 | X25_SKB_CB(skb)->flags = msg->msg_flags; | 1148 | X25_SKB_CB(skb)->flags = msg->msg_flags; |
@@ -1245,26 +1225,10 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1245 | len++; | 1225 | len++; |
1246 | } | 1226 | } |
1247 | 1227 | ||
1248 | /* | ||
1249 | * lock_sock() is currently only used to serialize this x25_kick() | ||
1250 | * against input-driven x25_kick() calls. It currently only blocks | ||
1251 | * incoming packets for this socket and does not protect against | ||
1252 | * any other socket state changes and is not called from anywhere | ||
1253 | * else. As x25_kick() cannot block and as long as all socket | ||
1254 | * operations are BKL-wrapped, we don't need take to care about | ||
1255 | * purging the backlog queue in x25_release(). | ||
1256 | * | ||
1257 | * Using lock_sock() to protect all socket operations entirely | ||
1258 | * (and making the whole x25 stack SMP aware) unfortunately would | ||
1259 | * require major changes to {send,recv}msg and skb allocation methods. | ||
1260 | * -> 2.5 ;) | ||
1261 | */ | ||
1262 | lock_sock(sk); | ||
1263 | x25_kick(sk); | 1228 | x25_kick(sk); |
1264 | release_sock(sk); | ||
1265 | rc = len; | 1229 | rc = len; |
1266 | out: | 1230 | out: |
1267 | unlock_kernel(); | 1231 | release_sock(sk); |
1268 | return rc; | 1232 | return rc; |
1269 | out_kfree_skb: | 1233 | out_kfree_skb: |
1270 | kfree_skb(skb); | 1234 | kfree_skb(skb); |
@@ -1285,7 +1249,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1285 | unsigned char *asmptr; | 1249 | unsigned char *asmptr; |
1286 | int rc = -ENOTCONN; | 1250 | int rc = -ENOTCONN; |
1287 | 1251 | ||
1288 | lock_kernel(); | 1252 | lock_sock(sk); |
1289 | /* | 1253 | /* |
1290 | * This works for seqpacket too. The receiver has ordered the queue for | 1254 | * This works for seqpacket too. The receiver has ordered the queue for |
1291 | * us! We do one quick check first though | 1255 | * us! We do one quick check first though |
@@ -1314,8 +1278,10 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1314 | msg->msg_flags |= MSG_OOB; | 1278 | msg->msg_flags |= MSG_OOB; |
1315 | } else { | 1279 | } else { |
1316 | /* Now we can treat all alike */ | 1280 | /* Now we can treat all alike */ |
1281 | release_sock(sk); | ||
1317 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1282 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
1318 | flags & MSG_DONTWAIT, &rc); | 1283 | flags & MSG_DONTWAIT, &rc); |
1284 | lock_sock(sk); | ||
1319 | if (!skb) | 1285 | if (!skb) |
1320 | goto out; | 1286 | goto out; |
1321 | 1287 | ||
@@ -1352,14 +1318,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1352 | 1318 | ||
1353 | msg->msg_namelen = sizeof(struct sockaddr_x25); | 1319 | msg->msg_namelen = sizeof(struct sockaddr_x25); |
1354 | 1320 | ||
1355 | lock_sock(sk); | ||
1356 | x25_check_rbuf(sk); | 1321 | x25_check_rbuf(sk); |
1357 | release_sock(sk); | ||
1358 | rc = copied; | 1322 | rc = copied; |
1359 | out_free_dgram: | 1323 | out_free_dgram: |
1360 | skb_free_datagram(sk, skb); | 1324 | skb_free_datagram(sk, skb); |
1361 | out: | 1325 | out: |
1362 | unlock_kernel(); | 1326 | release_sock(sk); |
1363 | return rc; | 1327 | return rc; |
1364 | } | 1328 | } |
1365 | 1329 | ||
@@ -1371,11 +1335,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1371 | void __user *argp = (void __user *)arg; | 1335 | void __user *argp = (void __user *)arg; |
1372 | int rc; | 1336 | int rc; |
1373 | 1337 | ||
1374 | lock_kernel(); | ||
1375 | switch (cmd) { | 1338 | switch (cmd) { |
1376 | case TIOCOUTQ: { | 1339 | case TIOCOUTQ: { |
1377 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1340 | int amount; |
1378 | 1341 | ||
1342 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | ||
1379 | if (amount < 0) | 1343 | if (amount < 0) |
1380 | amount = 0; | 1344 | amount = 0; |
1381 | rc = put_user(amount, (unsigned int __user *)argp); | 1345 | rc = put_user(amount, (unsigned int __user *)argp); |
@@ -1389,8 +1353,10 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1389 | * These two are safe on a single CPU system as | 1353 | * These two are safe on a single CPU system as |
1390 | * only user tasks fiddle here | 1354 | * only user tasks fiddle here |
1391 | */ | 1355 | */ |
1356 | lock_sock(sk); | ||
1392 | if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) | 1357 | if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) |
1393 | amount = skb->len; | 1358 | amount = skb->len; |
1359 | release_sock(sk); | ||
1394 | rc = put_user(amount, (unsigned int __user *)argp); | 1360 | rc = put_user(amount, (unsigned int __user *)argp); |
1395 | break; | 1361 | break; |
1396 | } | 1362 | } |
@@ -1436,9 +1402,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1436 | rc = x25_subscr_ioctl(cmd, argp); | 1402 | rc = x25_subscr_ioctl(cmd, argp); |
1437 | break; | 1403 | break; |
1438 | case SIOCX25GFACILITIES: { | 1404 | case SIOCX25GFACILITIES: { |
1439 | struct x25_facilities fac = x25->facilities; | 1405 | lock_sock(sk); |
1440 | rc = copy_to_user(argp, &fac, | 1406 | rc = copy_to_user(argp, &x25->facilities, |
1441 | sizeof(fac)) ? -EFAULT : 0; | 1407 | sizeof(x25->facilities)) |
1408 | ? -EFAULT : 0; | ||
1409 | release_sock(sk); | ||
1442 | break; | 1410 | break; |
1443 | } | 1411 | } |
1444 | 1412 | ||
@@ -1449,18 +1417,19 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1449 | sizeof(facilities))) | 1417 | sizeof(facilities))) |
1450 | break; | 1418 | break; |
1451 | rc = -EINVAL; | 1419 | rc = -EINVAL; |
1420 | lock_sock(sk); | ||
1452 | if (sk->sk_state != TCP_LISTEN && | 1421 | if (sk->sk_state != TCP_LISTEN && |
1453 | sk->sk_state != TCP_CLOSE) | 1422 | sk->sk_state != TCP_CLOSE) |
1454 | break; | 1423 | goto out_fac_release; |
1455 | if (facilities.pacsize_in < X25_PS16 || | 1424 | if (facilities.pacsize_in < X25_PS16 || |
1456 | facilities.pacsize_in > X25_PS4096) | 1425 | facilities.pacsize_in > X25_PS4096) |
1457 | break; | 1426 | goto out_fac_release; |
1458 | if (facilities.pacsize_out < X25_PS16 || | 1427 | if (facilities.pacsize_out < X25_PS16 || |
1459 | facilities.pacsize_out > X25_PS4096) | 1428 | facilities.pacsize_out > X25_PS4096) |
1460 | break; | 1429 | goto out_fac_release; |
1461 | if (facilities.winsize_in < 1 || | 1430 | if (facilities.winsize_in < 1 || |
1462 | facilities.winsize_in > 127) | 1431 | facilities.winsize_in > 127) |
1463 | break; | 1432 | goto out_fac_release; |
1464 | if (facilities.throughput) { | 1433 | if (facilities.throughput) { |
1465 | int out = facilities.throughput & 0xf0; | 1434 | int out = facilities.throughput & 0xf0; |
1466 | int in = facilities.throughput & 0x0f; | 1435 | int in = facilities.throughput & 0x0f; |
@@ -1468,24 +1437,28 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1468 | facilities.throughput |= | 1437 | facilities.throughput |= |
1469 | X25_DEFAULT_THROUGHPUT << 4; | 1438 | X25_DEFAULT_THROUGHPUT << 4; |
1470 | else if (out < 0x30 || out > 0xD0) | 1439 | else if (out < 0x30 || out > 0xD0) |
1471 | break; | 1440 | goto out_fac_release; |
1472 | if (!in) | 1441 | if (!in) |
1473 | facilities.throughput |= | 1442 | facilities.throughput |= |
1474 | X25_DEFAULT_THROUGHPUT; | 1443 | X25_DEFAULT_THROUGHPUT; |
1475 | else if (in < 0x03 || in > 0x0D) | 1444 | else if (in < 0x03 || in > 0x0D) |
1476 | break; | 1445 | goto out_fac_release; |
1477 | } | 1446 | } |
1478 | if (facilities.reverse && | 1447 | if (facilities.reverse && |
1479 | (facilities.reverse & 0x81) != 0x81) | 1448 | (facilities.reverse & 0x81) != 0x81) |
1480 | break; | 1449 | goto out_fac_release; |
1481 | x25->facilities = facilities; | 1450 | x25->facilities = facilities; |
1482 | rc = 0; | 1451 | rc = 0; |
1452 | out_fac_release: | ||
1453 | release_sock(sk); | ||
1483 | break; | 1454 | break; |
1484 | } | 1455 | } |
1485 | 1456 | ||
1486 | case SIOCX25GDTEFACILITIES: { | 1457 | case SIOCX25GDTEFACILITIES: { |
1458 | lock_sock(sk); | ||
1487 | rc = copy_to_user(argp, &x25->dte_facilities, | 1459 | rc = copy_to_user(argp, &x25->dte_facilities, |
1488 | sizeof(x25->dte_facilities)); | 1460 | sizeof(x25->dte_facilities)); |
1461 | release_sock(sk); | ||
1489 | if (rc) | 1462 | if (rc) |
1490 | rc = -EFAULT; | 1463 | rc = -EFAULT; |
1491 | break; | 1464 | break; |
@@ -1497,26 +1470,31 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1497 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) | 1470 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) |
1498 | break; | 1471 | break; |
1499 | rc = -EINVAL; | 1472 | rc = -EINVAL; |
1473 | lock_sock(sk); | ||
1500 | if (sk->sk_state != TCP_LISTEN && | 1474 | if (sk->sk_state != TCP_LISTEN && |
1501 | sk->sk_state != TCP_CLOSE) | 1475 | sk->sk_state != TCP_CLOSE) |
1502 | break; | 1476 | goto out_dtefac_release; |
1503 | if (dtefacs.calling_len > X25_MAX_AE_LEN) | 1477 | if (dtefacs.calling_len > X25_MAX_AE_LEN) |
1504 | break; | 1478 | goto out_dtefac_release; |
1505 | if (dtefacs.calling_ae == NULL) | 1479 | if (dtefacs.calling_ae == NULL) |
1506 | break; | 1480 | goto out_dtefac_release; |
1507 | if (dtefacs.called_len > X25_MAX_AE_LEN) | 1481 | if (dtefacs.called_len > X25_MAX_AE_LEN) |
1508 | break; | 1482 | goto out_dtefac_release; |
1509 | if (dtefacs.called_ae == NULL) | 1483 | if (dtefacs.called_ae == NULL) |
1510 | break; | 1484 | goto out_dtefac_release; |
1511 | x25->dte_facilities = dtefacs; | 1485 | x25->dte_facilities = dtefacs; |
1512 | rc = 0; | 1486 | rc = 0; |
1487 | out_dtefac_release: | ||
1488 | release_sock(sk); | ||
1513 | break; | 1489 | break; |
1514 | } | 1490 | } |
1515 | 1491 | ||
1516 | case SIOCX25GCALLUSERDATA: { | 1492 | case SIOCX25GCALLUSERDATA: { |
1517 | struct x25_calluserdata cud = x25->calluserdata; | 1493 | lock_sock(sk); |
1518 | rc = copy_to_user(argp, &cud, | 1494 | rc = copy_to_user(argp, &x25->calluserdata, |
1519 | sizeof(cud)) ? -EFAULT : 0; | 1495 | sizeof(x25->calluserdata)) |
1496 | ? -EFAULT : 0; | ||
1497 | release_sock(sk); | ||
1520 | break; | 1498 | break; |
1521 | } | 1499 | } |
1522 | 1500 | ||
@@ -1530,16 +1508,19 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1530 | rc = -EINVAL; | 1508 | rc = -EINVAL; |
1531 | if (calluserdata.cudlength > X25_MAX_CUD_LEN) | 1509 | if (calluserdata.cudlength > X25_MAX_CUD_LEN) |
1532 | break; | 1510 | break; |
1511 | lock_sock(sk); | ||
1533 | x25->calluserdata = calluserdata; | 1512 | x25->calluserdata = calluserdata; |
1513 | release_sock(sk); | ||
1534 | rc = 0; | 1514 | rc = 0; |
1535 | break; | 1515 | break; |
1536 | } | 1516 | } |
1537 | 1517 | ||
1538 | case SIOCX25GCAUSEDIAG: { | 1518 | case SIOCX25GCAUSEDIAG: { |
1539 | struct x25_causediag causediag; | 1519 | lock_sock(sk); |
1540 | causediag = x25->causediag; | 1520 | rc = copy_to_user(argp, &x25->causediag, |
1541 | rc = copy_to_user(argp, &causediag, | 1521 | sizeof(x25->causediag)) |
1542 | sizeof(causediag)) ? -EFAULT : 0; | 1522 | ? -EFAULT : 0; |
1523 | release_sock(sk); | ||
1543 | break; | 1524 | break; |
1544 | } | 1525 | } |
1545 | 1526 | ||
@@ -1548,7 +1529,9 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1548 | rc = -EFAULT; | 1529 | rc = -EFAULT; |
1549 | if (copy_from_user(&causediag, argp, sizeof(causediag))) | 1530 | if (copy_from_user(&causediag, argp, sizeof(causediag))) |
1550 | break; | 1531 | break; |
1532 | lock_sock(sk); | ||
1551 | x25->causediag = causediag; | 1533 | x25->causediag = causediag; |
1534 | release_sock(sk); | ||
1552 | rc = 0; | 1535 | rc = 0; |
1553 | break; | 1536 | break; |
1554 | 1537 | ||
@@ -1557,31 +1540,37 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1557 | case SIOCX25SCUDMATCHLEN: { | 1540 | case SIOCX25SCUDMATCHLEN: { |
1558 | struct x25_subaddr sub_addr; | 1541 | struct x25_subaddr sub_addr; |
1559 | rc = -EINVAL; | 1542 | rc = -EINVAL; |
1543 | lock_sock(sk); | ||
1560 | if(sk->sk_state != TCP_CLOSE) | 1544 | if(sk->sk_state != TCP_CLOSE) |
1561 | break; | 1545 | goto out_cud_release; |
1562 | rc = -EFAULT; | 1546 | rc = -EFAULT; |
1563 | if (copy_from_user(&sub_addr, argp, | 1547 | if (copy_from_user(&sub_addr, argp, |
1564 | sizeof(sub_addr))) | 1548 | sizeof(sub_addr))) |
1565 | break; | 1549 | goto out_cud_release; |
1566 | rc = -EINVAL; | 1550 | rc = -EINVAL; |
1567 | if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) | 1551 | if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) |
1568 | break; | 1552 | goto out_cud_release; |
1569 | x25->cudmatchlength = sub_addr.cudmatchlength; | 1553 | x25->cudmatchlength = sub_addr.cudmatchlength; |
1570 | rc = 0; | 1554 | rc = 0; |
1555 | out_cud_release: | ||
1556 | release_sock(sk); | ||
1571 | break; | 1557 | break; |
1572 | } | 1558 | } |
1573 | 1559 | ||
1574 | case SIOCX25CALLACCPTAPPRV: { | 1560 | case SIOCX25CALLACCPTAPPRV: { |
1575 | rc = -EINVAL; | 1561 | rc = -EINVAL; |
1562 | lock_sock(sk); | ||
1576 | if (sk->sk_state != TCP_CLOSE) | 1563 | if (sk->sk_state != TCP_CLOSE) |
1577 | break; | 1564 | break; |
1578 | clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); | 1565 | clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); |
1566 | release_sock(sk); | ||
1579 | rc = 0; | 1567 | rc = 0; |
1580 | break; | 1568 | break; |
1581 | } | 1569 | } |
1582 | 1570 | ||
1583 | case SIOCX25SENDCALLACCPT: { | 1571 | case SIOCX25SENDCALLACCPT: { |
1584 | rc = -EINVAL; | 1572 | rc = -EINVAL; |
1573 | lock_sock(sk); | ||
1585 | if (sk->sk_state != TCP_ESTABLISHED) | 1574 | if (sk->sk_state != TCP_ESTABLISHED) |
1586 | break; | 1575 | break; |
1587 | /* must call accptapprv above */ | 1576 | /* must call accptapprv above */ |
@@ -1589,6 +1578,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1589 | break; | 1578 | break; |
1590 | x25_write_internal(sk, X25_CALL_ACCEPTED); | 1579 | x25_write_internal(sk, X25_CALL_ACCEPTED); |
1591 | x25->state = X25_STATE_3; | 1580 | x25->state = X25_STATE_3; |
1581 | release_sock(sk); | ||
1592 | rc = 0; | 1582 | rc = 0; |
1593 | break; | 1583 | break; |
1594 | } | 1584 | } |
@@ -1597,7 +1587,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1597 | rc = -ENOIOCTLCMD; | 1587 | rc = -ENOIOCTLCMD; |
1598 | break; | 1588 | break; |
1599 | } | 1589 | } |
1600 | unlock_kernel(); | ||
1601 | 1590 | ||
1602 | return rc; | 1591 | return rc; |
1603 | } | 1592 | } |
@@ -1633,16 +1622,20 @@ static int compat_x25_subscr_ioctl(unsigned int cmd, | |||
1633 | dev_put(dev); | 1622 | dev_put(dev); |
1634 | 1623 | ||
1635 | if (cmd == SIOCX25GSUBSCRIP) { | 1624 | if (cmd == SIOCX25GSUBSCRIP) { |
1625 | read_lock_bh(&x25_neigh_list_lock); | ||
1636 | x25_subscr.extended = nb->extended; | 1626 | x25_subscr.extended = nb->extended; |
1637 | x25_subscr.global_facil_mask = nb->global_facil_mask; | 1627 | x25_subscr.global_facil_mask = nb->global_facil_mask; |
1628 | read_unlock_bh(&x25_neigh_list_lock); | ||
1638 | rc = copy_to_user(x25_subscr32, &x25_subscr, | 1629 | rc = copy_to_user(x25_subscr32, &x25_subscr, |
1639 | sizeof(*x25_subscr32)) ? -EFAULT : 0; | 1630 | sizeof(*x25_subscr32)) ? -EFAULT : 0; |
1640 | } else { | 1631 | } else { |
1641 | rc = -EINVAL; | 1632 | rc = -EINVAL; |
1642 | if (x25_subscr.extended == 0 || x25_subscr.extended == 1) { | 1633 | if (x25_subscr.extended == 0 || x25_subscr.extended == 1) { |
1643 | rc = 0; | 1634 | rc = 0; |
1635 | write_lock_bh(&x25_neigh_list_lock); | ||
1644 | nb->extended = x25_subscr.extended; | 1636 | nb->extended = x25_subscr.extended; |
1645 | nb->global_facil_mask = x25_subscr.global_facil_mask; | 1637 | nb->global_facil_mask = x25_subscr.global_facil_mask; |
1638 | write_unlock_bh(&x25_neigh_list_lock); | ||
1646 | } | 1639 | } |
1647 | } | 1640 | } |
1648 | x25_neigh_put(nb); | 1641 | x25_neigh_put(nb); |
@@ -1668,19 +1661,15 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1668 | break; | 1661 | break; |
1669 | case SIOCGSTAMP: | 1662 | case SIOCGSTAMP: |
1670 | rc = -EINVAL; | 1663 | rc = -EINVAL; |
1671 | lock_kernel(); | ||
1672 | if (sk) | 1664 | if (sk) |
1673 | rc = compat_sock_get_timestamp(sk, | 1665 | rc = compat_sock_get_timestamp(sk, |
1674 | (struct timeval __user*)argp); | 1666 | (struct timeval __user*)argp); |
1675 | unlock_kernel(); | ||
1676 | break; | 1667 | break; |
1677 | case SIOCGSTAMPNS: | 1668 | case SIOCGSTAMPNS: |
1678 | rc = -EINVAL; | 1669 | rc = -EINVAL; |
1679 | lock_kernel(); | ||
1680 | if (sk) | 1670 | if (sk) |
1681 | rc = compat_sock_get_timestampns(sk, | 1671 | rc = compat_sock_get_timestampns(sk, |
1682 | (struct timespec __user*)argp); | 1672 | (struct timespec __user*)argp); |
1683 | unlock_kernel(); | ||
1684 | break; | 1673 | break; |
1685 | case SIOCGIFADDR: | 1674 | case SIOCGIFADDR: |
1686 | case SIOCSIFADDR: | 1675 | case SIOCSIFADDR: |
@@ -1699,22 +1688,16 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1699 | rc = -EPERM; | 1688 | rc = -EPERM; |
1700 | if (!capable(CAP_NET_ADMIN)) | 1689 | if (!capable(CAP_NET_ADMIN)) |
1701 | break; | 1690 | break; |
1702 | lock_kernel(); | ||
1703 | rc = x25_route_ioctl(cmd, argp); | 1691 | rc = x25_route_ioctl(cmd, argp); |
1704 | unlock_kernel(); | ||
1705 | break; | 1692 | break; |
1706 | case SIOCX25GSUBSCRIP: | 1693 | case SIOCX25GSUBSCRIP: |
1707 | lock_kernel(); | ||
1708 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1694 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1709 | unlock_kernel(); | ||
1710 | break; | 1695 | break; |
1711 | case SIOCX25SSUBSCRIP: | 1696 | case SIOCX25SSUBSCRIP: |
1712 | rc = -EPERM; | 1697 | rc = -EPERM; |
1713 | if (!capable(CAP_NET_ADMIN)) | 1698 | if (!capable(CAP_NET_ADMIN)) |
1714 | break; | 1699 | break; |
1715 | lock_kernel(); | ||
1716 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1700 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1717 | unlock_kernel(); | ||
1718 | break; | 1701 | break; |
1719 | case SIOCX25GFACILITIES: | 1702 | case SIOCX25GFACILITIES: |
1720 | case SIOCX25SFACILITIES: | 1703 | case SIOCX25SFACILITIES: |
@@ -1746,7 +1729,7 @@ static const struct proto_ops x25_proto_ops = { | |||
1746 | .socketpair = sock_no_socketpair, | 1729 | .socketpair = sock_no_socketpair, |
1747 | .accept = x25_accept, | 1730 | .accept = x25_accept, |
1748 | .getname = x25_getname, | 1731 | .getname = x25_getname, |
1749 | .poll = x25_datagram_poll, | 1732 | .poll = datagram_poll, |
1750 | .ioctl = x25_ioctl, | 1733 | .ioctl = x25_ioctl, |
1751 | #ifdef CONFIG_COMPAT | 1734 | #ifdef CONFIG_COMPAT |
1752 | .compat_ioctl = compat_x25_ioctl, | 1735 | .compat_ioctl = compat_x25_ioctl, |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 771bab00754b..f77e4e75f914 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -27,9 +27,19 @@ | |||
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/x25.h> | 28 | #include <net/x25.h> |
29 | 29 | ||
30 | /* | 30 | /** |
31 | * Parse a set of facilities into the facilities structures. Unrecognised | 31 | * x25_parse_facilities - Parse facilities from skb into the facilities structs |
32 | * facilities are written to the debug log file. | 32 | * |
33 | * @skb: sk_buff to parse | ||
34 | * @facilities: Regular facilities, updated as facilities are found | ||
35 | * @dte_facs: ITU DTE facilities, updated as DTE facilities are found | ||
36 | * @vc_fac_mask: mask is updated with all facilities found | ||
37 | * | ||
38 | * Return codes: | ||
39 | * -1 - Parsing error, caller should drop call and clean up | ||
40 | * 0 - Parse OK, this skb has no facilities | ||
41 | * >0 - Parse OK, returns the length of the facilities header | ||
42 | * | ||
33 | */ | 43 | */ |
34 | 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, |
35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 45 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
@@ -61,6 +71,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
61 | while (len > 0) { | 71 | while (len > 0) { |
62 | switch (*p & X25_FAC_CLASS_MASK) { | 72 | switch (*p & X25_FAC_CLASS_MASK) { |
63 | case X25_FAC_CLASS_A: | 73 | case X25_FAC_CLASS_A: |
74 | if (len < 2) | ||
75 | return -1; | ||
64 | switch (*p) { | 76 | switch (*p) { |
65 | case X25_FAC_REVERSE: | 77 | case X25_FAC_REVERSE: |
66 | if((p[1] & 0x81) == 0x81) { | 78 | if((p[1] & 0x81) == 0x81) { |
@@ -104,6 +116,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
104 | len -= 2; | 116 | len -= 2; |
105 | break; | 117 | break; |
106 | case X25_FAC_CLASS_B: | 118 | case X25_FAC_CLASS_B: |
119 | if (len < 3) | ||
120 | return -1; | ||
107 | switch (*p) { | 121 | switch (*p) { |
108 | case X25_FAC_PACKET_SIZE: | 122 | case X25_FAC_PACKET_SIZE: |
109 | facilities->pacsize_in = p[1]; | 123 | facilities->pacsize_in = p[1]; |
@@ -125,6 +139,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
125 | len -= 3; | 139 | len -= 3; |
126 | break; | 140 | break; |
127 | case X25_FAC_CLASS_C: | 141 | case X25_FAC_CLASS_C: |
142 | if (len < 4) | ||
143 | return -1; | ||
128 | printk(KERN_DEBUG "X.25: unknown facility %02X, " | 144 | printk(KERN_DEBUG "X.25: unknown facility %02X, " |
129 | "values %02X, %02X, %02X\n", | 145 | "values %02X, %02X, %02X\n", |
130 | p[0], p[1], p[2], p[3]); | 146 | p[0], p[1], p[2], p[3]); |
@@ -132,26 +148,26 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
132 | len -= 4; | 148 | len -= 4; |
133 | break; | 149 | break; |
134 | case X25_FAC_CLASS_D: | 150 | case X25_FAC_CLASS_D: |
151 | if (len < p[1] + 2) | ||
152 | return -1; | ||
135 | switch (*p) { | 153 | switch (*p) { |
136 | case X25_FAC_CALLING_AE: | 154 | case X25_FAC_CALLING_AE: |
137 | if (p[1] > X25_MAX_DTE_FACIL_LEN) | 155 | if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) |
138 | break; | 156 | return -1; |
139 | dte_facs->calling_len = p[2]; | 157 | dte_facs->calling_len = p[2]; |
140 | memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); | 158 | memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); |
141 | *vc_fac_mask |= X25_MASK_CALLING_AE; | 159 | *vc_fac_mask |= X25_MASK_CALLING_AE; |
142 | break; | 160 | break; |
143 | case X25_FAC_CALLED_AE: | 161 | case X25_FAC_CALLED_AE: |
144 | if (p[1] > X25_MAX_DTE_FACIL_LEN) | 162 | if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) |
145 | break; | 163 | return -1; |
146 | dte_facs->called_len = p[2]; | 164 | dte_facs->called_len = p[2]; |
147 | memcpy(dte_facs->called_ae, &p[3], p[1] - 1); | 165 | memcpy(dte_facs->called_ae, &p[3], p[1] - 1); |
148 | *vc_fac_mask |= X25_MASK_CALLED_AE; | 166 | *vc_fac_mask |= X25_MASK_CALLED_AE; |
149 | break; | 167 | break; |
150 | default: | 168 | default: |
151 | printk(KERN_DEBUG "X.25: unknown facility %02X," | 169 | printk(KERN_DEBUG "X.25: unknown facility %02X," |
152 | "length %d, values %02X, %02X, " | 170 | "length %d\n", p[0], p[1]); |
153 | "%02X, %02X\n", | ||
154 | p[0], p[1], p[2], p[3], p[4], p[5]); | ||
155 | break; | 171 | break; |
156 | } | 172 | } |
157 | len -= p[1] + 2; | 173 | len -= p[1] + 2; |
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 25a810793968..c541b622ae16 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -31,7 +31,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
31 | goto out_no_route; | 31 | goto out_no_route; |
32 | 32 | ||
33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { | 33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { |
34 | /* This shouldnt happen, if it occurs somehow | 34 | /* This shouldn't happen, if it occurs somehow |
35 | * do something sensible | 35 | * do something sensible |
36 | */ | 36 | */ |
37 | goto out_put_route; | 37 | goto out_put_route; |
@@ -45,7 +45,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /* Remote end sending a call request on an already | 47 | /* Remote end sending a call request on an already |
48 | * established LCI? It shouldnt happen, just in case.. | 48 | * established LCI? It shouldn't happen, just in case.. |
49 | */ | 49 | */ |
50 | read_lock_bh(&x25_forward_list_lock); | 50 | read_lock_bh(&x25_forward_list_lock); |
51 | list_for_each(entry, &x25_forward_list) { | 51 | list_for_each(entry, &x25_forward_list) { |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 63178961efac..15de65f04719 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -91,10 +91,10 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
91 | { | 91 | { |
92 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
93 | int len; | 93 | int len; |
94 | struct x25_sock *x25 = x25_sk(sk); | ||
94 | 95 | ||
95 | switch (frametype) { | 96 | switch (frametype) { |
96 | case X25_CALL_ACCEPTED: { | 97 | case X25_CALL_ACCEPTED: { |
97 | struct x25_sock *x25 = x25_sk(sk); | ||
98 | 98 | ||
99 | x25_stop_timer(sk); | 99 | x25_stop_timer(sk); |
100 | x25->condition = 0x00; | 100 | x25->condition = 0x00; |
@@ -113,12 +113,16 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
113 | &dest_addr); | 113 | &dest_addr); |
114 | if (len > 0) | 114 | if (len > 0) |
115 | skb_pull(skb, len); | 115 | skb_pull(skb, len); |
116 | else if (len < 0) | ||
117 | goto out_clear; | ||
116 | 118 | ||
117 | len = x25_parse_facilities(skb, &x25->facilities, | 119 | len = x25_parse_facilities(skb, &x25->facilities, |
118 | &x25->dte_facilities, | 120 | &x25->dte_facilities, |
119 | &x25->vc_facil_mask); | 121 | &x25->vc_facil_mask); |
120 | if (len > 0) | 122 | if (len > 0) |
121 | skb_pull(skb, len); | 123 | skb_pull(skb, len); |
124 | else if (len < 0) | ||
125 | goto out_clear; | ||
122 | /* | 126 | /* |
123 | * Copy any Call User Data. | 127 | * Copy any Call User Data. |
124 | */ | 128 | */ |
@@ -142,6 +146,12 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
142 | } | 146 | } |
143 | 147 | ||
144 | return 0; | 148 | return 0; |
149 | |||
150 | out_clear: | ||
151 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
152 | x25->state = X25_STATE_2; | ||
153 | x25_start_t23timer(sk); | ||
154 | return 0; | ||
145 | } | 155 | } |
146 | 156 | ||
147 | /* | 157 | /* |
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 73e7b954ad28..21306928d47f 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c | |||
@@ -31,8 +31,8 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <net/x25.h> | 32 | #include <net/x25.h> |
33 | 33 | ||
34 | static LIST_HEAD(x25_neigh_list); | 34 | LIST_HEAD(x25_neigh_list); |
35 | static DEFINE_RWLOCK(x25_neigh_list_lock); | 35 | DEFINE_RWLOCK(x25_neigh_list_lock); |
36 | 36 | ||
37 | static void x25_t20timer_expiry(unsigned long); | 37 | static void x25_t20timer_expiry(unsigned long); |
38 | 38 | ||
@@ -360,16 +360,20 @@ int x25_subscr_ioctl(unsigned int cmd, void __user *arg) | |||
360 | dev_put(dev); | 360 | dev_put(dev); |
361 | 361 | ||
362 | if (cmd == SIOCX25GSUBSCRIP) { | 362 | if (cmd == SIOCX25GSUBSCRIP) { |
363 | read_lock_bh(&x25_neigh_list_lock); | ||
363 | x25_subscr.extended = nb->extended; | 364 | x25_subscr.extended = nb->extended; |
364 | x25_subscr.global_facil_mask = nb->global_facil_mask; | 365 | x25_subscr.global_facil_mask = nb->global_facil_mask; |
366 | read_unlock_bh(&x25_neigh_list_lock); | ||
365 | rc = copy_to_user(arg, &x25_subscr, | 367 | rc = copy_to_user(arg, &x25_subscr, |
366 | sizeof(x25_subscr)) ? -EFAULT : 0; | 368 | sizeof(x25_subscr)) ? -EFAULT : 0; |
367 | } else { | 369 | } else { |
368 | rc = -EINVAL; | 370 | rc = -EINVAL; |
369 | if (!(x25_subscr.extended && x25_subscr.extended != 1)) { | 371 | if (!(x25_subscr.extended && x25_subscr.extended != 1)) { |
370 | rc = 0; | 372 | rc = 0; |
373 | write_lock_bh(&x25_neigh_list_lock); | ||
371 | nb->extended = x25_subscr.extended; | 374 | nb->extended = x25_subscr.extended; |
372 | nb->global_facil_mask = x25_subscr.global_facil_mask; | 375 | nb->global_facil_mask = x25_subscr.global_facil_mask; |
376 | write_unlock_bh(&x25_neigh_list_lock); | ||
373 | } | 377 | } |
374 | } | 378 | } |
375 | x25_neigh_put(nb); | 379 | x25_neigh_put(nb); |
@@ -392,8 +396,12 @@ void __exit x25_link_free(void) | |||
392 | write_lock_bh(&x25_neigh_list_lock); | 396 | write_lock_bh(&x25_neigh_list_lock); |
393 | 397 | ||
394 | list_for_each_safe(entry, tmp, &x25_neigh_list) { | 398 | list_for_each_safe(entry, tmp, &x25_neigh_list) { |
399 | struct net_device *dev; | ||
400 | |||
395 | nb = list_entry(entry, struct x25_neigh, node); | 401 | nb = list_entry(entry, struct x25_neigh, node); |
402 | dev = nb->dev; | ||
396 | __x25_remove_neigh(nb); | 403 | __x25_remove_neigh(nb); |
404 | dev_put(dev); | ||
397 | } | 405 | } |
398 | write_unlock_bh(&x25_neigh_list_lock); | 406 | write_unlock_bh(&x25_neigh_list_lock); |
399 | } | 407 | } |
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index d00649fb251d..0144271d2184 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c | |||
@@ -68,8 +68,11 @@ int x25_output(struct sock *sk, struct sk_buff *skb) | |||
68 | frontlen = skb_headroom(skb); | 68 | frontlen = skb_headroom(skb); |
69 | 69 | ||
70 | while (skb->len > 0) { | 70 | while (skb->len > 0) { |
71 | if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, | 71 | release_sock(sk); |
72 | noblock, &err)) == NULL){ | 72 | skbn = sock_alloc_send_skb(sk, frontlen + max_len, |
73 | noblock, &err); | ||
74 | lock_sock(sk); | ||
75 | if (!skbn) { | ||
73 | if (err == -EWOULDBLOCK && noblock){ | 76 | if (err == -EWOULDBLOCK && noblock){ |
74 | kfree_skb(skb); | 77 | kfree_skb(skb); |
75 | return sent; | 78 | return sent; |