blob: 2ee993c7732ab5a51fc55f82d94a9124dd00daa8 [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>
117
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000118struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000119EXPORT_SYMBOL_GPL(unix_socket_table);
120DEFINE_SPINLOCK(unix_table_lock);
121EXPORT_SYMBOL_GPL(unix_table_lock);
Eric Dumazet518de9b2010-10-26 14:22:44 -0700122static atomic_long_t unix_nr_socks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000125static struct hlist_head *unix_sockets_unbound(void *addr)
126{
127 unsigned long hash = (unsigned long)addr;
128
129 hash ^= hash >> 16;
130 hash ^= hash >> 8;
131 hash %= UNIX_HASH_SIZE;
132 return &unix_socket_table[UNIX_HASH_SIZE + hash];
133}
134
135#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700137#ifdef CONFIG_SECURITY_NETWORK
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700138static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700139{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700140 memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700141}
142
143static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
144{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700145 scm->secid = *UNIXSID(skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700146}
147#else
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700148static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700149{ }
150
151static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
152{ }
153#endif /* CONFIG_SECURITY_NETWORK */
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155/*
156 * SMP locking strategy:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800157 * hash table is protected with spinlock unix_table_lock
Stephen Hemminger663717f2010-02-18 14:12:06 -0800158 * each socket state is protected by separate spin lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 */
160
Eric Dumazet95c96172012-04-15 05:58:06 +0000161static inline unsigned int unix_hash_fold(__wsum n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Eric Dumazet95c96172012-04-15 05:58:06 +0000163 unsigned int hash = (__force unsigned int)n;
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 hash ^= hash>>16;
166 hash ^= hash>>8;
167 return hash&(UNIX_HASH_SIZE-1);
168}
169
170#define unix_peer(sk) (unix_sk(sk)->peer)
171
172static inline int unix_our_peer(struct sock *sk, struct sock *osk)
173{
174 return unix_peer(osk) == sk;
175}
176
177static inline int unix_may_send(struct sock *sk, struct sock *osk)
178{
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800179 return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180}
181
Rainer Weikusat3c734192008-06-17 22:28:05 -0700182static inline int unix_recvq_full(struct sock const *sk)
183{
184 return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
185}
186
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000187struct sock *unix_peer_get(struct sock *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
189 struct sock *peer;
190
David S. Miller1c92b4e2007-05-31 13:24:26 -0700191 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 peer = unix_peer(s);
193 if (peer)
194 sock_hold(peer);
David S. Miller1c92b4e2007-05-31 13:24:26 -0700195 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 return peer;
197}
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000198EXPORT_SYMBOL_GPL(unix_peer_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200static inline void unix_release_addr(struct unix_address *addr)
201{
202 if (atomic_dec_and_test(&addr->refcnt))
203 kfree(addr);
204}
205
206/*
207 * Check unix socket name:
208 * - should be not zero length.
209 * - if started by not zero, should be NULL terminated (FS object)
210 * - if started by zero, it is abstract name.
211 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900212
Eric Dumazet95c96172012-04-15 05:58:06 +0000213static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 if (len <= sizeof(short) || len > sizeof(*sunaddr))
216 return -EINVAL;
217 if (!sunaddr || sunaddr->sun_family != AF_UNIX)
218 return -EINVAL;
219 if (sunaddr->sun_path[0]) {
220 /*
221 * This may look like an off by one error but it is a bit more
222 * subtle. 108 is the longest valid AF_UNIX path for a binding.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300223 * sun_path[108] doesn't as such exist. However in kernel space
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 * we are guaranteed that it is a valid memory location in our
225 * kernel address buffer.
226 */
Jianjun Konge27dfce2008-11-01 21:38:31 -0700227 ((char *)sunaddr)[len] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 len = strlen(sunaddr->sun_path)+1+sizeof(short);
229 return len;
230 }
231
Joe Perches07f07572008-11-19 15:44:53 -0800232 *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 return len;
234}
235
236static void __unix_remove_socket(struct sock *sk)
237{
238 sk_del_node_init(sk);
239}
240
241static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
242{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700243 WARN_ON(!sk_unhashed(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 sk_add_node(sk, list);
245}
246
247static inline void unix_remove_socket(struct sock *sk)
248{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800249 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 __unix_remove_socket(sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800251 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
254static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
255{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800256 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 __unix_insert_socket(list, sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800258 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800261static struct sock *__unix_find_socket_byname(struct net *net,
262 struct sockaddr_un *sunname,
Eric Dumazet95c96172012-04-15 05:58:06 +0000263 int len, int type, unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Sasha Levinb67bfe02013-02-27 17:06:00 -0800267 sk_for_each(s, &unix_socket_table[hash ^ type]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 struct unix_sock *u = unix_sk(s);
269
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900270 if (!net_eq(sock_net(s), net))
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800271 continue;
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 if (u->addr->len == len &&
274 !memcmp(u->addr->name, sunname, len))
275 goto found;
276 }
277 s = NULL;
278found:
279 return s;
280}
281
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800282static inline struct sock *unix_find_socket_byname(struct net *net,
283 struct sockaddr_un *sunname,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 int len, int type,
Eric Dumazet95c96172012-04-15 05:58:06 +0000285 unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
287 struct sock *s;
288
David S. Millerfbe9cc42005-12-13 23:26:29 -0800289 spin_lock(&unix_table_lock);
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800290 s = __unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 if (s)
292 sock_hold(s);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800293 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 return s;
295}
296
Eric W. Biederman6616f782010-06-13 03:35:48 +0000297static struct sock *unix_find_socket_byinode(struct inode *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
David S. Millerfbe9cc42005-12-13 23:26:29 -0800301 spin_lock(&unix_table_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800302 sk_for_each(s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
Al Viro40ffe672012-03-14 21:54:32 -0400304 struct dentry *dentry = unix_sk(s)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800306 if (dentry && dentry->d_inode == i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 sock_hold(s);
308 goto found;
309 }
310 }
311 s = NULL;
312found:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800313 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return s;
315}
316
317static inline int unix_writable(struct sock *sk)
318{
319 return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
320}
321
322static void unix_write_space(struct sock *sk)
323{
Eric Dumazet43815482010-04-29 11:01:49 +0000324 struct socket_wq *wq;
325
326 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 if (unix_writable(sk)) {
Eric Dumazet43815482010-04-29 11:01:49 +0000328 wq = rcu_dereference(sk->sk_wq);
329 if (wq_has_sleeper(wq))
Eric Dumazet67426b72010-10-29 20:44:44 +0000330 wake_up_interruptible_sync_poll(&wq->wait,
331 POLLOUT | POLLWRNORM | POLLWRBAND);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800332 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Eric Dumazet43815482010-04-29 11:01:49 +0000334 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335}
336
337/* When dgram socket disconnects (or changes its peer), we clear its receive
338 * queue of packets arrived from previous peer. First, it allows to do
339 * flow control based only on wmem_alloc; second, sk connected to peer
340 * may receive messages only from that peer. */
341static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
342{
David S. Millerb03efcf2005-07-08 14:57:23 -0700343 if (!skb_queue_empty(&sk->sk_receive_queue)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 skb_queue_purge(&sk->sk_receive_queue);
345 wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
346
347 /* If one link of bidirectional dgram pipe is disconnected,
348 * we signal error. Messages are lost. Do not make this,
349 * when peer was not connected to us.
350 */
351 if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
352 other->sk_err = ECONNRESET;
353 other->sk_error_report(other);
354 }
355 }
356}
357
358static void unix_sock_destructor(struct sock *sk)
359{
360 struct unix_sock *u = unix_sk(sk);
361
362 skb_queue_purge(&sk->sk_receive_queue);
363
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700364 WARN_ON(atomic_read(&sk->sk_wmem_alloc));
365 WARN_ON(!sk_unhashed(sk));
366 WARN_ON(sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (!sock_flag(sk, SOCK_DEAD)) {
Eric Dumazet6b41e7d2008-11-19 15:48:09 -0800368 printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 return;
370 }
371
372 if (u->addr)
373 unix_release_addr(u->addr);
374
Eric Dumazet518de9b2010-10-26 14:22:44 -0700375 atomic_long_dec(&unix_nr_socks);
David S. Miller6f756a82008-11-23 17:34:03 -0800376 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800377 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
David S. Miller6f756a82008-11-23 17:34:03 -0800378 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379#ifdef UNIX_REFCNT_DEBUG
Eric Dumazet518de9b2010-10-26 14:22:44 -0700380 printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
381 atomic_long_read(&unix_nr_socks));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382#endif
383}
384
Paul Mooreded34e02013-03-25 03:18:33 +0000385static void unix_release_sock(struct sock *sk, int embrion)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
387 struct unix_sock *u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400388 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 struct sock *skpair;
390 struct sk_buff *skb;
391 int state;
392
393 unix_remove_socket(sk);
394
395 /* Clear state */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700396 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 sock_orphan(sk);
398 sk->sk_shutdown = SHUTDOWN_MASK;
Al Viro40ffe672012-03-14 21:54:32 -0400399 path = u->path;
400 u->path.dentry = NULL;
401 u->path.mnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 state = sk->sk_state;
403 sk->sk_state = TCP_CLOSE;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700404 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406 wake_up_interruptible_all(&u->peer_wait);
407
Jianjun Konge27dfce2008-11-01 21:38:31 -0700408 skpair = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Jianjun Konge27dfce2008-11-01 21:38:31 -0700410 if (skpair != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
David S. Miller1c92b4e2007-05-31 13:24:26 -0700412 unix_state_lock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* No more writes */
414 skpair->sk_shutdown = SHUTDOWN_MASK;
415 if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
416 skpair->sk_err = ECONNRESET;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700417 unix_state_unlock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 skpair->sk_state_change(skpair);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800419 sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 }
421 sock_put(skpair); /* It may now die */
422 unix_peer(sk) = NULL;
423 }
424
425 /* Try to flush out this socket. Throw out buffers at least */
426
427 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
Jianjun Konge27dfce2008-11-01 21:38:31 -0700428 if (state == TCP_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 unix_release_sock(skb->sk, 1);
430 /* passed fds are erased in the kfree_skb hook */
431 kfree_skb(skb);
432 }
433
Al Viro40ffe672012-03-14 21:54:32 -0400434 if (path.dentry)
435 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 sock_put(sk);
438
439 /* ---- Socket is dead now and most probably destroyed ---- */
440
441 /*
Alan Coxe04dae82012-09-17 00:52:41 +0000442 * Fixme: BSD difference: In BSD all sockets connected to us get
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 * ECONNRESET and we die on the spot. In Linux we behave
444 * like files and pipes do and wait for the last
445 * dereference.
446 *
447 * Can't we simply set sock->err?
448 *
449 * What the above comment does talk about? --ANK(980817)
450 */
451
Pavel Emelyanov9305cfa2007-11-10 22:06:01 -0800452 if (unix_tot_inflight)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900453 unix_gc(); /* Garbage collect fds */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000456static void init_peercred(struct sock *sk)
457{
458 put_pid(sk->sk_peer_pid);
459 if (sk->sk_peer_cred)
460 put_cred(sk->sk_peer_cred);
461 sk->sk_peer_pid = get_pid(task_tgid(current));
462 sk->sk_peer_cred = get_current_cred();
463}
464
465static void copy_peercred(struct sock *sk, struct sock *peersk)
466{
467 put_pid(sk->sk_peer_pid);
468 if (sk->sk_peer_cred)
469 put_cred(sk->sk_peer_cred);
470 sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
471 sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
472}
473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474static int unix_listen(struct socket *sock, int backlog)
475{
476 int err;
477 struct sock *sk = sock->sk;
478 struct unix_sock *u = unix_sk(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000479 struct pid *old_pid = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800482 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
483 goto out; /* Only stream/seqpacket sockets accept */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 err = -EINVAL;
485 if (!u->addr)
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800486 goto out; /* No listens on an unbound socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700487 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
489 goto out_unlock;
490 if (backlog > sk->sk_max_ack_backlog)
491 wake_up_interruptible_all(&u->peer_wait);
492 sk->sk_max_ack_backlog = backlog;
493 sk->sk_state = TCP_LISTEN;
494 /* set credentials so connect can copy them */
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000495 init_peercred(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 err = 0;
497
498out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -0700499 unix_state_unlock(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000500 put_pid(old_pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501out:
502 return err;
503}
504
505static int unix_release(struct socket *);
506static int unix_bind(struct socket *, struct sockaddr *, int);
507static int unix_stream_connect(struct socket *, struct sockaddr *,
508 int addr_len, int flags);
509static int unix_socketpair(struct socket *, struct socket *);
510static int unix_accept(struct socket *, struct socket *, int);
511static int unix_getname(struct socket *, struct sockaddr *, int *, int);
512static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700513static unsigned int unix_dgram_poll(struct file *, struct socket *,
514 poll_table *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515static int unix_ioctl(struct socket *, unsigned int, unsigned long);
516static int unix_shutdown(struct socket *, int);
517static int unix_stream_sendmsg(struct kiocb *, struct socket *,
518 struct msghdr *, size_t);
519static int unix_stream_recvmsg(struct kiocb *, struct socket *,
520 struct msghdr *, size_t, int);
521static int unix_dgram_sendmsg(struct kiocb *, struct socket *,
522 struct msghdr *, size_t);
523static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
524 struct msghdr *, size_t, int);
525static int unix_dgram_connect(struct socket *, struct sockaddr *,
526 int, int);
527static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
528 struct msghdr *, size_t);
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000529static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
530 struct msghdr *, size_t, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
Sasha Levind90d9ff2013-12-07 17:26:27 -0500532static int unix_set_peek_off(struct sock *sk, int val)
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000533{
534 struct unix_sock *u = unix_sk(sk);
535
Sasha Levind90d9ff2013-12-07 17:26:27 -0500536 if (mutex_lock_interruptible(&u->readlock))
537 return -EINTR;
538
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000539 sk->sk_peek_off = val;
540 mutex_unlock(&u->readlock);
Sasha Levind90d9ff2013-12-07 17:26:27 -0500541
542 return 0;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000543}
544
545
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800546static const struct proto_ops unix_stream_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 .family = PF_UNIX,
548 .owner = THIS_MODULE,
549 .release = unix_release,
550 .bind = unix_bind,
551 .connect = unix_stream_connect,
552 .socketpair = unix_socketpair,
553 .accept = unix_accept,
554 .getname = unix_getname,
555 .poll = unix_poll,
556 .ioctl = unix_ioctl,
557 .listen = unix_listen,
558 .shutdown = unix_shutdown,
559 .setsockopt = sock_no_setsockopt,
560 .getsockopt = sock_no_getsockopt,
561 .sendmsg = unix_stream_sendmsg,
562 .recvmsg = unix_stream_recvmsg,
563 .mmap = sock_no_mmap,
564 .sendpage = sock_no_sendpage,
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +0000565 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566};
567
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800568static const struct proto_ops unix_dgram_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 .family = PF_UNIX,
570 .owner = THIS_MODULE,
571 .release = unix_release,
572 .bind = unix_bind,
573 .connect = unix_dgram_connect,
574 .socketpair = unix_socketpair,
575 .accept = sock_no_accept,
576 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700577 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 .ioctl = unix_ioctl,
579 .listen = sock_no_listen,
580 .shutdown = unix_shutdown,
581 .setsockopt = sock_no_setsockopt,
582 .getsockopt = sock_no_getsockopt,
583 .sendmsg = unix_dgram_sendmsg,
584 .recvmsg = unix_dgram_recvmsg,
585 .mmap = sock_no_mmap,
586 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000587 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588};
589
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800590static const struct proto_ops unix_seqpacket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 .family = PF_UNIX,
592 .owner = THIS_MODULE,
593 .release = unix_release,
594 .bind = unix_bind,
595 .connect = unix_stream_connect,
596 .socketpair = unix_socketpair,
597 .accept = unix_accept,
598 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700599 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 .ioctl = unix_ioctl,
601 .listen = unix_listen,
602 .shutdown = unix_shutdown,
603 .setsockopt = sock_no_setsockopt,
604 .getsockopt = sock_no_getsockopt,
605 .sendmsg = unix_seqpacket_sendmsg,
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000606 .recvmsg = unix_seqpacket_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 .mmap = sock_no_mmap,
608 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000609 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610};
611
612static struct proto unix_proto = {
Eric Dumazet248969a2008-11-17 00:00:30 -0800613 .name = "UNIX",
614 .owner = THIS_MODULE,
Eric Dumazet248969a2008-11-17 00:00:30 -0800615 .obj_size = sizeof(struct unix_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616};
617
Ingo Molnara09785a2006-07-03 00:25:12 -0700618/*
619 * AF_UNIX sockets do not interact with hardware, hence they
620 * dont trigger interrupts - so it's safe for them to have
621 * bh-unsafe locking for their sk_receive_queue.lock. Split off
622 * this special lock-class by reinitializing the spinlock key:
623 */
624static struct lock_class_key af_unix_sk_receive_queue_lock_key;
625
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800626static struct sock *unix_create1(struct net *net, struct socket *sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
628 struct sock *sk = NULL;
629 struct unix_sock *u;
630
Eric Dumazet518de9b2010-10-26 14:22:44 -0700631 atomic_long_inc(&unix_nr_socks);
632 if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 goto out;
634
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700635 sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (!sk)
637 goto out;
638
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800639 sock_init_data(sock, sk);
Ingo Molnara09785a2006-07-03 00:25:12 -0700640 lockdep_set_class(&sk->sk_receive_queue.lock,
641 &af_unix_sk_receive_queue_lock_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643 sk->sk_write_space = unix_write_space;
Denis V. Luneva0a53c82007-12-11 04:19:17 -0800644 sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 sk->sk_destruct = unix_sock_destructor;
646 u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400647 u->path.dentry = NULL;
648 u->path.mnt = NULL;
Benjamin LaHaisefd19f322006-01-03 14:10:46 -0800649 spin_lock_init(&u->lock);
Al Viro516e0cc2008-07-26 00:39:17 -0400650 atomic_long_set(&u->inflight, 0);
Miklos Szeredi1fd05ba2007-07-11 14:22:39 -0700651 INIT_LIST_HEAD(&u->link);
Ingo Molnar57b47a52006-03-20 22:35:41 -0800652 mutex_init(&u->readlock); /* single task reading lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 init_waitqueue_head(&u->peer_wait);
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000654 unix_insert_socket(unix_sockets_unbound(sk), sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655out:
Pavel Emelyanov284b3272007-11-10 22:08:30 -0800656 if (sk == NULL)
Eric Dumazet518de9b2010-10-26 14:22:44 -0700657 atomic_long_dec(&unix_nr_socks);
Eric Dumazet920de802008-11-24 00:09:29 -0800658 else {
659 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800660 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
Eric Dumazet920de802008-11-24 00:09:29 -0800661 local_bh_enable();
662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 return sk;
664}
665
Eric Paris3f378b62009-11-05 22:18:14 -0800666static int unix_create(struct net *net, struct socket *sock, int protocol,
667 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
669 if (protocol && protocol != PF_UNIX)
670 return -EPROTONOSUPPORT;
671
672 sock->state = SS_UNCONNECTED;
673
674 switch (sock->type) {
675 case SOCK_STREAM:
676 sock->ops = &unix_stream_ops;
677 break;
678 /*
679 * Believe it or not BSD has AF_UNIX, SOCK_RAW though
680 * nothing uses it.
681 */
682 case SOCK_RAW:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700683 sock->type = SOCK_DGRAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 case SOCK_DGRAM:
685 sock->ops = &unix_dgram_ops;
686 break;
687 case SOCK_SEQPACKET:
688 sock->ops = &unix_seqpacket_ops;
689 break;
690 default:
691 return -ESOCKTNOSUPPORT;
692 }
693
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700694 return unix_create1(net, sock) ? 0 : -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
697static int unix_release(struct socket *sock)
698{
699 struct sock *sk = sock->sk;
700
701 if (!sk)
702 return 0;
703
Paul Mooreded34e02013-03-25 03:18:33 +0000704 unix_release_sock(sk, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 sock->sk = NULL;
706
Paul Mooreded34e02013-03-25 03:18:33 +0000707 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708}
709
710static int unix_autobind(struct socket *sock)
711{
712 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900713 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 struct unix_sock *u = unix_sk(sk);
715 static u32 ordernum = 1;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800716 struct unix_address *addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 int err;
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000718 unsigned int retries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Ingo Molnar57b47a52006-03-20 22:35:41 -0800720 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 err = 0;
723 if (u->addr)
724 goto out;
725
726 err = -ENOMEM;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700727 addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 if (!addr)
729 goto out;
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 addr->name->sun_family = AF_UNIX;
732 atomic_set(&addr->refcnt, 1);
733
734retry:
735 addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
Joe Perches07f07572008-11-19 15:44:53 -0800736 addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
David S. Millerfbe9cc42005-12-13 23:26:29 -0800738 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 ordernum = (ordernum+1)&0xFFFFF;
740
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800741 if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 addr->hash)) {
David S. Millerfbe9cc42005-12-13 23:26:29 -0800743 spin_unlock(&unix_table_lock);
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000744 /*
745 * __unix_find_socket_byname() may take long time if many names
746 * are already in use.
747 */
748 cond_resched();
749 /* Give up if all names seems to be in use. */
750 if (retries++ == 0xFFFFF) {
751 err = -ENOSPC;
752 kfree(addr);
753 goto out;
754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 goto retry;
756 }
757 addr->hash ^= sk->sk_type;
758
759 __unix_remove_socket(sk);
760 u->addr = addr;
761 __unix_insert_socket(&unix_socket_table[addr->hash], sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800762 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 err = 0;
764
Ingo Molnar57b47a52006-03-20 22:35:41 -0800765out: mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return err;
767}
768
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800769static struct sock *unix_find_other(struct net *net,
770 struct sockaddr_un *sunname, int len,
Eric Dumazet95c96172012-04-15 05:58:06 +0000771 int type, unsigned int hash, int *error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 struct sock *u;
Al Viro421748e2008-08-02 01:04:36 -0400774 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 int err = 0;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900776
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 if (sunname->sun_path[0]) {
Al Viro421748e2008-08-02 01:04:36 -0400778 struct inode *inode;
779 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (err)
781 goto fail;
Al Viro421748e2008-08-02 01:04:36 -0400782 inode = path.dentry->d_inode;
783 err = inode_permission(inode, MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (err)
785 goto put_fail;
786
787 err = -ECONNREFUSED;
Al Viro421748e2008-08-02 01:04:36 -0400788 if (!S_ISSOCK(inode->i_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 goto put_fail;
Eric W. Biederman6616f782010-06-13 03:35:48 +0000790 u = unix_find_socket_byinode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 if (!u)
792 goto put_fail;
793
794 if (u->sk_type == type)
Al Viro68ac1232012-03-15 08:21:57 -0400795 touch_atime(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Al Viro421748e2008-08-02 01:04:36 -0400797 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Jianjun Konge27dfce2008-11-01 21:38:31 -0700799 err = -EPROTOTYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 if (u->sk_type != type) {
801 sock_put(u);
802 goto fail;
803 }
804 } else {
805 err = -ECONNREFUSED;
Jianjun Konge27dfce2008-11-01 21:38:31 -0700806 u = unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 if (u) {
808 struct dentry *dentry;
Al Viro40ffe672012-03-14 21:54:32 -0400809 dentry = unix_sk(u)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 if (dentry)
Al Viro68ac1232012-03-15 08:21:57 -0400811 touch_atime(&unix_sk(u)->path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 } else
813 goto fail;
814 }
815 return u;
816
817put_fail:
Al Viro421748e2008-08-02 01:04:36 -0400818 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819fail:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700820 *error = err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 return NULL;
822}
823
Al Virofaf02012012-07-20 02:37:29 +0400824static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
825{
826 struct dentry *dentry;
827 struct path path;
828 int err = 0;
829 /*
830 * Get the parent directory, calculate the hash for last
831 * component.
832 */
833 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
834 err = PTR_ERR(dentry);
835 if (IS_ERR(dentry))
836 return err;
837
838 /*
839 * All right, let's create it.
840 */
841 err = security_path_mknod(&path, dentry, mode, 0);
842 if (!err) {
843 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
844 if (!err) {
845 res->mnt = mntget(path.mnt);
846 res->dentry = dget(dentry);
847 }
848 }
849 done_path_create(&path, dentry);
850 return err;
851}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
853static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
854{
855 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900856 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700858 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400859 char *sun_path = sunaddr->sun_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000861 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 struct unix_address *addr;
863 struct hlist_head *list;
864
865 err = -EINVAL;
866 if (sunaddr->sun_family != AF_UNIX)
867 goto out;
868
Jianjun Konge27dfce2008-11-01 21:38:31 -0700869 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 err = unix_autobind(sock);
871 goto out;
872 }
873
874 err = unix_mkname(sunaddr, addr_len, &hash);
875 if (err < 0)
876 goto out;
877 addr_len = err;
878
Ingo Molnar57b47a52006-03-20 22:35:41 -0800879 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 err = -EINVAL;
882 if (u->addr)
883 goto out_up;
884
885 err = -ENOMEM;
886 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
887 if (!addr)
888 goto out_up;
889
890 memcpy(addr->name, sunaddr, addr_len);
891 addr->len = addr_len;
892 addr->hash = hash ^ sk->sk_type;
893 atomic_set(&addr->refcnt, 1);
894
Al Virodae6ad82011-06-26 11:50:15 -0400895 if (sun_path[0]) {
Al Virofaf02012012-07-20 02:37:29 +0400896 struct path path;
897 umode_t mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400898 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virofaf02012012-07-20 02:37:29 +0400899 err = unix_mknod(sun_path, mode, &path);
900 if (err) {
901 if (err == -EEXIST)
902 err = -EADDRINUSE;
903 unix_release_addr(addr);
904 goto out_up;
905 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 addr->hash = UNIX_HASH_SIZE;
Al Virofaf02012012-07-20 02:37:29 +0400907 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
908 spin_lock(&unix_table_lock);
909 u->path = path;
910 list = &unix_socket_table[hash];
911 } else {
912 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800914 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 sk->sk_type, hash)) {
916 unix_release_addr(addr);
917 goto out_unlock;
918 }
919
920 list = &unix_socket_table[addr->hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
922
923 err = 0;
924 __unix_remove_socket(sk);
925 u->addr = addr;
926 __unix_insert_socket(list, sk);
927
928out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800929 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800931 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932out:
933 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
David S. Miller278a3de2007-05-31 15:19:20 -0700936static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
937{
938 if (unlikely(sk1 == sk2) || !sk2) {
939 unix_state_lock(sk1);
940 return;
941 }
942 if (sk1 < sk2) {
943 unix_state_lock(sk1);
944 unix_state_lock_nested(sk2);
945 } else {
946 unix_state_lock(sk2);
947 unix_state_lock_nested(sk1);
948 }
949}
950
951static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
952{
953 if (unlikely(sk1 == sk2) || !sk2) {
954 unix_state_unlock(sk1);
955 return;
956 }
957 unix_state_unlock(sk1);
958 unix_state_unlock(sk2);
959}
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
962 int alen, int flags)
963{
964 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900965 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700966 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000968 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 int err;
970
971 if (addr->sa_family != AF_UNSPEC) {
972 err = unix_mkname(sunaddr, alen, &hash);
973 if (err < 0)
974 goto out;
975 alen = err;
976
977 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
978 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
979 goto out;
980
David S. Miller278a3de2007-05-31 15:19:20 -0700981restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700982 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 if (!other)
984 goto out;
985
David S. Miller278a3de2007-05-31 15:19:20 -0700986 unix_state_double_lock(sk, other);
987
988 /* Apparently VFS overslept socket death. Retry. */
989 if (sock_flag(other, SOCK_DEAD)) {
990 unix_state_double_unlock(sk, other);
991 sock_put(other);
992 goto restart;
993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995 err = -EPERM;
996 if (!unix_may_send(sk, other))
997 goto out_unlock;
998
999 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1000 if (err)
1001 goto out_unlock;
1002
1003 } else {
1004 /*
1005 * 1003.1g breaking connected state with AF_UNSPEC
1006 */
1007 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001008 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 }
1010
1011 /*
1012 * If it was connected, reconnect.
1013 */
1014 if (unix_peer(sk)) {
1015 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001016 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001017 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 if (other != old_peer)
1020 unix_dgram_disconnected(sk, old_peer);
1021 sock_put(old_peer);
1022 } else {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001023 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001024 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001026 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
1028out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001029 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 sock_put(other);
1031out:
1032 return err;
1033}
1034
1035static long unix_wait_for_peer(struct sock *other, long timeo)
1036{
1037 struct unix_sock *u = unix_sk(other);
1038 int sched;
1039 DEFINE_WAIT(wait);
1040
1041 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1042
1043 sched = !sock_flag(other, SOCK_DEAD) &&
1044 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001045 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
David S. Miller1c92b4e2007-05-31 13:24:26 -07001047 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049 if (sched)
1050 timeo = schedule_timeout(timeo);
1051
1052 finish_wait(&u->peer_wait, &wait);
1053 return timeo;
1054}
1055
1056static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1057 int addr_len, int flags)
1058{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001059 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001061 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1063 struct sock *newsk = NULL;
1064 struct sock *other = NULL;
1065 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001066 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 int st;
1068 int err;
1069 long timeo;
1070
1071 err = unix_mkname(sunaddr, addr_len, &hash);
1072 if (err < 0)
1073 goto out;
1074 addr_len = err;
1075
Joe Perchesf64f9e72009-11-29 16:55:45 -08001076 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1077 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 goto out;
1079
1080 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1081
1082 /* First of all allocate resources.
1083 If we will make it after state is locked,
1084 we will have to recheck all again in any case.
1085 */
1086
1087 err = -ENOMEM;
1088
1089 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001090 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 if (newsk == NULL)
1092 goto out;
1093
1094 /* Allocate skb for sending to listening sock */
1095 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1096 if (skb == NULL)
1097 goto out;
1098
1099restart:
1100 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001101 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 if (!other)
1103 goto out;
1104
1105 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001106 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 /* Apparently VFS overslept socket death. Retry. */
1109 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001110 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 sock_put(other);
1112 goto restart;
1113 }
1114
1115 err = -ECONNREFUSED;
1116 if (other->sk_state != TCP_LISTEN)
1117 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001118 if (other->sk_shutdown & RCV_SHUTDOWN)
1119 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
Rainer Weikusat3c734192008-06-17 22:28:05 -07001121 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 err = -EAGAIN;
1123 if (!timeo)
1124 goto out_unlock;
1125
1126 timeo = unix_wait_for_peer(other, timeo);
1127
1128 err = sock_intr_errno(timeo);
1129 if (signal_pending(current))
1130 goto out;
1131 sock_put(other);
1132 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 /* Latch our state.
1136
Daniel Balutae5537bf2011-03-14 15:25:33 -07001137 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 drop lock on peer. It is dangerous because deadlock is
1139 possible. Connect to self case and simultaneous
1140 attempt to connect are eliminated by checking socket
1141 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1142 check this before attempt to grab lock.
1143
1144 Well, and we have to recheck the state after socket locked.
1145 */
1146 st = sk->sk_state;
1147
1148 switch (st) {
1149 case TCP_CLOSE:
1150 /* This is ok... continue with connect */
1151 break;
1152 case TCP_ESTABLISHED:
1153 /* Socket is already connected */
1154 err = -EISCONN;
1155 goto out_unlock;
1156 default:
1157 err = -EINVAL;
1158 goto out_unlock;
1159 }
1160
David S. Miller1c92b4e2007-05-31 13:24:26 -07001161 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001164 unix_state_unlock(sk);
1165 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 sock_put(other);
1167 goto restart;
1168 }
1169
David S. Miller3610cda2011-01-05 15:38:53 -08001170 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001172 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 goto out_unlock;
1174 }
1175
1176 /* The way is open! Fastly set all the necessary fields... */
1177
1178 sock_hold(sk);
1179 unix_peer(newsk) = sk;
1180 newsk->sk_state = TCP_ESTABLISHED;
1181 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001182 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001184 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 otheru = unix_sk(other);
1186
1187 /* copy address information from listening to new sock*/
1188 if (otheru->addr) {
1189 atomic_inc(&otheru->addr->refcnt);
1190 newu->addr = otheru->addr;
1191 }
Al Viro40ffe672012-03-14 21:54:32 -04001192 if (otheru->path.dentry) {
1193 path_get(&otheru->path);
1194 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
1196
1197 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001198 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 sock->state = SS_CONNECTED;
1201 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001202 sock_hold(newsk);
1203
1204 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1205 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
David S. Miller1c92b4e2007-05-31 13:24:26 -07001207 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 /* take ten and and send info to listening sock */
1210 spin_lock(&other->sk_receive_queue.lock);
1211 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001213 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 other->sk_data_ready(other, 0);
1215 sock_put(other);
1216 return 0;
1217
1218out_unlock:
1219 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001220 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001223 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 if (newsk)
1225 unix_release_sock(newsk, 0);
1226 if (other)
1227 sock_put(other);
1228 return err;
1229}
1230
1231static int unix_socketpair(struct socket *socka, struct socket *sockb)
1232{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001233 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 /* Join our sockets back to back */
1236 sock_hold(ska);
1237 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001238 unix_peer(ska) = skb;
1239 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001240 init_peercred(ska);
1241 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 if (ska->sk_type != SOCK_DGRAM) {
1244 ska->sk_state = TCP_ESTABLISHED;
1245 skb->sk_state = TCP_ESTABLISHED;
1246 socka->state = SS_CONNECTED;
1247 sockb->state = SS_CONNECTED;
1248 }
1249 return 0;
1250}
1251
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001252static void unix_sock_inherit_flags(const struct socket *old,
1253 struct socket *new)
1254{
1255 if (test_bit(SOCK_PASSCRED, &old->flags))
1256 set_bit(SOCK_PASSCRED, &new->flags);
1257 if (test_bit(SOCK_PASSSEC, &old->flags))
1258 set_bit(SOCK_PASSSEC, &new->flags);
1259}
1260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1262{
1263 struct sock *sk = sock->sk;
1264 struct sock *tsk;
1265 struct sk_buff *skb;
1266 int err;
1267
1268 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001269 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 goto out;
1271
1272 err = -EINVAL;
1273 if (sk->sk_state != TCP_LISTEN)
1274 goto out;
1275
1276 /* If socket state is TCP_LISTEN it cannot change (for now...),
1277 * so that no locks are necessary.
1278 */
1279
1280 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1281 if (!skb) {
1282 /* This means receive shutdown. */
1283 if (err == 0)
1284 err = -EINVAL;
1285 goto out;
1286 }
1287
1288 tsk = skb->sk;
1289 skb_free_datagram(sk, skb);
1290 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1291
1292 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001293 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 newsock->state = SS_CONNECTED;
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001295 unix_sock_inherit_flags(sock, newsock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001297 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return 0;
1299
1300out:
1301 return err;
1302}
1303
1304
1305static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1306{
1307 struct sock *sk = sock->sk;
1308 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001309 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 int err = 0;
1311
1312 if (peer) {
1313 sk = unix_peer_get(sk);
1314
1315 err = -ENOTCONN;
1316 if (!sk)
1317 goto out;
1318 err = 0;
1319 } else {
1320 sock_hold(sk);
1321 }
1322
1323 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001324 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 if (!u->addr) {
1326 sunaddr->sun_family = AF_UNIX;
1327 sunaddr->sun_path[0] = 0;
1328 *uaddr_len = sizeof(short);
1329 } else {
1330 struct unix_address *addr = u->addr;
1331
1332 *uaddr_len = addr->len;
1333 memcpy(sunaddr, addr->name, *uaddr_len);
1334 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001335 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 sock_put(sk);
1337out:
1338 return err;
1339}
1340
1341static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1342{
1343 int i;
1344
1345 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 UNIXCB(skb).fp = NULL;
1347
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001348 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 unix_notinflight(scm->fp->fp[i]);
1350}
1351
Eric W. Biederman7361c362010-06-13 03:34:33 +00001352static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353{
1354 struct scm_cookie scm;
1355 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001356 scm.pid = UNIXCB(skb).pid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001357 if (UNIXCB(skb).fp)
1358 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 /* Alas, it calls VFS */
1361 /* So fscking what? fput() had been SMP-safe since the last Summer */
1362 scm_destroy(&scm);
1363 sock_wfree(skb);
1364}
1365
Eric Dumazet25888e32010-11-25 04:11:39 +00001366#define MAX_RECURSION_LEVEL 4
1367
Miklos Szeredi62093442008-11-09 15:23:57 +01001368static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001371 unsigned char max_level = 0;
1372 int unix_sock_count = 0;
1373
1374 for (i = scm->fp->count - 1; i >= 0; i--) {
1375 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1376
1377 if (sk) {
1378 unix_sock_count++;
1379 max_level = max(max_level,
1380 unix_sk(sk)->recursion_level);
1381 }
1382 }
1383 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1384 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001385
1386 /*
1387 * Need to duplicate file references for the sake of garbage
1388 * collection. Otherwise a socket in the fps might become a
1389 * candidate for GC while the skb is not yet queued.
1390 */
1391 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1392 if (!UNIXCB(skb).fp)
1393 return -ENOMEM;
1394
Eric Dumazet25888e32010-11-25 04:11:39 +00001395 if (unix_sock_count) {
1396 for (i = scm->fp->count - 1; i >= 0; i--)
1397 unix_inflight(scm->fp->fp[i]);
1398 }
1399 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400}
1401
David S. Millerf78a5fd2011-09-16 19:34:00 -04001402static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001403{
1404 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001405
David S. Millerf78a5fd2011-09-16 19:34:00 -04001406 UNIXCB(skb).pid = get_pid(scm->pid);
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001407 UNIXCB(skb).uid = scm->creds.uid;
1408 UNIXCB(skb).gid = scm->creds.gid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001409 UNIXCB(skb).fp = NULL;
1410 if (scm->fp && send_fds)
1411 err = unix_attach_fds(scm, skb);
1412
1413 skb->destructor = unix_destruct_scm;
1414 return err;
1415}
1416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001418 * Some apps rely on write() giving SCM_CREDENTIALS
1419 * We include credentials if source or destination socket
1420 * asserted SOCK_PASSCRED.
1421 */
1422static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1423 const struct sock *other)
1424{
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001425 if (UNIXCB(skb).pid)
Eric Dumazet16e57262011-09-19 05:52:27 +00001426 return;
1427 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
Eric W. Biederman25da0e32013-04-03 16:13:35 +00001428 !other->sk_socket ||
1429 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
Eric Dumazet16e57262011-09-19 05:52:27 +00001430 UNIXCB(skb).pid = get_pid(task_tgid(current));
David S. Miller6e0895c2013-04-22 20:32:51 -04001431 current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001432 }
1433}
1434
1435/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 * Send AF_UNIX data.
1437 */
1438
1439static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1440 struct msghdr *msg, size_t len)
1441{
1442 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1443 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001444 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001446 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 struct sock *other = NULL;
1448 int namelen = 0; /* fake GCC */
1449 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001450 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001451 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 long timeo;
1453 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001454 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001455 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 if (NULL == siocb->scm)
1458 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001459 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001460 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 if (err < 0)
1462 return err;
1463
1464 err = -EOPNOTSUPP;
1465 if (msg->msg_flags&MSG_OOB)
1466 goto out;
1467
1468 if (msg->msg_namelen) {
1469 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1470 if (err < 0)
1471 goto out;
1472 namelen = err;
1473 } else {
1474 sunaddr = NULL;
1475 err = -ENOTCONN;
1476 other = unix_peer_get(sk);
1477 if (!other)
1478 goto out;
1479 }
1480
Joe Perchesf64f9e72009-11-29 16:55:45 -08001481 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1482 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 goto out;
1484
1485 err = -EMSGSIZE;
1486 if (len > sk->sk_sndbuf - 32)
1487 goto out;
1488
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001489 if (len > SKB_MAX_ALLOC)
1490 data_len = min_t(size_t,
1491 len - SKB_MAX_ALLOC,
1492 MAX_SKB_FRAGS * PAGE_SIZE);
1493
1494 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1495 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001496 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 goto out;
1498
David S. Millerf78a5fd2011-09-16 19:34:00 -04001499 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001500 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001501 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001502 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001503 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001504
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001505 skb_put(skb, len - data_len);
1506 skb->data_len = data_len;
1507 skb->len = len;
1508 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 if (err)
1510 goto out_free;
1511
1512 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1513
1514restart:
1515 if (!other) {
1516 err = -ECONNRESET;
1517 if (sunaddr == NULL)
1518 goto out_free;
1519
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001520 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001522 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 goto out_free;
1524 }
1525
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001526 if (sk_filter(other, skb) < 0) {
1527 /* Toss the packet but do not return any error to the sender */
1528 err = len;
1529 goto out_free;
1530 }
1531
David S. Miller1c92b4e2007-05-31 13:24:26 -07001532 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 err = -EPERM;
1534 if (!unix_may_send(sk, other))
1535 goto out_unlock;
1536
1537 if (sock_flag(other, SOCK_DEAD)) {
1538 /*
1539 * Check with 1003.1g - what should
1540 * datagram error
1541 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001542 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 sock_put(other);
1544
1545 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001546 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001548 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001549 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
1551 unix_dgram_disconnected(sk, other);
1552 sock_put(other);
1553 err = -ECONNREFUSED;
1554 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001555 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 }
1557
1558 other = NULL;
1559 if (err)
1560 goto out_free;
1561 goto restart;
1562 }
1563
1564 err = -EPIPE;
1565 if (other->sk_shutdown & RCV_SHUTDOWN)
1566 goto out_unlock;
1567
1568 if (sk->sk_type != SOCK_SEQPACKET) {
1569 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1570 if (err)
1571 goto out_unlock;
1572 }
1573
Rainer Weikusat3c734192008-06-17 22:28:05 -07001574 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 if (!timeo) {
1576 err = -EAGAIN;
1577 goto out_unlock;
1578 }
1579
1580 timeo = unix_wait_for_peer(other, timeo);
1581
1582 err = sock_intr_errno(timeo);
1583 if (signal_pending(current))
1584 goto out_free;
1585
1586 goto restart;
1587 }
1588
Alban Crequy3f661162010-10-04 08:48:28 +00001589 if (sock_flag(other, SOCK_RCVTSTAMP))
1590 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001591 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001593 if (max_level > unix_sk(other)->recursion_level)
1594 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001595 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 other->sk_data_ready(other, len);
1597 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001598 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 return len;
1600
1601out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001602 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603out_free:
1604 kfree_skb(skb);
1605out:
1606 if (other)
1607 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001608 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 return err;
1610}
1611
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1614 struct msghdr *msg, size_t len)
1615{
1616 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1617 struct sock *sk = sock->sk;
1618 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001619 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001620 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001621 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001623 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001624 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
1626 if (NULL == siocb->scm)
1627 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001628 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001629 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (err < 0)
1631 return err;
1632
1633 err = -EOPNOTSUPP;
1634 if (msg->msg_flags&MSG_OOB)
1635 goto out_err;
1636
1637 if (msg->msg_namelen) {
1638 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1639 goto out_err;
1640 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001642 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 if (!other)
1644 goto out_err;
1645 }
1646
1647 if (sk->sk_shutdown & SEND_SHUTDOWN)
1648 goto pipe_err;
1649
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001650 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 /*
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001652 * Optimisation for the fact that under 0.01% of X
1653 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 */
1655
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001656 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001659 if (size > ((sk->sk_sndbuf >> 1) - 64))
1660 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 if (size > SKB_MAX_ALLOC)
1663 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001664
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 /*
1666 * Grab a buffer
1667 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001668
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001669 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1670 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
Jianjun Konge27dfce2008-11-01 21:38:31 -07001672 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 goto out_err;
1674
1675 /*
1676 * If you pass two values to the sock_alloc_send_skb
1677 * it tries to grab the large buffer with GFP_NOFS
1678 * (which can fail easily), and if it fails grab the
1679 * fallback size buffer which is under a page and will
1680 * succeed. [Alan]
1681 */
1682 size = min_t(int, size, skb_tailroom(skb));
1683
Eric W. Biederman7361c362010-06-13 03:34:33 +00001684
David S. Millerf78a5fd2011-09-16 19:34:00 -04001685 /* Only send the fds in the first buffer */
1686 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001687 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001688 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001689 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001690 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001691 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001692 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001694 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1695 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001697 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 }
1699
David S. Miller1c92b4e2007-05-31 13:24:26 -07001700 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 if (sock_flag(other, SOCK_DEAD) ||
1703 (other->sk_shutdown & RCV_SHUTDOWN))
1704 goto pipe_err_free;
1705
Eric Dumazet16e57262011-09-19 05:52:27 +00001706 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001708 if (max_level > unix_sk(other)->recursion_level)
1709 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001710 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001712 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
David S. Millerf78a5fd2011-09-16 19:34:00 -04001715 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 siocb->scm = NULL;
1717
1718 return sent;
1719
1720pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001721 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 kfree_skb(skb);
1723pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001724 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1725 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 err = -EPIPE;
1727out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001728 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 siocb->scm = NULL;
1730 return sent ? : err;
1731}
1732
1733static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1734 struct msghdr *msg, size_t len)
1735{
1736 int err;
1737 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 err = sock_error(sk);
1740 if (err)
1741 return err;
1742
1743 if (sk->sk_state != TCP_ESTABLISHED)
1744 return -ENOTCONN;
1745
1746 if (msg->msg_namelen)
1747 msg->msg_namelen = 0;
1748
1749 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1750}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001751
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001752static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1753 struct msghdr *msg, size_t size,
1754 int flags)
1755{
1756 struct sock *sk = sock->sk;
1757
1758 if (sk->sk_state != TCP_ESTABLISHED)
1759 return -ENOTCONN;
1760
1761 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1762}
1763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1765{
1766 struct unix_sock *u = unix_sk(sk);
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 if (u->addr) {
1769 msg->msg_namelen = u->addr->len;
1770 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1771 }
1772}
1773
1774static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1775 struct msghdr *msg, size_t size,
1776 int flags)
1777{
1778 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1779 struct scm_cookie tmp_scm;
1780 struct sock *sk = sock->sk;
1781 struct unix_sock *u = unix_sk(sk);
1782 int noblock = flags & MSG_DONTWAIT;
1783 struct sk_buff *skb;
1784 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001785 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 err = -EOPNOTSUPP;
1788 if (flags&MSG_OOB)
1789 goto out;
1790
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001791 err = mutex_lock_interruptible(&u->readlock);
1792 if (err) {
1793 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1794 goto out;
1795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001797 skip = sk_peek_offset(sk, flags);
1798
1799 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001800 if (!skb) {
1801 unix_state_lock(sk);
1802 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1803 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1804 (sk->sk_shutdown & RCV_SHUTDOWN))
1805 err = 0;
1806 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
Eric Dumazet67426b72010-10-29 20:44:44 +00001810 wake_up_interruptible_sync_poll(&u->peer_wait,
1811 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 if (msg->msg_name)
1814 unix_copy_addr(msg, skb->sk);
1815
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001816 if (size > skb->len - skip)
1817 size = skb->len - skip;
1818 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 msg->msg_flags |= MSG_TRUNC;
1820
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001821 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 if (err)
1823 goto out_free;
1824
Alban Crequy3f661162010-10-04 08:48:28 +00001825 if (sock_flag(sk, SOCK_RCVTSTAMP))
1826 __sock_recv_timestamp(msg, sk, skb);
1827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 if (!siocb->scm) {
1829 siocb->scm = &tmp_scm;
1830 memset(&tmp_scm, 0, sizeof(tmp_scm));
1831 }
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001832 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001833 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001835 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 if (UNIXCB(skb).fp)
1837 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001838
1839 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001840 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 /* It is questionable: on PEEK we could:
1842 - do not return fds - good, but too simple 8)
1843 - return fds, and do not return them on read (old strategy,
1844 apparently wrong)
1845 - clone fds (I chose it for now, it is the most universal
1846 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001847
1848 POSIX 1003.1g does not actually define this clearly
1849 at all. POSIX 1003.1g doesn't define a lot of things
1850 clearly however!
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001853
1854 sk_peek_offset_fwd(sk, size);
1855
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 if (UNIXCB(skb).fp)
1857 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1858 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001859 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
1861 scm_recv(sock, msg, siocb->scm, flags);
1862
1863out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001864 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001866 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867out:
1868 return err;
1869}
1870
1871/*
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001872 * Sleep until more data has arrived. But check for races..
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 */
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001874static long unix_stream_data_wait(struct sock *sk, long timeo,
1875 struct sk_buff *last)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876{
1877 DEFINE_WAIT(wait);
1878
David S. Miller1c92b4e2007-05-31 13:24:26 -07001879 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
1881 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001882 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001884 if (skb_peek_tail(&sk->sk_receive_queue) != last ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 sk->sk_err ||
1886 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1887 signal_pending(current) ||
1888 !timeo)
1889 break;
1890
1891 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001892 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 timeo = schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001894 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1896 }
1897
Eric Dumazetaa395142010-04-20 13:03:51 +00001898 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001899 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 return timeo;
1901}
1902
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1904 struct msghdr *msg, size_t size,
1905 int flags)
1906{
1907 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1908 struct scm_cookie tmp_scm;
1909 struct sock *sk = sock->sk;
1910 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001911 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 int copied = 0;
1913 int check_creds = 0;
1914 int target;
1915 int err = 0;
1916 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001917 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
1919 err = -EINVAL;
1920 if (sk->sk_state != TCP_ESTABLISHED)
1921 goto out;
1922
1923 err = -EOPNOTSUPP;
1924 if (flags&MSG_OOB)
1925 goto out;
1926
1927 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1928 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 /* Lock the socket to prevent queue disordering
1931 * while sleeps in memcpy_tomsg
1932 */
1933
1934 if (!siocb->scm) {
1935 siocb->scm = &tmp_scm;
1936 memset(&tmp_scm, 0, sizeof(tmp_scm));
1937 }
1938
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001939 err = mutex_lock_interruptible(&u->readlock);
1940 if (err) {
1941 err = sock_intr_errno(timeo);
1942 goto out;
1943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001945 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 int chunk;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001947 struct sk_buff *skb, *last;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001949 unix_state_lock(sk);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001950 last = skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001951again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001952 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001953 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001955 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956
1957 /*
1958 * POSIX 1003.1g mandates this order.
1959 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001960
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001961 err = sock_error(sk);
1962 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001963 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001965 goto unlock;
1966
1967 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 err = -EAGAIN;
1969 if (!timeo)
1970 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001971 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001973 timeo = unix_stream_data_wait(sk, timeo, last);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001975 if (signal_pending(current)
1976 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 err = sock_intr_errno(timeo);
1978 goto out;
1979 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001982 unlock:
1983 unix_state_unlock(sk);
1984 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001986
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001987 skip = sk_peek_offset(sk, flags);
1988 while (skip >= skb->len) {
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001989 skip -= skb->len;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001990 last = skb;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001991 skb = skb_peek_next(skb, &sk->sk_receive_queue);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001992 if (!skb)
1993 goto again;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001994 }
1995
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001996 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
1998 if (check_creds) {
1999 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00002000 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00002001 !uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) ||
2002 !gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 break;
Eric W. Biederman0e82e7f6d2013-04-03 16:14:47 +00002004 } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 /* Copy credentials */
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00002006 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 check_creds = 1;
2008 }
2009
2010 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002011 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 unix_copy_addr(msg, skb->sk);
2013 sunaddr = NULL;
2014 }
2015
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002016 chunk = min_t(unsigned int, skb->len - skip, size);
2017 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 if (copied == 0)
2019 copied = -EFAULT;
2020 break;
2021 }
2022 copied += chunk;
2023 size -= chunk;
2024
2025 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002026 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 skb_pull(skb, chunk);
2028
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002029 sk_peek_offset_bwd(sk, chunk);
2030
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 if (UNIXCB(skb).fp)
2032 unix_detach_fds(siocb->scm, skb);
2033
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002034 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002037 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002038 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
2040 if (siocb->scm->fp)
2041 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002042 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 /* It is questionable, see note in unix_dgram_recvmsg.
2044 */
2045 if (UNIXCB(skb).fp)
2046 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2047
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002048 sk_peek_offset_fwd(sk, chunk);
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 break;
2051 }
2052 } while (size);
2053
Ingo Molnar57b47a52006-03-20 22:35:41 -08002054 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 scm_recv(sock, msg, siocb->scm, flags);
2056out:
2057 return copied ? : err;
2058}
2059
2060static int unix_shutdown(struct socket *sock, int mode)
2061{
2062 struct sock *sk = sock->sk;
2063 struct sock *other;
2064
Xi Wangfc61b922012-08-26 16:47:13 +00002065 if (mode < SHUT_RD || mode > SHUT_RDWR)
2066 return -EINVAL;
2067 /* This maps:
2068 * SHUT_RD (0) -> RCV_SHUTDOWN (1)
2069 * SHUT_WR (1) -> SEND_SHUTDOWN (2)
2070 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
2071 */
2072 ++mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Alban Crequy7180a032011-01-19 04:56:36 +00002074 unix_state_lock(sk);
2075 sk->sk_shutdown |= mode;
2076 other = unix_peer(sk);
2077 if (other)
2078 sock_hold(other);
2079 unix_state_unlock(sk);
2080 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
Alban Crequy7180a032011-01-19 04:56:36 +00002082 if (other &&
2083 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
Alban Crequy7180a032011-01-19 04:56:36 +00002085 int peer_mode = 0;
2086
2087 if (mode&RCV_SHUTDOWN)
2088 peer_mode |= SEND_SHUTDOWN;
2089 if (mode&SEND_SHUTDOWN)
2090 peer_mode |= RCV_SHUTDOWN;
2091 unix_state_lock(other);
2092 other->sk_shutdown |= peer_mode;
2093 unix_state_unlock(other);
2094 other->sk_state_change(other);
2095 if (peer_mode == SHUTDOWN_MASK)
2096 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2097 else if (peer_mode & RCV_SHUTDOWN)
2098 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 }
Alban Crequy7180a032011-01-19 04:56:36 +00002100 if (other)
2101 sock_put(other);
2102
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 return 0;
2104}
2105
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002106long unix_inq_len(struct sock *sk)
2107{
2108 struct sk_buff *skb;
2109 long amount = 0;
2110
2111 if (sk->sk_state == TCP_LISTEN)
2112 return -EINVAL;
2113
2114 spin_lock(&sk->sk_receive_queue.lock);
2115 if (sk->sk_type == SOCK_STREAM ||
2116 sk->sk_type == SOCK_SEQPACKET) {
2117 skb_queue_walk(&sk->sk_receive_queue, skb)
2118 amount += skb->len;
2119 } else {
2120 skb = skb_peek(&sk->sk_receive_queue);
2121 if (skb)
2122 amount = skb->len;
2123 }
2124 spin_unlock(&sk->sk_receive_queue.lock);
2125
2126 return amount;
2127}
2128EXPORT_SYMBOL_GPL(unix_inq_len);
2129
2130long unix_outq_len(struct sock *sk)
2131{
2132 return sk_wmem_alloc_get(sk);
2133}
2134EXPORT_SYMBOL_GPL(unix_outq_len);
2135
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2137{
2138 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002139 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 int err;
2141
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002142 switch (cmd) {
2143 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002144 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002145 err = put_user(amount, (int __user *)arg);
2146 break;
2147 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002148 amount = unix_inq_len(sk);
2149 if (amount < 0)
2150 err = amount;
2151 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002153 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002154 default:
2155 err = -ENOIOCTLCMD;
2156 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 }
2158 return err;
2159}
2160
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002161static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162{
2163 struct sock *sk = sock->sk;
2164 unsigned int mask;
2165
Eric Dumazetaa395142010-04-20 13:03:51 +00002166 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 mask = 0;
2168
2169 /* exceptional events? */
2170 if (sk->sk_err)
2171 mask |= POLLERR;
2172 if (sk->sk_shutdown == SHUTDOWN_MASK)
2173 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002174 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002175 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
2177 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002178 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 mask |= POLLIN | POLLRDNORM;
2180
2181 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002182 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2183 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 mask |= POLLHUP;
2185
2186 /*
2187 * we set writable also when the other side has shut down the
2188 * connection. This prevents stuck sockets.
2189 */
2190 if (unix_writable(sk))
2191 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2192
2193 return mask;
2194}
2195
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002196static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2197 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002198{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002199 struct sock *sk = sock->sk, *other;
2200 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002201
Eric Dumazetaa395142010-04-20 13:03:51 +00002202 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002203 mask = 0;
2204
2205 /* exceptional events? */
2206 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002207 mask |= POLLERR |
Jacob Keller8facd5f2013-04-02 13:55:40 -07002208 (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002209
Rainer Weikusat3c734192008-06-17 22:28:05 -07002210 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazet5456f092010-10-31 05:36:23 +00002211 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002212 if (sk->sk_shutdown == SHUTDOWN_MASK)
2213 mask |= POLLHUP;
2214
2215 /* readable? */
Eric Dumazet5456f092010-10-31 05:36:23 +00002216 if (!skb_queue_empty(&sk->sk_receive_queue))
Rainer Weikusat3c734192008-06-17 22:28:05 -07002217 mask |= POLLIN | POLLRDNORM;
2218
2219 /* Connection-based need to check for termination and startup */
2220 if (sk->sk_type == SOCK_SEQPACKET) {
2221 if (sk->sk_state == TCP_CLOSE)
2222 mask |= POLLHUP;
2223 /* connection hasn't started yet? */
2224 if (sk->sk_state == TCP_SYN_SENT)
2225 return mask;
2226 }
2227
Eric Dumazet973a34a2010-10-31 05:38:25 +00002228 /* No write status requested, avoid expensive OUT tests. */
Hans Verkuil626cf232012-03-23 15:02:27 -07002229 if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
Eric Dumazet973a34a2010-10-31 05:38:25 +00002230 return mask;
2231
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002232 writable = unix_writable(sk);
Eric Dumazet5456f092010-10-31 05:36:23 +00002233 other = unix_peer_get(sk);
2234 if (other) {
2235 if (unix_peer(other) != sk) {
2236 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2237 if (unix_recvq_full(other))
2238 writable = 0;
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002239 }
Eric Dumazet5456f092010-10-31 05:36:23 +00002240 sock_put(other);
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002241 }
2242
2243 if (writable)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002244 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2245 else
2246 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
2247
Rainer Weikusat3c734192008-06-17 22:28:05 -07002248 return mask;
2249}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
2251#ifdef CONFIG_PROC_FS
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002252
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002253#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
2254
2255#define get_bucket(x) ((x) >> BUCKET_SPACE)
2256#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
2257#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002258
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002259static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002261 unsigned long offset = get_offset(*pos);
2262 unsigned long bucket = get_bucket(*pos);
2263 struct sock *sk;
2264 unsigned long count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002266 for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
2267 if (sock_net(sk) != seq_file_net(seq))
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002268 continue;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002269 if (++count == offset)
2270 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 }
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002272
2273 return sk;
2274}
2275
2276static struct sock *unix_next_socket(struct seq_file *seq,
2277 struct sock *sk,
2278 loff_t *pos)
2279{
2280 unsigned long bucket;
2281
2282 while (sk > (struct sock *)SEQ_START_TOKEN) {
2283 sk = sk_next(sk);
2284 if (!sk)
2285 goto next_bucket;
2286 if (sock_net(sk) == seq_file_net(seq))
2287 return sk;
2288 }
2289
2290 do {
2291 sk = unix_from_bucket(seq, pos);
2292 if (sk)
2293 return sk;
2294
2295next_bucket:
2296 bucket = get_bucket(*pos) + 1;
2297 *pos = set_bucket_offset(bucket, 1);
2298 } while (bucket < ARRAY_SIZE(unix_socket_table));
2299
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 return NULL;
2301}
2302
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002304 __acquires(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002306 spin_lock(&unix_table_lock);
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002307
2308 if (!*pos)
2309 return SEQ_START_TOKEN;
2310
2311 if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
2312 return NULL;
2313
2314 return unix_next_socket(seq, NULL, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315}
2316
2317static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2318{
2319 ++*pos;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002320 return unix_next_socket(seq, v, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321}
2322
2323static void unix_seq_stop(struct seq_file *seq, void *v)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002324 __releases(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002326 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327}
2328
2329static int unix_seq_show(struct seq_file *seq, void *v)
2330{
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002331
Joe Perchesb9f31242008-04-12 19:04:38 -07002332 if (v == SEQ_START_TOKEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 seq_puts(seq, "Num RefCount Protocol Flags Type St "
2334 "Inode Path\n");
2335 else {
2336 struct sock *s = v;
2337 struct unix_sock *u = unix_sk(s);
David S. Miller1c92b4e2007-05-31 13:24:26 -07002338 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
Dan Rosenberg71338aa2011-05-23 12:17:35 +00002340 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 s,
2342 atomic_read(&s->sk_refcnt),
2343 0,
2344 s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
2345 s->sk_type,
2346 s->sk_socket ?
2347 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
2348 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
2349 sock_i_ino(s));
2350
2351 if (u->addr) {
2352 int i, len;
2353 seq_putc(seq, ' ');
2354
2355 i = 0;
2356 len = u->addr->len - sizeof(short);
2357 if (!UNIX_ABSTRACT(s))
2358 len--;
2359 else {
2360 seq_putc(seq, '@');
2361 i++;
2362 }
2363 for ( ; i < len; i++)
2364 seq_putc(seq, u->addr->name->sun_path[i]);
2365 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07002366 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 seq_putc(seq, '\n');
2368 }
2369
2370 return 0;
2371}
2372
Philippe De Muyter56b3d972007-07-10 23:07:31 -07002373static const struct seq_operations unix_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 .start = unix_seq_start,
2375 .next = unix_seq_next,
2376 .stop = unix_seq_stop,
2377 .show = unix_seq_show,
2378};
2379
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380static int unix_seq_open(struct inode *inode, struct file *file)
2381{
Denis V. Luneve372c412007-11-19 22:31:54 -08002382 return seq_open_net(inode, file, &unix_seq_ops,
Eric Dumazet8b51b062012-06-08 22:10:20 +00002383 sizeof(struct seq_net_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384}
2385
Arjan van de Venda7071d2007-02-12 00:55:36 -08002386static const struct file_operations unix_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 .owner = THIS_MODULE,
2388 .open = unix_seq_open,
2389 .read = seq_read,
2390 .llseek = seq_lseek,
Denis V. Luneve372c412007-11-19 22:31:54 -08002391 .release = seq_release_net,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392};
2393
2394#endif
2395
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00002396static const struct net_proto_family unix_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 .family = PF_UNIX,
2398 .create = unix_create,
2399 .owner = THIS_MODULE,
2400};
2401
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002402
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002403static int __net_init unix_net_init(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002404{
2405 int error = -ENOMEM;
2406
Denis V. Luneva0a53c82007-12-11 04:19:17 -08002407 net->unx.sysctl_max_dgram_qlen = 10;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002408 if (unix_sysctl_register(net))
2409 goto out;
Pavel Emelyanovd392e492007-12-01 23:44:15 +11002410
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002411#ifdef CONFIG_PROC_FS
Gao fengd4beaa62013-02-18 01:34:54 +00002412 if (!proc_create("unix", 0, net->proc_net, &unix_seq_fops)) {
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002413 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002414 goto out;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002415 }
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002416#endif
2417 error = 0;
2418out:
Jianjun Kong48dcc33e2008-11-01 21:37:27 -07002419 return error;
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002420}
2421
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002422static void __net_exit unix_net_exit(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002423{
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002424 unix_sysctl_unregister(net);
Gao fengece31ff2013-02-18 01:34:56 +00002425 remove_proc_entry("unix", net->proc_net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002426}
2427
2428static struct pernet_operations unix_net_ops = {
2429 .init = unix_net_init,
2430 .exit = unix_net_exit,
2431};
2432
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433static int __init af_unix_init(void)
2434{
2435 int rc = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
YOSHIFUJI Hideaki / 吉藤英明b4fff5f2013-01-09 07:20:07 +00002437 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
2439 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002440 if (rc != 0) {
2441 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002442 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 goto out;
2444 }
2445
2446 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002447 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448out:
2449 return rc;
2450}
2451
2452static void __exit af_unix_exit(void)
2453{
2454 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002456 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457}
2458
David Woodhouse3d366962008-04-24 00:59:25 -07002459/* Earlier than device_initcall() so that other drivers invoking
2460 request_module() don't end up in a loop when modprobe tries
2461 to use a UNIX socket. But later than subsys_initcall() because
2462 we depend on stuff initialised there */
2463fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464module_exit(af_unix_exit);
2465
2466MODULE_LICENSE("GPL");
2467MODULE_ALIAS_NETPROTO(PF_UNIX);