blob: f246812680d7b9749d1f19dc54f83c6035dcf014 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NET4: Implementation of BSD Unix domain sockets.
3 *
Alan Cox113aa832008-10-13 19:01:08 -07004 * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * Fixes:
12 * Linus Torvalds : Assorted bug cures.
13 * Niibe Yutaka : async I/O support.
14 * Carsten Paeth : PF_UNIX check, address fixes.
15 * Alan Cox : Limit size of allocated blocks.
16 * Alan Cox : Fixed the stupid socketpair bug.
17 * Alan Cox : BSD compatibility fine tuning.
18 * Alan Cox : Fixed a bug in connect when interrupted.
19 * Alan Cox : Sorted out a proper draft version of
20 * file descriptor passing hacked up from
21 * Mike Shaver's work.
22 * Marty Leisner : Fixes to fd passing
23 * Nick Nevin : recvmsg bugfix.
24 * Alan Cox : Started proper garbage collector
25 * Heiko EiBfeldt : Missing verify_area check
26 * Alan Cox : Started POSIXisms
27 * Andreas Schwab : Replace inode by dentry for proper
28 * reference counting
29 * Kirk Petersen : Made this a module
30 * Christoph Rohland : Elegant non-blocking accept/connect algorithm.
31 * Lots of bug fixes.
32 * Alexey Kuznetosv : Repaired (I hope) bugs introduces
33 * by above two patches.
34 * Andrea Arcangeli : If possible we block in connect(2)
35 * if the max backlog of the listen socket
36 * is been reached. This won't break
37 * old apps and it will avoid huge amount
38 * of socks hashed (this for unix_gc()
39 * performances reasons).
40 * Security fix that limits the max
41 * number of socks to 2*max_files and
42 * the number of skb queueable in the
43 * dgram receiver.
44 * Artur Skawina : Hash function optimizations
45 * Alexey Kuznetsov : Full scale SMP. Lot of bugs are introduced 8)
46 * Malcolm Beattie : Set peercred for socketpair
47 * Michal Ostrowski : Module initialization cleanup.
48 * Arnaldo C. Melo : Remove MOD_{INC,DEC}_USE_COUNT,
49 * the core infrastructure is doing that
50 * for all net proto families now (2.5.69+)
51 *
52 *
53 * Known differences from reference BSD that was tested:
54 *
55 * [TO FIX]
56 * ECONNREFUSED is not returned from one end of a connected() socket to the
57 * other the moment one end closes.
58 * fstat() doesn't return st_dev=0, and give the blksize as high water mark
59 * and a fake inode identifier (nor the BSD first socket fstat twice bug).
60 * [NOT TO FIX]
61 * accept() returns a path name even if the connecting socket has closed
62 * in the meantime (BSD loses the path and gives up).
63 * accept() returns 0 length path for an unbound connector. BSD returns 16
64 * and a null first byte in the path (but not for gethost/peername - BSD bug ??)
65 * socketpair(...SOCK_RAW..) doesn't panic the kernel.
66 * BSD af_unix apparently has connect forgetting to block properly.
67 * (need to check this with the POSIX spec in detail)
68 *
69 * Differences from 2.0.0-11-... (ANK)
70 * Bug fixes and improvements.
71 * - client shutdown killed server socket.
72 * - removed all useless cli/sti pairs.
73 *
74 * Semantic changes/extensions.
75 * - generic control message passing.
76 * - SCM_CREDENTIALS control message.
77 * - "Abstract" (not FS based) socket bindings.
78 * Abstract names are sequences of bytes (not zero terminated)
79 * started by 0, so that this name space does not intersect
80 * with BSD names.
81 */
82
83#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/signal.h>
86#include <linux/sched.h>
87#include <linux/errno.h>
88#include <linux/string.h>
89#include <linux/stat.h>
90#include <linux/dcache.h>
91#include <linux/namei.h>
92#include <linux/socket.h>
93#include <linux/un.h>
94#include <linux/fcntl.h>
95#include <linux/termios.h>
96#include <linux/sockios.h>
97#include <linux/net.h>
98#include <linux/in.h>
99#include <linux/fs.h>
100#include <linux/slab.h>
101#include <asm/uaccess.h>
102#include <linux/skbuff.h>
103#include <linux/netdevice.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +0200104#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105#include <net/sock.h>
Arnaldo Carvalho de Meloc752f072005-08-09 20:08:28 -0700106#include <net/tcp_states.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#include <net/af_unix.h>
108#include <linux/proc_fs.h>
109#include <linux/seq_file.h>
110#include <net/scm.h>
111#include <linux/init.h>
112#include <linux/poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#include <linux/rtnetlink.h>
114#include <linux/mount.h>
115#include <net/checksum.h>
116#include <linux/security.h>
Colin Cross1dc14992013-05-06 23:50:21 +0000117#include <linux/freezer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000119struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000120EXPORT_SYMBOL_GPL(unix_socket_table);
121DEFINE_SPINLOCK(unix_table_lock);
122EXPORT_SYMBOL_GPL(unix_table_lock);
Eric Dumazet518de9b2010-10-26 14:22:44 -0700123static atomic_long_t unix_nr_socks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000126static struct hlist_head *unix_sockets_unbound(void *addr)
127{
128 unsigned long hash = (unsigned long)addr;
129
130 hash ^= hash >> 16;
131 hash ^= hash >> 8;
132 hash %= UNIX_HASH_SIZE;
133 return &unix_socket_table[UNIX_HASH_SIZE + hash];
134}
135
136#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700138#ifdef CONFIG_SECURITY_NETWORK
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700139static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700140{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700141 memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700142}
143
144static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
145{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700146 scm->secid = *UNIXSID(skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700147}
148#else
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700149static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700150{ }
151
152static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
153{ }
154#endif /* CONFIG_SECURITY_NETWORK */
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156/*
157 * SMP locking strategy:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800158 * hash table is protected with spinlock unix_table_lock
Stephen Hemminger663717f2010-02-18 14:12:06 -0800159 * each socket state is protected by separate spin lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 */
161
Eric Dumazet95c96172012-04-15 05:58:06 +0000162static inline unsigned int unix_hash_fold(__wsum n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163{
Eric Dumazet95c96172012-04-15 05:58:06 +0000164 unsigned int hash = (__force unsigned int)n;
165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 hash ^= hash>>16;
167 hash ^= hash>>8;
168 return hash&(UNIX_HASH_SIZE-1);
169}
170
171#define unix_peer(sk) (unix_sk(sk)->peer)
172
173static inline int unix_our_peer(struct sock *sk, struct sock *osk)
174{
175 return unix_peer(osk) == sk;
176}
177
178static inline int unix_may_send(struct sock *sk, struct sock *osk)
179{
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800180 return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181}
182
Rainer Weikusat3c734192008-06-17 22:28:05 -0700183static inline int unix_recvq_full(struct sock const *sk)
184{
185 return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
186}
187
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000188struct sock *unix_peer_get(struct sock *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189{
190 struct sock *peer;
191
David S. Miller1c92b4e2007-05-31 13:24:26 -0700192 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 peer = unix_peer(s);
194 if (peer)
195 sock_hold(peer);
David S. Miller1c92b4e2007-05-31 13:24:26 -0700196 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 return peer;
198}
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000199EXPORT_SYMBOL_GPL(unix_peer_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201static inline void unix_release_addr(struct unix_address *addr)
202{
203 if (atomic_dec_and_test(&addr->refcnt))
204 kfree(addr);
205}
206
207/*
208 * Check unix socket name:
209 * - should be not zero length.
210 * - if started by not zero, should be NULL terminated (FS object)
211 * - if started by zero, it is abstract name.
212 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900213
Eric Dumazet95c96172012-04-15 05:58:06 +0000214static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
216 if (len <= sizeof(short) || len > sizeof(*sunaddr))
217 return -EINVAL;
218 if (!sunaddr || sunaddr->sun_family != AF_UNIX)
219 return -EINVAL;
220 if (sunaddr->sun_path[0]) {
221 /*
222 * This may look like an off by one error but it is a bit more
223 * subtle. 108 is the longest valid AF_UNIX path for a binding.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300224 * sun_path[108] doesn't as such exist. However in kernel space
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 * we are guaranteed that it is a valid memory location in our
226 * kernel address buffer.
227 */
Jianjun Konge27dfce2008-11-01 21:38:31 -0700228 ((char *)sunaddr)[len] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 len = strlen(sunaddr->sun_path)+1+sizeof(short);
230 return len;
231 }
232
Joe Perches07f07572008-11-19 15:44:53 -0800233 *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 return len;
235}
236
237static void __unix_remove_socket(struct sock *sk)
238{
239 sk_del_node_init(sk);
240}
241
242static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
243{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700244 WARN_ON(!sk_unhashed(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 sk_add_node(sk, list);
246}
247
248static inline void unix_remove_socket(struct sock *sk)
249{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800250 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 __unix_remove_socket(sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800252 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253}
254
255static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
256{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800257 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 __unix_insert_socket(list, sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800259 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260}
261
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800262static struct sock *__unix_find_socket_byname(struct net *net,
263 struct sockaddr_un *sunname,
Eric Dumazet95c96172012-04-15 05:58:06 +0000264 int len, int type, unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
266 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Sasha Levinb67bfe02013-02-27 17:06:00 -0800268 sk_for_each(s, &unix_socket_table[hash ^ type]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 struct unix_sock *u = unix_sk(s);
270
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900271 if (!net_eq(sock_net(s), net))
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800272 continue;
273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 if (u->addr->len == len &&
275 !memcmp(u->addr->name, sunname, len))
276 goto found;
277 }
278 s = NULL;
279found:
280 return s;
281}
282
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800283static inline struct sock *unix_find_socket_byname(struct net *net,
284 struct sockaddr_un *sunname,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 int len, int type,
Eric Dumazet95c96172012-04-15 05:58:06 +0000286 unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
288 struct sock *s;
289
David S. Millerfbe9cc42005-12-13 23:26:29 -0800290 spin_lock(&unix_table_lock);
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800291 s = __unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 if (s)
293 sock_hold(s);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800294 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return s;
296}
297
Eric W. Biederman6616f782010-06-13 03:35:48 +0000298static struct sock *unix_find_socket_byinode(struct inode *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
300 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
David S. Millerfbe9cc42005-12-13 23:26:29 -0800302 spin_lock(&unix_table_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800303 sk_for_each(s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
Al Viro40ffe672012-03-14 21:54:32 -0400305 struct dentry *dentry = unix_sk(s)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800307 if (dentry && dentry->d_inode == i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sock_hold(s);
309 goto found;
310 }
311 }
312 s = NULL;
313found:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800314 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 return s;
316}
317
318static inline int unix_writable(struct sock *sk)
319{
320 return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
321}
322
323static void unix_write_space(struct sock *sk)
324{
Eric Dumazet43815482010-04-29 11:01:49 +0000325 struct socket_wq *wq;
326
327 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 if (unix_writable(sk)) {
Eric Dumazet43815482010-04-29 11:01:49 +0000329 wq = rcu_dereference(sk->sk_wq);
330 if (wq_has_sleeper(wq))
Eric Dumazet67426b72010-10-29 20:44:44 +0000331 wake_up_interruptible_sync_poll(&wq->wait,
332 POLLOUT | POLLWRNORM | POLLWRBAND);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800333 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Eric Dumazet43815482010-04-29 11:01:49 +0000335 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336}
337
338/* When dgram socket disconnects (or changes its peer), we clear its receive
339 * queue of packets arrived from previous peer. First, it allows to do
340 * flow control based only on wmem_alloc; second, sk connected to peer
341 * may receive messages only from that peer. */
342static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
343{
David S. Millerb03efcf2005-07-08 14:57:23 -0700344 if (!skb_queue_empty(&sk->sk_receive_queue)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 skb_queue_purge(&sk->sk_receive_queue);
346 wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
347
348 /* If one link of bidirectional dgram pipe is disconnected,
349 * we signal error. Messages are lost. Do not make this,
350 * when peer was not connected to us.
351 */
352 if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
353 other->sk_err = ECONNRESET;
354 other->sk_error_report(other);
355 }
356 }
357}
358
359static void unix_sock_destructor(struct sock *sk)
360{
361 struct unix_sock *u = unix_sk(sk);
362
363 skb_queue_purge(&sk->sk_receive_queue);
364
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700365 WARN_ON(atomic_read(&sk->sk_wmem_alloc));
366 WARN_ON(!sk_unhashed(sk));
367 WARN_ON(sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 if (!sock_flag(sk, SOCK_DEAD)) {
Eric Dumazet6b41e7d2008-11-19 15:48:09 -0800369 printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return;
371 }
372
373 if (u->addr)
374 unix_release_addr(u->addr);
375
Eric Dumazet518de9b2010-10-26 14:22:44 -0700376 atomic_long_dec(&unix_nr_socks);
David S. Miller6f756a82008-11-23 17:34:03 -0800377 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800378 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
David S. Miller6f756a82008-11-23 17:34:03 -0800379 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380#ifdef UNIX_REFCNT_DEBUG
Eric Dumazet518de9b2010-10-26 14:22:44 -0700381 printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
382 atomic_long_read(&unix_nr_socks));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383#endif
384}
385
Paul Mooreded34e02013-03-25 03:18:33 +0000386static void unix_release_sock(struct sock *sk, int embrion)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
388 struct unix_sock *u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400389 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 struct sock *skpair;
391 struct sk_buff *skb;
392 int state;
393
394 unix_remove_socket(sk);
395
396 /* Clear state */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700397 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 sock_orphan(sk);
399 sk->sk_shutdown = SHUTDOWN_MASK;
Al Viro40ffe672012-03-14 21:54:32 -0400400 path = u->path;
401 u->path.dentry = NULL;
402 u->path.mnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 state = sk->sk_state;
404 sk->sk_state = TCP_CLOSE;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700405 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 wake_up_interruptible_all(&u->peer_wait);
408
Jianjun Konge27dfce2008-11-01 21:38:31 -0700409 skpair = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Jianjun Konge27dfce2008-11-01 21:38:31 -0700411 if (skpair != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
David S. Miller1c92b4e2007-05-31 13:24:26 -0700413 unix_state_lock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 /* No more writes */
415 skpair->sk_shutdown = SHUTDOWN_MASK;
416 if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
417 skpair->sk_err = ECONNRESET;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700418 unix_state_unlock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 skpair->sk_state_change(skpair);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800420 sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 }
422 sock_put(skpair); /* It may now die */
423 unix_peer(sk) = NULL;
424 }
425
426 /* Try to flush out this socket. Throw out buffers at least */
427
428 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
Jianjun Konge27dfce2008-11-01 21:38:31 -0700429 if (state == TCP_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 unix_release_sock(skb->sk, 1);
431 /* passed fds are erased in the kfree_skb hook */
432 kfree_skb(skb);
433 }
434
Al Viro40ffe672012-03-14 21:54:32 -0400435 if (path.dentry)
436 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 sock_put(sk);
439
440 /* ---- Socket is dead now and most probably destroyed ---- */
441
442 /*
Alan Coxe04dae82012-09-17 00:52:41 +0000443 * Fixme: BSD difference: In BSD all sockets connected to us get
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 * ECONNRESET and we die on the spot. In Linux we behave
445 * like files and pipes do and wait for the last
446 * dereference.
447 *
448 * Can't we simply set sock->err?
449 *
450 * What the above comment does talk about? --ANK(980817)
451 */
452
Pavel Emelyanov9305cfa2007-11-10 22:06:01 -0800453 if (unix_tot_inflight)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900454 unix_gc(); /* Garbage collect fds */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455}
456
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000457static void init_peercred(struct sock *sk)
458{
459 put_pid(sk->sk_peer_pid);
460 if (sk->sk_peer_cred)
461 put_cred(sk->sk_peer_cred);
462 sk->sk_peer_pid = get_pid(task_tgid(current));
463 sk->sk_peer_cred = get_current_cred();
464}
465
466static void copy_peercred(struct sock *sk, struct sock *peersk)
467{
468 put_pid(sk->sk_peer_pid);
469 if (sk->sk_peer_cred)
470 put_cred(sk->sk_peer_cred);
471 sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
472 sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
473}
474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475static int unix_listen(struct socket *sock, int backlog)
476{
477 int err;
478 struct sock *sk = sock->sk;
479 struct unix_sock *u = unix_sk(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000480 struct pid *old_pid = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800483 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
484 goto out; /* Only stream/seqpacket sockets accept */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 err = -EINVAL;
486 if (!u->addr)
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800487 goto out; /* No listens on an unbound socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700488 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
490 goto out_unlock;
491 if (backlog > sk->sk_max_ack_backlog)
492 wake_up_interruptible_all(&u->peer_wait);
493 sk->sk_max_ack_backlog = backlog;
494 sk->sk_state = TCP_LISTEN;
495 /* set credentials so connect can copy them */
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000496 init_peercred(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 err = 0;
498
499out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -0700500 unix_state_unlock(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000501 put_pid(old_pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502out:
503 return err;
504}
505
506static int unix_release(struct socket *);
507static int unix_bind(struct socket *, struct sockaddr *, int);
508static int unix_stream_connect(struct socket *, struct sockaddr *,
509 int addr_len, int flags);
510static int unix_socketpair(struct socket *, struct socket *);
511static int unix_accept(struct socket *, struct socket *, int);
512static int unix_getname(struct socket *, struct sockaddr *, int *, int);
513static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700514static unsigned int unix_dgram_poll(struct file *, struct socket *,
515 poll_table *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516static int unix_ioctl(struct socket *, unsigned int, unsigned long);
517static int unix_shutdown(struct socket *, int);
518static int unix_stream_sendmsg(struct kiocb *, struct socket *,
519 struct msghdr *, size_t);
520static int unix_stream_recvmsg(struct kiocb *, struct socket *,
521 struct msghdr *, size_t, int);
522static int unix_dgram_sendmsg(struct kiocb *, struct socket *,
523 struct msghdr *, size_t);
524static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
525 struct msghdr *, size_t, int);
526static int unix_dgram_connect(struct socket *, struct sockaddr *,
527 int, int);
528static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
529 struct msghdr *, size_t);
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000530static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
531 struct msghdr *, size_t, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Sasha Levind90d9ff2013-12-07 17:26:27 -0500533static int unix_set_peek_off(struct sock *sk, int val)
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000534{
535 struct unix_sock *u = unix_sk(sk);
536
Sasha Levind90d9ff2013-12-07 17:26:27 -0500537 if (mutex_lock_interruptible(&u->readlock))
538 return -EINTR;
539
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000540 sk->sk_peek_off = val;
541 mutex_unlock(&u->readlock);
Sasha Levind90d9ff2013-12-07 17:26:27 -0500542
543 return 0;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000544}
545
546
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800547static const struct proto_ops unix_stream_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 .family = PF_UNIX,
549 .owner = THIS_MODULE,
550 .release = unix_release,
551 .bind = unix_bind,
552 .connect = unix_stream_connect,
553 .socketpair = unix_socketpair,
554 .accept = unix_accept,
555 .getname = unix_getname,
556 .poll = unix_poll,
557 .ioctl = unix_ioctl,
558 .listen = unix_listen,
559 .shutdown = unix_shutdown,
560 .setsockopt = sock_no_setsockopt,
561 .getsockopt = sock_no_getsockopt,
562 .sendmsg = unix_stream_sendmsg,
563 .recvmsg = unix_stream_recvmsg,
564 .mmap = sock_no_mmap,
565 .sendpage = sock_no_sendpage,
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +0000566 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567};
568
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800569static const struct proto_ops unix_dgram_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 .family = PF_UNIX,
571 .owner = THIS_MODULE,
572 .release = unix_release,
573 .bind = unix_bind,
574 .connect = unix_dgram_connect,
575 .socketpair = unix_socketpair,
576 .accept = sock_no_accept,
577 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700578 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 .ioctl = unix_ioctl,
580 .listen = sock_no_listen,
581 .shutdown = unix_shutdown,
582 .setsockopt = sock_no_setsockopt,
583 .getsockopt = sock_no_getsockopt,
584 .sendmsg = unix_dgram_sendmsg,
585 .recvmsg = unix_dgram_recvmsg,
586 .mmap = sock_no_mmap,
587 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000588 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589};
590
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800591static const struct proto_ops unix_seqpacket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 .family = PF_UNIX,
593 .owner = THIS_MODULE,
594 .release = unix_release,
595 .bind = unix_bind,
596 .connect = unix_stream_connect,
597 .socketpair = unix_socketpair,
598 .accept = unix_accept,
599 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700600 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 .ioctl = unix_ioctl,
602 .listen = unix_listen,
603 .shutdown = unix_shutdown,
604 .setsockopt = sock_no_setsockopt,
605 .getsockopt = sock_no_getsockopt,
606 .sendmsg = unix_seqpacket_sendmsg,
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000607 .recvmsg = unix_seqpacket_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 .mmap = sock_no_mmap,
609 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000610 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
613static struct proto unix_proto = {
Eric Dumazet248969a2008-11-17 00:00:30 -0800614 .name = "UNIX",
615 .owner = THIS_MODULE,
Eric Dumazet248969a2008-11-17 00:00:30 -0800616 .obj_size = sizeof(struct unix_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617};
618
Ingo Molnara09785a2006-07-03 00:25:12 -0700619/*
620 * AF_UNIX sockets do not interact with hardware, hence they
621 * dont trigger interrupts - so it's safe for them to have
622 * bh-unsafe locking for their sk_receive_queue.lock. Split off
623 * this special lock-class by reinitializing the spinlock key:
624 */
625static struct lock_class_key af_unix_sk_receive_queue_lock_key;
626
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800627static struct sock *unix_create1(struct net *net, struct socket *sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 struct sock *sk = NULL;
630 struct unix_sock *u;
631
Eric Dumazet518de9b2010-10-26 14:22:44 -0700632 atomic_long_inc(&unix_nr_socks);
633 if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 goto out;
635
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700636 sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if (!sk)
638 goto out;
639
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800640 sock_init_data(sock, sk);
Ingo Molnara09785a2006-07-03 00:25:12 -0700641 lockdep_set_class(&sk->sk_receive_queue.lock,
642 &af_unix_sk_receive_queue_lock_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
644 sk->sk_write_space = unix_write_space;
Denis V. Luneva0a53c82007-12-11 04:19:17 -0800645 sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 sk->sk_destruct = unix_sock_destructor;
647 u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400648 u->path.dentry = NULL;
649 u->path.mnt = NULL;
Benjamin LaHaisefd19f322006-01-03 14:10:46 -0800650 spin_lock_init(&u->lock);
Al Viro516e0cc2008-07-26 00:39:17 -0400651 atomic_long_set(&u->inflight, 0);
Miklos Szeredi1fd05ba2007-07-11 14:22:39 -0700652 INIT_LIST_HEAD(&u->link);
Ingo Molnar57b47a52006-03-20 22:35:41 -0800653 mutex_init(&u->readlock); /* single task reading lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 init_waitqueue_head(&u->peer_wait);
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000655 unix_insert_socket(unix_sockets_unbound(sk), sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656out:
Pavel Emelyanov284b3272007-11-10 22:08:30 -0800657 if (sk == NULL)
Eric Dumazet518de9b2010-10-26 14:22:44 -0700658 atomic_long_dec(&unix_nr_socks);
Eric Dumazet920de802008-11-24 00:09:29 -0800659 else {
660 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800661 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
Eric Dumazet920de802008-11-24 00:09:29 -0800662 local_bh_enable();
663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 return sk;
665}
666
Eric Paris3f378b62009-11-05 22:18:14 -0800667static int unix_create(struct net *net, struct socket *sock, int protocol,
668 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
670 if (protocol && protocol != PF_UNIX)
671 return -EPROTONOSUPPORT;
672
673 sock->state = SS_UNCONNECTED;
674
675 switch (sock->type) {
676 case SOCK_STREAM:
677 sock->ops = &unix_stream_ops;
678 break;
679 /*
680 * Believe it or not BSD has AF_UNIX, SOCK_RAW though
681 * nothing uses it.
682 */
683 case SOCK_RAW:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700684 sock->type = SOCK_DGRAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 case SOCK_DGRAM:
686 sock->ops = &unix_dgram_ops;
687 break;
688 case SOCK_SEQPACKET:
689 sock->ops = &unix_seqpacket_ops;
690 break;
691 default:
692 return -ESOCKTNOSUPPORT;
693 }
694
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700695 return unix_create1(net, sock) ? 0 : -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696}
697
698static int unix_release(struct socket *sock)
699{
700 struct sock *sk = sock->sk;
701
702 if (!sk)
703 return 0;
704
Paul Mooreded34e02013-03-25 03:18:33 +0000705 unix_release_sock(sk, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 sock->sk = NULL;
707
Paul Mooreded34e02013-03-25 03:18:33 +0000708 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709}
710
711static int unix_autobind(struct socket *sock)
712{
713 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900714 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 struct unix_sock *u = unix_sk(sk);
716 static u32 ordernum = 1;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800717 struct unix_address *addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 int err;
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000719 unsigned int retries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
Sasha Levin57bc52e2013-12-13 10:54:22 -0500721 err = mutex_lock_interruptible(&u->readlock);
722 if (err)
723 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 err = 0;
726 if (u->addr)
727 goto out;
728
729 err = -ENOMEM;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700730 addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 if (!addr)
732 goto out;
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 addr->name->sun_family = AF_UNIX;
735 atomic_set(&addr->refcnt, 1);
736
737retry:
738 addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
Joe Perches07f07572008-11-19 15:44:53 -0800739 addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
David S. Millerfbe9cc42005-12-13 23:26:29 -0800741 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 ordernum = (ordernum+1)&0xFFFFF;
743
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800744 if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 addr->hash)) {
David S. Millerfbe9cc42005-12-13 23:26:29 -0800746 spin_unlock(&unix_table_lock);
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000747 /*
748 * __unix_find_socket_byname() may take long time if many names
749 * are already in use.
750 */
751 cond_resched();
752 /* Give up if all names seems to be in use. */
753 if (retries++ == 0xFFFFF) {
754 err = -ENOSPC;
755 kfree(addr);
756 goto out;
757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 goto retry;
759 }
760 addr->hash ^= sk->sk_type;
761
762 __unix_remove_socket(sk);
763 u->addr = addr;
764 __unix_insert_socket(&unix_socket_table[addr->hash], sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800765 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 err = 0;
767
Ingo Molnar57b47a52006-03-20 22:35:41 -0800768out: mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 return err;
770}
771
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800772static struct sock *unix_find_other(struct net *net,
773 struct sockaddr_un *sunname, int len,
Eric Dumazet95c96172012-04-15 05:58:06 +0000774 int type, unsigned int hash, int *error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
776 struct sock *u;
Al Viro421748e2008-08-02 01:04:36 -0400777 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 int err = 0;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (sunname->sun_path[0]) {
Al Viro421748e2008-08-02 01:04:36 -0400781 struct inode *inode;
782 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 if (err)
784 goto fail;
Al Viro421748e2008-08-02 01:04:36 -0400785 inode = path.dentry->d_inode;
786 err = inode_permission(inode, MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (err)
788 goto put_fail;
789
790 err = -ECONNREFUSED;
Al Viro421748e2008-08-02 01:04:36 -0400791 if (!S_ISSOCK(inode->i_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 goto put_fail;
Eric W. Biederman6616f782010-06-13 03:35:48 +0000793 u = unix_find_socket_byinode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (!u)
795 goto put_fail;
796
797 if (u->sk_type == type)
Al Viro68ac1232012-03-15 08:21:57 -0400798 touch_atime(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Al Viro421748e2008-08-02 01:04:36 -0400800 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Jianjun Konge27dfce2008-11-01 21:38:31 -0700802 err = -EPROTOTYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 if (u->sk_type != type) {
804 sock_put(u);
805 goto fail;
806 }
807 } else {
808 err = -ECONNREFUSED;
Jianjun Konge27dfce2008-11-01 21:38:31 -0700809 u = unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 if (u) {
811 struct dentry *dentry;
Al Viro40ffe672012-03-14 21:54:32 -0400812 dentry = unix_sk(u)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (dentry)
Al Viro68ac1232012-03-15 08:21:57 -0400814 touch_atime(&unix_sk(u)->path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 } else
816 goto fail;
817 }
818 return u;
819
820put_fail:
Al Viro421748e2008-08-02 01:04:36 -0400821 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822fail:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700823 *error = err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 return NULL;
825}
826
Al Virofaf02012012-07-20 02:37:29 +0400827static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
828{
829 struct dentry *dentry;
830 struct path path;
831 int err = 0;
832 /*
833 * Get the parent directory, calculate the hash for last
834 * component.
835 */
836 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
837 err = PTR_ERR(dentry);
838 if (IS_ERR(dentry))
839 return err;
840
841 /*
842 * All right, let's create it.
843 */
844 err = security_path_mknod(&path, dentry, mode, 0);
845 if (!err) {
846 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
847 if (!err) {
848 res->mnt = mntget(path.mnt);
849 res->dentry = dget(dentry);
850 }
851 }
852 done_path_create(&path, dentry);
853 return err;
854}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
856static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
857{
858 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900859 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700861 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400862 char *sun_path = sunaddr->sun_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000864 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 struct unix_address *addr;
866 struct hlist_head *list;
867
868 err = -EINVAL;
869 if (sunaddr->sun_family != AF_UNIX)
870 goto out;
871
Jianjun Konge27dfce2008-11-01 21:38:31 -0700872 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 err = unix_autobind(sock);
874 goto out;
875 }
876
877 err = unix_mkname(sunaddr, addr_len, &hash);
878 if (err < 0)
879 goto out;
880 addr_len = err;
881
Sasha Levin57bc52e2013-12-13 10:54:22 -0500882 err = mutex_lock_interruptible(&u->readlock);
883 if (err)
884 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 err = -EINVAL;
887 if (u->addr)
888 goto out_up;
889
890 err = -ENOMEM;
891 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
892 if (!addr)
893 goto out_up;
894
895 memcpy(addr->name, sunaddr, addr_len);
896 addr->len = addr_len;
897 addr->hash = hash ^ sk->sk_type;
898 atomic_set(&addr->refcnt, 1);
899
Al Virodae6ad82011-06-26 11:50:15 -0400900 if (sun_path[0]) {
Al Virofaf02012012-07-20 02:37:29 +0400901 struct path path;
902 umode_t mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400903 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virofaf02012012-07-20 02:37:29 +0400904 err = unix_mknod(sun_path, mode, &path);
905 if (err) {
906 if (err == -EEXIST)
907 err = -EADDRINUSE;
908 unix_release_addr(addr);
909 goto out_up;
910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 addr->hash = UNIX_HASH_SIZE;
Al Virofaf02012012-07-20 02:37:29 +0400912 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
913 spin_lock(&unix_table_lock);
914 u->path = path;
915 list = &unix_socket_table[hash];
916 } else {
917 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800919 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 sk->sk_type, hash)) {
921 unix_release_addr(addr);
922 goto out_unlock;
923 }
924
925 list = &unix_socket_table[addr->hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 }
927
928 err = 0;
929 __unix_remove_socket(sk);
930 u->addr = addr;
931 __unix_insert_socket(list, sk);
932
933out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800934 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800936 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937out:
938 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939}
940
David S. Miller278a3de2007-05-31 15:19:20 -0700941static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
942{
943 if (unlikely(sk1 == sk2) || !sk2) {
944 unix_state_lock(sk1);
945 return;
946 }
947 if (sk1 < sk2) {
948 unix_state_lock(sk1);
949 unix_state_lock_nested(sk2);
950 } else {
951 unix_state_lock(sk2);
952 unix_state_lock_nested(sk1);
953 }
954}
955
956static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
957{
958 if (unlikely(sk1 == sk2) || !sk2) {
959 unix_state_unlock(sk1);
960 return;
961 }
962 unix_state_unlock(sk1);
963 unix_state_unlock(sk2);
964}
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
967 int alen, int flags)
968{
969 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900970 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700971 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000973 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 int err;
975
976 if (addr->sa_family != AF_UNSPEC) {
977 err = unix_mkname(sunaddr, alen, &hash);
978 if (err < 0)
979 goto out;
980 alen = err;
981
982 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
983 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
984 goto out;
985
David S. Miller278a3de2007-05-31 15:19:20 -0700986restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700987 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 if (!other)
989 goto out;
990
David S. Miller278a3de2007-05-31 15:19:20 -0700991 unix_state_double_lock(sk, other);
992
993 /* Apparently VFS overslept socket death. Retry. */
994 if (sock_flag(other, SOCK_DEAD)) {
995 unix_state_double_unlock(sk, other);
996 sock_put(other);
997 goto restart;
998 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 err = -EPERM;
1001 if (!unix_may_send(sk, other))
1002 goto out_unlock;
1003
1004 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1005 if (err)
1006 goto out_unlock;
1007
1008 } else {
1009 /*
1010 * 1003.1g breaking connected state with AF_UNSPEC
1011 */
1012 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001013 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015
1016 /*
1017 * If it was connected, reconnect.
1018 */
1019 if (unix_peer(sk)) {
1020 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001021 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001022 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
1024 if (other != old_peer)
1025 unix_dgram_disconnected(sk, old_peer);
1026 sock_put(old_peer);
1027 } else {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001028 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001029 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001031 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
1033out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001034 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 sock_put(other);
1036out:
1037 return err;
1038}
1039
1040static long unix_wait_for_peer(struct sock *other, long timeo)
1041{
1042 struct unix_sock *u = unix_sk(other);
1043 int sched;
1044 DEFINE_WAIT(wait);
1045
1046 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1047
1048 sched = !sock_flag(other, SOCK_DEAD) &&
1049 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001050 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
David S. Miller1c92b4e2007-05-31 13:24:26 -07001052 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 if (sched)
1055 timeo = schedule_timeout(timeo);
1056
1057 finish_wait(&u->peer_wait, &wait);
1058 return timeo;
1059}
1060
1061static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1062 int addr_len, int flags)
1063{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001064 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001066 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1068 struct sock *newsk = NULL;
1069 struct sock *other = NULL;
1070 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001071 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 int st;
1073 int err;
1074 long timeo;
1075
1076 err = unix_mkname(sunaddr, addr_len, &hash);
1077 if (err < 0)
1078 goto out;
1079 addr_len = err;
1080
Joe Perchesf64f9e72009-11-29 16:55:45 -08001081 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1082 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 goto out;
1084
1085 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1086
1087 /* First of all allocate resources.
1088 If we will make it after state is locked,
1089 we will have to recheck all again in any case.
1090 */
1091
1092 err = -ENOMEM;
1093
1094 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001095 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 if (newsk == NULL)
1097 goto out;
1098
1099 /* Allocate skb for sending to listening sock */
1100 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1101 if (skb == NULL)
1102 goto out;
1103
1104restart:
1105 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001106 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 if (!other)
1108 goto out;
1109
1110 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001111 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113 /* Apparently VFS overslept socket death. Retry. */
1114 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001115 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 sock_put(other);
1117 goto restart;
1118 }
1119
1120 err = -ECONNREFUSED;
1121 if (other->sk_state != TCP_LISTEN)
1122 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001123 if (other->sk_shutdown & RCV_SHUTDOWN)
1124 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Rainer Weikusat3c734192008-06-17 22:28:05 -07001126 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 err = -EAGAIN;
1128 if (!timeo)
1129 goto out_unlock;
1130
1131 timeo = unix_wait_for_peer(other, timeo);
1132
1133 err = sock_intr_errno(timeo);
1134 if (signal_pending(current))
1135 goto out;
1136 sock_put(other);
1137 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140 /* Latch our state.
1141
Daniel Balutae5537bf2011-03-14 15:25:33 -07001142 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 drop lock on peer. It is dangerous because deadlock is
1144 possible. Connect to self case and simultaneous
1145 attempt to connect are eliminated by checking socket
1146 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1147 check this before attempt to grab lock.
1148
1149 Well, and we have to recheck the state after socket locked.
1150 */
1151 st = sk->sk_state;
1152
1153 switch (st) {
1154 case TCP_CLOSE:
1155 /* This is ok... continue with connect */
1156 break;
1157 case TCP_ESTABLISHED:
1158 /* Socket is already connected */
1159 err = -EISCONN;
1160 goto out_unlock;
1161 default:
1162 err = -EINVAL;
1163 goto out_unlock;
1164 }
1165
David S. Miller1c92b4e2007-05-31 13:24:26 -07001166 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
1168 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001169 unix_state_unlock(sk);
1170 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 sock_put(other);
1172 goto restart;
1173 }
1174
David S. Miller3610cda2011-01-05 15:38:53 -08001175 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001177 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 goto out_unlock;
1179 }
1180
1181 /* The way is open! Fastly set all the necessary fields... */
1182
1183 sock_hold(sk);
1184 unix_peer(newsk) = sk;
1185 newsk->sk_state = TCP_ESTABLISHED;
1186 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001187 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001189 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 otheru = unix_sk(other);
1191
1192 /* copy address information from listening to new sock*/
1193 if (otheru->addr) {
1194 atomic_inc(&otheru->addr->refcnt);
1195 newu->addr = otheru->addr;
1196 }
Al Viro40ffe672012-03-14 21:54:32 -04001197 if (otheru->path.dentry) {
1198 path_get(&otheru->path);
1199 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
1201
1202 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001203 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 sock->state = SS_CONNECTED;
1206 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001207 sock_hold(newsk);
1208
1209 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1210 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
David S. Miller1c92b4e2007-05-31 13:24:26 -07001212 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
1214 /* take ten and and send info to listening sock */
1215 spin_lock(&other->sk_receive_queue.lock);
1216 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001218 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 other->sk_data_ready(other, 0);
1220 sock_put(other);
1221 return 0;
1222
1223out_unlock:
1224 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001225 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001228 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (newsk)
1230 unix_release_sock(newsk, 0);
1231 if (other)
1232 sock_put(other);
1233 return err;
1234}
1235
1236static int unix_socketpair(struct socket *socka, struct socket *sockb)
1237{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001238 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 /* Join our sockets back to back */
1241 sock_hold(ska);
1242 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001243 unix_peer(ska) = skb;
1244 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001245 init_peercred(ska);
1246 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
1248 if (ska->sk_type != SOCK_DGRAM) {
1249 ska->sk_state = TCP_ESTABLISHED;
1250 skb->sk_state = TCP_ESTABLISHED;
1251 socka->state = SS_CONNECTED;
1252 sockb->state = SS_CONNECTED;
1253 }
1254 return 0;
1255}
1256
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001257static void unix_sock_inherit_flags(const struct socket *old,
1258 struct socket *new)
1259{
1260 if (test_bit(SOCK_PASSCRED, &old->flags))
1261 set_bit(SOCK_PASSCRED, &new->flags);
1262 if (test_bit(SOCK_PASSSEC, &old->flags))
1263 set_bit(SOCK_PASSSEC, &new->flags);
1264}
1265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1267{
1268 struct sock *sk = sock->sk;
1269 struct sock *tsk;
1270 struct sk_buff *skb;
1271 int err;
1272
1273 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001274 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 goto out;
1276
1277 err = -EINVAL;
1278 if (sk->sk_state != TCP_LISTEN)
1279 goto out;
1280
1281 /* If socket state is TCP_LISTEN it cannot change (for now...),
1282 * so that no locks are necessary.
1283 */
1284
1285 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1286 if (!skb) {
1287 /* This means receive shutdown. */
1288 if (err == 0)
1289 err = -EINVAL;
1290 goto out;
1291 }
1292
1293 tsk = skb->sk;
1294 skb_free_datagram(sk, skb);
1295 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1296
1297 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001298 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 newsock->state = SS_CONNECTED;
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001300 unix_sock_inherit_flags(sock, newsock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001302 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 return 0;
1304
1305out:
1306 return err;
1307}
1308
1309
1310static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1311{
1312 struct sock *sk = sock->sk;
1313 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001314 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 int err = 0;
1316
1317 if (peer) {
1318 sk = unix_peer_get(sk);
1319
1320 err = -ENOTCONN;
1321 if (!sk)
1322 goto out;
1323 err = 0;
1324 } else {
1325 sock_hold(sk);
1326 }
1327
1328 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001329 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 if (!u->addr) {
1331 sunaddr->sun_family = AF_UNIX;
1332 sunaddr->sun_path[0] = 0;
1333 *uaddr_len = sizeof(short);
1334 } else {
1335 struct unix_address *addr = u->addr;
1336
1337 *uaddr_len = addr->len;
1338 memcpy(sunaddr, addr->name, *uaddr_len);
1339 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001340 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 sock_put(sk);
1342out:
1343 return err;
1344}
1345
1346static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1347{
1348 int i;
1349
1350 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 UNIXCB(skb).fp = NULL;
1352
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001353 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 unix_notinflight(scm->fp->fp[i]);
1355}
1356
Eric W. Biederman7361c362010-06-13 03:34:33 +00001357static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
1359 struct scm_cookie scm;
1360 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001361 scm.pid = UNIXCB(skb).pid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001362 if (UNIXCB(skb).fp)
1363 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 /* Alas, it calls VFS */
1366 /* So fscking what? fput() had been SMP-safe since the last Summer */
1367 scm_destroy(&scm);
1368 sock_wfree(skb);
1369}
1370
Eric Dumazet25888e32010-11-25 04:11:39 +00001371#define MAX_RECURSION_LEVEL 4
1372
Miklos Szeredi62093442008-11-09 15:23:57 +01001373static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
1375 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001376 unsigned char max_level = 0;
1377 int unix_sock_count = 0;
1378
1379 for (i = scm->fp->count - 1; i >= 0; i--) {
1380 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1381
1382 if (sk) {
1383 unix_sock_count++;
1384 max_level = max(max_level,
1385 unix_sk(sk)->recursion_level);
1386 }
1387 }
1388 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1389 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001390
1391 /*
1392 * Need to duplicate file references for the sake of garbage
1393 * collection. Otherwise a socket in the fps might become a
1394 * candidate for GC while the skb is not yet queued.
1395 */
1396 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1397 if (!UNIXCB(skb).fp)
1398 return -ENOMEM;
1399
Eric Dumazet25888e32010-11-25 04:11:39 +00001400 if (unix_sock_count) {
1401 for (i = scm->fp->count - 1; i >= 0; i--)
1402 unix_inflight(scm->fp->fp[i]);
1403 }
1404 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
David S. Millerf78a5fd2011-09-16 19:34:00 -04001407static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001408{
1409 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001410
David S. Millerf78a5fd2011-09-16 19:34:00 -04001411 UNIXCB(skb).pid = get_pid(scm->pid);
Eric W. Biederman6b0ee8c2013-04-03 17:28:16 +00001412 UNIXCB(skb).uid = scm->creds.uid;
1413 UNIXCB(skb).gid = scm->creds.gid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001414 UNIXCB(skb).fp = NULL;
1415 if (scm->fp && send_fds)
1416 err = unix_attach_fds(scm, skb);
1417
1418 skb->destructor = unix_destruct_scm;
1419 return err;
1420}
1421
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001423 * Some apps rely on write() giving SCM_CREDENTIALS
1424 * We include credentials if source or destination socket
1425 * asserted SOCK_PASSCRED.
1426 */
1427static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1428 const struct sock *other)
1429{
Eric W. Biederman6b0ee8c2013-04-03 17:28:16 +00001430 if (UNIXCB(skb).pid)
Eric Dumazet16e57262011-09-19 05:52:27 +00001431 return;
1432 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
Eric W. Biederman25da0e32013-04-03 16:13:35 +00001433 !other->sk_socket ||
1434 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
Eric Dumazet16e57262011-09-19 05:52:27 +00001435 UNIXCB(skb).pid = get_pid(task_tgid(current));
David S. Miller6e0895c2013-04-22 20:32:51 -04001436 current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001437 }
1438}
1439
1440/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 * Send AF_UNIX data.
1442 */
1443
1444static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1445 struct msghdr *msg, size_t len)
1446{
1447 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1448 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001449 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001451 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 struct sock *other = NULL;
1453 int namelen = 0; /* fake GCC */
1454 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001455 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001456 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 long timeo;
1458 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001459 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001460 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 if (NULL == siocb->scm)
1463 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001464 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001465 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if (err < 0)
1467 return err;
1468
1469 err = -EOPNOTSUPP;
1470 if (msg->msg_flags&MSG_OOB)
1471 goto out;
1472
1473 if (msg->msg_namelen) {
1474 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1475 if (err < 0)
1476 goto out;
1477 namelen = err;
1478 } else {
1479 sunaddr = NULL;
1480 err = -ENOTCONN;
1481 other = unix_peer_get(sk);
1482 if (!other)
1483 goto out;
1484 }
1485
Joe Perchesf64f9e72009-11-29 16:55:45 -08001486 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1487 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 goto out;
1489
1490 err = -EMSGSIZE;
1491 if (len > sk->sk_sndbuf - 32)
1492 goto out;
1493
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001494 if (len > SKB_MAX_ALLOC)
1495 data_len = min_t(size_t,
1496 len - SKB_MAX_ALLOC,
1497 MAX_SKB_FRAGS * PAGE_SIZE);
1498
1499 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1500 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001501 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 goto out;
1503
David S. Millerf78a5fd2011-09-16 19:34:00 -04001504 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001505 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001506 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001507 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001508 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001509
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001510 skb_put(skb, len - data_len);
1511 skb->data_len = data_len;
1512 skb->len = len;
1513 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (err)
1515 goto out_free;
1516
1517 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1518
1519restart:
1520 if (!other) {
1521 err = -ECONNRESET;
1522 if (sunaddr == NULL)
1523 goto out_free;
1524
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001525 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001527 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 goto out_free;
1529 }
1530
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001531 if (sk_filter(other, skb) < 0) {
1532 /* Toss the packet but do not return any error to the sender */
1533 err = len;
1534 goto out_free;
1535 }
1536
David S. Miller1c92b4e2007-05-31 13:24:26 -07001537 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 err = -EPERM;
1539 if (!unix_may_send(sk, other))
1540 goto out_unlock;
1541
1542 if (sock_flag(other, SOCK_DEAD)) {
1543 /*
1544 * Check with 1003.1g - what should
1545 * datagram error
1546 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001547 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 sock_put(other);
1549
1550 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001551 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001553 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001554 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 unix_dgram_disconnected(sk, other);
1557 sock_put(other);
1558 err = -ECONNREFUSED;
1559 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001560 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 }
1562
1563 other = NULL;
1564 if (err)
1565 goto out_free;
1566 goto restart;
1567 }
1568
1569 err = -EPIPE;
1570 if (other->sk_shutdown & RCV_SHUTDOWN)
1571 goto out_unlock;
1572
1573 if (sk->sk_type != SOCK_SEQPACKET) {
1574 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1575 if (err)
1576 goto out_unlock;
1577 }
1578
Rainer Weikusat3c734192008-06-17 22:28:05 -07001579 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 if (!timeo) {
1581 err = -EAGAIN;
1582 goto out_unlock;
1583 }
1584
1585 timeo = unix_wait_for_peer(other, timeo);
1586
1587 err = sock_intr_errno(timeo);
1588 if (signal_pending(current))
1589 goto out_free;
1590
1591 goto restart;
1592 }
1593
Alban Crequy3f661162010-10-04 08:48:28 +00001594 if (sock_flag(other, SOCK_RCVTSTAMP))
1595 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001596 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001598 if (max_level > unix_sk(other)->recursion_level)
1599 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001600 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 other->sk_data_ready(other, len);
1602 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001603 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 return len;
1605
1606out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001607 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608out_free:
1609 kfree_skb(skb);
1610out:
1611 if (other)
1612 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001613 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 return err;
1615}
1616
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001617
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1619 struct msghdr *msg, size_t len)
1620{
1621 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1622 struct sock *sk = sock->sk;
1623 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001624 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001625 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001626 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001628 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001629 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
1631 if (NULL == siocb->scm)
1632 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001633 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001634 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (err < 0)
1636 return err;
1637
1638 err = -EOPNOTSUPP;
1639 if (msg->msg_flags&MSG_OOB)
1640 goto out_err;
1641
1642 if (msg->msg_namelen) {
1643 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1644 goto out_err;
1645 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001647 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 if (!other)
1649 goto out_err;
1650 }
1651
1652 if (sk->sk_shutdown & SEND_SHUTDOWN)
1653 goto pipe_err;
1654
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001655 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 /*
Benjamin LaHaisee9df7d72006-03-20 21:29:05 -08001657 * Optimisation for the fact that under 0.01% of X
1658 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 */
1660
Benjamin LaHaisee9df7d72006-03-20 21:29:05 -08001661 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d72006-03-20 21:29:05 -08001664 if (size > ((sk->sk_sndbuf >> 1) - 64))
1665 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 if (size > SKB_MAX_ALLOC)
1668 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001669
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 /*
1671 * Grab a buffer
1672 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001673
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001674 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1675 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
Jianjun Konge27dfce2008-11-01 21:38:31 -07001677 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 goto out_err;
1679
1680 /*
1681 * If you pass two values to the sock_alloc_send_skb
1682 * it tries to grab the large buffer with GFP_NOFS
1683 * (which can fail easily), and if it fails grab the
1684 * fallback size buffer which is under a page and will
1685 * succeed. [Alan]
1686 */
1687 size = min_t(int, size, skb_tailroom(skb));
1688
Eric W. Biederman7361c362010-06-13 03:34:33 +00001689
David S. Millerf78a5fd2011-09-16 19:34:00 -04001690 /* Only send the fds in the first buffer */
1691 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001692 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001693 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001694 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001695 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001696 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001697 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001699 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1700 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001702 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 }
1704
David S. Miller1c92b4e2007-05-31 13:24:26 -07001705 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 if (sock_flag(other, SOCK_DEAD) ||
1708 (other->sk_shutdown & RCV_SHUTDOWN))
1709 goto pipe_err_free;
1710
Eric Dumazet16e57262011-09-19 05:52:27 +00001711 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001713 if (max_level > unix_sk(other)->recursion_level)
1714 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001715 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001717 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
David S. Millerf78a5fd2011-09-16 19:34:00 -04001720 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 siocb->scm = NULL;
1722
1723 return sent;
1724
1725pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001726 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 kfree_skb(skb);
1728pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001729 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1730 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 err = -EPIPE;
1732out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001733 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 siocb->scm = NULL;
1735 return sent ? : err;
1736}
1737
1738static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1739 struct msghdr *msg, size_t len)
1740{
1741 int err;
1742 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001743
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 err = sock_error(sk);
1745 if (err)
1746 return err;
1747
1748 if (sk->sk_state != TCP_ESTABLISHED)
1749 return -ENOTCONN;
1750
1751 if (msg->msg_namelen)
1752 msg->msg_namelen = 0;
1753
1754 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1755}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001756
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001757static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1758 struct msghdr *msg, size_t size,
1759 int flags)
1760{
1761 struct sock *sk = sock->sk;
1762
1763 if (sk->sk_state != TCP_ESTABLISHED)
1764 return -ENOTCONN;
1765
1766 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1767}
1768
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1770{
1771 struct unix_sock *u = unix_sk(sk);
1772
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 if (u->addr) {
1774 msg->msg_namelen = u->addr->len;
1775 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1776 }
1777}
1778
1779static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1780 struct msghdr *msg, size_t size,
1781 int flags)
1782{
1783 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1784 struct scm_cookie tmp_scm;
1785 struct sock *sk = sock->sk;
1786 struct unix_sock *u = unix_sk(sk);
1787 int noblock = flags & MSG_DONTWAIT;
1788 struct sk_buff *skb;
1789 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001790 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
1792 err = -EOPNOTSUPP;
1793 if (flags&MSG_OOB)
1794 goto out;
1795
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001796 err = mutex_lock_interruptible(&u->readlock);
1797 if (err) {
1798 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1799 goto out;
1800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001802 skip = sk_peek_offset(sk, flags);
1803
1804 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001805 if (!skb) {
1806 unix_state_lock(sk);
1807 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1808 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1809 (sk->sk_shutdown & RCV_SHUTDOWN))
1810 err = 0;
1811 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Eric Dumazet67426b72010-10-29 20:44:44 +00001815 wake_up_interruptible_sync_poll(&u->peer_wait,
1816 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 if (msg->msg_name)
1819 unix_copy_addr(msg, skb->sk);
1820
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001821 if (size > skb->len - skip)
1822 size = skb->len - skip;
1823 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 msg->msg_flags |= MSG_TRUNC;
1825
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001826 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 if (err)
1828 goto out_free;
1829
Alban Crequy3f661162010-10-04 08:48:28 +00001830 if (sock_flag(sk, SOCK_RCVTSTAMP))
1831 __sock_recv_timestamp(msg, sk, skb);
1832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 if (!siocb->scm) {
1834 siocb->scm = &tmp_scm;
1835 memset(&tmp_scm, 0, sizeof(tmp_scm));
1836 }
Eric W. Biederman6b0ee8c2013-04-03 17:28:16 +00001837 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001838 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001840 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (UNIXCB(skb).fp)
1842 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001843
1844 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001845 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 /* It is questionable: on PEEK we could:
1847 - do not return fds - good, but too simple 8)
1848 - return fds, and do not return them on read (old strategy,
1849 apparently wrong)
1850 - clone fds (I chose it for now, it is the most universal
1851 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001852
1853 POSIX 1003.1g does not actually define this clearly
1854 at all. POSIX 1003.1g doesn't define a lot of things
1855 clearly however!
1856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001858
1859 sk_peek_offset_fwd(sk, size);
1860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 if (UNIXCB(skb).fp)
1862 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1863 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001864 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
1866 scm_recv(sock, msg, siocb->scm, flags);
1867
1868out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001869 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001871 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872out:
1873 return err;
1874}
1875
1876/*
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001877 * Sleep until more data has arrived. But check for races..
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 */
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001879static long unix_stream_data_wait(struct sock *sk, long timeo,
1880 struct sk_buff *last)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881{
1882 DEFINE_WAIT(wait);
1883
David S. Miller1c92b4e2007-05-31 13:24:26 -07001884 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
1886 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001887 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001889 if (skb_peek_tail(&sk->sk_receive_queue) != last ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 sk->sk_err ||
1891 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1892 signal_pending(current) ||
1893 !timeo)
1894 break;
1895
1896 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001897 unix_state_unlock(sk);
Colin Cross1dc14992013-05-06 23:50:21 +00001898 timeo = freezable_schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001899 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1901 }
1902
Eric Dumazetaa395142010-04-20 13:03:51 +00001903 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001904 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 return timeo;
1906}
1907
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1909 struct msghdr *msg, size_t size,
1910 int flags)
1911{
1912 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1913 struct scm_cookie tmp_scm;
1914 struct sock *sk = sock->sk;
1915 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001916 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 int copied = 0;
1918 int check_creds = 0;
1919 int target;
1920 int err = 0;
1921 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001922 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923
1924 err = -EINVAL;
1925 if (sk->sk_state != TCP_ESTABLISHED)
1926 goto out;
1927
1928 err = -EOPNOTSUPP;
1929 if (flags&MSG_OOB)
1930 goto out;
1931
1932 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1933 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1934
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 /* Lock the socket to prevent queue disordering
1936 * while sleeps in memcpy_tomsg
1937 */
1938
1939 if (!siocb->scm) {
1940 siocb->scm = &tmp_scm;
1941 memset(&tmp_scm, 0, sizeof(tmp_scm));
1942 }
1943
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001944 err = mutex_lock_interruptible(&u->readlock);
1945 if (err) {
1946 err = sock_intr_errno(timeo);
1947 goto out;
1948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001950 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 int chunk;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001952 struct sk_buff *skb, *last;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001954 unix_state_lock(sk);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001955 last = skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001956again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001957 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001958 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001960 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
1962 /*
1963 * POSIX 1003.1g mandates this order.
1964 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001965
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001966 err = sock_error(sk);
1967 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001968 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001970 goto unlock;
1971
1972 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 err = -EAGAIN;
1974 if (!timeo)
1975 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001976 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001978 timeo = unix_stream_data_wait(sk, timeo, last);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001980 if (signal_pending(current)
1981 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 err = sock_intr_errno(timeo);
1983 goto out;
1984 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001985
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001987 unlock:
1988 unix_state_unlock(sk);
1989 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001991
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001992 skip = sk_peek_offset(sk, flags);
1993 while (skip >= skb->len) {
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001994 skip -= skb->len;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001995 last = skb;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001996 skb = skb_peek_next(skb, &sk->sk_receive_queue);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001997 if (!skb)
1998 goto again;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001999 }
2000
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07002001 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
2003 if (check_creds) {
2004 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00002005 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric W. Biederman6b0ee8c2013-04-03 17:28:16 +00002006 !uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) ||
2007 !gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 break;
Eric W. Biederman0e82e7f6d2013-04-03 16:14:47 +00002009 } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 /* Copy credentials */
Eric W. Biederman6b0ee8c2013-04-03 17:28:16 +00002011 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 check_creds = 1;
2013 }
2014
2015 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002016 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 unix_copy_addr(msg, skb->sk);
2018 sunaddr = NULL;
2019 }
2020
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002021 chunk = min_t(unsigned int, skb->len - skip, size);
2022 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (copied == 0)
2024 copied = -EFAULT;
2025 break;
2026 }
2027 copied += chunk;
2028 size -= chunk;
2029
2030 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002031 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 skb_pull(skb, chunk);
2033
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002034 sk_peek_offset_bwd(sk, chunk);
2035
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 if (UNIXCB(skb).fp)
2037 unix_detach_fds(siocb->scm, skb);
2038
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002039 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002042 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002043 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
2045 if (siocb->scm->fp)
2046 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002047 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 /* It is questionable, see note in unix_dgram_recvmsg.
2049 */
2050 if (UNIXCB(skb).fp)
2051 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2052
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002053 sk_peek_offset_fwd(sk, chunk);
2054
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 break;
2056 }
2057 } while (size);
2058
Ingo Molnar57b47a52006-03-20 22:35:41 -08002059 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 scm_recv(sock, msg, siocb->scm, flags);
2061out:
2062 return copied ? : err;
2063}
2064
2065static int unix_shutdown(struct socket *sock, int mode)
2066{
2067 struct sock *sk = sock->sk;
2068 struct sock *other;
2069
Xi Wangfc61b922012-08-26 16:47:13 +00002070 if (mode < SHUT_RD || mode > SHUT_RDWR)
2071 return -EINVAL;
2072 /* This maps:
2073 * SHUT_RD (0) -> RCV_SHUTDOWN (1)
2074 * SHUT_WR (1) -> SEND_SHUTDOWN (2)
2075 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
2076 */
2077 ++mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Alban Crequy7180a032011-01-19 04:56:36 +00002079 unix_state_lock(sk);
2080 sk->sk_shutdown |= mode;
2081 other = unix_peer(sk);
2082 if (other)
2083 sock_hold(other);
2084 unix_state_unlock(sk);
2085 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
Alban Crequy7180a032011-01-19 04:56:36 +00002087 if (other &&
2088 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
Alban Crequy7180a032011-01-19 04:56:36 +00002090 int peer_mode = 0;
2091
2092 if (mode&RCV_SHUTDOWN)
2093 peer_mode |= SEND_SHUTDOWN;
2094 if (mode&SEND_SHUTDOWN)
2095 peer_mode |= RCV_SHUTDOWN;
2096 unix_state_lock(other);
2097 other->sk_shutdown |= peer_mode;
2098 unix_state_unlock(other);
2099 other->sk_state_change(other);
2100 if (peer_mode == SHUTDOWN_MASK)
2101 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2102 else if (peer_mode & RCV_SHUTDOWN)
2103 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 }
Alban Crequy7180a032011-01-19 04:56:36 +00002105 if (other)
2106 sock_put(other);
2107
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 return 0;
2109}
2110
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002111long unix_inq_len(struct sock *sk)
2112{
2113 struct sk_buff *skb;
2114 long amount = 0;
2115
2116 if (sk->sk_state == TCP_LISTEN)
2117 return -EINVAL;
2118
2119 spin_lock(&sk->sk_receive_queue.lock);
2120 if (sk->sk_type == SOCK_STREAM ||
2121 sk->sk_type == SOCK_SEQPACKET) {
2122 skb_queue_walk(&sk->sk_receive_queue, skb)
2123 amount += skb->len;
2124 } else {
2125 skb = skb_peek(&sk->sk_receive_queue);
2126 if (skb)
2127 amount = skb->len;
2128 }
2129 spin_unlock(&sk->sk_receive_queue.lock);
2130
2131 return amount;
2132}
2133EXPORT_SYMBOL_GPL(unix_inq_len);
2134
2135long unix_outq_len(struct sock *sk)
2136{
2137 return sk_wmem_alloc_get(sk);
2138}
2139EXPORT_SYMBOL_GPL(unix_outq_len);
2140
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2142{
2143 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002144 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 int err;
2146
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002147 switch (cmd) {
2148 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002149 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002150 err = put_user(amount, (int __user *)arg);
2151 break;
2152 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002153 amount = unix_inq_len(sk);
2154 if (amount < 0)
2155 err = amount;
2156 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002158 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002159 default:
2160 err = -ENOIOCTLCMD;
2161 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 }
2163 return err;
2164}
2165
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002166static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
2168 struct sock *sk = sock->sk;
2169 unsigned int mask;
2170
Eric Dumazetaa395142010-04-20 13:03:51 +00002171 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 mask = 0;
2173
2174 /* exceptional events? */
2175 if (sk->sk_err)
2176 mask |= POLLERR;
2177 if (sk->sk_shutdown == SHUTDOWN_MASK)
2178 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002179 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002180 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
2182 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002183 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 mask |= POLLIN | POLLRDNORM;
2185
2186 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002187 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2188 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 mask |= POLLHUP;
2190
2191 /*
2192 * we set writable also when the other side has shut down the
2193 * connection. This prevents stuck sockets.
2194 */
2195 if (unix_writable(sk))
2196 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2197
2198 return mask;
2199}
2200
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002201static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2202 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002203{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002204 struct sock *sk = sock->sk, *other;
2205 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002206
Eric Dumazetaa395142010-04-20 13:03:51 +00002207 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002208 mask = 0;
2209
2210 /* exceptional events? */
2211 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002212 mask |= POLLERR |
Jacob Keller8facd5f2013-04-02 13:55:40 -07002213 (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002214
Rainer Weikusat3c734192008-06-17 22:28:05 -07002215 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazet5456f092010-10-31 05:36:23 +00002216 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002217 if (sk->sk_shutdown == SHUTDOWN_MASK)
2218 mask |= POLLHUP;
2219
2220 /* readable? */
Eric Dumazet5456f092010-10-31 05:36:23 +00002221 if (!skb_queue_empty(&sk->sk_receive_queue))
Rainer Weikusat3c734192008-06-17 22:28:05 -07002222 mask |= POLLIN | POLLRDNORM;
2223
2224 /* Connection-based need to check for termination and startup */
2225 if (sk->sk_type == SOCK_SEQPACKET) {
2226 if (sk->sk_state == TCP_CLOSE)
2227 mask |= POLLHUP;
2228 /* connection hasn't started yet? */
2229 if (sk->sk_state == TCP_SYN_SENT)
2230 return mask;
2231 }
2232
Eric Dumazet973a34a2010-10-31 05:38:25 +00002233 /* No write status requested, avoid expensive OUT tests. */
Hans Verkuil626cf232012-03-23 15:02:27 -07002234 if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
Eric Dumazet973a34a2010-10-31 05:38:25 +00002235 return mask;
2236
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002237 writable = unix_writable(sk);
Eric Dumazet5456f092010-10-31 05:36:23 +00002238 other = unix_peer_get(sk);
2239 if (other) {
2240 if (unix_peer(other) != sk) {
2241 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2242 if (unix_recvq_full(other))
2243 writable = 0;
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002244 }
Eric Dumazet5456f092010-10-31 05:36:23 +00002245 sock_put(other);
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002246 }
2247
2248 if (writable)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002249 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2250 else
2251 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
2252
Rainer Weikusat3c734192008-06-17 22:28:05 -07002253 return mask;
2254}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
2256#ifdef CONFIG_PROC_FS
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002257
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002258#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
2259
2260#define get_bucket(x) ((x) >> BUCKET_SPACE)
2261#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
2262#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002263
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002264static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002266 unsigned long offset = get_offset(*pos);
2267 unsigned long bucket = get_bucket(*pos);
2268 struct sock *sk;
2269 unsigned long count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002271 for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
2272 if (sock_net(sk) != seq_file_net(seq))
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002273 continue;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002274 if (++count == offset)
2275 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 }
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002277
2278 return sk;
2279}
2280
2281static struct sock *unix_next_socket(struct seq_file *seq,
2282 struct sock *sk,
2283 loff_t *pos)
2284{
2285 unsigned long bucket;
2286
2287 while (sk > (struct sock *)SEQ_START_TOKEN) {
2288 sk = sk_next(sk);
2289 if (!sk)
2290 goto next_bucket;
2291 if (sock_net(sk) == seq_file_net(seq))
2292 return sk;
2293 }
2294
2295 do {
2296 sk = unix_from_bucket(seq, pos);
2297 if (sk)
2298 return sk;
2299
2300next_bucket:
2301 bucket = get_bucket(*pos) + 1;
2302 *pos = set_bucket_offset(bucket, 1);
2303 } while (bucket < ARRAY_SIZE(unix_socket_table));
2304
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 return NULL;
2306}
2307
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002309 __acquires(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002311 spin_lock(&unix_table_lock);
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002312
2313 if (!*pos)
2314 return SEQ_START_TOKEN;
2315
2316 if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
2317 return NULL;
2318
2319 return unix_next_socket(seq, NULL, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320}
2321
2322static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2323{
2324 ++*pos;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002325 return unix_next_socket(seq, v, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326}
2327
2328static void unix_seq_stop(struct seq_file *seq, void *v)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002329 __releases(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002331 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332}
2333
2334static int unix_seq_show(struct seq_file *seq, void *v)
2335{
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002336
Joe Perchesb9f31242008-04-12 19:04:38 -07002337 if (v == SEQ_START_TOKEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 seq_puts(seq, "Num RefCount Protocol Flags Type St "
2339 "Inode Path\n");
2340 else {
2341 struct sock *s = v;
2342 struct unix_sock *u = unix_sk(s);
David S. Miller1c92b4e2007-05-31 13:24:26 -07002343 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
Dan Rosenberg71338aa2011-05-23 12:17:35 +00002345 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 s,
2347 atomic_read(&s->sk_refcnt),
2348 0,
2349 s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
2350 s->sk_type,
2351 s->sk_socket ?
2352 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
2353 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
2354 sock_i_ino(s));
2355
2356 if (u->addr) {
2357 int i, len;
2358 seq_putc(seq, ' ');
2359
2360 i = 0;
2361 len = u->addr->len - sizeof(short);
2362 if (!UNIX_ABSTRACT(s))
2363 len--;
2364 else {
2365 seq_putc(seq, '@');
2366 i++;
2367 }
2368 for ( ; i < len; i++)
2369 seq_putc(seq, u->addr->name->sun_path[i]);
2370 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07002371 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 seq_putc(seq, '\n');
2373 }
2374
2375 return 0;
2376}
2377
Philippe De Muyter56b3d972007-07-10 23:07:31 -07002378static const struct seq_operations unix_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 .start = unix_seq_start,
2380 .next = unix_seq_next,
2381 .stop = unix_seq_stop,
2382 .show = unix_seq_show,
2383};
2384
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385static int unix_seq_open(struct inode *inode, struct file *file)
2386{
Denis V. Luneve372c412007-11-19 22:31:54 -08002387 return seq_open_net(inode, file, &unix_seq_ops,
Eric Dumazet8b51b062012-06-08 22:10:20 +00002388 sizeof(struct seq_net_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389}
2390
Arjan van de Venda7071d2007-02-12 00:55:36 -08002391static const struct file_operations unix_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 .owner = THIS_MODULE,
2393 .open = unix_seq_open,
2394 .read = seq_read,
2395 .llseek = seq_lseek,
Denis V. Luneve372c412007-11-19 22:31:54 -08002396 .release = seq_release_net,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397};
2398
2399#endif
2400
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00002401static const struct net_proto_family unix_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 .family = PF_UNIX,
2403 .create = unix_create,
2404 .owner = THIS_MODULE,
2405};
2406
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002407
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002408static int __net_init unix_net_init(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002409{
2410 int error = -ENOMEM;
2411
Denis V. Luneva0a53c82007-12-11 04:19:17 -08002412 net->unx.sysctl_max_dgram_qlen = 10;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002413 if (unix_sysctl_register(net))
2414 goto out;
Pavel Emelyanovd392e492007-12-01 23:44:15 +11002415
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002416#ifdef CONFIG_PROC_FS
Gao fengd4beaa62013-02-18 01:34:54 +00002417 if (!proc_create("unix", 0, net->proc_net, &unix_seq_fops)) {
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002418 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002419 goto out;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002420 }
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002421#endif
2422 error = 0;
2423out:
Jianjun Kong48dcc332008-11-01 21:37:27 -07002424 return error;
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002425}
2426
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002427static void __net_exit unix_net_exit(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002428{
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002429 unix_sysctl_unregister(net);
Gao fengece31ff2013-02-18 01:34:56 +00002430 remove_proc_entry("unix", net->proc_net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002431}
2432
2433static struct pernet_operations unix_net_ops = {
2434 .init = unix_net_init,
2435 .exit = unix_net_exit,
2436};
2437
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438static int __init af_unix_init(void)
2439{
2440 int rc = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
YOSHIFUJI Hideaki / 吉藤英明b4fff5f2013-01-09 07:20:07 +00002442 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
2444 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002445 if (rc != 0) {
2446 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002447 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 goto out;
2449 }
2450
2451 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002452 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453out:
2454 return rc;
2455}
2456
2457static void __exit af_unix_exit(void)
2458{
2459 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002461 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462}
2463
David Woodhouse3d366962008-04-24 00:59:25 -07002464/* Earlier than device_initcall() so that other drivers invoking
2465 request_module() don't end up in a loop when modprobe tries
2466 to use a UNIX socket. But later than subsys_initcall() because
2467 we depend on stuff initialised there */
2468fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469module_exit(af_unix_exit);
2470
2471MODULE_LICENSE("GPL");
2472MODULE_ALIAS_NETPROTO(PF_UNIX);