aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c73
1 files changed, 50 insertions, 23 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3c95304a0817..dd419d286204 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -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();
@@ -1156,7 +1157,7 @@ restart:
1156 goto restart; 1157 goto restart;
1157 } 1158 }
1158 1159
1159 err = security_unix_stream_connect(sock, other->sk_socket, newsk); 1160 err = security_unix_stream_connect(sk, other, newsk);
1160 if (err) { 1161 if (err) {
1161 unix_state_unlock(sk); 1162 unix_state_unlock(sk);
1162 goto out_unlock; 1163 goto out_unlock;
@@ -1343,9 +1344,25 @@ static void unix_destruct_scm(struct sk_buff *skb)
1343 sock_wfree(skb); 1344 sock_wfree(skb);
1344} 1345}
1345 1346
1347#define MAX_RECURSION_LEVEL 4
1348
1346static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) 1349static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1347{ 1350{
1348 int i; 1351 int i;
1352 unsigned char max_level = 0;
1353 int unix_sock_count = 0;
1354
1355 for (i = scm->fp->count - 1; i >= 0; i--) {
1356 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1357
1358 if (sk) {
1359 unix_sock_count++;
1360 max_level = max(max_level,
1361 unix_sk(sk)->recursion_level);
1362 }
1363 }
1364 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1365 return -ETOOMANYREFS;
1349 1366
1350 /* 1367 /*
1351 * Need to duplicate file references for the sake of garbage 1368 * Need to duplicate file references for the sake of garbage
@@ -1356,9 +1373,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1356 if (!UNIXCB(skb).fp) 1373 if (!UNIXCB(skb).fp)
1357 return -ENOMEM; 1374 return -ENOMEM;
1358 1375
1359 for (i = scm->fp->count-1; i >= 0; i--) 1376 if (unix_sock_count) {
1360 unix_inflight(scm->fp->fp[i]); 1377 for (i = scm->fp->count - 1; i >= 0; i--)
1361 return 0; 1378 unix_inflight(scm->fp->fp[i]);
1379 }
1380 return max_level;
1362} 1381}
1363 1382
1364static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) 1383static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
@@ -1393,6 +1412,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1393 struct sk_buff *skb; 1412 struct sk_buff *skb;
1394 long timeo; 1413 long timeo;
1395 struct scm_cookie tmp_scm; 1414 struct scm_cookie tmp_scm;
1415 int max_level;
1396 1416
1397 if (NULL == siocb->scm) 1417 if (NULL == siocb->scm)
1398 siocb->scm = &tmp_scm; 1418 siocb->scm = &tmp_scm;
@@ -1431,8 +1451,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1431 goto out; 1451 goto out;
1432 1452
1433 err = unix_scm_to_skb(siocb->scm, skb, true); 1453 err = unix_scm_to_skb(siocb->scm, skb, true);
1434 if (err) 1454 if (err < 0)
1435 goto out_free; 1455 goto out_free;
1456 max_level = err + 1;
1436 unix_get_secdata(siocb->scm, skb); 1457 unix_get_secdata(siocb->scm, skb);
1437 1458
1438 skb_reset_transport_header(skb); 1459 skb_reset_transport_header(skb);
@@ -1514,6 +1535,8 @@ restart:
1514 if (sock_flag(other, SOCK_RCVTSTAMP)) 1535 if (sock_flag(other, SOCK_RCVTSTAMP))
1515 __net_timestamp(skb); 1536 __net_timestamp(skb);
1516 skb_queue_tail(&other->sk_receive_queue, skb); 1537 skb_queue_tail(&other->sk_receive_queue, skb);
1538 if (max_level > unix_sk(other)->recursion_level)
1539 unix_sk(other)->recursion_level = max_level;
1517 unix_state_unlock(other); 1540 unix_state_unlock(other);
1518 other->sk_data_ready(other, len); 1541 other->sk_data_ready(other, len);
1519 sock_put(other); 1542 sock_put(other);
@@ -1544,6 +1567,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1544 int sent = 0; 1567 int sent = 0;
1545 struct scm_cookie tmp_scm; 1568 struct scm_cookie tmp_scm;
1546 bool fds_sent = false; 1569 bool fds_sent = false;
1570 int max_level;
1547 1571
1548 if (NULL == siocb->scm) 1572 if (NULL == siocb->scm)
1549 siocb->scm = &tmp_scm; 1573 siocb->scm = &tmp_scm;
@@ -1607,10 +1631,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1607 1631
1608 /* Only send the fds in the first buffer */ 1632 /* Only send the fds in the first buffer */
1609 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); 1633 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
1610 if (err) { 1634 if (err < 0) {
1611 kfree_skb(skb); 1635 kfree_skb(skb);
1612 goto out_err; 1636 goto out_err;
1613 } 1637 }
1638 max_level = err + 1;
1614 fds_sent = true; 1639 fds_sent = true;
1615 1640
1616 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 1641 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
@@ -1626,6 +1651,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1626 goto pipe_err_free; 1651 goto pipe_err_free;
1627 1652
1628 skb_queue_tail(&other->sk_receive_queue, skb); 1653 skb_queue_tail(&other->sk_receive_queue, skb);
1654 if (max_level > unix_sk(other)->recursion_level)
1655 unix_sk(other)->recursion_level = max_level;
1629 unix_state_unlock(other); 1656 unix_state_unlock(other);
1630 other->sk_data_ready(other, size); 1657 other->sk_data_ready(other, size);
1631 sent += size; 1658 sent += size;
@@ -1710,7 +1737,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1710 goto out_unlock; 1737 goto out_unlock;
1711 } 1738 }
1712 1739
1713 wake_up_interruptible_sync(&u->peer_wait); 1740 wake_up_interruptible_sync_poll(&u->peer_wait,
1741 POLLOUT | POLLWRNORM | POLLWRBAND);
1714 1742
1715 if (msg->msg_name) 1743 if (msg->msg_name)
1716 unix_copy_addr(msg, skb->sk); 1744 unix_copy_addr(msg, skb->sk);
@@ -1845,6 +1873,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1845 unix_state_lock(sk); 1873 unix_state_lock(sk);
1846 skb = skb_dequeue(&sk->sk_receive_queue); 1874 skb = skb_dequeue(&sk->sk_receive_queue);
1847 if (skb == NULL) { 1875 if (skb == NULL) {
1876 unix_sk(sk)->recursion_level = 0;
1848 if (copied >= target) 1877 if (copied >= target)
1849 goto unlock; 1878 goto unlock;
1850 1879
@@ -2072,13 +2101,12 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2072 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 2101 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
2073 mask |= POLLERR; 2102 mask |= POLLERR;
2074 if (sk->sk_shutdown & RCV_SHUTDOWN) 2103 if (sk->sk_shutdown & RCV_SHUTDOWN)
2075 mask |= POLLRDHUP; 2104 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
2076 if (sk->sk_shutdown == SHUTDOWN_MASK) 2105 if (sk->sk_shutdown == SHUTDOWN_MASK)
2077 mask |= POLLHUP; 2106 mask |= POLLHUP;
2078 2107
2079 /* readable? */ 2108 /* readable? */
2080 if (!skb_queue_empty(&sk->sk_receive_queue) || 2109 if (!skb_queue_empty(&sk->sk_receive_queue))
2081 (sk->sk_shutdown & RCV_SHUTDOWN))
2082 mask |= POLLIN | POLLRDNORM; 2110 mask |= POLLIN | POLLRDNORM;
2083 2111
2084 /* Connection-based need to check for termination and startup */ 2112 /* Connection-based need to check for termination and startup */
@@ -2090,20 +2118,19 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2090 return mask; 2118 return mask;
2091 } 2119 }
2092 2120
2093 /* writable? */ 2121 /* No write status requested, avoid expensive OUT tests. */
2094 writable = unix_writable(sk); 2122 if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT)))
2095 if (writable) { 2123 return mask;
2096 other = unix_peer_get(sk);
2097 if (other) {
2098 if (unix_peer(other) != sk) {
2099 sock_poll_wait(file, &unix_sk(other)->peer_wait,
2100 wait);
2101 if (unix_recvq_full(other))
2102 writable = 0;
2103 }
2104 2124
2105 sock_put(other); 2125 writable = unix_writable(sk);
2126 other = unix_peer_get(sk);
2127 if (other) {
2128 if (unix_peer(other) != sk) {
2129 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2130 if (unix_recvq_full(other))
2131 writable = 0;
2106 } 2132 }
2133 sock_put(other);
2107 } 2134 }
2108 2135
2109 if (writable) 2136 if (writable)