aboutsummaryrefslogtreecommitdiffstats
path: root/net/x25
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25')
-rw-r--r--net/x25/af_x25.c179
-rw-r--r--net/x25/x25_facilities.c36
-rw-r--r--net/x25/x25_forward.c4
-rw-r--r--net/x25/x25_in.c12
-rw-r--r--net/x25/x25_link.c12
-rw-r--r--net/x25/x25_out.c7
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
435static 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);
680out: 671out:
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");
711out: 704out:
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);
830out: 821out:
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)
897out2: 890out2:
898 release_sock(sk); 891 release_sock(sk);
899out: 892out:
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
925out: 916out:
926 unlock_kernel();
927 return rc;
928}
929
930static 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;
1266out: 1230out:
1267 unlock_kernel(); 1231 release_sock(sk);
1268 return rc; 1232 return rc;
1269out_kfree_skb: 1233out_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;
1359out_free_dgram: 1323out_free_dgram:
1360 skb_free_datagram(sk, skb); 1324 skb_free_datagram(sk, skb);
1361out: 1325out:
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;
1452out_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;
1487out_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;
1555out_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 */
34int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, 44int 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
150out_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
34static LIST_HEAD(x25_neigh_list); 34LIST_HEAD(x25_neigh_list);
35static DEFINE_RWLOCK(x25_neigh_list_lock); 35DEFINE_RWLOCK(x25_neigh_list_lock);
36 36
37static void x25_t20timer_expiry(unsigned long); 37static 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;