diff options
| -rw-r--r-- | net/irda/af_irda.c | 370 |
1 files changed, 196 insertions, 174 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index bf3635129b17..7f097989cde2 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
| @@ -715,14 +715,11 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
| 715 | struct sockaddr_irda saddr; | 715 | struct sockaddr_irda saddr; |
| 716 | struct sock *sk = sock->sk; | 716 | struct sock *sk = sock->sk; |
| 717 | struct irda_sock *self = irda_sk(sk); | 717 | struct irda_sock *self = irda_sk(sk); |
| 718 | int err; | ||
| 719 | 718 | ||
| 720 | lock_kernel(); | ||
| 721 | memset(&saddr, 0, sizeof(saddr)); | 719 | memset(&saddr, 0, sizeof(saddr)); |
| 722 | if (peer) { | 720 | if (peer) { |
| 723 | err = -ENOTCONN; | ||
| 724 | if (sk->sk_state != TCP_ESTABLISHED) | 721 | if (sk->sk_state != TCP_ESTABLISHED) |
| 725 | goto out; | 722 | return -ENOTCONN; |
| 726 | 723 | ||
| 727 | saddr.sir_family = AF_IRDA; | 724 | saddr.sir_family = AF_IRDA; |
| 728 | saddr.sir_lsap_sel = self->dtsap_sel; | 725 | saddr.sir_lsap_sel = self->dtsap_sel; |
| @@ -739,10 +736,8 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
| 739 | /* uaddr_len come to us uninitialised */ | 736 | /* uaddr_len come to us uninitialised */ |
| 740 | *uaddr_len = sizeof (struct sockaddr_irda); | 737 | *uaddr_len = sizeof (struct sockaddr_irda); |
| 741 | memcpy(uaddr, &saddr, *uaddr_len); | 738 | memcpy(uaddr, &saddr, *uaddr_len); |
| 742 | err = 0; | 739 | |
| 743 | out: | 740 | return 0; |
| 744 | unlock_kernel(); | ||
| 745 | return err; | ||
| 746 | } | 741 | } |
| 747 | 742 | ||
| 748 | /* | 743 | /* |
| @@ -758,7 +753,8 @@ static int irda_listen(struct socket *sock, int backlog) | |||
| 758 | 753 | ||
| 759 | IRDA_DEBUG(2, "%s()\n", __func__); | 754 | IRDA_DEBUG(2, "%s()\n", __func__); |
| 760 | 755 | ||
| 761 | lock_kernel(); | 756 | lock_sock(sk); |
| 757 | |||
| 762 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && | 758 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && |
| 763 | (sk->sk_type != SOCK_DGRAM)) | 759 | (sk->sk_type != SOCK_DGRAM)) |
| 764 | goto out; | 760 | goto out; |
| @@ -770,7 +766,7 @@ static int irda_listen(struct socket *sock, int backlog) | |||
| 770 | err = 0; | 766 | err = 0; |
| 771 | } | 767 | } |
| 772 | out: | 768 | out: |
| 773 | unlock_kernel(); | 769 | release_sock(sk); |
| 774 | 770 | ||
| 775 | return err; | 771 | return err; |
| 776 | } | 772 | } |
| @@ -793,7 +789,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 793 | if (addr_len != sizeof(struct sockaddr_irda)) | 789 | if (addr_len != sizeof(struct sockaddr_irda)) |
| 794 | return -EINVAL; | 790 | return -EINVAL; |
| 795 | 791 | ||
| 796 | lock_kernel(); | 792 | lock_sock(sk); |
| 797 | #ifdef CONFIG_IRDA_ULTRA | 793 | #ifdef CONFIG_IRDA_ULTRA |
| 798 | /* Special care for Ultra sockets */ | 794 | /* Special care for Ultra sockets */ |
| 799 | if ((sk->sk_type == SOCK_DGRAM) && | 795 | if ((sk->sk_type == SOCK_DGRAM) && |
| @@ -836,7 +832,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 836 | 832 | ||
| 837 | err = 0; | 833 | err = 0; |
| 838 | out: | 834 | out: |
| 839 | unlock_kernel(); | 835 | release_sock(sk); |
| 840 | return err; | 836 | return err; |
| 841 | } | 837 | } |
| 842 | 838 | ||
| @@ -856,12 +852,13 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 856 | 852 | ||
| 857 | IRDA_DEBUG(2, "%s()\n", __func__); | 853 | IRDA_DEBUG(2, "%s()\n", __func__); |
| 858 | 854 | ||
| 859 | lock_kernel(); | ||
| 860 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); | 855 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); |
| 861 | if (err) | 856 | if (err) |
| 862 | goto out; | 857 | return err; |
| 863 | 858 | ||
| 864 | err = -EINVAL; | 859 | err = -EINVAL; |
| 860 | |||
| 861 | lock_sock(sk); | ||
| 865 | if (sock->state != SS_UNCONNECTED) | 862 | if (sock->state != SS_UNCONNECTED) |
| 866 | goto out; | 863 | goto out; |
| 867 | 864 | ||
| @@ -947,7 +944,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 947 | irda_connect_response(new); | 944 | irda_connect_response(new); |
| 948 | err = 0; | 945 | err = 0; |
| 949 | out: | 946 | out: |
| 950 | unlock_kernel(); | 947 | release_sock(sk); |
| 951 | return err; | 948 | return err; |
| 952 | } | 949 | } |
| 953 | 950 | ||
| @@ -981,7 +978,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 981 | 978 | ||
| 982 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 979 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
| 983 | 980 | ||
| 984 | lock_kernel(); | 981 | lock_sock(sk); |
| 985 | /* Don't allow connect for Ultra sockets */ | 982 | /* Don't allow connect for Ultra sockets */ |
| 986 | err = -ESOCKTNOSUPPORT; | 983 | err = -ESOCKTNOSUPPORT; |
| 987 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) | 984 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) |
| @@ -1072,6 +1069,8 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 1072 | 1069 | ||
| 1073 | if (sk->sk_state != TCP_ESTABLISHED) { | 1070 | if (sk->sk_state != TCP_ESTABLISHED) { |
| 1074 | sock->state = SS_UNCONNECTED; | 1071 | sock->state = SS_UNCONNECTED; |
| 1072 | if (sk->sk_prot->disconnect(sk, flags)) | ||
| 1073 | sock->state = SS_DISCONNECTING; | ||
| 1075 | err = sock_error(sk); | 1074 | err = sock_error(sk); |
| 1076 | if (!err) | 1075 | if (!err) |
| 1077 | err = -ECONNRESET; | 1076 | err = -ECONNRESET; |
| @@ -1084,7 +1083,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 1084 | self->saddr = irttp_get_saddr(self->tsap); | 1083 | self->saddr = irttp_get_saddr(self->tsap); |
| 1085 | err = 0; | 1084 | err = 0; |
| 1086 | out: | 1085 | out: |
| 1087 | unlock_kernel(); | 1086 | release_sock(sk); |
| 1088 | return err; | 1087 | return err; |
| 1089 | } | 1088 | } |
| 1090 | 1089 | ||
| @@ -1231,7 +1230,6 @@ static int irda_release(struct socket *sock) | |||
| 1231 | if (sk == NULL) | 1230 | if (sk == NULL) |
| 1232 | return 0; | 1231 | return 0; |
| 1233 | 1232 | ||
| 1234 | lock_kernel(); | ||
| 1235 | lock_sock(sk); | 1233 | lock_sock(sk); |
| 1236 | sk->sk_state = TCP_CLOSE; | 1234 | sk->sk_state = TCP_CLOSE; |
| 1237 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1235 | sk->sk_shutdown |= SEND_SHUTDOWN; |
| @@ -1250,7 +1248,6 @@ static int irda_release(struct socket *sock) | |||
| 1250 | /* Destroy networking socket if we are the last reference on it, | 1248 | /* Destroy networking socket if we are the last reference on it, |
| 1251 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ | 1249 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ |
| 1252 | sock_put(sk); | 1250 | sock_put(sk); |
| 1253 | unlock_kernel(); | ||
| 1254 | 1251 | ||
| 1255 | /* Notes on socket locking and deallocation... - Jean II | 1252 | /* Notes on socket locking and deallocation... - Jean II |
| 1256 | * In theory we should put pairs of sock_hold() / sock_put() to | 1253 | * In theory we should put pairs of sock_hold() / sock_put() to |
| @@ -1298,7 +1295,6 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1298 | 1295 | ||
| 1299 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1296 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
| 1300 | 1297 | ||
| 1301 | lock_kernel(); | ||
| 1302 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ | 1298 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ |
| 1303 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | | 1299 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | |
| 1304 | MSG_NOSIGNAL)) { | 1300 | MSG_NOSIGNAL)) { |
| @@ -1306,6 +1302,8 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1306 | goto out; | 1302 | goto out; |
| 1307 | } | 1303 | } |
| 1308 | 1304 | ||
| 1305 | lock_sock(sk); | ||
| 1306 | |||
| 1309 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1307 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
| 1310 | goto out_err; | 1308 | goto out_err; |
| 1311 | 1309 | ||
| @@ -1361,14 +1359,14 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1361 | goto out_err; | 1359 | goto out_err; |
| 1362 | } | 1360 | } |
| 1363 | 1361 | ||
| 1364 | unlock_kernel(); | 1362 | release_sock(sk); |
| 1365 | /* Tell client how much data we actually sent */ | 1363 | /* Tell client how much data we actually sent */ |
| 1366 | return len; | 1364 | return len; |
| 1367 | 1365 | ||
| 1368 | out_err: | 1366 | out_err: |
| 1369 | err = sk_stream_error(sk, msg->msg_flags, err); | 1367 | err = sk_stream_error(sk, msg->msg_flags, err); |
| 1370 | out: | 1368 | out: |
| 1371 | unlock_kernel(); | 1369 | release_sock(sk); |
| 1372 | return err; | 1370 | return err; |
| 1373 | 1371 | ||
| 1374 | } | 1372 | } |
| @@ -1390,14 +1388,10 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
| 1390 | 1388 | ||
| 1391 | IRDA_DEBUG(4, "%s()\n", __func__); | 1389 | IRDA_DEBUG(4, "%s()\n", __func__); |
| 1392 | 1390 | ||
| 1393 | lock_kernel(); | ||
| 1394 | if ((err = sock_error(sk)) < 0) | ||
| 1395 | goto out; | ||
| 1396 | |||
| 1397 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1391 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
| 1398 | flags & MSG_DONTWAIT, &err); | 1392 | flags & MSG_DONTWAIT, &err); |
| 1399 | if (!skb) | 1393 | if (!skb) |
| 1400 | goto out; | 1394 | return err; |
| 1401 | 1395 | ||
| 1402 | skb_reset_transport_header(skb); | 1396 | skb_reset_transport_header(skb); |
| 1403 | copied = skb->len; | 1397 | copied = skb->len; |
| @@ -1425,12 +1419,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
| 1425 | irttp_flow_request(self->tsap, FLOW_START); | 1419 | irttp_flow_request(self->tsap, FLOW_START); |
| 1426 | } | 1420 | } |
| 1427 | } | 1421 | } |
| 1428 | unlock_kernel(); | ||
| 1429 | return copied; | ||
| 1430 | 1422 | ||
| 1431 | out: | 1423 | return copied; |
| 1432 | unlock_kernel(); | ||
| 1433 | return err; | ||
| 1434 | } | 1424 | } |
| 1435 | 1425 | ||
| 1436 | /* | 1426 | /* |
| @@ -1448,17 +1438,15 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1448 | 1438 | ||
| 1449 | IRDA_DEBUG(3, "%s()\n", __func__); | 1439 | IRDA_DEBUG(3, "%s()\n", __func__); |
| 1450 | 1440 | ||
| 1451 | lock_kernel(); | ||
| 1452 | if ((err = sock_error(sk)) < 0) | 1441 | if ((err = sock_error(sk)) < 0) |
| 1453 | goto out; | 1442 | return err; |
| 1454 | 1443 | ||
| 1455 | err = -EINVAL; | ||
| 1456 | if (sock->flags & __SO_ACCEPTCON) | 1444 | if (sock->flags & __SO_ACCEPTCON) |
| 1457 | goto out; | 1445 | return -EINVAL; |
| 1458 | 1446 | ||
| 1459 | err =-EOPNOTSUPP; | 1447 | err =-EOPNOTSUPP; |
| 1460 | if (flags & MSG_OOB) | 1448 | if (flags & MSG_OOB) |
| 1461 | goto out; | 1449 | return -EOPNOTSUPP; |
| 1462 | 1450 | ||
| 1463 | err = 0; | 1451 | err = 0; |
| 1464 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); | 1452 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); |
| @@ -1500,7 +1488,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1500 | finish_wait(sk_sleep(sk), &wait); | 1488 | finish_wait(sk_sleep(sk), &wait); |
| 1501 | 1489 | ||
| 1502 | if (err) | 1490 | if (err) |
| 1503 | goto out; | 1491 | return err; |
| 1504 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 1492 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
| 1505 | break; | 1493 | break; |
| 1506 | 1494 | ||
| @@ -1553,9 +1541,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1553 | } | 1541 | } |
| 1554 | } | 1542 | } |
| 1555 | 1543 | ||
| 1556 | out: | 1544 | return copied; |
| 1557 | unlock_kernel(); | ||
| 1558 | return err ? : copied; | ||
| 1559 | } | 1545 | } |
| 1560 | 1546 | ||
| 1561 | /* | 1547 | /* |
| @@ -1573,13 +1559,12 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
| 1573 | struct sk_buff *skb; | 1559 | struct sk_buff *skb; |
| 1574 | int err; | 1560 | int err; |
| 1575 | 1561 | ||
| 1576 | lock_kernel(); | ||
| 1577 | |||
| 1578 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1562 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
| 1579 | 1563 | ||
| 1580 | err = -EINVAL; | ||
| 1581 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1564 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
| 1582 | goto out; | 1565 | return -EINVAL; |
| 1566 | |||
| 1567 | lock_sock(sk); | ||
| 1583 | 1568 | ||
| 1584 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1569 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
| 1585 | send_sig(SIGPIPE, current, 0); | 1570 | send_sig(SIGPIPE, current, 0); |
| @@ -1630,10 +1615,12 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
| 1630 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1615 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
| 1631 | goto out; | 1616 | goto out; |
| 1632 | } | 1617 | } |
| 1633 | unlock_kernel(); | 1618 | |
| 1619 | release_sock(sk); | ||
| 1634 | return len; | 1620 | return len; |
| 1621 | |||
| 1635 | out: | 1622 | out: |
| 1636 | unlock_kernel(); | 1623 | release_sock(sk); |
| 1637 | return err; | 1624 | return err; |
| 1638 | } | 1625 | } |
| 1639 | 1626 | ||
| @@ -1656,10 +1643,11 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
| 1656 | 1643 | ||
| 1657 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1644 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
| 1658 | 1645 | ||
| 1659 | lock_kernel(); | ||
| 1660 | err = -EINVAL; | 1646 | err = -EINVAL; |
| 1661 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1647 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
| 1662 | goto out; | 1648 | return -EINVAL; |
| 1649 | |||
| 1650 | lock_sock(sk); | ||
| 1663 | 1651 | ||
| 1664 | err = -EPIPE; | 1652 | err = -EPIPE; |
| 1665 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1653 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
| @@ -1732,7 +1720,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
| 1732 | if (err) | 1720 | if (err) |
| 1733 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1721 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
| 1734 | out: | 1722 | out: |
| 1735 | unlock_kernel(); | 1723 | release_sock(sk); |
| 1736 | return err ? : len; | 1724 | return err ? : len; |
| 1737 | } | 1725 | } |
| 1738 | #endif /* CONFIG_IRDA_ULTRA */ | 1726 | #endif /* CONFIG_IRDA_ULTRA */ |
| @@ -1747,7 +1735,7 @@ static int irda_shutdown(struct socket *sock, int how) | |||
| 1747 | 1735 | ||
| 1748 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); | 1736 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); |
| 1749 | 1737 | ||
| 1750 | lock_kernel(); | 1738 | lock_sock(sk); |
| 1751 | 1739 | ||
| 1752 | sk->sk_state = TCP_CLOSE; | 1740 | sk->sk_state = TCP_CLOSE; |
| 1753 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1741 | sk->sk_shutdown |= SEND_SHUTDOWN; |
| @@ -1769,7 +1757,7 @@ static int irda_shutdown(struct socket *sock, int how) | |||
| 1769 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ | 1757 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ |
| 1770 | self->saddr = 0x0; /* so IrLMP assign us any link */ | 1758 | self->saddr = 0x0; /* so IrLMP assign us any link */ |
| 1771 | 1759 | ||
| 1772 | unlock_kernel(); | 1760 | release_sock(sk); |
| 1773 | 1761 | ||
| 1774 | return 0; | 1762 | return 0; |
| 1775 | } | 1763 | } |
| @@ -1786,7 +1774,6 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
| 1786 | 1774 | ||
| 1787 | IRDA_DEBUG(4, "%s()\n", __func__); | 1775 | IRDA_DEBUG(4, "%s()\n", __func__); |
| 1788 | 1776 | ||
| 1789 | lock_kernel(); | ||
| 1790 | poll_wait(file, sk_sleep(sk), wait); | 1777 | poll_wait(file, sk_sleep(sk), wait); |
| 1791 | mask = 0; | 1778 | mask = 0; |
| 1792 | 1779 | ||
| @@ -1834,20 +1821,8 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
| 1834 | default: | 1821 | default: |
| 1835 | break; | 1822 | break; |
| 1836 | } | 1823 | } |
| 1837 | unlock_kernel(); | ||
| 1838 | return mask; | ||
| 1839 | } | ||
| 1840 | 1824 | ||
| 1841 | static unsigned int irda_datagram_poll(struct file *file, struct socket *sock, | 1825 | return mask; |
| 1842 | poll_table *wait) | ||
| 1843 | { | ||
| 1844 | int err; | ||
| 1845 | |||
| 1846 | lock_kernel(); | ||
| 1847 | err = datagram_poll(file, sock, wait); | ||
| 1848 | unlock_kernel(); | ||
| 1849 | |||
| 1850 | return err; | ||
| 1851 | } | 1826 | } |
| 1852 | 1827 | ||
| 1853 | /* | 1828 | /* |
| @@ -1860,7 +1835,6 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1860 | 1835 | ||
| 1861 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); | 1836 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); |
| 1862 | 1837 | ||
| 1863 | lock_kernel(); | ||
| 1864 | err = -EINVAL; | 1838 | err = -EINVAL; |
| 1865 | switch (cmd) { | 1839 | switch (cmd) { |
| 1866 | case TIOCOUTQ: { | 1840 | case TIOCOUTQ: { |
| @@ -1903,7 +1877,6 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1903 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); | 1877 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); |
| 1904 | err = -ENOIOCTLCMD; | 1878 | err = -ENOIOCTLCMD; |
| 1905 | } | 1879 | } |
| 1906 | unlock_kernel(); | ||
| 1907 | 1880 | ||
| 1908 | return err; | 1881 | return err; |
| 1909 | } | 1882 | } |
| @@ -1927,7 +1900,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon | |||
| 1927 | * Set some options for the socket | 1900 | * Set some options for the socket |
| 1928 | * | 1901 | * |
| 1929 | */ | 1902 | */ |
| 1930 | static int __irda_setsockopt(struct socket *sock, int level, int optname, | 1903 | static int irda_setsockopt(struct socket *sock, int level, int optname, |
| 1931 | char __user *optval, unsigned int optlen) | 1904 | char __user *optval, unsigned int optlen) |
| 1932 | { | 1905 | { |
| 1933 | struct sock *sk = sock->sk; | 1906 | struct sock *sk = sock->sk; |
| @@ -1935,13 +1908,15 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 1935 | struct irda_ias_set *ias_opt; | 1908 | struct irda_ias_set *ias_opt; |
| 1936 | struct ias_object *ias_obj; | 1909 | struct ias_object *ias_obj; |
| 1937 | struct ias_attrib * ias_attr; /* Attribute in IAS object */ | 1910 | struct ias_attrib * ias_attr; /* Attribute in IAS object */ |
| 1938 | int opt, free_ias = 0; | 1911 | int opt, free_ias = 0, err = 0; |
| 1939 | 1912 | ||
| 1940 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 1913 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
| 1941 | 1914 | ||
| 1942 | if (level != SOL_IRLMP) | 1915 | if (level != SOL_IRLMP) |
| 1943 | return -ENOPROTOOPT; | 1916 | return -ENOPROTOOPT; |
| 1944 | 1917 | ||
| 1918 | lock_sock(sk); | ||
| 1919 | |||
| 1945 | switch (optname) { | 1920 | switch (optname) { |
| 1946 | case IRLMP_IAS_SET: | 1921 | case IRLMP_IAS_SET: |
| 1947 | /* The user want to add an attribute to an existing IAS object | 1922 | /* The user want to add an attribute to an existing IAS object |
| @@ -1951,17 +1926,22 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 1951 | * create the right attribute... | 1926 | * create the right attribute... |
| 1952 | */ | 1927 | */ |
| 1953 | 1928 | ||
| 1954 | if (optlen != sizeof(struct irda_ias_set)) | 1929 | if (optlen != sizeof(struct irda_ias_set)) { |
| 1955 | return -EINVAL; | 1930 | err = -EINVAL; |
| 1931 | goto out; | ||
| 1932 | } | ||
| 1956 | 1933 | ||
| 1957 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 1934 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
| 1958 | if (ias_opt == NULL) | 1935 | if (ias_opt == NULL) { |
| 1959 | return -ENOMEM; | 1936 | err = -ENOMEM; |
| 1937 | goto out; | ||
| 1938 | } | ||
| 1960 | 1939 | ||
| 1961 | /* Copy query to the driver. */ | 1940 | /* Copy query to the driver. */ |
| 1962 | if (copy_from_user(ias_opt, optval, optlen)) { | 1941 | if (copy_from_user(ias_opt, optval, optlen)) { |
| 1963 | kfree(ias_opt); | 1942 | kfree(ias_opt); |
| 1964 | return -EFAULT; | 1943 | err = -EFAULT; |
| 1944 | goto out; | ||
| 1965 | } | 1945 | } |
| 1966 | 1946 | ||
| 1967 | /* Find the object we target. | 1947 | /* Find the object we target. |
| @@ -1971,7 +1951,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 1971 | if(ias_opt->irda_class_name[0] == '\0') { | 1951 | if(ias_opt->irda_class_name[0] == '\0') { |
| 1972 | if(self->ias_obj == NULL) { | 1952 | if(self->ias_obj == NULL) { |
| 1973 | kfree(ias_opt); | 1953 | kfree(ias_opt); |
| 1974 | return -EINVAL; | 1954 | err = -EINVAL; |
| 1955 | goto out; | ||
| 1975 | } | 1956 | } |
| 1976 | ias_obj = self->ias_obj; | 1957 | ias_obj = self->ias_obj; |
| 1977 | } else | 1958 | } else |
| @@ -1983,7 +1964,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 1983 | if((!capable(CAP_NET_ADMIN)) && | 1964 | if((!capable(CAP_NET_ADMIN)) && |
| 1984 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { | 1965 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { |
| 1985 | kfree(ias_opt); | 1966 | kfree(ias_opt); |
| 1986 | return -EPERM; | 1967 | err = -EPERM; |
| 1968 | goto out; | ||
| 1987 | } | 1969 | } |
| 1988 | 1970 | ||
| 1989 | /* If the object doesn't exist, create it */ | 1971 | /* If the object doesn't exist, create it */ |
| @@ -1993,7 +1975,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 1993 | jiffies); | 1975 | jiffies); |
| 1994 | if (ias_obj == NULL) { | 1976 | if (ias_obj == NULL) { |
| 1995 | kfree(ias_opt); | 1977 | kfree(ias_opt); |
| 1996 | return -ENOMEM; | 1978 | err = -ENOMEM; |
| 1979 | goto out; | ||
| 1997 | } | 1980 | } |
| 1998 | free_ias = 1; | 1981 | free_ias = 1; |
| 1999 | } | 1982 | } |
| @@ -2005,7 +1988,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2005 | kfree(ias_obj->name); | 1988 | kfree(ias_obj->name); |
| 2006 | kfree(ias_obj); | 1989 | kfree(ias_obj); |
| 2007 | } | 1990 | } |
| 2008 | return -EINVAL; | 1991 | err = -EINVAL; |
| 1992 | goto out; | ||
| 2009 | } | 1993 | } |
| 2010 | 1994 | ||
| 2011 | /* Look at the type */ | 1995 | /* Look at the type */ |
| @@ -2028,7 +2012,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2028 | kfree(ias_obj); | 2012 | kfree(ias_obj); |
| 2029 | } | 2013 | } |
| 2030 | 2014 | ||
| 2031 | return -EINVAL; | 2015 | err = -EINVAL; |
| 2016 | goto out; | ||
| 2032 | } | 2017 | } |
| 2033 | /* Add an octet sequence attribute */ | 2018 | /* Add an octet sequence attribute */ |
| 2034 | irias_add_octseq_attrib( | 2019 | irias_add_octseq_attrib( |
| @@ -2060,7 +2045,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2060 | kfree(ias_obj->name); | 2045 | kfree(ias_obj->name); |
| 2061 | kfree(ias_obj); | 2046 | kfree(ias_obj); |
| 2062 | } | 2047 | } |
| 2063 | return -EINVAL; | 2048 | err = -EINVAL; |
| 2049 | goto out; | ||
| 2064 | } | 2050 | } |
| 2065 | irias_insert_object(ias_obj); | 2051 | irias_insert_object(ias_obj); |
| 2066 | kfree(ias_opt); | 2052 | kfree(ias_opt); |
| @@ -2071,17 +2057,22 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2071 | * object is not owned by the kernel and delete it. | 2057 | * object is not owned by the kernel and delete it. |
| 2072 | */ | 2058 | */ |
| 2073 | 2059 | ||
| 2074 | if (optlen != sizeof(struct irda_ias_set)) | 2060 | if (optlen != sizeof(struct irda_ias_set)) { |
| 2075 | return -EINVAL; | 2061 | err = -EINVAL; |
| 2062 | goto out; | ||
| 2063 | } | ||
| 2076 | 2064 | ||
| 2077 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2065 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
| 2078 | if (ias_opt == NULL) | 2066 | if (ias_opt == NULL) { |
| 2079 | return -ENOMEM; | 2067 | err = -ENOMEM; |
| 2068 | goto out; | ||
| 2069 | } | ||
| 2080 | 2070 | ||
| 2081 | /* Copy query to the driver. */ | 2071 | /* Copy query to the driver. */ |
| 2082 | if (copy_from_user(ias_opt, optval, optlen)) { | 2072 | if (copy_from_user(ias_opt, optval, optlen)) { |
| 2083 | kfree(ias_opt); | 2073 | kfree(ias_opt); |
| 2084 | return -EFAULT; | 2074 | err = -EFAULT; |
| 2075 | goto out; | ||
| 2085 | } | 2076 | } |
| 2086 | 2077 | ||
| 2087 | /* Find the object we target. | 2078 | /* Find the object we target. |
| @@ -2094,7 +2085,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2094 | ias_obj = irias_find_object(ias_opt->irda_class_name); | 2085 | ias_obj = irias_find_object(ias_opt->irda_class_name); |
| 2095 | if(ias_obj == (struct ias_object *) NULL) { | 2086 | if(ias_obj == (struct ias_object *) NULL) { |
| 2096 | kfree(ias_opt); | 2087 | kfree(ias_opt); |
| 2097 | return -EINVAL; | 2088 | err = -EINVAL; |
| 2089 | goto out; | ||
| 2098 | } | 2090 | } |
| 2099 | 2091 | ||
| 2100 | /* Only ROOT can mess with the global IAS database. | 2092 | /* Only ROOT can mess with the global IAS database. |
| @@ -2103,7 +2095,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2103 | if((!capable(CAP_NET_ADMIN)) && | 2095 | if((!capable(CAP_NET_ADMIN)) && |
| 2104 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { | 2096 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { |
| 2105 | kfree(ias_opt); | 2097 | kfree(ias_opt); |
| 2106 | return -EPERM; | 2098 | err = -EPERM; |
| 2099 | goto out; | ||
| 2107 | } | 2100 | } |
| 2108 | 2101 | ||
| 2109 | /* Find the attribute (in the object) we target */ | 2102 | /* Find the attribute (in the object) we target */ |
| @@ -2111,14 +2104,16 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2111 | ias_opt->irda_attrib_name); | 2104 | ias_opt->irda_attrib_name); |
| 2112 | if(ias_attr == (struct ias_attrib *) NULL) { | 2105 | if(ias_attr == (struct ias_attrib *) NULL) { |
| 2113 | kfree(ias_opt); | 2106 | kfree(ias_opt); |
| 2114 | return -EINVAL; | 2107 | err = -EINVAL; |
| 2108 | goto out; | ||
| 2115 | } | 2109 | } |
| 2116 | 2110 | ||
| 2117 | /* Check is the user space own the object */ | 2111 | /* Check is the user space own the object */ |
| 2118 | if(ias_attr->value->owner != IAS_USER_ATTR) { | 2112 | if(ias_attr->value->owner != IAS_USER_ATTR) { |
| 2119 | IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__); | 2113 | IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__); |
| 2120 | kfree(ias_opt); | 2114 | kfree(ias_opt); |
| 2121 | return -EPERM; | 2115 | err = -EPERM; |
| 2116 | goto out; | ||
| 2122 | } | 2117 | } |
| 2123 | 2118 | ||
| 2124 | /* Remove the attribute (and maybe the object) */ | 2119 | /* Remove the attribute (and maybe the object) */ |
| @@ -2126,11 +2121,15 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2126 | kfree(ias_opt); | 2121 | kfree(ias_opt); |
| 2127 | break; | 2122 | break; |
| 2128 | case IRLMP_MAX_SDU_SIZE: | 2123 | case IRLMP_MAX_SDU_SIZE: |
| 2129 | if (optlen < sizeof(int)) | 2124 | if (optlen < sizeof(int)) { |
| 2130 | return -EINVAL; | 2125 | err = -EINVAL; |
| 2126 | goto out; | ||
| 2127 | } | ||
| 2131 | 2128 | ||
| 2132 | if (get_user(opt, (int __user *)optval)) | 2129 | if (get_user(opt, (int __user *)optval)) { |
| 2133 | return -EFAULT; | 2130 | err = -EFAULT; |
| 2131 | goto out; | ||
| 2132 | } | ||
| 2134 | 2133 | ||
| 2135 | /* Only possible for a seqpacket service (TTP with SAR) */ | 2134 | /* Only possible for a seqpacket service (TTP with SAR) */ |
| 2136 | if (sk->sk_type != SOCK_SEQPACKET) { | 2135 | if (sk->sk_type != SOCK_SEQPACKET) { |
| @@ -2140,16 +2139,21 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2140 | } else { | 2139 | } else { |
| 2141 | IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n", | 2140 | IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n", |
| 2142 | __func__); | 2141 | __func__); |
| 2143 | return -ENOPROTOOPT; | 2142 | err = -ENOPROTOOPT; |
| 2143 | goto out; | ||
| 2144 | } | 2144 | } |
| 2145 | break; | 2145 | break; |
| 2146 | case IRLMP_HINTS_SET: | 2146 | case IRLMP_HINTS_SET: |
| 2147 | if (optlen < sizeof(int)) | 2147 | if (optlen < sizeof(int)) { |
| 2148 | return -EINVAL; | 2148 | err = -EINVAL; |
| 2149 | goto out; | ||
| 2150 | } | ||
| 2149 | 2151 | ||
| 2150 | /* The input is really a (__u8 hints[2]), easier as an int */ | 2152 | /* The input is really a (__u8 hints[2]), easier as an int */ |
| 2151 | if (get_user(opt, (int __user *)optval)) | 2153 | if (get_user(opt, (int __user *)optval)) { |
| 2152 | return -EFAULT; | 2154 | err = -EFAULT; |
| 2155 | goto out; | ||
| 2156 | } | ||
| 2153 | 2157 | ||
| 2154 | /* Unregister any old registration */ | 2158 | /* Unregister any old registration */ |
| 2155 | if (self->skey) | 2159 | if (self->skey) |
| @@ -2163,12 +2167,16 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2163 | * making a discovery (nodes which don't match any hint | 2167 | * making a discovery (nodes which don't match any hint |
| 2164 | * bit in the mask are not reported). | 2168 | * bit in the mask are not reported). |
| 2165 | */ | 2169 | */ |
| 2166 | if (optlen < sizeof(int)) | 2170 | if (optlen < sizeof(int)) { |
| 2167 | return -EINVAL; | 2171 | err = -EINVAL; |
| 2172 | goto out; | ||
| 2173 | } | ||
| 2168 | 2174 | ||
| 2169 | /* The input is really a (__u8 hints[2]), easier as an int */ | 2175 | /* The input is really a (__u8 hints[2]), easier as an int */ |
| 2170 | if (get_user(opt, (int __user *)optval)) | 2176 | if (get_user(opt, (int __user *)optval)) { |
| 2171 | return -EFAULT; | 2177 | err = -EFAULT; |
| 2178 | goto out; | ||
| 2179 | } | ||
| 2172 | 2180 | ||
| 2173 | /* Set the new hint mask */ | 2181 | /* Set the new hint mask */ |
| 2174 | self->mask.word = (__u16) opt; | 2182 | self->mask.word = (__u16) opt; |
| @@ -2180,19 +2188,12 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
| 2180 | 2188 | ||
| 2181 | break; | 2189 | break; |
| 2182 | default: | 2190 | default: |
| 2183 | return -ENOPROTOOPT; | 2191 | err = -ENOPROTOOPT; |
| 2192 | break; | ||
| 2184 | } | 2193 | } |
| 2185 | return 0; | ||
| 2186 | } | ||
| 2187 | 2194 | ||
| 2188 | static int irda_setsockopt(struct socket *sock, int level, int optname, | 2195 | out: |
| 2189 | char __user *optval, unsigned int optlen) | 2196 | release_sock(sk); |
| 2190 | { | ||
| 2191 | int err; | ||
| 2192 | |||
| 2193 | lock_kernel(); | ||
| 2194 | err = __irda_setsockopt(sock, level, optname, optval, optlen); | ||
| 2195 | unlock_kernel(); | ||
| 2196 | 2197 | ||
| 2197 | return err; | 2198 | return err; |
| 2198 | } | 2199 | } |
| @@ -2249,7 +2250,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt, | |||
| 2249 | /* | 2250 | /* |
| 2250 | * Function irda_getsockopt (sock, level, optname, optval, optlen) | 2251 | * Function irda_getsockopt (sock, level, optname, optval, optlen) |
| 2251 | */ | 2252 | */ |
| 2252 | static int __irda_getsockopt(struct socket *sock, int level, int optname, | 2253 | static int irda_getsockopt(struct socket *sock, int level, int optname, |
| 2253 | char __user *optval, int __user *optlen) | 2254 | char __user *optval, int __user *optlen) |
| 2254 | { | 2255 | { |
| 2255 | struct sock *sk = sock->sk; | 2256 | struct sock *sk = sock->sk; |
| @@ -2262,7 +2263,7 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
| 2262 | int daddr = DEV_ADDR_ANY; /* Dest address for IAS queries */ | 2263 | int daddr = DEV_ADDR_ANY; /* Dest address for IAS queries */ |
| 2263 | int val = 0; | 2264 | int val = 0; |
| 2264 | int len = 0; | 2265 | int len = 0; |
| 2265 | int err; | 2266 | int err = 0; |
| 2266 | int offset, total; | 2267 | int offset, total; |
| 2267 | 2268 | ||
| 2268 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 2269 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
| @@ -2276,15 +2277,18 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
| 2276 | if(len < 0) | 2277 | if(len < 0) |
| 2277 | return -EINVAL; | 2278 | return -EINVAL; |
| 2278 | 2279 | ||
| 2280 | lock_sock(sk); | ||
| 2281 | |||
| 2279 | switch (optname) { | 2282 | switch (optname) { |
| 2280 | case IRLMP_ENUMDEVICES: | 2283 | case IRLMP_ENUMDEVICES: |
| 2281 | /* Ask lmp for the current discovery log */ | 2284 | /* Ask lmp for the current discovery log */ |
| 2282 | discoveries = irlmp_get_discoveries(&list.len, self->mask.word, | 2285 | discoveries = irlmp_get_discoveries(&list.len, self->mask.word, |
| 2283 | self->nslots); | 2286 | self->nslots); |
| 2284 | /* Check if the we got some results */ | 2287 | /* Check if the we got some results */ |
| 2285 | if (discoveries == NULL) | 2288 | if (discoveries == NULL) { |
| 2286 | return -EAGAIN; /* Didn't find any devices */ | 2289 | err = -EAGAIN; |
| 2287 | err = 0; | 2290 | goto out; /* Didn't find any devices */ |
| 2291 | } | ||
| 2288 | 2292 | ||
| 2289 | /* Write total list length back to client */ | 2293 | /* Write total list length back to client */ |
| 2290 | if (copy_to_user(optval, &list, | 2294 | if (copy_to_user(optval, &list, |
| @@ -2297,8 +2301,7 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
| 2297 | sizeof(struct irda_device_info); | 2301 | sizeof(struct irda_device_info); |
| 2298 | 2302 | ||
| 2299 | /* Copy the list itself - watch for overflow */ | 2303 | /* Copy the list itself - watch for overflow */ |
| 2300 | if(list.len > 2048) | 2304 | if (list.len > 2048) { |
| 2301 | { | ||
| 2302 | err = -EINVAL; | 2305 | err = -EINVAL; |
| 2303 | goto bed; | 2306 | goto bed; |
| 2304 | } | 2307 | } |
| @@ -2314,17 +2317,20 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
| 2314 | bed: | 2317 | bed: |
| 2315 | /* Free up our buffer */ | 2318 | /* Free up our buffer */ |
| 2316 | kfree(discoveries); | 2319 | kfree(discoveries); |
| 2317 | if (err) | ||
| 2318 | return err; | ||
| 2319 | break; | 2320 | break; |
| 2320 | case IRLMP_MAX_SDU_SIZE: | 2321 | case IRLMP_MAX_SDU_SIZE: |
| 2321 | val = self->max_data_size; | 2322 | val = self->max_data_size; |
| 2322 | len = sizeof(int); | 2323 | len = sizeof(int); |
| 2323 | if (put_user(len, optlen)) | 2324 | if (put_user(len, optlen)) { |
| 2324 | return -EFAULT; | 2325 | err = -EFAULT; |
| 2326 | goto out; | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | if (copy_to_user(optval, &val, len)) { | ||
| 2330 | err = -EFAULT; | ||
| 2331 | goto out; | ||
| 2332 | } | ||
| 2325 | 2333 | ||
| 2326 | if (copy_to_user(optval, &val, len)) | ||
| 2327 | return -EFAULT; | ||
| 2328 | break; | 2334 | break; |
| 2329 | case IRLMP_IAS_GET: | 2335 | case IRLMP_IAS_GET: |
| 2330 | /* The user want an object from our local IAS database. | 2336 | /* The user want an object from our local IAS database. |
| @@ -2332,17 +2338,22 @@ bed: | |||
| 2332 | * that we found */ | 2338 | * that we found */ |
| 2333 | 2339 | ||
| 2334 | /* Check that the user has allocated the right space for us */ | 2340 | /* Check that the user has allocated the right space for us */ |
| 2335 | if (len != sizeof(struct irda_ias_set)) | 2341 | if (len != sizeof(struct irda_ias_set)) { |
| 2336 | return -EINVAL; | 2342 | err = -EINVAL; |
| 2343 | goto out; | ||
| 2344 | } | ||
| 2337 | 2345 | ||
| 2338 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2346 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
| 2339 | if (ias_opt == NULL) | 2347 | if (ias_opt == NULL) { |
| 2340 | return -ENOMEM; | 2348 | err = -ENOMEM; |
| 2349 | goto out; | ||
| 2350 | } | ||
| 2341 | 2351 | ||
| 2342 | /* Copy query to the driver. */ | 2352 | /* Copy query to the driver. */ |
| 2343 | if (copy_from_user(ias_opt, optval, len)) { | 2353 | if (copy_from_user(ias_opt, optval, len)) { |
| 2344 | kfree(ias_opt); | 2354 | kfree(ias_opt); |
| 2345 | return -EFAULT; | 2355 | err = -EFAULT; |
| 2356 | goto out; | ||
| 2346 | } | 2357 | } |
| 2347 | 2358 | ||
| 2348 | /* Find the object we target. | 2359 | /* Find the object we target. |
| @@ -2355,7 +2366,8 @@ bed: | |||
| 2355 | ias_obj = irias_find_object(ias_opt->irda_class_name); | 2366 | ias_obj = irias_find_object(ias_opt->irda_class_name); |
| 2356 | if(ias_obj == (struct ias_object *) NULL) { | 2367 | if(ias_obj == (struct ias_object *) NULL) { |
| 2357 | kfree(ias_opt); | 2368 | kfree(ias_opt); |
| 2358 | return -EINVAL; | 2369 | err = -EINVAL; |
| 2370 | goto out; | ||
| 2359 | } | 2371 | } |
| 2360 | 2372 | ||
| 2361 | /* Find the attribute (in the object) we target */ | 2373 | /* Find the attribute (in the object) we target */ |
| @@ -2363,21 +2375,23 @@ bed: | |||
| 2363 | ias_opt->irda_attrib_name); | 2375 | ias_opt->irda_attrib_name); |
| 2364 | if(ias_attr == (struct ias_attrib *) NULL) { | 2376 | if(ias_attr == (struct ias_attrib *) NULL) { |
| 2365 | kfree(ias_opt); | 2377 | kfree(ias_opt); |
| 2366 | return -EINVAL; | 2378 | err = -EINVAL; |
| 2379 | goto out; | ||
| 2367 | } | 2380 | } |
| 2368 | 2381 | ||
| 2369 | /* Translate from internal to user structure */ | 2382 | /* Translate from internal to user structure */ |
| 2370 | err = irda_extract_ias_value(ias_opt, ias_attr->value); | 2383 | err = irda_extract_ias_value(ias_opt, ias_attr->value); |
| 2371 | if(err) { | 2384 | if(err) { |
| 2372 | kfree(ias_opt); | 2385 | kfree(ias_opt); |
| 2373 | return err; | 2386 | goto out; |
| 2374 | } | 2387 | } |
| 2375 | 2388 | ||
| 2376 | /* Copy reply to the user */ | 2389 | /* Copy reply to the user */ |
| 2377 | if (copy_to_user(optval, ias_opt, | 2390 | if (copy_to_user(optval, ias_opt, |
| 2378 | sizeof(struct irda_ias_set))) { | 2391 | sizeof(struct irda_ias_set))) { |
| 2379 | kfree(ias_opt); | 2392 | kfree(ias_opt); |
| 2380 | return -EFAULT; | 2393 | err = -EFAULT; |
| 2394 | goto out; | ||
| 2381 | } | 2395 | } |
| 2382 | /* Note : don't need to put optlen, we checked it */ | 2396 | /* Note : don't need to put optlen, we checked it */ |
| 2383 | kfree(ias_opt); | 2397 | kfree(ias_opt); |
| @@ -2388,17 +2402,22 @@ bed: | |||
| 2388 | * then wait for the answer to come back. */ | 2402 | * then wait for the answer to come back. */ |
| 2389 | 2403 | ||
| 2390 | /* Check that the user has allocated the right space for us */ | 2404 | /* Check that the user has allocated the right space for us */ |
| 2391 | if (len != sizeof(struct irda_ias_set)) | 2405 | if (len != sizeof(struct irda_ias_set)) { |
| 2392 | return -EINVAL; | 2406 | err = -EINVAL; |
| 2407 | goto out; | ||
| 2408 | } | ||
| 2393 | 2409 | ||
| 2394 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2410 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
| 2395 | if (ias_opt == NULL) | 2411 | if (ias_opt == NULL) { |
| 2396 | return -ENOMEM; | 2412 | err = -ENOMEM; |
| 2413 | goto out; | ||
| 2414 | } | ||
| 2397 | 2415 | ||
| 2398 | /* Copy query to the driver. */ | 2416 | /* Copy query to the driver. */ |
| 2399 | if (copy_from_user(ias_opt, optval, len)) { | 2417 | if (copy_from_user(ias_opt, optval, len)) { |
| 2400 | kfree(ias_opt); | 2418 | kfree(ias_opt); |
| 2401 | return -EFAULT; | 2419 | err = -EFAULT; |
| 2420 | goto out; | ||
| 2402 | } | 2421 | } |
| 2403 | 2422 | ||
| 2404 | /* At this point, there are two cases... | 2423 | /* At this point, there are two cases... |
| @@ -2419,7 +2438,8 @@ bed: | |||
| 2419 | daddr = ias_opt->daddr; | 2438 | daddr = ias_opt->daddr; |
| 2420 | if((!daddr) || (daddr == DEV_ADDR_ANY)) { | 2439 | if((!daddr) || (daddr == DEV_ADDR_ANY)) { |
| 2421 | kfree(ias_opt); | 2440 | kfree(ias_opt); |
| 2422 | return -EINVAL; | 2441 | err = -EINVAL; |
| 2442 | goto out; | ||
| 2423 | } | 2443 | } |
| 2424 | } | 2444 | } |
| 2425 | 2445 | ||
| @@ -2428,7 +2448,8 @@ bed: | |||
| 2428 | IRDA_WARNING("%s: busy with a previous query\n", | 2448 | IRDA_WARNING("%s: busy with a previous query\n", |
| 2429 | __func__); | 2449 | __func__); |
| 2430 | kfree(ias_opt); | 2450 | kfree(ias_opt); |
| 2431 | return -EBUSY; | 2451 | err = -EBUSY; |
| 2452 | goto out; | ||
| 2432 | } | 2453 | } |
| 2433 | 2454 | ||
| 2434 | self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, | 2455 | self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, |
| @@ -2436,7 +2457,8 @@ bed: | |||
| 2436 | 2457 | ||
| 2437 | if (self->iriap == NULL) { | 2458 | if (self->iriap == NULL) { |
| 2438 | kfree(ias_opt); | 2459 | kfree(ias_opt); |
| 2439 | return -ENOMEM; | 2460 | err = -ENOMEM; |
| 2461 | goto out; | ||
| 2440 | } | 2462 | } |
| 2441 | 2463 | ||
| 2442 | /* Treat unexpected wakeup as disconnect */ | 2464 | /* Treat unexpected wakeup as disconnect */ |
| @@ -2455,7 +2477,8 @@ bed: | |||
| 2455 | * we can free it regardless! */ | 2477 | * we can free it regardless! */ |
| 2456 | kfree(ias_opt); | 2478 | kfree(ias_opt); |
| 2457 | /* Treat signals as disconnect */ | 2479 | /* Treat signals as disconnect */ |
| 2458 | return -EHOSTUNREACH; | 2480 | err = -EHOSTUNREACH; |
| 2481 | goto out; | ||
| 2459 | } | 2482 | } |
| 2460 | 2483 | ||
| 2461 | /* Check what happened */ | 2484 | /* Check what happened */ |
| @@ -2465,9 +2488,11 @@ bed: | |||
| 2465 | /* Requested object/attribute doesn't exist */ | 2488 | /* Requested object/attribute doesn't exist */ |
| 2466 | if((self->errno == IAS_CLASS_UNKNOWN) || | 2489 | if((self->errno == IAS_CLASS_UNKNOWN) || |
| 2467 | (self->errno == IAS_ATTRIB_UNKNOWN)) | 2490 | (self->errno == IAS_ATTRIB_UNKNOWN)) |
| 2468 | return -EADDRNOTAVAIL; | 2491 | err = -EADDRNOTAVAIL; |
| 2469 | else | 2492 | else |
| 2470 | return -EHOSTUNREACH; | 2493 | err = -EHOSTUNREACH; |
| 2494 | |||
| 2495 | goto out; | ||
| 2471 | } | 2496 | } |
| 2472 | 2497 | ||
| 2473 | /* Translate from internal to user structure */ | 2498 | /* Translate from internal to user structure */ |
| @@ -2476,14 +2501,15 @@ bed: | |||
| 2476 | irias_delete_value(self->ias_result); | 2501 | irias_delete_value(self->ias_result); |
| 2477 | if (err) { | 2502 | if (err) { |
| 2478 | kfree(ias_opt); | 2503 | kfree(ias_opt); |
| 2479 | return err; | 2504 | goto out; |
| 2480 | } | 2505 | } |
| 2481 | 2506 | ||
| 2482 | /* Copy reply to the user */ | 2507 | /* Copy reply to the user */ |
| 2483 | if (copy_to_user(optval, ias_opt, | 2508 | if (copy_to_user(optval, ias_opt, |
| 2484 | sizeof(struct irda_ias_set))) { | 2509 | sizeof(struct irda_ias_set))) { |
| 2485 | kfree(ias_opt); | 2510 | kfree(ias_opt); |
| 2486 | return -EFAULT; | 2511 | err = -EFAULT; |
| 2512 | goto out; | ||
| 2487 | } | 2513 | } |
| 2488 | /* Note : don't need to put optlen, we checked it */ | 2514 | /* Note : don't need to put optlen, we checked it */ |
| 2489 | kfree(ias_opt); | 2515 | kfree(ias_opt); |
| @@ -2504,11 +2530,15 @@ bed: | |||
| 2504 | */ | 2530 | */ |
| 2505 | 2531 | ||
| 2506 | /* Check that the user is passing us an int */ | 2532 | /* Check that the user is passing us an int */ |
| 2507 | if (len != sizeof(int)) | 2533 | if (len != sizeof(int)) { |
| 2508 | return -EINVAL; | 2534 | err = -EINVAL; |
| 2535 | goto out; | ||
| 2536 | } | ||
| 2509 | /* Get timeout in ms (max time we block the caller) */ | 2537 | /* Get timeout in ms (max time we block the caller) */ |
| 2510 | if (get_user(val, (int __user *)optval)) | 2538 | if (get_user(val, (int __user *)optval)) { |
| 2511 | return -EFAULT; | 2539 | err = -EFAULT; |
| 2540 | goto out; | ||
| 2541 | } | ||
| 2512 | 2542 | ||
| 2513 | /* Tell IrLMP we want to be notified */ | 2543 | /* Tell IrLMP we want to be notified */ |
| 2514 | irlmp_update_client(self->ckey, self->mask.word, | 2544 | irlmp_update_client(self->ckey, self->mask.word, |
| @@ -2520,8 +2550,6 @@ bed: | |||
| 2520 | 2550 | ||
| 2521 | /* Wait until a node is discovered */ | 2551 | /* Wait until a node is discovered */ |
| 2522 | if (!self->cachedaddr) { | 2552 | if (!self->cachedaddr) { |
| 2523 | int ret = 0; | ||
| 2524 | |||
| 2525 | IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__); | 2553 | IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__); |
| 2526 | 2554 | ||
| 2527 | /* Set watchdog timer to expire in <val> ms. */ | 2555 | /* Set watchdog timer to expire in <val> ms. */ |
| @@ -2534,7 +2562,7 @@ bed: | |||
| 2534 | /* Wait for IR-LMP to call us back */ | 2562 | /* Wait for IR-LMP to call us back */ |
| 2535 | __wait_event_interruptible(self->query_wait, | 2563 | __wait_event_interruptible(self->query_wait, |
| 2536 | (self->cachedaddr != 0 || self->errno == -ETIME), | 2564 | (self->cachedaddr != 0 || self->errno == -ETIME), |
| 2537 | ret); | 2565 | err); |
| 2538 | 2566 | ||
| 2539 | /* If watchdog is still activated, kill it! */ | 2567 | /* If watchdog is still activated, kill it! */ |
| 2540 | if(timer_pending(&(self->watchdog))) | 2568 | if(timer_pending(&(self->watchdog))) |
| @@ -2542,8 +2570,8 @@ bed: | |||
| 2542 | 2570 | ||
| 2543 | IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__); | 2571 | IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__); |
| 2544 | 2572 | ||
| 2545 | if (ret != 0) | 2573 | if (err != 0) |
| 2546 | return ret; | 2574 | goto out; |
| 2547 | } | 2575 | } |
| 2548 | else | 2576 | else |
| 2549 | IRDA_DEBUG(1, "%s(), found immediately !\n", | 2577 | IRDA_DEBUG(1, "%s(), found immediately !\n", |
| @@ -2566,25 +2594,19 @@ bed: | |||
| 2566 | * If the user want more details, he should query | 2594 | * If the user want more details, he should query |
| 2567 | * the whole discovery log and pick one device... | 2595 | * the whole discovery log and pick one device... |
| 2568 | */ | 2596 | */ |
| 2569 | if (put_user(daddr, (int __user *)optval)) | 2597 | if (put_user(daddr, (int __user *)optval)) { |
| 2570 | return -EFAULT; | 2598 | err = -EFAULT; |
| 2599 | goto out; | ||
| 2600 | } | ||
| 2571 | 2601 | ||
| 2572 | break; | 2602 | break; |
| 2573 | default: | 2603 | default: |
| 2574 | return -ENOPROTOOPT; | 2604 | err = -ENOPROTOOPT; |
| 2575 | } | 2605 | } |
| 2576 | 2606 | ||
| 2577 | return 0; | 2607 | out: |
| 2578 | } | ||
| 2579 | |||
| 2580 | static int irda_getsockopt(struct socket *sock, int level, int optname, | ||
| 2581 | char __user *optval, int __user *optlen) | ||
| 2582 | { | ||
| 2583 | int err; | ||
| 2584 | 2608 | ||
| 2585 | lock_kernel(); | 2609 | release_sock(sk); |
| 2586 | err = __irda_getsockopt(sock, level, optname, optval, optlen); | ||
| 2587 | unlock_kernel(); | ||
| 2588 | 2610 | ||
| 2589 | return err; | 2611 | return err; |
| 2590 | } | 2612 | } |
| @@ -2628,7 +2650,7 @@ static const struct proto_ops irda_seqpacket_ops = { | |||
| 2628 | .socketpair = sock_no_socketpair, | 2650 | .socketpair = sock_no_socketpair, |
| 2629 | .accept = irda_accept, | 2651 | .accept = irda_accept, |
| 2630 | .getname = irda_getname, | 2652 | .getname = irda_getname, |
| 2631 | .poll = irda_datagram_poll, | 2653 | .poll = datagram_poll, |
| 2632 | .ioctl = irda_ioctl, | 2654 | .ioctl = irda_ioctl, |
| 2633 | #ifdef CONFIG_COMPAT | 2655 | #ifdef CONFIG_COMPAT |
| 2634 | .compat_ioctl = irda_compat_ioctl, | 2656 | .compat_ioctl = irda_compat_ioctl, |
| @@ -2652,7 +2674,7 @@ static const struct proto_ops irda_dgram_ops = { | |||
| 2652 | .socketpair = sock_no_socketpair, | 2674 | .socketpair = sock_no_socketpair, |
| 2653 | .accept = irda_accept, | 2675 | .accept = irda_accept, |
| 2654 | .getname = irda_getname, | 2676 | .getname = irda_getname, |
| 2655 | .poll = irda_datagram_poll, | 2677 | .poll = datagram_poll, |
| 2656 | .ioctl = irda_ioctl, | 2678 | .ioctl = irda_ioctl, |
| 2657 | #ifdef CONFIG_COMPAT | 2679 | #ifdef CONFIG_COMPAT |
| 2658 | .compat_ioctl = irda_compat_ioctl, | 2680 | .compat_ioctl = irda_compat_ioctl, |
| @@ -2677,7 +2699,7 @@ static const struct proto_ops irda_ultra_ops = { | |||
| 2677 | .socketpair = sock_no_socketpair, | 2699 | .socketpair = sock_no_socketpair, |
| 2678 | .accept = sock_no_accept, | 2700 | .accept = sock_no_accept, |
| 2679 | .getname = irda_getname, | 2701 | .getname = irda_getname, |
| 2680 | .poll = irda_datagram_poll, | 2702 | .poll = datagram_poll, |
| 2681 | .ioctl = irda_ioctl, | 2703 | .ioctl = irda_ioctl, |
| 2682 | #ifdef CONFIG_COMPAT | 2704 | #ifdef CONFIG_COMPAT |
| 2683 | .compat_ioctl = irda_compat_ioctl, | 2705 | .compat_ioctl = irda_compat_ioctl, |
