blob: 3ca7927520b0e7023634a40046de0e97b98a0fcd [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
Sasha Levin57bc52e2013-12-13 10:54:22 -0500720 err = mutex_lock_interruptible(&u->readlock);
721 if (err)
722 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 err = 0;
725 if (u->addr)
726 goto out;
727
728 err = -ENOMEM;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700729 addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 if (!addr)
731 goto out;
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 addr->name->sun_family = AF_UNIX;
734 atomic_set(&addr->refcnt, 1);
735
736retry:
737 addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
Joe Perches07f07572008-11-19 15:44:53 -0800738 addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
David S. Millerfbe9cc42005-12-13 23:26:29 -0800740 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 ordernum = (ordernum+1)&0xFFFFF;
742
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800743 if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 addr->hash)) {
David S. Millerfbe9cc42005-12-13 23:26:29 -0800745 spin_unlock(&unix_table_lock);
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000746 /*
747 * __unix_find_socket_byname() may take long time if many names
748 * are already in use.
749 */
750 cond_resched();
751 /* Give up if all names seems to be in use. */
752 if (retries++ == 0xFFFFF) {
753 err = -ENOSPC;
754 kfree(addr);
755 goto out;
756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 goto retry;
758 }
759 addr->hash ^= sk->sk_type;
760
761 __unix_remove_socket(sk);
762 u->addr = addr;
763 __unix_insert_socket(&unix_socket_table[addr->hash], sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800764 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 err = 0;
766
Ingo Molnar57b47a52006-03-20 22:35:41 -0800767out: mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 return err;
769}
770
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800771static struct sock *unix_find_other(struct net *net,
772 struct sockaddr_un *sunname, int len,
Eric Dumazet95c96172012-04-15 05:58:06 +0000773 int type, unsigned int hash, int *error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
775 struct sock *u;
Al Viro421748e2008-08-02 01:04:36 -0400776 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 int err = 0;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 if (sunname->sun_path[0]) {
Al Viro421748e2008-08-02 01:04:36 -0400780 struct inode *inode;
781 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 if (err)
783 goto fail;
Al Viro421748e2008-08-02 01:04:36 -0400784 inode = path.dentry->d_inode;
785 err = inode_permission(inode, MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 if (err)
787 goto put_fail;
788
789 err = -ECONNREFUSED;
Al Viro421748e2008-08-02 01:04:36 -0400790 if (!S_ISSOCK(inode->i_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 goto put_fail;
Eric W. Biederman6616f782010-06-13 03:35:48 +0000792 u = unix_find_socket_byinode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 if (!u)
794 goto put_fail;
795
796 if (u->sk_type == type)
Al Viro68ac1232012-03-15 08:21:57 -0400797 touch_atime(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Al Viro421748e2008-08-02 01:04:36 -0400799 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Jianjun Konge27dfce2008-11-01 21:38:31 -0700801 err = -EPROTOTYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 if (u->sk_type != type) {
803 sock_put(u);
804 goto fail;
805 }
806 } else {
807 err = -ECONNREFUSED;
Jianjun Konge27dfce2008-11-01 21:38:31 -0700808 u = unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (u) {
810 struct dentry *dentry;
Al Viro40ffe672012-03-14 21:54:32 -0400811 dentry = unix_sk(u)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 if (dentry)
Al Viro68ac1232012-03-15 08:21:57 -0400813 touch_atime(&unix_sk(u)->path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 } else
815 goto fail;
816 }
817 return u;
818
819put_fail:
Al Viro421748e2008-08-02 01:04:36 -0400820 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821fail:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700822 *error = err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 return NULL;
824}
825
Al Virofaf02012012-07-20 02:37:29 +0400826static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
827{
828 struct dentry *dentry;
829 struct path path;
830 int err = 0;
831 /*
832 * Get the parent directory, calculate the hash for last
833 * component.
834 */
835 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
836 err = PTR_ERR(dentry);
837 if (IS_ERR(dentry))
838 return err;
839
840 /*
841 * All right, let's create it.
842 */
843 err = security_path_mknod(&path, dentry, mode, 0);
844 if (!err) {
845 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
846 if (!err) {
847 res->mnt = mntget(path.mnt);
848 res->dentry = dget(dentry);
849 }
850 }
851 done_path_create(&path, dentry);
852 return err;
853}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
855static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
856{
857 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900858 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700860 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400861 char *sun_path = sunaddr->sun_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000863 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 struct unix_address *addr;
865 struct hlist_head *list;
866
867 err = -EINVAL;
868 if (sunaddr->sun_family != AF_UNIX)
869 goto out;
870
Jianjun Konge27dfce2008-11-01 21:38:31 -0700871 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 err = unix_autobind(sock);
873 goto out;
874 }
875
876 err = unix_mkname(sunaddr, addr_len, &hash);
877 if (err < 0)
878 goto out;
879 addr_len = err;
880
Sasha Levin57bc52e2013-12-13 10:54:22 -0500881 err = mutex_lock_interruptible(&u->readlock);
882 if (err)
883 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 err = -EINVAL;
886 if (u->addr)
887 goto out_up;
888
889 err = -ENOMEM;
890 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
891 if (!addr)
892 goto out_up;
893
894 memcpy(addr->name, sunaddr, addr_len);
895 addr->len = addr_len;
896 addr->hash = hash ^ sk->sk_type;
897 atomic_set(&addr->refcnt, 1);
898
Al Virodae6ad82011-06-26 11:50:15 -0400899 if (sun_path[0]) {
Al Virofaf02012012-07-20 02:37:29 +0400900 struct path path;
901 umode_t mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400902 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virofaf02012012-07-20 02:37:29 +0400903 err = unix_mknod(sun_path, mode, &path);
904 if (err) {
905 if (err == -EEXIST)
906 err = -EADDRINUSE;
907 unix_release_addr(addr);
908 goto out_up;
909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 addr->hash = UNIX_HASH_SIZE;
Al Virofaf02012012-07-20 02:37:29 +0400911 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
912 spin_lock(&unix_table_lock);
913 u->path = path;
914 list = &unix_socket_table[hash];
915 } else {
916 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800918 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 sk->sk_type, hash)) {
920 unix_release_addr(addr);
921 goto out_unlock;
922 }
923
924 list = &unix_socket_table[addr->hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 }
926
927 err = 0;
928 __unix_remove_socket(sk);
929 u->addr = addr;
930 __unix_insert_socket(list, sk);
931
932out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800933 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800935 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936out:
937 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938}
939
David S. Miller278a3de2007-05-31 15:19:20 -0700940static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
941{
942 if (unlikely(sk1 == sk2) || !sk2) {
943 unix_state_lock(sk1);
944 return;
945 }
946 if (sk1 < sk2) {
947 unix_state_lock(sk1);
948 unix_state_lock_nested(sk2);
949 } else {
950 unix_state_lock(sk2);
951 unix_state_lock_nested(sk1);
952 }
953}
954
955static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
956{
957 if (unlikely(sk1 == sk2) || !sk2) {
958 unix_state_unlock(sk1);
959 return;
960 }
961 unix_state_unlock(sk1);
962 unix_state_unlock(sk2);
963}
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
966 int alen, int flags)
967{
968 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900969 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700970 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000972 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 int err;
974
975 if (addr->sa_family != AF_UNSPEC) {
976 err = unix_mkname(sunaddr, alen, &hash);
977 if (err < 0)
978 goto out;
979 alen = err;
980
981 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
982 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
983 goto out;
984
David S. Miller278a3de2007-05-31 15:19:20 -0700985restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700986 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 if (!other)
988 goto out;
989
David S. Miller278a3de2007-05-31 15:19:20 -0700990 unix_state_double_lock(sk, other);
991
992 /* Apparently VFS overslept socket death. Retry. */
993 if (sock_flag(other, SOCK_DEAD)) {
994 unix_state_double_unlock(sk, other);
995 sock_put(other);
996 goto restart;
997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 err = -EPERM;
1000 if (!unix_may_send(sk, other))
1001 goto out_unlock;
1002
1003 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1004 if (err)
1005 goto out_unlock;
1006
1007 } else {
1008 /*
1009 * 1003.1g breaking connected state with AF_UNSPEC
1010 */
1011 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001012 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 }
1014
1015 /*
1016 * If it was connected, reconnect.
1017 */
1018 if (unix_peer(sk)) {
1019 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001020 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001021 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023 if (other != old_peer)
1024 unix_dgram_disconnected(sk, old_peer);
1025 sock_put(old_peer);
1026 } else {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001027 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001028 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001030 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001033 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 sock_put(other);
1035out:
1036 return err;
1037}
1038
1039static long unix_wait_for_peer(struct sock *other, long timeo)
1040{
1041 struct unix_sock *u = unix_sk(other);
1042 int sched;
1043 DEFINE_WAIT(wait);
1044
1045 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1046
1047 sched = !sock_flag(other, SOCK_DEAD) &&
1048 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001049 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
David S. Miller1c92b4e2007-05-31 13:24:26 -07001051 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 if (sched)
1054 timeo = schedule_timeout(timeo);
1055
1056 finish_wait(&u->peer_wait, &wait);
1057 return timeo;
1058}
1059
1060static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1061 int addr_len, int flags)
1062{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001063 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001065 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1067 struct sock *newsk = NULL;
1068 struct sock *other = NULL;
1069 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001070 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 int st;
1072 int err;
1073 long timeo;
1074
1075 err = unix_mkname(sunaddr, addr_len, &hash);
1076 if (err < 0)
1077 goto out;
1078 addr_len = err;
1079
Joe Perchesf64f9e72009-11-29 16:55:45 -08001080 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1081 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 goto out;
1083
1084 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1085
1086 /* First of all allocate resources.
1087 If we will make it after state is locked,
1088 we will have to recheck all again in any case.
1089 */
1090
1091 err = -ENOMEM;
1092
1093 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001094 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 if (newsk == NULL)
1096 goto out;
1097
1098 /* Allocate skb for sending to listening sock */
1099 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1100 if (skb == NULL)
1101 goto out;
1102
1103restart:
1104 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001105 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 if (!other)
1107 goto out;
1108
1109 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001110 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 /* Apparently VFS overslept socket death. Retry. */
1113 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001114 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 sock_put(other);
1116 goto restart;
1117 }
1118
1119 err = -ECONNREFUSED;
1120 if (other->sk_state != TCP_LISTEN)
1121 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001122 if (other->sk_shutdown & RCV_SHUTDOWN)
1123 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Rainer Weikusat3c734192008-06-17 22:28:05 -07001125 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 err = -EAGAIN;
1127 if (!timeo)
1128 goto out_unlock;
1129
1130 timeo = unix_wait_for_peer(other, timeo);
1131
1132 err = sock_intr_errno(timeo);
1133 if (signal_pending(current))
1134 goto out;
1135 sock_put(other);
1136 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
1139 /* Latch our state.
1140
Daniel Balutae5537bf2011-03-14 15:25:33 -07001141 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 drop lock on peer. It is dangerous because deadlock is
1143 possible. Connect to self case and simultaneous
1144 attempt to connect are eliminated by checking socket
1145 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1146 check this before attempt to grab lock.
1147
1148 Well, and we have to recheck the state after socket locked.
1149 */
1150 st = sk->sk_state;
1151
1152 switch (st) {
1153 case TCP_CLOSE:
1154 /* This is ok... continue with connect */
1155 break;
1156 case TCP_ESTABLISHED:
1157 /* Socket is already connected */
1158 err = -EISCONN;
1159 goto out_unlock;
1160 default:
1161 err = -EINVAL;
1162 goto out_unlock;
1163 }
1164
David S. Miller1c92b4e2007-05-31 13:24:26 -07001165 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
1167 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001168 unix_state_unlock(sk);
1169 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 sock_put(other);
1171 goto restart;
1172 }
1173
David S. Miller3610cda2011-01-05 15:38:53 -08001174 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001176 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 goto out_unlock;
1178 }
1179
1180 /* The way is open! Fastly set all the necessary fields... */
1181
1182 sock_hold(sk);
1183 unix_peer(newsk) = sk;
1184 newsk->sk_state = TCP_ESTABLISHED;
1185 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001186 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001188 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 otheru = unix_sk(other);
1190
1191 /* copy address information from listening to new sock*/
1192 if (otheru->addr) {
1193 atomic_inc(&otheru->addr->refcnt);
1194 newu->addr = otheru->addr;
1195 }
Al Viro40ffe672012-03-14 21:54:32 -04001196 if (otheru->path.dentry) {
1197 path_get(&otheru->path);
1198 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
1200
1201 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001202 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 sock->state = SS_CONNECTED;
1205 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001206 sock_hold(newsk);
1207
1208 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1209 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
David S. Miller1c92b4e2007-05-31 13:24:26 -07001211 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 /* take ten and and send info to listening sock */
1214 spin_lock(&other->sk_receive_queue.lock);
1215 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001217 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 other->sk_data_ready(other, 0);
1219 sock_put(other);
1220 return 0;
1221
1222out_unlock:
1223 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001224 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001227 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 if (newsk)
1229 unix_release_sock(newsk, 0);
1230 if (other)
1231 sock_put(other);
1232 return err;
1233}
1234
1235static int unix_socketpair(struct socket *socka, struct socket *sockb)
1236{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001237 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239 /* Join our sockets back to back */
1240 sock_hold(ska);
1241 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001242 unix_peer(ska) = skb;
1243 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001244 init_peercred(ska);
1245 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 if (ska->sk_type != SOCK_DGRAM) {
1248 ska->sk_state = TCP_ESTABLISHED;
1249 skb->sk_state = TCP_ESTABLISHED;
1250 socka->state = SS_CONNECTED;
1251 sockb->state = SS_CONNECTED;
1252 }
1253 return 0;
1254}
1255
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001256static void unix_sock_inherit_flags(const struct socket *old,
1257 struct socket *new)
1258{
1259 if (test_bit(SOCK_PASSCRED, &old->flags))
1260 set_bit(SOCK_PASSCRED, &new->flags);
1261 if (test_bit(SOCK_PASSSEC, &old->flags))
1262 set_bit(SOCK_PASSSEC, &new->flags);
1263}
1264
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1266{
1267 struct sock *sk = sock->sk;
1268 struct sock *tsk;
1269 struct sk_buff *skb;
1270 int err;
1271
1272 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001273 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 goto out;
1275
1276 err = -EINVAL;
1277 if (sk->sk_state != TCP_LISTEN)
1278 goto out;
1279
1280 /* If socket state is TCP_LISTEN it cannot change (for now...),
1281 * so that no locks are necessary.
1282 */
1283
1284 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1285 if (!skb) {
1286 /* This means receive shutdown. */
1287 if (err == 0)
1288 err = -EINVAL;
1289 goto out;
1290 }
1291
1292 tsk = skb->sk;
1293 skb_free_datagram(sk, skb);
1294 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1295
1296 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001297 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 newsock->state = SS_CONNECTED;
Daniel Borkmanna769ad62013-10-17 22:51:31 +02001299 unix_sock_inherit_flags(sock, newsock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001301 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return 0;
1303
1304out:
1305 return err;
1306}
1307
1308
1309static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1310{
1311 struct sock *sk = sock->sk;
1312 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001313 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 int err = 0;
1315
1316 if (peer) {
1317 sk = unix_peer_get(sk);
1318
1319 err = -ENOTCONN;
1320 if (!sk)
1321 goto out;
1322 err = 0;
1323 } else {
1324 sock_hold(sk);
1325 }
1326
1327 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001328 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 if (!u->addr) {
1330 sunaddr->sun_family = AF_UNIX;
1331 sunaddr->sun_path[0] = 0;
1332 *uaddr_len = sizeof(short);
1333 } else {
1334 struct unix_address *addr = u->addr;
1335
1336 *uaddr_len = addr->len;
1337 memcpy(sunaddr, addr->name, *uaddr_len);
1338 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001339 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 sock_put(sk);
1341out:
1342 return err;
1343}
1344
1345static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1346{
1347 int i;
1348
1349 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 UNIXCB(skb).fp = NULL;
1351
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001352 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 unix_notinflight(scm->fp->fp[i]);
1354}
1355
Eric W. Biederman7361c362010-06-13 03:34:33 +00001356static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357{
1358 struct scm_cookie scm;
1359 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001360 scm.pid = UNIXCB(skb).pid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001361 if (UNIXCB(skb).fp)
1362 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364 /* Alas, it calls VFS */
1365 /* So fscking what? fput() had been SMP-safe since the last Summer */
1366 scm_destroy(&scm);
1367 sock_wfree(skb);
1368}
1369
Eric Dumazet25888e32010-11-25 04:11:39 +00001370#define MAX_RECURSION_LEVEL 4
1371
Miklos Szeredi62093442008-11-09 15:23:57 +01001372static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373{
1374 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001375 unsigned char max_level = 0;
1376 int unix_sock_count = 0;
1377
1378 for (i = scm->fp->count - 1; i >= 0; i--) {
1379 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1380
1381 if (sk) {
1382 unix_sock_count++;
1383 max_level = max(max_level,
1384 unix_sk(sk)->recursion_level);
1385 }
1386 }
1387 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1388 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001389
1390 /*
1391 * Need to duplicate file references for the sake of garbage
1392 * collection. Otherwise a socket in the fps might become a
1393 * candidate for GC while the skb is not yet queued.
1394 */
1395 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1396 if (!UNIXCB(skb).fp)
1397 return -ENOMEM;
1398
Eric Dumazet25888e32010-11-25 04:11:39 +00001399 if (unix_sock_count) {
1400 for (i = scm->fp->count - 1; i >= 0; i--)
1401 unix_inflight(scm->fp->fp[i]);
1402 }
1403 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404}
1405
David S. Millerf78a5fd2011-09-16 19:34:00 -04001406static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001407{
1408 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001409
David S. Millerf78a5fd2011-09-16 19:34:00 -04001410 UNIXCB(skb).pid = get_pid(scm->pid);
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001411 UNIXCB(skb).uid = scm->creds.uid;
1412 UNIXCB(skb).gid = scm->creds.gid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001413 UNIXCB(skb).fp = NULL;
1414 if (scm->fp && send_fds)
1415 err = unix_attach_fds(scm, skb);
1416
1417 skb->destructor = unix_destruct_scm;
1418 return err;
1419}
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001422 * Some apps rely on write() giving SCM_CREDENTIALS
1423 * We include credentials if source or destination socket
1424 * asserted SOCK_PASSCRED.
1425 */
1426static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1427 const struct sock *other)
1428{
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001429 if (UNIXCB(skb).pid)
Eric Dumazet16e57262011-09-19 05:52:27 +00001430 return;
1431 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
Eric W. Biederman25da0e32013-04-03 16:13:35 +00001432 !other->sk_socket ||
1433 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
Eric Dumazet16e57262011-09-19 05:52:27 +00001434 UNIXCB(skb).pid = get_pid(task_tgid(current));
David S. Miller6e0895c2013-04-22 20:32:51 -04001435 current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001436 }
1437}
1438
1439/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 * Send AF_UNIX data.
1441 */
1442
1443static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1444 struct msghdr *msg, size_t len)
1445{
1446 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1447 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001448 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001450 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 struct sock *other = NULL;
1452 int namelen = 0; /* fake GCC */
1453 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001454 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001455 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 long timeo;
1457 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001458 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001459 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 if (NULL == siocb->scm)
1462 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001463 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001464 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (err < 0)
1466 return err;
1467
1468 err = -EOPNOTSUPP;
1469 if (msg->msg_flags&MSG_OOB)
1470 goto out;
1471
1472 if (msg->msg_namelen) {
1473 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1474 if (err < 0)
1475 goto out;
1476 namelen = err;
1477 } else {
1478 sunaddr = NULL;
1479 err = -ENOTCONN;
1480 other = unix_peer_get(sk);
1481 if (!other)
1482 goto out;
1483 }
1484
Joe Perchesf64f9e72009-11-29 16:55:45 -08001485 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1486 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 goto out;
1488
1489 err = -EMSGSIZE;
1490 if (len > sk->sk_sndbuf - 32)
1491 goto out;
1492
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001493 if (len > SKB_MAX_ALLOC)
1494 data_len = min_t(size_t,
1495 len - SKB_MAX_ALLOC,
1496 MAX_SKB_FRAGS * PAGE_SIZE);
1497
1498 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1499 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001500 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 goto out;
1502
David S. Millerf78a5fd2011-09-16 19:34:00 -04001503 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001504 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001505 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001506 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001507 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001508
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001509 skb_put(skb, len - data_len);
1510 skb->data_len = data_len;
1511 skb->len = len;
1512 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 if (err)
1514 goto out_free;
1515
1516 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1517
1518restart:
1519 if (!other) {
1520 err = -ECONNRESET;
1521 if (sunaddr == NULL)
1522 goto out_free;
1523
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001524 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001526 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 goto out_free;
1528 }
1529
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001530 if (sk_filter(other, skb) < 0) {
1531 /* Toss the packet but do not return any error to the sender */
1532 err = len;
1533 goto out_free;
1534 }
1535
David S. Miller1c92b4e2007-05-31 13:24:26 -07001536 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 err = -EPERM;
1538 if (!unix_may_send(sk, other))
1539 goto out_unlock;
1540
1541 if (sock_flag(other, SOCK_DEAD)) {
1542 /*
1543 * Check with 1003.1g - what should
1544 * datagram error
1545 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001546 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 sock_put(other);
1548
1549 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001550 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001552 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001553 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 unix_dgram_disconnected(sk, other);
1556 sock_put(other);
1557 err = -ECONNREFUSED;
1558 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001559 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 }
1561
1562 other = NULL;
1563 if (err)
1564 goto out_free;
1565 goto restart;
1566 }
1567
1568 err = -EPIPE;
1569 if (other->sk_shutdown & RCV_SHUTDOWN)
1570 goto out_unlock;
1571
1572 if (sk->sk_type != SOCK_SEQPACKET) {
1573 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1574 if (err)
1575 goto out_unlock;
1576 }
1577
Rainer Weikusat3c734192008-06-17 22:28:05 -07001578 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 if (!timeo) {
1580 err = -EAGAIN;
1581 goto out_unlock;
1582 }
1583
1584 timeo = unix_wait_for_peer(other, timeo);
1585
1586 err = sock_intr_errno(timeo);
1587 if (signal_pending(current))
1588 goto out_free;
1589
1590 goto restart;
1591 }
1592
Alban Crequy3f661162010-10-04 08:48:28 +00001593 if (sock_flag(other, SOCK_RCVTSTAMP))
1594 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001595 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001597 if (max_level > unix_sk(other)->recursion_level)
1598 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001599 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 other->sk_data_ready(other, len);
1601 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001602 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 return len;
1604
1605out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001606 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607out_free:
1608 kfree_skb(skb);
1609out:
1610 if (other)
1611 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001612 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 return err;
1614}
1615
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001616
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1618 struct msghdr *msg, size_t len)
1619{
1620 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1621 struct sock *sk = sock->sk;
1622 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001623 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001624 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001625 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001627 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001628 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
1630 if (NULL == siocb->scm)
1631 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001632 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001633 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 if (err < 0)
1635 return err;
1636
1637 err = -EOPNOTSUPP;
1638 if (msg->msg_flags&MSG_OOB)
1639 goto out_err;
1640
1641 if (msg->msg_namelen) {
1642 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1643 goto out_err;
1644 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001646 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 if (!other)
1648 goto out_err;
1649 }
1650
1651 if (sk->sk_shutdown & SEND_SHUTDOWN)
1652 goto pipe_err;
1653
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001654 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 /*
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001656 * Optimisation for the fact that under 0.01% of X
1657 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 */
1659
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001660 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001663 if (size > ((sk->sk_sndbuf >> 1) - 64))
1664 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 if (size > SKB_MAX_ALLOC)
1667 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 /*
1670 * Grab a buffer
1671 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001672
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001673 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1674 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Jianjun Konge27dfce2008-11-01 21:38:31 -07001676 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 goto out_err;
1678
1679 /*
1680 * If you pass two values to the sock_alloc_send_skb
1681 * it tries to grab the large buffer with GFP_NOFS
1682 * (which can fail easily), and if it fails grab the
1683 * fallback size buffer which is under a page and will
1684 * succeed. [Alan]
1685 */
1686 size = min_t(int, size, skb_tailroom(skb));
1687
Eric W. Biederman7361c362010-06-13 03:34:33 +00001688
David S. Millerf78a5fd2011-09-16 19:34:00 -04001689 /* Only send the fds in the first buffer */
1690 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001691 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001692 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001693 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001694 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001695 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001696 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001698 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1699 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001701 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 }
1703
David S. Miller1c92b4e2007-05-31 13:24:26 -07001704 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 if (sock_flag(other, SOCK_DEAD) ||
1707 (other->sk_shutdown & RCV_SHUTDOWN))
1708 goto pipe_err_free;
1709
Eric Dumazet16e57262011-09-19 05:52:27 +00001710 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001712 if (max_level > unix_sk(other)->recursion_level)
1713 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001714 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001716 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
David S. Millerf78a5fd2011-09-16 19:34:00 -04001719 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 siocb->scm = NULL;
1721
1722 return sent;
1723
1724pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001725 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 kfree_skb(skb);
1727pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001728 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1729 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 err = -EPIPE;
1731out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001732 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 siocb->scm = NULL;
1734 return sent ? : err;
1735}
1736
1737static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1738 struct msghdr *msg, size_t len)
1739{
1740 int err;
1741 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001742
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 err = sock_error(sk);
1744 if (err)
1745 return err;
1746
1747 if (sk->sk_state != TCP_ESTABLISHED)
1748 return -ENOTCONN;
1749
1750 if (msg->msg_namelen)
1751 msg->msg_namelen = 0;
1752
1753 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1754}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001755
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001756static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1757 struct msghdr *msg, size_t size,
1758 int flags)
1759{
1760 struct sock *sk = sock->sk;
1761
1762 if (sk->sk_state != TCP_ESTABLISHED)
1763 return -ENOTCONN;
1764
1765 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1766}
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1769{
1770 struct unix_sock *u = unix_sk(sk);
1771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 if (u->addr) {
1773 msg->msg_namelen = u->addr->len;
1774 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1775 }
1776}
1777
1778static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1779 struct msghdr *msg, size_t size,
1780 int flags)
1781{
1782 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1783 struct scm_cookie tmp_scm;
1784 struct sock *sk = sock->sk;
1785 struct unix_sock *u = unix_sk(sk);
1786 int noblock = flags & MSG_DONTWAIT;
1787 struct sk_buff *skb;
1788 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001789 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
1791 err = -EOPNOTSUPP;
1792 if (flags&MSG_OOB)
1793 goto out;
1794
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001795 err = mutex_lock_interruptible(&u->readlock);
1796 if (err) {
1797 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1798 goto out;
1799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001801 skip = sk_peek_offset(sk, flags);
1802
1803 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001804 if (!skb) {
1805 unix_state_lock(sk);
1806 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1807 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1808 (sk->sk_shutdown & RCV_SHUTDOWN))
1809 err = 0;
1810 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
Eric Dumazet67426b72010-10-29 20:44:44 +00001814 wake_up_interruptible_sync_poll(&u->peer_wait,
1815 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
1817 if (msg->msg_name)
1818 unix_copy_addr(msg, skb->sk);
1819
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001820 if (size > skb->len - skip)
1821 size = skb->len - skip;
1822 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 msg->msg_flags |= MSG_TRUNC;
1824
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001825 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 if (err)
1827 goto out_free;
1828
Alban Crequy3f661162010-10-04 08:48:28 +00001829 if (sock_flag(sk, SOCK_RCVTSTAMP))
1830 __sock_recv_timestamp(msg, sk, skb);
1831
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 if (!siocb->scm) {
1833 siocb->scm = &tmp_scm;
1834 memset(&tmp_scm, 0, sizeof(tmp_scm));
1835 }
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001836 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001837 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001839 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 if (UNIXCB(skb).fp)
1841 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001842
1843 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001844 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 /* It is questionable: on PEEK we could:
1846 - do not return fds - good, but too simple 8)
1847 - return fds, and do not return them on read (old strategy,
1848 apparently wrong)
1849 - clone fds (I chose it for now, it is the most universal
1850 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001851
1852 POSIX 1003.1g does not actually define this clearly
1853 at all. POSIX 1003.1g doesn't define a lot of things
1854 clearly however!
1855
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001857
1858 sk_peek_offset_fwd(sk, size);
1859
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 if (UNIXCB(skb).fp)
1861 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1862 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001863 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
1865 scm_recv(sock, msg, siocb->scm, flags);
1866
1867out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001868 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001870 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871out:
1872 return err;
1873}
1874
1875/*
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001876 * Sleep until more data has arrived. But check for races..
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 */
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001878static long unix_stream_data_wait(struct sock *sk, long timeo,
1879 struct sk_buff *last)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880{
1881 DEFINE_WAIT(wait);
1882
David S. Miller1c92b4e2007-05-31 13:24:26 -07001883 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
1885 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001886 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001888 if (skb_peek_tail(&sk->sk_receive_queue) != last ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 sk->sk_err ||
1890 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1891 signal_pending(current) ||
1892 !timeo)
1893 break;
1894
1895 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001896 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 timeo = schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001898 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1900 }
1901
Eric Dumazetaa395142010-04-20 13:03:51 +00001902 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001903 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 return timeo;
1905}
1906
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1908 struct msghdr *msg, size_t size,
1909 int flags)
1910{
1911 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1912 struct scm_cookie tmp_scm;
1913 struct sock *sk = sock->sk;
1914 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001915 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 int copied = 0;
1917 int check_creds = 0;
1918 int target;
1919 int err = 0;
1920 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001921 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
1923 err = -EINVAL;
1924 if (sk->sk_state != TCP_ESTABLISHED)
1925 goto out;
1926
1927 err = -EOPNOTSUPP;
1928 if (flags&MSG_OOB)
1929 goto out;
1930
1931 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1932 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 /* Lock the socket to prevent queue disordering
1935 * while sleeps in memcpy_tomsg
1936 */
1937
1938 if (!siocb->scm) {
1939 siocb->scm = &tmp_scm;
1940 memset(&tmp_scm, 0, sizeof(tmp_scm));
1941 }
1942
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001943 err = mutex_lock_interruptible(&u->readlock);
1944 if (err) {
1945 err = sock_intr_errno(timeo);
1946 goto out;
1947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001949 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 int chunk;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001951 struct sk_buff *skb, *last;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001953 unix_state_lock(sk);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001954 last = skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001955again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001956 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001957 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001959 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
1961 /*
1962 * POSIX 1003.1g mandates this order.
1963 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001964
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001965 err = sock_error(sk);
1966 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001967 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001969 goto unlock;
1970
1971 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 err = -EAGAIN;
1973 if (!timeo)
1974 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001975 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001977 timeo = unix_stream_data_wait(sk, timeo, last);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001979 if (signal_pending(current)
1980 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 err = sock_intr_errno(timeo);
1982 goto out;
1983 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001984
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001986 unlock:
1987 unix_state_unlock(sk);
1988 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001990
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001991 skip = sk_peek_offset(sk, flags);
1992 while (skip >= skb->len) {
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001993 skip -= skb->len;
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001994 last = skb;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001995 skb = skb_peek_next(skb, &sk->sk_receive_queue);
Benjamin Poirier79f632c2013-04-29 11:42:14 +00001996 if (!skb)
1997 goto again;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001998 }
1999
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07002000 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
2002 if (check_creds) {
2003 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00002004 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00002005 !uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) ||
2006 !gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 break;
Eric W. Biederman0e82e7f6d2013-04-03 16:14:47 +00002008 } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 /* Copy credentials */
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00002010 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 check_creds = 1;
2012 }
2013
2014 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002015 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 unix_copy_addr(msg, skb->sk);
2017 sunaddr = NULL;
2018 }
2019
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002020 chunk = min_t(unsigned int, skb->len - skip, size);
2021 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 if (copied == 0)
2023 copied = -EFAULT;
2024 break;
2025 }
2026 copied += chunk;
2027 size -= chunk;
2028
2029 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002030 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 skb_pull(skb, chunk);
2032
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002033 sk_peek_offset_bwd(sk, chunk);
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 if (UNIXCB(skb).fp)
2036 unix_detach_fds(siocb->scm, skb);
2037
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002038 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002041 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002042 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
2044 if (siocb->scm->fp)
2045 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002046 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 /* It is questionable, see note in unix_dgram_recvmsg.
2048 */
2049 if (UNIXCB(skb).fp)
2050 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2051
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002052 sk_peek_offset_fwd(sk, chunk);
2053
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 break;
2055 }
2056 } while (size);
2057
Ingo Molnar57b47a52006-03-20 22:35:41 -08002058 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 scm_recv(sock, msg, siocb->scm, flags);
2060out:
2061 return copied ? : err;
2062}
2063
2064static int unix_shutdown(struct socket *sock, int mode)
2065{
2066 struct sock *sk = sock->sk;
2067 struct sock *other;
2068
Xi Wangfc61b922012-08-26 16:47:13 +00002069 if (mode < SHUT_RD || mode > SHUT_RDWR)
2070 return -EINVAL;
2071 /* This maps:
2072 * SHUT_RD (0) -> RCV_SHUTDOWN (1)
2073 * SHUT_WR (1) -> SEND_SHUTDOWN (2)
2074 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
2075 */
2076 ++mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Alban Crequy7180a032011-01-19 04:56:36 +00002078 unix_state_lock(sk);
2079 sk->sk_shutdown |= mode;
2080 other = unix_peer(sk);
2081 if (other)
2082 sock_hold(other);
2083 unix_state_unlock(sk);
2084 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Alban Crequy7180a032011-01-19 04:56:36 +00002086 if (other &&
2087 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Alban Crequy7180a032011-01-19 04:56:36 +00002089 int peer_mode = 0;
2090
2091 if (mode&RCV_SHUTDOWN)
2092 peer_mode |= SEND_SHUTDOWN;
2093 if (mode&SEND_SHUTDOWN)
2094 peer_mode |= RCV_SHUTDOWN;
2095 unix_state_lock(other);
2096 other->sk_shutdown |= peer_mode;
2097 unix_state_unlock(other);
2098 other->sk_state_change(other);
2099 if (peer_mode == SHUTDOWN_MASK)
2100 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2101 else if (peer_mode & RCV_SHUTDOWN)
2102 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
Alban Crequy7180a032011-01-19 04:56:36 +00002104 if (other)
2105 sock_put(other);
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 return 0;
2108}
2109
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002110long unix_inq_len(struct sock *sk)
2111{
2112 struct sk_buff *skb;
2113 long amount = 0;
2114
2115 if (sk->sk_state == TCP_LISTEN)
2116 return -EINVAL;
2117
2118 spin_lock(&sk->sk_receive_queue.lock);
2119 if (sk->sk_type == SOCK_STREAM ||
2120 sk->sk_type == SOCK_SEQPACKET) {
2121 skb_queue_walk(&sk->sk_receive_queue, skb)
2122 amount += skb->len;
2123 } else {
2124 skb = skb_peek(&sk->sk_receive_queue);
2125 if (skb)
2126 amount = skb->len;
2127 }
2128 spin_unlock(&sk->sk_receive_queue.lock);
2129
2130 return amount;
2131}
2132EXPORT_SYMBOL_GPL(unix_inq_len);
2133
2134long unix_outq_len(struct sock *sk)
2135{
2136 return sk_wmem_alloc_get(sk);
2137}
2138EXPORT_SYMBOL_GPL(unix_outq_len);
2139
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2141{
2142 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002143 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 int err;
2145
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002146 switch (cmd) {
2147 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002148 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002149 err = put_user(amount, (int __user *)arg);
2150 break;
2151 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002152 amount = unix_inq_len(sk);
2153 if (amount < 0)
2154 err = amount;
2155 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002157 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002158 default:
2159 err = -ENOIOCTLCMD;
2160 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
2162 return err;
2163}
2164
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002165static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166{
2167 struct sock *sk = sock->sk;
2168 unsigned int mask;
2169
Eric Dumazetaa395142010-04-20 13:03:51 +00002170 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 mask = 0;
2172
2173 /* exceptional events? */
2174 if (sk->sk_err)
2175 mask |= POLLERR;
2176 if (sk->sk_shutdown == SHUTDOWN_MASK)
2177 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002178 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002179 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
2181 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002182 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 mask |= POLLIN | POLLRDNORM;
2184
2185 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002186 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2187 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 mask |= POLLHUP;
2189
2190 /*
2191 * we set writable also when the other side has shut down the
2192 * connection. This prevents stuck sockets.
2193 */
2194 if (unix_writable(sk))
2195 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2196
2197 return mask;
2198}
2199
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002200static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2201 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002202{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002203 struct sock *sk = sock->sk, *other;
2204 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002205
Eric Dumazetaa395142010-04-20 13:03:51 +00002206 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002207 mask = 0;
2208
2209 /* exceptional events? */
2210 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002211 mask |= POLLERR |
Jacob Keller8facd5f2013-04-02 13:55:40 -07002212 (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002213
Rainer Weikusat3c734192008-06-17 22:28:05 -07002214 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazet5456f092010-10-31 05:36:23 +00002215 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002216 if (sk->sk_shutdown == SHUTDOWN_MASK)
2217 mask |= POLLHUP;
2218
2219 /* readable? */
Eric Dumazet5456f092010-10-31 05:36:23 +00002220 if (!skb_queue_empty(&sk->sk_receive_queue))
Rainer Weikusat3c734192008-06-17 22:28:05 -07002221 mask |= POLLIN | POLLRDNORM;
2222
2223 /* Connection-based need to check for termination and startup */
2224 if (sk->sk_type == SOCK_SEQPACKET) {
2225 if (sk->sk_state == TCP_CLOSE)
2226 mask |= POLLHUP;
2227 /* connection hasn't started yet? */
2228 if (sk->sk_state == TCP_SYN_SENT)
2229 return mask;
2230 }
2231
Eric Dumazet973a34a2010-10-31 05:38:25 +00002232 /* No write status requested, avoid expensive OUT tests. */
Hans Verkuil626cf232012-03-23 15:02:27 -07002233 if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
Eric Dumazet973a34a2010-10-31 05:38:25 +00002234 return mask;
2235
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002236 writable = unix_writable(sk);
Eric Dumazet5456f092010-10-31 05:36:23 +00002237 other = unix_peer_get(sk);
2238 if (other) {
2239 if (unix_peer(other) != sk) {
2240 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2241 if (unix_recvq_full(other))
2242 writable = 0;
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002243 }
Eric Dumazet5456f092010-10-31 05:36:23 +00002244 sock_put(other);
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002245 }
2246
2247 if (writable)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002248 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2249 else
2250 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
2251
Rainer Weikusat3c734192008-06-17 22:28:05 -07002252 return mask;
2253}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
2255#ifdef CONFIG_PROC_FS
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002256
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002257#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
2258
2259#define get_bucket(x) ((x) >> BUCKET_SPACE)
2260#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
2261#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002262
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002263static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264{
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002265 unsigned long offset = get_offset(*pos);
2266 unsigned long bucket = get_bucket(*pos);
2267 struct sock *sk;
2268 unsigned long count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002270 for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
2271 if (sock_net(sk) != seq_file_net(seq))
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002272 continue;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002273 if (++count == offset)
2274 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 }
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002276
2277 return sk;
2278}
2279
2280static struct sock *unix_next_socket(struct seq_file *seq,
2281 struct sock *sk,
2282 loff_t *pos)
2283{
2284 unsigned long bucket;
2285
2286 while (sk > (struct sock *)SEQ_START_TOKEN) {
2287 sk = sk_next(sk);
2288 if (!sk)
2289 goto next_bucket;
2290 if (sock_net(sk) == seq_file_net(seq))
2291 return sk;
2292 }
2293
2294 do {
2295 sk = unix_from_bucket(seq, pos);
2296 if (sk)
2297 return sk;
2298
2299next_bucket:
2300 bucket = get_bucket(*pos) + 1;
2301 *pos = set_bucket_offset(bucket, 1);
2302 } while (bucket < ARRAY_SIZE(unix_socket_table));
2303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 return NULL;
2305}
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002308 __acquires(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002310 spin_lock(&unix_table_lock);
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002311
2312 if (!*pos)
2313 return SEQ_START_TOKEN;
2314
2315 if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
2316 return NULL;
2317
2318 return unix_next_socket(seq, NULL, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319}
2320
2321static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2322{
2323 ++*pos;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002324 return unix_next_socket(seq, v, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325}
2326
2327static void unix_seq_stop(struct seq_file *seq, void *v)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002328 __releases(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002330 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331}
2332
2333static int unix_seq_show(struct seq_file *seq, void *v)
2334{
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002335
Joe Perchesb9f31242008-04-12 19:04:38 -07002336 if (v == SEQ_START_TOKEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 seq_puts(seq, "Num RefCount Protocol Flags Type St "
2338 "Inode Path\n");
2339 else {
2340 struct sock *s = v;
2341 struct unix_sock *u = unix_sk(s);
David S. Miller1c92b4e2007-05-31 13:24:26 -07002342 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
Dan Rosenberg71338aa2011-05-23 12:17:35 +00002344 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 s,
2346 atomic_read(&s->sk_refcnt),
2347 0,
2348 s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
2349 s->sk_type,
2350 s->sk_socket ?
2351 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
2352 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
2353 sock_i_ino(s));
2354
2355 if (u->addr) {
2356 int i, len;
2357 seq_putc(seq, ' ');
2358
2359 i = 0;
2360 len = u->addr->len - sizeof(short);
2361 if (!UNIX_ABSTRACT(s))
2362 len--;
2363 else {
2364 seq_putc(seq, '@');
2365 i++;
2366 }
2367 for ( ; i < len; i++)
2368 seq_putc(seq, u->addr->name->sun_path[i]);
2369 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07002370 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 seq_putc(seq, '\n');
2372 }
2373
2374 return 0;
2375}
2376
Philippe De Muyter56b3d972007-07-10 23:07:31 -07002377static const struct seq_operations unix_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 .start = unix_seq_start,
2379 .next = unix_seq_next,
2380 .stop = unix_seq_stop,
2381 .show = unix_seq_show,
2382};
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384static int unix_seq_open(struct inode *inode, struct file *file)
2385{
Denis V. Luneve372c412007-11-19 22:31:54 -08002386 return seq_open_net(inode, file, &unix_seq_ops,
Eric Dumazet8b51b062012-06-08 22:10:20 +00002387 sizeof(struct seq_net_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388}
2389
Arjan van de Venda7071d2007-02-12 00:55:36 -08002390static const struct file_operations unix_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 .owner = THIS_MODULE,
2392 .open = unix_seq_open,
2393 .read = seq_read,
2394 .llseek = seq_lseek,
Denis V. Luneve372c412007-11-19 22:31:54 -08002395 .release = seq_release_net,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396};
2397
2398#endif
2399
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00002400static const struct net_proto_family unix_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 .family = PF_UNIX,
2402 .create = unix_create,
2403 .owner = THIS_MODULE,
2404};
2405
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002406
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002407static int __net_init unix_net_init(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002408{
2409 int error = -ENOMEM;
2410
Denis V. Luneva0a53c82007-12-11 04:19:17 -08002411 net->unx.sysctl_max_dgram_qlen = 10;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002412 if (unix_sysctl_register(net))
2413 goto out;
Pavel Emelyanovd392e492007-12-01 23:44:15 +11002414
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002415#ifdef CONFIG_PROC_FS
Gao fengd4beaa62013-02-18 01:34:54 +00002416 if (!proc_create("unix", 0, net->proc_net, &unix_seq_fops)) {
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002417 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002418 goto out;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002419 }
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002420#endif
2421 error = 0;
2422out:
Jianjun Kong48dcc33e2008-11-01 21:37:27 -07002423 return error;
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002424}
2425
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002426static void __net_exit unix_net_exit(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002427{
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002428 unix_sysctl_unregister(net);
Gao fengece31ff2013-02-18 01:34:56 +00002429 remove_proc_entry("unix", net->proc_net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002430}
2431
2432static struct pernet_operations unix_net_ops = {
2433 .init = unix_net_init,
2434 .exit = unix_net_exit,
2435};
2436
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437static int __init af_unix_init(void)
2438{
2439 int rc = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
YOSHIFUJI Hideaki / 吉藤英明b4fff5f2013-01-09 07:20:07 +00002441 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
2443 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002444 if (rc != 0) {
2445 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002446 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 goto out;
2448 }
2449
2450 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002451 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452out:
2453 return rc;
2454}
2455
2456static void __exit af_unix_exit(void)
2457{
2458 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002460 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461}
2462
David Woodhouse3d366962008-04-24 00:59:25 -07002463/* Earlier than device_initcall() so that other drivers invoking
2464 request_module() don't end up in a loop when modprobe tries
2465 to use a UNIX socket. But later than subsys_initcall() because
2466 we depend on stuff initialised there */
2467fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468module_exit(af_unix_exit);
2469
2470MODULE_LICENSE("GPL");
2471MODULE_ALIAS_NETPROTO(PF_UNIX);