diff options
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 208 | ||||
-rw-r--r-- | net/unix/garbage.c | 11 |
2 files changed, 143 insertions, 76 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0b39b2451ea5..0722a25a3a33 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -117,7 +117,7 @@ | |||
117 | 117 | ||
118 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; | 118 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; |
119 | static DEFINE_SPINLOCK(unix_table_lock); | 119 | static DEFINE_SPINLOCK(unix_table_lock); |
120 | static atomic_t unix_nr_socks = ATOMIC_INIT(0); | 120 | static atomic_long_t unix_nr_socks; |
121 | 121 | ||
122 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) | 122 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) |
123 | 123 | ||
@@ -207,7 +207,7 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) | |||
207 | /* | 207 | /* |
208 | * This may look like an off by one error but it is a bit more | 208 | * This may look like an off by one error but it is a bit more |
209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. | 209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. |
210 | * sun_path[108] doesnt as such exist. However in kernel space | 210 | * sun_path[108] doesn't as such exist. However in kernel space |
211 | * we are guaranteed that it is a valid memory location in our | 211 | * we are guaranteed that it is a valid memory location in our |
212 | * kernel address buffer. | 212 | * kernel address buffer. |
213 | */ | 213 | */ |
@@ -316,7 +316,8 @@ static void unix_write_space(struct sock *sk) | |||
316 | if (unix_writable(sk)) { | 316 | if (unix_writable(sk)) { |
317 | wq = rcu_dereference(sk->sk_wq); | 317 | wq = rcu_dereference(sk->sk_wq); |
318 | if (wq_has_sleeper(wq)) | 318 | if (wq_has_sleeper(wq)) |
319 | wake_up_interruptible_sync(&wq->wait); | 319 | wake_up_interruptible_sync_poll(&wq->wait, |
320 | POLLOUT | POLLWRNORM | POLLWRBAND); | ||
320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 321 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
321 | } | 322 | } |
322 | rcu_read_unlock(); | 323 | rcu_read_unlock(); |
@@ -360,13 +361,13 @@ static void unix_sock_destructor(struct sock *sk) | |||
360 | if (u->addr) | 361 | if (u->addr) |
361 | unix_release_addr(u->addr); | 362 | unix_release_addr(u->addr); |
362 | 363 | ||
363 | atomic_dec(&unix_nr_socks); | 364 | atomic_long_dec(&unix_nr_socks); |
364 | local_bh_disable(); | 365 | local_bh_disable(); |
365 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 366 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
366 | local_bh_enable(); | 367 | local_bh_enable(); |
367 | #ifdef UNIX_REFCNT_DEBUG | 368 | #ifdef UNIX_REFCNT_DEBUG |
368 | printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, | 369 | printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk, |
369 | atomic_read(&unix_nr_socks)); | 370 | atomic_long_read(&unix_nr_socks)); |
370 | #endif | 371 | #endif |
371 | } | 372 | } |
372 | 373 | ||
@@ -523,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *, | |||
523 | int, int); | 524 | int, int); |
524 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | 525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, |
525 | struct msghdr *, size_t); | 526 | struct msghdr *, size_t); |
527 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | ||
528 | struct msghdr *, size_t, int); | ||
526 | 529 | ||
527 | static const struct proto_ops unix_stream_ops = { | 530 | static const struct proto_ops unix_stream_ops = { |
528 | .family = PF_UNIX, | 531 | .family = PF_UNIX, |
@@ -582,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
582 | .setsockopt = sock_no_setsockopt, | 585 | .setsockopt = sock_no_setsockopt, |
583 | .getsockopt = sock_no_getsockopt, | 586 | .getsockopt = sock_no_getsockopt, |
584 | .sendmsg = unix_seqpacket_sendmsg, | 587 | .sendmsg = unix_seqpacket_sendmsg, |
585 | .recvmsg = unix_dgram_recvmsg, | 588 | .recvmsg = unix_seqpacket_recvmsg, |
586 | .mmap = sock_no_mmap, | 589 | .mmap = sock_no_mmap, |
587 | .sendpage = sock_no_sendpage, | 590 | .sendpage = sock_no_sendpage, |
588 | }; | 591 | }; |
@@ -606,8 +609,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
606 | struct sock *sk = NULL; | 609 | struct sock *sk = NULL; |
607 | struct unix_sock *u; | 610 | struct unix_sock *u; |
608 | 611 | ||
609 | atomic_inc(&unix_nr_socks); | 612 | atomic_long_inc(&unix_nr_socks); |
610 | if (atomic_read(&unix_nr_socks) > 2 * get_max_files()) | 613 | if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) |
611 | goto out; | 614 | goto out; |
612 | 615 | ||
613 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); | 616 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); |
@@ -632,7 +635,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
632 | unix_insert_socket(unix_sockets_unbound, sk); | 635 | unix_insert_socket(unix_sockets_unbound, sk); |
633 | out: | 636 | out: |
634 | if (sk == NULL) | 637 | if (sk == NULL) |
635 | atomic_dec(&unix_nr_socks); | 638 | atomic_long_dec(&unix_nr_socks); |
636 | else { | 639 | else { |
637 | local_bh_disable(); | 640 | local_bh_disable(); |
638 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 641 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
@@ -849,7 +852,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
849 | * Get the parent directory, calculate the hash for last | 852 | * Get the parent directory, calculate the hash for last |
850 | * component. | 853 | * component. |
851 | */ | 854 | */ |
852 | err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd); | 855 | err = kern_path_parent(sunaddr->sun_path, &nd); |
853 | if (err) | 856 | if (err) |
854 | goto out_mknod_parent; | 857 | goto out_mknod_parent; |
855 | 858 | ||
@@ -1123,7 +1126,7 @@ restart: | |||
1123 | 1126 | ||
1124 | /* Latch our state. | 1127 | /* Latch our state. |
1125 | 1128 | ||
1126 | It is tricky place. We need to grab write lock and cannot | 1129 | It is tricky place. We need to grab our state lock and cannot |
1127 | drop lock on peer. It is dangerous because deadlock is | 1130 | drop lock on peer. It is dangerous because deadlock is |
1128 | possible. Connect to self case and simultaneous | 1131 | possible. Connect to self case and simultaneous |
1129 | attempt to connect are eliminated by checking socket | 1132 | attempt to connect are eliminated by checking socket |
@@ -1156,7 +1159,7 @@ restart: | |||
1156 | goto restart; | 1159 | goto restart; |
1157 | } | 1160 | } |
1158 | 1161 | ||
1159 | err = security_unix_stream_connect(sock, other->sk_socket, newsk); | 1162 | err = security_unix_stream_connect(sk, other, newsk); |
1160 | if (err) { | 1163 | if (err) { |
1161 | unix_state_unlock(sk); | 1164 | unix_state_unlock(sk); |
1162 | goto out_unlock; | 1165 | goto out_unlock; |
@@ -1170,7 +1173,7 @@ restart: | |||
1170 | newsk->sk_type = sk->sk_type; | 1173 | newsk->sk_type = sk->sk_type; |
1171 | init_peercred(newsk); | 1174 | init_peercred(newsk); |
1172 | newu = unix_sk(newsk); | 1175 | newu = unix_sk(newsk); |
1173 | newsk->sk_wq = &newu->peer_wq; | 1176 | RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); |
1174 | otheru = unix_sk(other); | 1177 | otheru = unix_sk(other); |
1175 | 1178 | ||
1176 | /* copy address information from listening to new sock*/ | 1179 | /* copy address information from listening to new sock*/ |
@@ -1343,9 +1346,25 @@ static void unix_destruct_scm(struct sk_buff *skb) | |||
1343 | sock_wfree(skb); | 1346 | sock_wfree(skb); |
1344 | } | 1347 | } |
1345 | 1348 | ||
1349 | #define MAX_RECURSION_LEVEL 4 | ||
1350 | |||
1346 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1351 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) |
1347 | { | 1352 | { |
1348 | int i; | 1353 | int i; |
1354 | unsigned char max_level = 0; | ||
1355 | int unix_sock_count = 0; | ||
1356 | |||
1357 | for (i = scm->fp->count - 1; i >= 0; i--) { | ||
1358 | struct sock *sk = unix_get_socket(scm->fp->fp[i]); | ||
1359 | |||
1360 | if (sk) { | ||
1361 | unix_sock_count++; | ||
1362 | max_level = max(max_level, | ||
1363 | unix_sk(sk)->recursion_level); | ||
1364 | } | ||
1365 | } | ||
1366 | if (unlikely(max_level > MAX_RECURSION_LEVEL)) | ||
1367 | return -ETOOMANYREFS; | ||
1349 | 1368 | ||
1350 | /* | 1369 | /* |
1351 | * Need to duplicate file references for the sake of garbage | 1370 | * Need to duplicate file references for the sake of garbage |
@@ -1356,9 +1375,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1356 | if (!UNIXCB(skb).fp) | 1375 | if (!UNIXCB(skb).fp) |
1357 | return -ENOMEM; | 1376 | return -ENOMEM; |
1358 | 1377 | ||
1359 | for (i = scm->fp->count-1; i >= 0; i--) | 1378 | if (unix_sock_count) { |
1360 | unix_inflight(scm->fp->fp[i]); | 1379 | for (i = scm->fp->count - 1; i >= 0; i--) |
1361 | return 0; | 1380 | unix_inflight(scm->fp->fp[i]); |
1381 | } | ||
1382 | return max_level; | ||
1362 | } | 1383 | } |
1363 | 1384 | ||
1364 | static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) | 1385 | static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) |
@@ -1393,6 +1414,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1393 | struct sk_buff *skb; | 1414 | struct sk_buff *skb; |
1394 | long timeo; | 1415 | long timeo; |
1395 | struct scm_cookie tmp_scm; | 1416 | struct scm_cookie tmp_scm; |
1417 | int max_level; | ||
1396 | 1418 | ||
1397 | if (NULL == siocb->scm) | 1419 | if (NULL == siocb->scm) |
1398 | siocb->scm = &tmp_scm; | 1420 | siocb->scm = &tmp_scm; |
@@ -1431,8 +1453,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1431 | goto out; | 1453 | goto out; |
1432 | 1454 | ||
1433 | err = unix_scm_to_skb(siocb->scm, skb, true); | 1455 | err = unix_scm_to_skb(siocb->scm, skb, true); |
1434 | if (err) | 1456 | if (err < 0) |
1435 | goto out_free; | 1457 | goto out_free; |
1458 | max_level = err + 1; | ||
1436 | unix_get_secdata(siocb->scm, skb); | 1459 | unix_get_secdata(siocb->scm, skb); |
1437 | 1460 | ||
1438 | skb_reset_transport_header(skb); | 1461 | skb_reset_transport_header(skb); |
@@ -1454,6 +1477,12 @@ restart: | |||
1454 | goto out_free; | 1477 | goto out_free; |
1455 | } | 1478 | } |
1456 | 1479 | ||
1480 | if (sk_filter(other, skb) < 0) { | ||
1481 | /* Toss the packet but do not return any error to the sender */ | ||
1482 | err = len; | ||
1483 | goto out_free; | ||
1484 | } | ||
1485 | |||
1457 | unix_state_lock(other); | 1486 | unix_state_lock(other); |
1458 | err = -EPERM; | 1487 | err = -EPERM; |
1459 | if (!unix_may_send(sk, other)) | 1488 | if (!unix_may_send(sk, other)) |
@@ -1511,7 +1540,11 @@ restart: | |||
1511 | goto restart; | 1540 | goto restart; |
1512 | } | 1541 | } |
1513 | 1542 | ||
1543 | if (sock_flag(other, SOCK_RCVTSTAMP)) | ||
1544 | __net_timestamp(skb); | ||
1514 | skb_queue_tail(&other->sk_receive_queue, skb); | 1545 | skb_queue_tail(&other->sk_receive_queue, skb); |
1546 | if (max_level > unix_sk(other)->recursion_level) | ||
1547 | unix_sk(other)->recursion_level = max_level; | ||
1515 | unix_state_unlock(other); | 1548 | unix_state_unlock(other); |
1516 | other->sk_data_ready(other, len); | 1549 | other->sk_data_ready(other, len); |
1517 | sock_put(other); | 1550 | sock_put(other); |
@@ -1536,12 +1569,12 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1536 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1569 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1537 | struct sock *sk = sock->sk; | 1570 | struct sock *sk = sock->sk; |
1538 | struct sock *other = NULL; | 1571 | struct sock *other = NULL; |
1539 | struct sockaddr_un *sunaddr = msg->msg_name; | ||
1540 | int err, size; | 1572 | int err, size; |
1541 | struct sk_buff *skb; | 1573 | struct sk_buff *skb; |
1542 | int sent = 0; | 1574 | int sent = 0; |
1543 | struct scm_cookie tmp_scm; | 1575 | struct scm_cookie tmp_scm; |
1544 | bool fds_sent = false; | 1576 | bool fds_sent = false; |
1577 | int max_level; | ||
1545 | 1578 | ||
1546 | if (NULL == siocb->scm) | 1579 | if (NULL == siocb->scm) |
1547 | siocb->scm = &tmp_scm; | 1580 | siocb->scm = &tmp_scm; |
@@ -1558,7 +1591,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1558 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; | 1591 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; |
1559 | goto out_err; | 1592 | goto out_err; |
1560 | } else { | 1593 | } else { |
1561 | sunaddr = NULL; | ||
1562 | err = -ENOTCONN; | 1594 | err = -ENOTCONN; |
1563 | other = unix_peer(sk); | 1595 | other = unix_peer(sk); |
1564 | if (!other) | 1596 | if (!other) |
@@ -1605,10 +1637,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1605 | 1637 | ||
1606 | /* Only send the fds in the first buffer */ | 1638 | /* Only send the fds in the first buffer */ |
1607 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); | 1639 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); |
1608 | if (err) { | 1640 | if (err < 0) { |
1609 | kfree_skb(skb); | 1641 | kfree_skb(skb); |
1610 | goto out_err; | 1642 | goto out_err; |
1611 | } | 1643 | } |
1644 | max_level = err + 1; | ||
1612 | fds_sent = true; | 1645 | fds_sent = true; |
1613 | 1646 | ||
1614 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 1647 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
@@ -1624,6 +1657,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1624 | goto pipe_err_free; | 1657 | goto pipe_err_free; |
1625 | 1658 | ||
1626 | skb_queue_tail(&other->sk_receive_queue, skb); | 1659 | skb_queue_tail(&other->sk_receive_queue, skb); |
1660 | if (max_level > unix_sk(other)->recursion_level) | ||
1661 | unix_sk(other)->recursion_level = max_level; | ||
1627 | unix_state_unlock(other); | 1662 | unix_state_unlock(other); |
1628 | other->sk_data_ready(other, size); | 1663 | other->sk_data_ready(other, size); |
1629 | sent += size; | 1664 | sent += size; |
@@ -1666,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1666 | return unix_dgram_sendmsg(kiocb, sock, msg, len); | 1701 | return unix_dgram_sendmsg(kiocb, sock, msg, len); |
1667 | } | 1702 | } |
1668 | 1703 | ||
1704 | static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
1705 | struct msghdr *msg, size_t size, | ||
1706 | int flags) | ||
1707 | { | ||
1708 | struct sock *sk = sock->sk; | ||
1709 | |||
1710 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1711 | return -ENOTCONN; | ||
1712 | |||
1713 | return unix_dgram_recvmsg(iocb, sock, msg, size, flags); | ||
1714 | } | ||
1715 | |||
1669 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) | 1716 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) |
1670 | { | 1717 | { |
1671 | struct unix_sock *u = unix_sk(sk); | 1718 | struct unix_sock *u = unix_sk(sk); |
@@ -1695,7 +1742,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1695 | 1742 | ||
1696 | msg->msg_namelen = 0; | 1743 | msg->msg_namelen = 0; |
1697 | 1744 | ||
1698 | mutex_lock(&u->readlock); | 1745 | err = mutex_lock_interruptible(&u->readlock); |
1746 | if (err) { | ||
1747 | err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); | ||
1748 | goto out; | ||
1749 | } | ||
1699 | 1750 | ||
1700 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 1751 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
1701 | if (!skb) { | 1752 | if (!skb) { |
@@ -1708,7 +1759,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1708 | goto out_unlock; | 1759 | goto out_unlock; |
1709 | } | 1760 | } |
1710 | 1761 | ||
1711 | wake_up_interruptible_sync(&u->peer_wait); | 1762 | wake_up_interruptible_sync_poll(&u->peer_wait, |
1763 | POLLOUT | POLLWRNORM | POLLWRBAND); | ||
1712 | 1764 | ||
1713 | if (msg->msg_name) | 1765 | if (msg->msg_name) |
1714 | unix_copy_addr(msg, skb->sk); | 1766 | unix_copy_addr(msg, skb->sk); |
@@ -1722,6 +1774,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1722 | if (err) | 1774 | if (err) |
1723 | goto out_free; | 1775 | goto out_free; |
1724 | 1776 | ||
1777 | if (sock_flag(sk, SOCK_RCVTSTAMP)) | ||
1778 | __sock_recv_timestamp(msg, sk, skb); | ||
1779 | |||
1725 | if (!siocb->scm) { | 1780 | if (!siocb->scm) { |
1726 | siocb->scm = &tmp_scm; | 1781 | siocb->scm = &tmp_scm; |
1727 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1782 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
@@ -1831,7 +1886,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1831 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1886 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
1832 | } | 1887 | } |
1833 | 1888 | ||
1834 | mutex_lock(&u->readlock); | 1889 | err = mutex_lock_interruptible(&u->readlock); |
1890 | if (err) { | ||
1891 | err = sock_intr_errno(timeo); | ||
1892 | goto out; | ||
1893 | } | ||
1835 | 1894 | ||
1836 | do { | 1895 | do { |
1837 | int chunk; | 1896 | int chunk; |
@@ -1840,6 +1899,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1840 | unix_state_lock(sk); | 1899 | unix_state_lock(sk); |
1841 | skb = skb_dequeue(&sk->sk_receive_queue); | 1900 | skb = skb_dequeue(&sk->sk_receive_queue); |
1842 | if (skb == NULL) { | 1901 | if (skb == NULL) { |
1902 | unix_sk(sk)->recursion_level = 0; | ||
1843 | if (copied >= target) | 1903 | if (copied >= target) |
1844 | goto unlock; | 1904 | goto unlock; |
1845 | 1905 | ||
@@ -1861,11 +1921,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1861 | 1921 | ||
1862 | timeo = unix_stream_data_wait(sk, timeo); | 1922 | timeo = unix_stream_data_wait(sk, timeo); |
1863 | 1923 | ||
1864 | if (signal_pending(current)) { | 1924 | if (signal_pending(current) |
1925 | || mutex_lock_interruptible(&u->readlock)) { | ||
1865 | err = sock_intr_errno(timeo); | 1926 | err = sock_intr_errno(timeo); |
1866 | goto out; | 1927 | goto out; |
1867 | } | 1928 | } |
1868 | mutex_lock(&u->readlock); | 1929 | |
1869 | continue; | 1930 | continue; |
1870 | unlock: | 1931 | unlock: |
1871 | unix_state_unlock(sk); | 1932 | unix_state_unlock(sk); |
@@ -1944,36 +2005,38 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1944 | 2005 | ||
1945 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); | 2006 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); |
1946 | 2007 | ||
1947 | if (mode) { | 2008 | if (!mode) |
1948 | unix_state_lock(sk); | 2009 | return 0; |
1949 | sk->sk_shutdown |= mode; | 2010 | |
1950 | other = unix_peer(sk); | 2011 | unix_state_lock(sk); |
1951 | if (other) | 2012 | sk->sk_shutdown |= mode; |
1952 | sock_hold(other); | 2013 | other = unix_peer(sk); |
1953 | unix_state_unlock(sk); | 2014 | if (other) |
1954 | sk->sk_state_change(sk); | 2015 | sock_hold(other); |
1955 | 2016 | unix_state_unlock(sk); | |
1956 | if (other && | 2017 | sk->sk_state_change(sk); |
1957 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { | 2018 | |
1958 | 2019 | if (other && | |
1959 | int peer_mode = 0; | 2020 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { |
1960 | 2021 | ||
1961 | if (mode&RCV_SHUTDOWN) | 2022 | int peer_mode = 0; |
1962 | peer_mode |= SEND_SHUTDOWN; | 2023 | |
1963 | if (mode&SEND_SHUTDOWN) | 2024 | if (mode&RCV_SHUTDOWN) |
1964 | peer_mode |= RCV_SHUTDOWN; | 2025 | peer_mode |= SEND_SHUTDOWN; |
1965 | unix_state_lock(other); | 2026 | if (mode&SEND_SHUTDOWN) |
1966 | other->sk_shutdown |= peer_mode; | 2027 | peer_mode |= RCV_SHUTDOWN; |
1967 | unix_state_unlock(other); | 2028 | unix_state_lock(other); |
1968 | other->sk_state_change(other); | 2029 | other->sk_shutdown |= peer_mode; |
1969 | if (peer_mode == SHUTDOWN_MASK) | 2030 | unix_state_unlock(other); |
1970 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 2031 | other->sk_state_change(other); |
1971 | else if (peer_mode & RCV_SHUTDOWN) | 2032 | if (peer_mode == SHUTDOWN_MASK) |
1972 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 2033 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
1973 | } | 2034 | else if (peer_mode & RCV_SHUTDOWN) |
1974 | if (other) | 2035 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
1975 | sock_put(other); | ||
1976 | } | 2036 | } |
2037 | if (other) | ||
2038 | sock_put(other); | ||
2039 | |||
1977 | return 0; | 2040 | return 0; |
1978 | } | 2041 | } |
1979 | 2042 | ||
@@ -2033,11 +2096,10 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
2033 | if (sk->sk_shutdown == SHUTDOWN_MASK) | 2096 | if (sk->sk_shutdown == SHUTDOWN_MASK) |
2034 | mask |= POLLHUP; | 2097 | mask |= POLLHUP; |
2035 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 2098 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
2036 | mask |= POLLRDHUP; | 2099 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
2037 | 2100 | ||
2038 | /* readable? */ | 2101 | /* readable? */ |
2039 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 2102 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
2040 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
2041 | mask |= POLLIN | POLLRDNORM; | 2103 | mask |= POLLIN | POLLRDNORM; |
2042 | 2104 | ||
2043 | /* Connection-based need to check for termination and startup */ | 2105 | /* Connection-based need to check for termination and startup */ |
@@ -2068,13 +2130,12 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2068 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) | 2130 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
2069 | mask |= POLLERR; | 2131 | mask |= POLLERR; |
2070 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 2132 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
2071 | mask |= POLLRDHUP; | 2133 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
2072 | if (sk->sk_shutdown == SHUTDOWN_MASK) | 2134 | if (sk->sk_shutdown == SHUTDOWN_MASK) |
2073 | mask |= POLLHUP; | 2135 | mask |= POLLHUP; |
2074 | 2136 | ||
2075 | /* readable? */ | 2137 | /* readable? */ |
2076 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 2138 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
2077 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
2078 | mask |= POLLIN | POLLRDNORM; | 2139 | mask |= POLLIN | POLLRDNORM; |
2079 | 2140 | ||
2080 | /* Connection-based need to check for termination and startup */ | 2141 | /* Connection-based need to check for termination and startup */ |
@@ -2086,20 +2147,19 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2086 | return mask; | 2147 | return mask; |
2087 | } | 2148 | } |
2088 | 2149 | ||
2089 | /* writable? */ | 2150 | /* No write status requested, avoid expensive OUT tests. */ |
2090 | writable = unix_writable(sk); | 2151 | if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) |
2091 | if (writable) { | 2152 | return mask; |
2092 | other = unix_peer_get(sk); | ||
2093 | if (other) { | ||
2094 | if (unix_peer(other) != sk) { | ||
2095 | sock_poll_wait(file, &unix_sk(other)->peer_wait, | ||
2096 | wait); | ||
2097 | if (unix_recvq_full(other)) | ||
2098 | writable = 0; | ||
2099 | } | ||
2100 | 2153 | ||
2101 | sock_put(other); | 2154 | writable = unix_writable(sk); |
2155 | other = unix_peer_get(sk); | ||
2156 | if (other) { | ||
2157 | if (unix_peer(other) != sk) { | ||
2158 | sock_poll_wait(file, &unix_sk(other)->peer_wait, wait); | ||
2159 | if (unix_recvq_full(other)) | ||
2160 | writable = 0; | ||
2102 | } | 2161 | } |
2162 | sock_put(other); | ||
2103 | } | 2163 | } |
2104 | 2164 | ||
2105 | if (writable) | 2165 | if (writable) |
@@ -2194,7 +2254,7 @@ static int unix_seq_show(struct seq_file *seq, void *v) | |||
2194 | struct unix_sock *u = unix_sk(s); | 2254 | struct unix_sock *u = unix_sk(s); |
2195 | unix_state_lock(s); | 2255 | unix_state_lock(s); |
2196 | 2256 | ||
2197 | seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", | 2257 | seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu", |
2198 | s, | 2258 | s, |
2199 | atomic_read(&s->sk_refcnt), | 2259 | atomic_read(&s->sk_refcnt), |
2200 | 0, | 2260 | 0, |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index c8df6fda0b1f..b6f4b994eb35 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); | |||
96 | unsigned int unix_tot_inflight; | 96 | unsigned int unix_tot_inflight; |
97 | 97 | ||
98 | 98 | ||
99 | static struct sock *unix_get_socket(struct file *filp) | 99 | struct sock *unix_get_socket(struct file *filp) |
100 | { | 100 | { |
101 | struct sock *u_sock = NULL; | 101 | struct sock *u_sock = NULL; |
102 | struct inode *inode = filp->f_path.dentry->d_inode; | 102 | struct inode *inode = filp->f_path.dentry->d_inode; |
@@ -104,7 +104,7 @@ static struct sock *unix_get_socket(struct file *filp) | |||
104 | /* | 104 | /* |
105 | * Socket ? | 105 | * Socket ? |
106 | */ | 106 | */ |
107 | if (S_ISSOCK(inode->i_mode)) { | 107 | if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) { |
108 | struct socket *sock = SOCKET_I(inode); | 108 | struct socket *sock = SOCKET_I(inode); |
109 | struct sock *s = sock->sk; | 109 | struct sock *s = sock->sk; |
110 | 110 | ||
@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u) | |||
259 | } | 259 | } |
260 | 260 | ||
261 | static bool gc_in_progress = false; | 261 | static bool gc_in_progress = false; |
262 | #define UNIX_INFLIGHT_TRIGGER_GC 16000 | ||
262 | 263 | ||
263 | void wait_for_unix_gc(void) | 264 | void wait_for_unix_gc(void) |
264 | { | 265 | { |
266 | /* | ||
267 | * If number of inflight sockets is insane, | ||
268 | * force a garbage collect right now. | ||
269 | */ | ||
270 | if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) | ||
271 | unix_gc(); | ||
265 | wait_event(unix_gc_wait, gc_in_progress == false); | 272 | wait_event(unix_gc_wait, gc_in_progress == false); |
266 | } | 273 | } |
267 | 274 | ||