diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fc3ebb906911..fef2cc5e9d2b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -144,7 +144,7 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) | |||
144 | /* | 144 | /* |
145 | * SMP locking strategy: | 145 | * SMP locking strategy: |
146 | * hash table is protected with spinlock unix_table_lock | 146 | * hash table is protected with spinlock unix_table_lock |
147 | * each socket state is protected by separate rwlock. | 147 | * each socket state is protected by separate spin lock. |
148 | */ | 148 | */ |
149 | 149 | ||
150 | static inline unsigned unix_hash_fold(__wsum n) | 150 | static inline unsigned unix_hash_fold(__wsum n) |
@@ -313,13 +313,16 @@ static inline int unix_writable(struct sock *sk) | |||
313 | 313 | ||
314 | static void unix_write_space(struct sock *sk) | 314 | static void unix_write_space(struct sock *sk) |
315 | { | 315 | { |
316 | read_lock(&sk->sk_callback_lock); | 316 | struct socket_wq *wq; |
317 | |||
318 | rcu_read_lock(); | ||
317 | if (unix_writable(sk)) { | 319 | if (unix_writable(sk)) { |
318 | if (sk_has_sleeper(sk)) | 320 | wq = rcu_dereference(sk->sk_wq); |
319 | wake_up_interruptible_sync(sk->sk_sleep); | 321 | if (wq_has_sleeper(wq)) |
322 | wake_up_interruptible_sync(&wq->wait); | ||
320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 323 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
321 | } | 324 | } |
322 | read_unlock(&sk->sk_callback_lock); | 325 | rcu_read_unlock(); |
323 | } | 326 | } |
324 | 327 | ||
325 | /* When dgram socket disconnects (or changes its peer), we clear its receive | 328 | /* When dgram socket disconnects (or changes its peer), we clear its receive |
@@ -406,9 +409,7 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
406 | skpair->sk_err = ECONNRESET; | 409 | skpair->sk_err = ECONNRESET; |
407 | unix_state_unlock(skpair); | 410 | unix_state_unlock(skpair); |
408 | skpair->sk_state_change(skpair); | 411 | skpair->sk_state_change(skpair); |
409 | read_lock(&skpair->sk_callback_lock); | ||
410 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); | 412 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
411 | read_unlock(&skpair->sk_callback_lock); | ||
412 | } | 413 | } |
413 | sock_put(skpair); /* It may now die */ | 414 | sock_put(skpair); /* It may now die */ |
414 | unix_peer(sk) = NULL; | 415 | unix_peer(sk) = NULL; |
@@ -621,7 +622,8 @@ out: | |||
621 | return sk; | 622 | return sk; |
622 | } | 623 | } |
623 | 624 | ||
624 | static int unix_create(struct net *net, struct socket *sock, int protocol) | 625 | static int unix_create(struct net *net, struct socket *sock, int protocol, |
626 | int kern) | ||
625 | { | 627 | { |
626 | if (protocol && protocol != PF_UNIX) | 628 | if (protocol && protocol != PF_UNIX) |
627 | return -EPROTONOSUPPORT; | 629 | return -EPROTONOSUPPORT; |
@@ -1032,8 +1034,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1032 | goto out; | 1034 | goto out; |
1033 | addr_len = err; | 1035 | addr_len = err; |
1034 | 1036 | ||
1035 | if (test_bit(SOCK_PASSCRED, &sock->flags) | 1037 | if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr && |
1036 | && !u->addr && (err = unix_autobind(sock)) != 0) | 1038 | (err = unix_autobind(sock)) != 0) |
1037 | goto out; | 1039 | goto out; |
1038 | 1040 | ||
1039 | timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); | 1041 | timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); |
@@ -1074,6 +1076,8 @@ restart: | |||
1074 | err = -ECONNREFUSED; | 1076 | err = -ECONNREFUSED; |
1075 | if (other->sk_state != TCP_LISTEN) | 1077 | if (other->sk_state != TCP_LISTEN) |
1076 | goto out_unlock; | 1078 | goto out_unlock; |
1079 | if (other->sk_shutdown & RCV_SHUTDOWN) | ||
1080 | goto out_unlock; | ||
1077 | 1081 | ||
1078 | if (unix_recvq_full(other)) { | 1082 | if (unix_recvq_full(other)) { |
1079 | err = -EAGAIN; | 1083 | err = -EAGAIN; |
@@ -1139,7 +1143,7 @@ restart: | |||
1139 | newsk->sk_peercred.pid = task_tgid_vnr(current); | 1143 | newsk->sk_peercred.pid = task_tgid_vnr(current); |
1140 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); | 1144 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); |
1141 | newu = unix_sk(newsk); | 1145 | newu = unix_sk(newsk); |
1142 | newsk->sk_sleep = &newu->peer_wait; | 1146 | newsk->sk_wq = &newu->peer_wq; |
1143 | otheru = unix_sk(other); | 1147 | otheru = unix_sk(other); |
1144 | 1148 | ||
1145 | /* copy address information from listening to new sock*/ | 1149 | /* copy address information from listening to new sock*/ |
@@ -1256,7 +1260,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ | |||
1256 | { | 1260 | { |
1257 | struct sock *sk = sock->sk; | 1261 | struct sock *sk = sock->sk; |
1258 | struct unix_sock *u; | 1262 | struct unix_sock *u; |
1259 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; | 1263 | DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr); |
1260 | int err = 0; | 1264 | int err = 0; |
1261 | 1265 | ||
1262 | if (peer) { | 1266 | if (peer) { |
@@ -1375,8 +1379,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1375 | goto out; | 1379 | goto out; |
1376 | } | 1380 | } |
1377 | 1381 | ||
1378 | if (test_bit(SOCK_PASSCRED, &sock->flags) | 1382 | if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr |
1379 | && !u->addr && (err = unix_autobind(sock)) != 0) | 1383 | && (err = unix_autobind(sock)) != 0) |
1380 | goto out; | 1384 | goto out; |
1381 | 1385 | ||
1382 | err = -EMSGSIZE; | 1386 | err = -EMSGSIZE; |
@@ -1501,6 +1505,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1501 | struct sk_buff *skb; | 1505 | struct sk_buff *skb; |
1502 | int sent = 0; | 1506 | int sent = 0; |
1503 | struct scm_cookie tmp_scm; | 1507 | struct scm_cookie tmp_scm; |
1508 | bool fds_sent = false; | ||
1504 | 1509 | ||
1505 | if (NULL == siocb->scm) | 1510 | if (NULL == siocb->scm) |
1506 | siocb->scm = &tmp_scm; | 1511 | siocb->scm = &tmp_scm; |
@@ -1562,12 +1567,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1562 | size = min_t(int, size, skb_tailroom(skb)); | 1567 | size = min_t(int, size, skb_tailroom(skb)); |
1563 | 1568 | ||
1564 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); | 1569 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); |
1565 | if (siocb->scm->fp) { | 1570 | /* Only send the fds in the first buffer */ |
1571 | if (siocb->scm->fp && !fds_sent) { | ||
1566 | err = unix_attach_fds(siocb->scm, skb); | 1572 | err = unix_attach_fds(siocb->scm, skb); |
1567 | if (err) { | 1573 | if (err) { |
1568 | kfree_skb(skb); | 1574 | kfree_skb(skb); |
1569 | goto out_err; | 1575 | goto out_err; |
1570 | } | 1576 | } |
1577 | fds_sent = true; | ||
1571 | } | 1578 | } |
1572 | 1579 | ||
1573 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 1580 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
@@ -1730,7 +1737,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1730 | unix_state_lock(sk); | 1737 | unix_state_lock(sk); |
1731 | 1738 | ||
1732 | for (;;) { | 1739 | for (;;) { |
1733 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1740 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1734 | 1741 | ||
1735 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 1742 | if (!skb_queue_empty(&sk->sk_receive_queue) || |
1736 | sk->sk_err || | 1743 | sk->sk_err || |
@@ -1746,7 +1753,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1746 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1753 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1747 | } | 1754 | } |
1748 | 1755 | ||
1749 | finish_wait(sk->sk_sleep, &wait); | 1756 | finish_wait(sk_sleep(sk), &wait); |
1750 | unix_state_unlock(sk); | 1757 | unix_state_unlock(sk); |
1751 | return timeo; | 1758 | return timeo; |
1752 | } | 1759 | } |
@@ -1925,12 +1932,10 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1925 | other->sk_shutdown |= peer_mode; | 1932 | other->sk_shutdown |= peer_mode; |
1926 | unix_state_unlock(other); | 1933 | unix_state_unlock(other); |
1927 | other->sk_state_change(other); | 1934 | other->sk_state_change(other); |
1928 | read_lock(&other->sk_callback_lock); | ||
1929 | if (peer_mode == SHUTDOWN_MASK) | 1935 | if (peer_mode == SHUTDOWN_MASK) |
1930 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 1936 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
1931 | else if (peer_mode & RCV_SHUTDOWN) | 1937 | else if (peer_mode & RCV_SHUTDOWN) |
1932 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 1938 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
1933 | read_unlock(&other->sk_callback_lock); | ||
1934 | } | 1939 | } |
1935 | if (other) | 1940 | if (other) |
1936 | sock_put(other); | 1941 | sock_put(other); |
@@ -1985,7 +1990,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
1985 | struct sock *sk = sock->sk; | 1990 | struct sock *sk = sock->sk; |
1986 | unsigned int mask; | 1991 | unsigned int mask; |
1987 | 1992 | ||
1988 | sock_poll_wait(file, sk->sk_sleep, wait); | 1993 | sock_poll_wait(file, sk_sleep(sk), wait); |
1989 | mask = 0; | 1994 | mask = 0; |
1990 | 1995 | ||
1991 | /* exceptional events? */ | 1996 | /* exceptional events? */ |
@@ -2022,7 +2027,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2022 | struct sock *sk = sock->sk, *other; | 2027 | struct sock *sk = sock->sk, *other; |
2023 | unsigned int mask, writable; | 2028 | unsigned int mask, writable; |
2024 | 2029 | ||
2025 | sock_poll_wait(file, sk->sk_sleep, wait); | 2030 | sock_poll_wait(file, sk_sleep(sk), wait); |
2026 | mask = 0; | 2031 | mask = 0; |
2027 | 2032 | ||
2028 | /* exceptional events? */ | 2033 | /* exceptional events? */ |
@@ -2211,14 +2216,14 @@ static const struct file_operations unix_seq_fops = { | |||
2211 | 2216 | ||
2212 | #endif | 2217 | #endif |
2213 | 2218 | ||
2214 | static struct net_proto_family unix_family_ops = { | 2219 | static const struct net_proto_family unix_family_ops = { |
2215 | .family = PF_UNIX, | 2220 | .family = PF_UNIX, |
2216 | .create = unix_create, | 2221 | .create = unix_create, |
2217 | .owner = THIS_MODULE, | 2222 | .owner = THIS_MODULE, |
2218 | }; | 2223 | }; |
2219 | 2224 | ||
2220 | 2225 | ||
2221 | static int unix_net_init(struct net *net) | 2226 | static int __net_init unix_net_init(struct net *net) |
2222 | { | 2227 | { |
2223 | int error = -ENOMEM; | 2228 | int error = -ENOMEM; |
2224 | 2229 | ||
@@ -2237,7 +2242,7 @@ out: | |||
2237 | return error; | 2242 | return error; |
2238 | } | 2243 | } |
2239 | 2244 | ||
2240 | static void unix_net_exit(struct net *net) | 2245 | static void __net_exit unix_net_exit(struct net *net) |
2241 | { | 2246 | { |
2242 | unix_sysctl_unregister(net); | 2247 | unix_sysctl_unregister(net); |
2243 | proc_net_remove(net, "unix"); | 2248 | proc_net_remove(net, "unix"); |