blob: 79981d97bc9c013904062b1bedfd1ebcae97f845 [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;
266 struct hlist_node *node;
267
268 sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
269 struct unix_sock *u = unix_sk(s);
270
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900271 if (!net_eq(sock_net(s), net))
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800272 continue;
273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 if (u->addr->len == len &&
275 !memcmp(u->addr->name, sunname, len))
276 goto found;
277 }
278 s = NULL;
279found:
280 return s;
281}
282
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800283static inline struct sock *unix_find_socket_byname(struct net *net,
284 struct sockaddr_un *sunname,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 int len, int type,
Eric Dumazet95c96172012-04-15 05:58:06 +0000286 unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
288 struct sock *s;
289
David S. Millerfbe9cc42005-12-13 23:26:29 -0800290 spin_lock(&unix_table_lock);
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800291 s = __unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 if (s)
293 sock_hold(s);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800294 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return s;
296}
297
Eric W. Biederman6616f782010-06-13 03:35:48 +0000298static struct sock *unix_find_socket_byinode(struct inode *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
300 struct sock *s;
301 struct hlist_node *node;
302
David S. Millerfbe9cc42005-12-13 23:26:29 -0800303 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 sk_for_each(s, node,
305 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
Al Viro40ffe672012-03-14 21:54:32 -0400306 struct dentry *dentry = unix_sk(s)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800308 if (dentry && dentry->d_inode == i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 sock_hold(s);
310 goto found;
311 }
312 }
313 s = NULL;
314found:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800315 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 return s;
317}
318
319static inline int unix_writable(struct sock *sk)
320{
321 return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
322}
323
324static void unix_write_space(struct sock *sk)
325{
Eric Dumazet43815482010-04-29 11:01:49 +0000326 struct socket_wq *wq;
327
328 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if (unix_writable(sk)) {
Eric Dumazet43815482010-04-29 11:01:49 +0000330 wq = rcu_dereference(sk->sk_wq);
331 if (wq_has_sleeper(wq))
Eric Dumazet67426b72010-10-29 20:44:44 +0000332 wake_up_interruptible_sync_poll(&wq->wait,
333 POLLOUT | POLLWRNORM | POLLWRBAND);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800334 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
Eric Dumazet43815482010-04-29 11:01:49 +0000336 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337}
338
339/* When dgram socket disconnects (or changes its peer), we clear its receive
340 * queue of packets arrived from previous peer. First, it allows to do
341 * flow control based only on wmem_alloc; second, sk connected to peer
342 * may receive messages only from that peer. */
343static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
344{
David S. Millerb03efcf2005-07-08 14:57:23 -0700345 if (!skb_queue_empty(&sk->sk_receive_queue)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 skb_queue_purge(&sk->sk_receive_queue);
347 wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
348
349 /* If one link of bidirectional dgram pipe is disconnected,
350 * we signal error. Messages are lost. Do not make this,
351 * when peer was not connected to us.
352 */
353 if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
354 other->sk_err = ECONNRESET;
355 other->sk_error_report(other);
356 }
357 }
358}
359
360static void unix_sock_destructor(struct sock *sk)
361{
362 struct unix_sock *u = unix_sk(sk);
363
364 skb_queue_purge(&sk->sk_receive_queue);
365
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700366 WARN_ON(atomic_read(&sk->sk_wmem_alloc));
367 WARN_ON(!sk_unhashed(sk));
368 WARN_ON(sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 if (!sock_flag(sk, SOCK_DEAD)) {
Eric Dumazet6b41e7d2008-11-19 15:48:09 -0800370 printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 return;
372 }
373
374 if (u->addr)
375 unix_release_addr(u->addr);
376
Eric Dumazet518de9b2010-10-26 14:22:44 -0700377 atomic_long_dec(&unix_nr_socks);
David S. Miller6f756a82008-11-23 17:34:03 -0800378 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800379 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
David S. Miller6f756a82008-11-23 17:34:03 -0800380 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381#ifdef UNIX_REFCNT_DEBUG
Eric Dumazet518de9b2010-10-26 14:22:44 -0700382 printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
383 atomic_long_read(&unix_nr_socks));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384#endif
385}
386
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800387static int unix_release_sock(struct sock *sk, int embrion)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388{
389 struct unix_sock *u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400390 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 struct sock *skpair;
392 struct sk_buff *skb;
393 int state;
394
395 unix_remove_socket(sk);
396
397 /* Clear state */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700398 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 sock_orphan(sk);
400 sk->sk_shutdown = SHUTDOWN_MASK;
Al Viro40ffe672012-03-14 21:54:32 -0400401 path = u->path;
402 u->path.dentry = NULL;
403 u->path.mnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 state = sk->sk_state;
405 sk->sk_state = TCP_CLOSE;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700406 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
408 wake_up_interruptible_all(&u->peer_wait);
409
Jianjun Konge27dfce2008-11-01 21:38:31 -0700410 skpair = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Jianjun Konge27dfce2008-11-01 21:38:31 -0700412 if (skpair != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
David S. Miller1c92b4e2007-05-31 13:24:26 -0700414 unix_state_lock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* No more writes */
416 skpair->sk_shutdown = SHUTDOWN_MASK;
417 if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
418 skpair->sk_err = ECONNRESET;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700419 unix_state_unlock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 skpair->sk_state_change(skpair);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800421 sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 }
423 sock_put(skpair); /* It may now die */
424 unix_peer(sk) = NULL;
425 }
426
427 /* Try to flush out this socket. Throw out buffers at least */
428
429 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
Jianjun Konge27dfce2008-11-01 21:38:31 -0700430 if (state == TCP_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 unix_release_sock(skb->sk, 1);
432 /* passed fds are erased in the kfree_skb hook */
433 kfree_skb(skb);
434 }
435
Al Viro40ffe672012-03-14 21:54:32 -0400436 if (path.dentry)
437 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 sock_put(sk);
440
441 /* ---- Socket is dead now and most probably destroyed ---- */
442
443 /*
444 * Fixme: BSD difference: In BSD all sockets connected to use get
445 * ECONNRESET and we die on the spot. In Linux we behave
446 * like files and pipes do and wait for the last
447 * dereference.
448 *
449 * Can't we simply set sock->err?
450 *
451 * What the above comment does talk about? --ANK(980817)
452 */
453
Pavel Emelyanov9305cfa2007-11-10 22:06:01 -0800454 if (unix_tot_inflight)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900455 unix_gc(); /* Garbage collect fds */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457 return 0;
458}
459
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000460static void init_peercred(struct sock *sk)
461{
462 put_pid(sk->sk_peer_pid);
463 if (sk->sk_peer_cred)
464 put_cred(sk->sk_peer_cred);
465 sk->sk_peer_pid = get_pid(task_tgid(current));
466 sk->sk_peer_cred = get_current_cred();
467}
468
469static void copy_peercred(struct sock *sk, struct sock *peersk)
470{
471 put_pid(sk->sk_peer_pid);
472 if (sk->sk_peer_cred)
473 put_cred(sk->sk_peer_cred);
474 sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
475 sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
476}
477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478static int unix_listen(struct socket *sock, int backlog)
479{
480 int err;
481 struct sock *sk = sock->sk;
482 struct unix_sock *u = unix_sk(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000483 struct pid *old_pid = NULL;
484 const struct cred *old_cred = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
486 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800487 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
488 goto out; /* Only stream/seqpacket sockets accept */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 err = -EINVAL;
490 if (!u->addr)
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800491 goto out; /* No listens on an unbound socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700492 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
494 goto out_unlock;
495 if (backlog > sk->sk_max_ack_backlog)
496 wake_up_interruptible_all(&u->peer_wait);
497 sk->sk_max_ack_backlog = backlog;
498 sk->sk_state = TCP_LISTEN;
499 /* set credentials so connect can copy them */
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000500 init_peercred(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 err = 0;
502
503out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -0700504 unix_state_unlock(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000505 put_pid(old_pid);
506 if (old_cred)
507 put_cred(old_cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508out:
509 return err;
510}
511
512static int unix_release(struct socket *);
513static int unix_bind(struct socket *, struct sockaddr *, int);
514static int unix_stream_connect(struct socket *, struct sockaddr *,
515 int addr_len, int flags);
516static int unix_socketpair(struct socket *, struct socket *);
517static int unix_accept(struct socket *, struct socket *, int);
518static int unix_getname(struct socket *, struct sockaddr *, int *, int);
519static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700520static unsigned int unix_dgram_poll(struct file *, struct socket *,
521 poll_table *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522static int unix_ioctl(struct socket *, unsigned int, unsigned long);
523static int unix_shutdown(struct socket *, int);
524static int unix_stream_sendmsg(struct kiocb *, struct socket *,
525 struct msghdr *, size_t);
526static int unix_stream_recvmsg(struct kiocb *, struct socket *,
527 struct msghdr *, size_t, int);
528static int unix_dgram_sendmsg(struct kiocb *, struct socket *,
529 struct msghdr *, size_t);
530static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
531 struct msghdr *, size_t, int);
532static int unix_dgram_connect(struct socket *, struct sockaddr *,
533 int, int);
534static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
535 struct msghdr *, size_t);
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000536static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
537 struct msghdr *, size_t, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000539static void unix_set_peek_off(struct sock *sk, int val)
540{
541 struct unix_sock *u = unix_sk(sk);
542
543 mutex_lock(&u->readlock);
544 sk->sk_peek_off = val;
545 mutex_unlock(&u->readlock);
546}
547
548
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800549static const struct proto_ops unix_stream_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 .family = PF_UNIX,
551 .owner = THIS_MODULE,
552 .release = unix_release,
553 .bind = unix_bind,
554 .connect = unix_stream_connect,
555 .socketpair = unix_socketpair,
556 .accept = unix_accept,
557 .getname = unix_getname,
558 .poll = unix_poll,
559 .ioctl = unix_ioctl,
560 .listen = unix_listen,
561 .shutdown = unix_shutdown,
562 .setsockopt = sock_no_setsockopt,
563 .getsockopt = sock_no_getsockopt,
564 .sendmsg = unix_stream_sendmsg,
565 .recvmsg = unix_stream_recvmsg,
566 .mmap = sock_no_mmap,
567 .sendpage = sock_no_sendpage,
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +0000568 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569};
570
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800571static const struct proto_ops unix_dgram_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 .family = PF_UNIX,
573 .owner = THIS_MODULE,
574 .release = unix_release,
575 .bind = unix_bind,
576 .connect = unix_dgram_connect,
577 .socketpair = unix_socketpair,
578 .accept = sock_no_accept,
579 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700580 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 .ioctl = unix_ioctl,
582 .listen = sock_no_listen,
583 .shutdown = unix_shutdown,
584 .setsockopt = sock_no_setsockopt,
585 .getsockopt = sock_no_getsockopt,
586 .sendmsg = unix_dgram_sendmsg,
587 .recvmsg = unix_dgram_recvmsg,
588 .mmap = sock_no_mmap,
589 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000590 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591};
592
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800593static const struct proto_ops unix_seqpacket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 .family = PF_UNIX,
595 .owner = THIS_MODULE,
596 .release = unix_release,
597 .bind = unix_bind,
598 .connect = unix_stream_connect,
599 .socketpair = unix_socketpair,
600 .accept = unix_accept,
601 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700602 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 .ioctl = unix_ioctl,
604 .listen = unix_listen,
605 .shutdown = unix_shutdown,
606 .setsockopt = sock_no_setsockopt,
607 .getsockopt = sock_no_getsockopt,
608 .sendmsg = unix_seqpacket_sendmsg,
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000609 .recvmsg = unix_seqpacket_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 .mmap = sock_no_mmap,
611 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000612 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613};
614
615static struct proto unix_proto = {
Eric Dumazet248969a2008-11-17 00:00:30 -0800616 .name = "UNIX",
617 .owner = THIS_MODULE,
Eric Dumazet248969a2008-11-17 00:00:30 -0800618 .obj_size = sizeof(struct unix_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619};
620
Ingo Molnara09785a2006-07-03 00:25:12 -0700621/*
622 * AF_UNIX sockets do not interact with hardware, hence they
623 * dont trigger interrupts - so it's safe for them to have
624 * bh-unsafe locking for their sk_receive_queue.lock. Split off
625 * this special lock-class by reinitializing the spinlock key:
626 */
627static struct lock_class_key af_unix_sk_receive_queue_lock_key;
628
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800629static struct sock *unix_create1(struct net *net, struct socket *sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 struct sock *sk = NULL;
632 struct unix_sock *u;
633
Eric Dumazet518de9b2010-10-26 14:22:44 -0700634 atomic_long_inc(&unix_nr_socks);
635 if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 goto out;
637
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700638 sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (!sk)
640 goto out;
641
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800642 sock_init_data(sock, sk);
Ingo Molnara09785a2006-07-03 00:25:12 -0700643 lockdep_set_class(&sk->sk_receive_queue.lock,
644 &af_unix_sk_receive_queue_lock_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646 sk->sk_write_space = unix_write_space;
Denis V. Luneva0a53c82007-12-11 04:19:17 -0800647 sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 sk->sk_destruct = unix_sock_destructor;
649 u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400650 u->path.dentry = NULL;
651 u->path.mnt = NULL;
Benjamin LaHaisefd19f322006-01-03 14:10:46 -0800652 spin_lock_init(&u->lock);
Al Viro516e0cc2008-07-26 00:39:17 -0400653 atomic_long_set(&u->inflight, 0);
Miklos Szeredi1fd05ba2007-07-11 14:22:39 -0700654 INIT_LIST_HEAD(&u->link);
Ingo Molnar57b47a52006-03-20 22:35:41 -0800655 mutex_init(&u->readlock); /* single task reading lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 init_waitqueue_head(&u->peer_wait);
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000657 unix_insert_socket(unix_sockets_unbound(sk), sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658out:
Pavel Emelyanov284b3272007-11-10 22:08:30 -0800659 if (sk == NULL)
Eric Dumazet518de9b2010-10-26 14:22:44 -0700660 atomic_long_dec(&unix_nr_socks);
Eric Dumazet920de802008-11-24 00:09:29 -0800661 else {
662 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800663 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
Eric Dumazet920de802008-11-24 00:09:29 -0800664 local_bh_enable();
665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 return sk;
667}
668
Eric Paris3f378b62009-11-05 22:18:14 -0800669static int unix_create(struct net *net, struct socket *sock, int protocol,
670 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
672 if (protocol && protocol != PF_UNIX)
673 return -EPROTONOSUPPORT;
674
675 sock->state = SS_UNCONNECTED;
676
677 switch (sock->type) {
678 case SOCK_STREAM:
679 sock->ops = &unix_stream_ops;
680 break;
681 /*
682 * Believe it or not BSD has AF_UNIX, SOCK_RAW though
683 * nothing uses it.
684 */
685 case SOCK_RAW:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700686 sock->type = SOCK_DGRAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 case SOCK_DGRAM:
688 sock->ops = &unix_dgram_ops;
689 break;
690 case SOCK_SEQPACKET:
691 sock->ops = &unix_seqpacket_ops;
692 break;
693 default:
694 return -ESOCKTNOSUPPORT;
695 }
696
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700697 return unix_create1(net, sock) ? 0 : -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700static int unix_release(struct socket *sock)
701{
702 struct sock *sk = sock->sk;
703
704 if (!sk)
705 return 0;
706
707 sock->sk = NULL;
708
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800709 return unix_release_sock(sk, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
712static int unix_autobind(struct socket *sock)
713{
714 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900715 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 struct unix_sock *u = unix_sk(sk);
717 static u32 ordernum = 1;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800718 struct unix_address *addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 int err;
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000720 unsigned int retries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Ingo Molnar57b47a52006-03-20 22:35:41 -0800722 mutex_lock(&u->readlock);
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
826
827static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
828{
829 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900830 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700832 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400833 char *sun_path = sunaddr->sun_path;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800834 struct dentry *dentry = NULL;
Al Virodae6ad82011-06-26 11:50:15 -0400835 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000837 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 struct unix_address *addr;
839 struct hlist_head *list;
840
841 err = -EINVAL;
842 if (sunaddr->sun_family != AF_UNIX)
843 goto out;
844
Jianjun Konge27dfce2008-11-01 21:38:31 -0700845 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 err = unix_autobind(sock);
847 goto out;
848 }
849
850 err = unix_mkname(sunaddr, addr_len, &hash);
851 if (err < 0)
852 goto out;
853 addr_len = err;
854
Ingo Molnar57b47a52006-03-20 22:35:41 -0800855 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
857 err = -EINVAL;
858 if (u->addr)
859 goto out_up;
860
861 err = -ENOMEM;
862 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
863 if (!addr)
864 goto out_up;
865
866 memcpy(addr->name, sunaddr, addr_len);
867 addr->len = addr_len;
868 addr->hash = hash ^ sk->sk_type;
869 atomic_set(&addr->refcnt, 1);
870
Al Virodae6ad82011-06-26 11:50:15 -0400871 if (sun_path[0]) {
Al Viro04fc66e2011-11-21 14:58:38 -0500872 umode_t mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 err = 0;
874 /*
875 * Get the parent directory, calculate the hash for last
876 * component.
877 */
Al Virodae6ad82011-06-26 11:50:15 -0400878 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 err = PTR_ERR(dentry);
880 if (IS_ERR(dentry))
Al Virodae6ad82011-06-26 11:50:15 -0400881 goto out_mknod_parent;
Christoph Hellwigf81a0bf2005-05-19 12:26:43 -0700882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 /*
884 * All right, let's create it.
885 */
886 mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400887 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virodae6ad82011-06-26 11:50:15 -0400888 err = mnt_want_write(path.mnt);
Dave Hansen463c3192008-02-15 14:37:57 -0800889 if (err)
890 goto out_mknod_dput;
Al Virodae6ad82011-06-26 11:50:15 -0400891 err = security_path_mknod(&path, dentry, mode, 0);
Kentaro Takedabe6d3e52008-12-17 13:24:15 +0900892 if (err)
893 goto out_mknod_drop_write;
Al Virodae6ad82011-06-26 11:50:15 -0400894 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
Kentaro Takedabe6d3e52008-12-17 13:24:15 +0900895out_mknod_drop_write:
Al Virodae6ad82011-06-26 11:50:15 -0400896 mnt_drop_write(path.mnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 if (err)
898 goto out_mknod_dput;
Al Virodae6ad82011-06-26 11:50:15 -0400899 mutex_unlock(&path.dentry->d_inode->i_mutex);
900 dput(path.dentry);
901 path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
903 addr->hash = UNIX_HASH_SIZE;
904 }
905
David S. Millerfbe9cc42005-12-13 23:26:29 -0800906 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
Al Virodae6ad82011-06-26 11:50:15 -0400908 if (!sun_path[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800910 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 sk->sk_type, hash)) {
912 unix_release_addr(addr);
913 goto out_unlock;
914 }
915
916 list = &unix_socket_table[addr->hash];
917 } else {
918 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
Al Viro40ffe672012-03-14 21:54:32 -0400919 u->path = path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921
922 err = 0;
923 __unix_remove_socket(sk);
924 u->addr = addr;
925 __unix_insert_socket(list, sk);
926
927out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800928 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800930 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931out:
932 return err;
933
934out_mknod_dput:
935 dput(dentry);
Al Virodae6ad82011-06-26 11:50:15 -0400936 mutex_unlock(&path.dentry->d_inode->i_mutex);
937 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938out_mknod_parent:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700939 if (err == -EEXIST)
940 err = -EADDRINUSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 unix_release_addr(addr);
942 goto out_up;
943}
944
David S. Miller278a3de2007-05-31 15:19:20 -0700945static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
946{
947 if (unlikely(sk1 == sk2) || !sk2) {
948 unix_state_lock(sk1);
949 return;
950 }
951 if (sk1 < sk2) {
952 unix_state_lock(sk1);
953 unix_state_lock_nested(sk2);
954 } else {
955 unix_state_lock(sk2);
956 unix_state_lock_nested(sk1);
957 }
958}
959
960static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
961{
962 if (unlikely(sk1 == sk2) || !sk2) {
963 unix_state_unlock(sk1);
964 return;
965 }
966 unix_state_unlock(sk1);
967 unix_state_unlock(sk2);
968}
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
971 int alen, int flags)
972{
973 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900974 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700975 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000977 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 int err;
979
980 if (addr->sa_family != AF_UNSPEC) {
981 err = unix_mkname(sunaddr, alen, &hash);
982 if (err < 0)
983 goto out;
984 alen = err;
985
986 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
987 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
988 goto out;
989
David S. Miller278a3de2007-05-31 15:19:20 -0700990restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700991 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if (!other)
993 goto out;
994
David S. Miller278a3de2007-05-31 15:19:20 -0700995 unix_state_double_lock(sk, other);
996
997 /* Apparently VFS overslept socket death. Retry. */
998 if (sock_flag(other, SOCK_DEAD)) {
999 unix_state_double_unlock(sk, other);
1000 sock_put(other);
1001 goto restart;
1002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004 err = -EPERM;
1005 if (!unix_may_send(sk, other))
1006 goto out_unlock;
1007
1008 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1009 if (err)
1010 goto out_unlock;
1011
1012 } else {
1013 /*
1014 * 1003.1g breaking connected state with AF_UNSPEC
1015 */
1016 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001017 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 }
1019
1020 /*
1021 * If it was connected, reconnect.
1022 */
1023 if (unix_peer(sk)) {
1024 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001025 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001026 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
1028 if (other != old_peer)
1029 unix_dgram_disconnected(sk, old_peer);
1030 sock_put(old_peer);
1031 } else {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001032 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001033 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001035 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001038 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 sock_put(other);
1040out:
1041 return err;
1042}
1043
1044static long unix_wait_for_peer(struct sock *other, long timeo)
1045{
1046 struct unix_sock *u = unix_sk(other);
1047 int sched;
1048 DEFINE_WAIT(wait);
1049
1050 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1051
1052 sched = !sock_flag(other, SOCK_DEAD) &&
1053 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001054 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
David S. Miller1c92b4e2007-05-31 13:24:26 -07001056 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 if (sched)
1059 timeo = schedule_timeout(timeo);
1060
1061 finish_wait(&u->peer_wait, &wait);
1062 return timeo;
1063}
1064
1065static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1066 int addr_len, int flags)
1067{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001068 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001070 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1072 struct sock *newsk = NULL;
1073 struct sock *other = NULL;
1074 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001075 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 int st;
1077 int err;
1078 long timeo;
1079
1080 err = unix_mkname(sunaddr, addr_len, &hash);
1081 if (err < 0)
1082 goto out;
1083 addr_len = err;
1084
Joe Perchesf64f9e72009-11-29 16:55:45 -08001085 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1086 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 goto out;
1088
1089 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1090
1091 /* First of all allocate resources.
1092 If we will make it after state is locked,
1093 we will have to recheck all again in any case.
1094 */
1095
1096 err = -ENOMEM;
1097
1098 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001099 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 if (newsk == NULL)
1101 goto out;
1102
1103 /* Allocate skb for sending to listening sock */
1104 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1105 if (skb == NULL)
1106 goto out;
1107
1108restart:
1109 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001110 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 if (!other)
1112 goto out;
1113
1114 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001115 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
1117 /* Apparently VFS overslept socket death. Retry. */
1118 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001119 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 sock_put(other);
1121 goto restart;
1122 }
1123
1124 err = -ECONNREFUSED;
1125 if (other->sk_state != TCP_LISTEN)
1126 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001127 if (other->sk_shutdown & RCV_SHUTDOWN)
1128 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
Rainer Weikusat3c734192008-06-17 22:28:05 -07001130 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 err = -EAGAIN;
1132 if (!timeo)
1133 goto out_unlock;
1134
1135 timeo = unix_wait_for_peer(other, timeo);
1136
1137 err = sock_intr_errno(timeo);
1138 if (signal_pending(current))
1139 goto out;
1140 sock_put(other);
1141 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
1144 /* Latch our state.
1145
Daniel Balutae5537bf2011-03-14 15:25:33 -07001146 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 drop lock on peer. It is dangerous because deadlock is
1148 possible. Connect to self case and simultaneous
1149 attempt to connect are eliminated by checking socket
1150 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1151 check this before attempt to grab lock.
1152
1153 Well, and we have to recheck the state after socket locked.
1154 */
1155 st = sk->sk_state;
1156
1157 switch (st) {
1158 case TCP_CLOSE:
1159 /* This is ok... continue with connect */
1160 break;
1161 case TCP_ESTABLISHED:
1162 /* Socket is already connected */
1163 err = -EISCONN;
1164 goto out_unlock;
1165 default:
1166 err = -EINVAL;
1167 goto out_unlock;
1168 }
1169
David S. Miller1c92b4e2007-05-31 13:24:26 -07001170 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001173 unix_state_unlock(sk);
1174 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 sock_put(other);
1176 goto restart;
1177 }
1178
David S. Miller3610cda2011-01-05 15:38:53 -08001179 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001181 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 goto out_unlock;
1183 }
1184
1185 /* The way is open! Fastly set all the necessary fields... */
1186
1187 sock_hold(sk);
1188 unix_peer(newsk) = sk;
1189 newsk->sk_state = TCP_ESTABLISHED;
1190 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001191 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001193 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 otheru = unix_sk(other);
1195
1196 /* copy address information from listening to new sock*/
1197 if (otheru->addr) {
1198 atomic_inc(&otheru->addr->refcnt);
1199 newu->addr = otheru->addr;
1200 }
Al Viro40ffe672012-03-14 21:54:32 -04001201 if (otheru->path.dentry) {
1202 path_get(&otheru->path);
1203 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 }
1205
1206 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001207 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 sock->state = SS_CONNECTED;
1210 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001211 sock_hold(newsk);
1212
1213 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1214 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
David S. Miller1c92b4e2007-05-31 13:24:26 -07001216 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 /* take ten and and send info to listening sock */
1219 spin_lock(&other->sk_receive_queue.lock);
1220 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001222 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 other->sk_data_ready(other, 0);
1224 sock_put(other);
1225 return 0;
1226
1227out_unlock:
1228 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001229 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001232 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 if (newsk)
1234 unix_release_sock(newsk, 0);
1235 if (other)
1236 sock_put(other);
1237 return err;
1238}
1239
1240static int unix_socketpair(struct socket *socka, struct socket *sockb)
1241{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001242 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
1244 /* Join our sockets back to back */
1245 sock_hold(ska);
1246 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001247 unix_peer(ska) = skb;
1248 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001249 init_peercred(ska);
1250 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252 if (ska->sk_type != SOCK_DGRAM) {
1253 ska->sk_state = TCP_ESTABLISHED;
1254 skb->sk_state = TCP_ESTABLISHED;
1255 socka->state = SS_CONNECTED;
1256 sockb->state = SS_CONNECTED;
1257 }
1258 return 0;
1259}
1260
1261static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1262{
1263 struct sock *sk = sock->sk;
1264 struct sock *tsk;
1265 struct sk_buff *skb;
1266 int err;
1267
1268 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001269 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 goto out;
1271
1272 err = -EINVAL;
1273 if (sk->sk_state != TCP_LISTEN)
1274 goto out;
1275
1276 /* If socket state is TCP_LISTEN it cannot change (for now...),
1277 * so that no locks are necessary.
1278 */
1279
1280 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1281 if (!skb) {
1282 /* This means receive shutdown. */
1283 if (err == 0)
1284 err = -EINVAL;
1285 goto out;
1286 }
1287
1288 tsk = skb->sk;
1289 skb_free_datagram(sk, skb);
1290 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1291
1292 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001293 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 newsock->state = SS_CONNECTED;
1295 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001296 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return 0;
1298
1299out:
1300 return err;
1301}
1302
1303
1304static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1305{
1306 struct sock *sk = sock->sk;
1307 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001308 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 int err = 0;
1310
1311 if (peer) {
1312 sk = unix_peer_get(sk);
1313
1314 err = -ENOTCONN;
1315 if (!sk)
1316 goto out;
1317 err = 0;
1318 } else {
1319 sock_hold(sk);
1320 }
1321
1322 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001323 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (!u->addr) {
1325 sunaddr->sun_family = AF_UNIX;
1326 sunaddr->sun_path[0] = 0;
1327 *uaddr_len = sizeof(short);
1328 } else {
1329 struct unix_address *addr = u->addr;
1330
1331 *uaddr_len = addr->len;
1332 memcpy(sunaddr, addr->name, *uaddr_len);
1333 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001334 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 sock_put(sk);
1336out:
1337 return err;
1338}
1339
1340static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1341{
1342 int i;
1343
1344 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 UNIXCB(skb).fp = NULL;
1346
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001347 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 unix_notinflight(scm->fp->fp[i]);
1349}
1350
Eric W. Biederman7361c362010-06-13 03:34:33 +00001351static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
1353 struct scm_cookie scm;
1354 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001355 scm.pid = UNIXCB(skb).pid;
1356 scm.cred = UNIXCB(skb).cred;
1357 if (UNIXCB(skb).fp)
1358 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 /* Alas, it calls VFS */
1361 /* So fscking what? fput() had been SMP-safe since the last Summer */
1362 scm_destroy(&scm);
1363 sock_wfree(skb);
1364}
1365
Eric Dumazet25888e32010-11-25 04:11:39 +00001366#define MAX_RECURSION_LEVEL 4
1367
Miklos Szeredi62093442008-11-09 15:23:57 +01001368static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001371 unsigned char max_level = 0;
1372 int unix_sock_count = 0;
1373
1374 for (i = scm->fp->count - 1; i >= 0; i--) {
1375 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1376
1377 if (sk) {
1378 unix_sock_count++;
1379 max_level = max(max_level,
1380 unix_sk(sk)->recursion_level);
1381 }
1382 }
1383 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1384 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001385
1386 /*
1387 * Need to duplicate file references for the sake of garbage
1388 * collection. Otherwise a socket in the fps might become a
1389 * candidate for GC while the skb is not yet queued.
1390 */
1391 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1392 if (!UNIXCB(skb).fp)
1393 return -ENOMEM;
1394
Eric Dumazet25888e32010-11-25 04:11:39 +00001395 if (unix_sock_count) {
1396 for (i = scm->fp->count - 1; i >= 0; i--)
1397 unix_inflight(scm->fp->fp[i]);
1398 }
1399 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400}
1401
David S. Millerf78a5fd2011-09-16 19:34:00 -04001402static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001403{
1404 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001405
David S. Millerf78a5fd2011-09-16 19:34:00 -04001406 UNIXCB(skb).pid = get_pid(scm->pid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001407 if (scm->cred)
1408 UNIXCB(skb).cred = get_cred(scm->cred);
Eric W. Biederman7361c362010-06-13 03:34:33 +00001409 UNIXCB(skb).fp = NULL;
1410 if (scm->fp && send_fds)
1411 err = unix_attach_fds(scm, skb);
1412
1413 skb->destructor = unix_destruct_scm;
1414 return err;
1415}
1416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001418 * Some apps rely on write() giving SCM_CREDENTIALS
1419 * We include credentials if source or destination socket
1420 * asserted SOCK_PASSCRED.
1421 */
1422static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1423 const struct sock *other)
1424{
1425 if (UNIXCB(skb).cred)
1426 return;
1427 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
1428 !other->sk_socket ||
1429 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
1430 UNIXCB(skb).pid = get_pid(task_tgid(current));
1431 UNIXCB(skb).cred = get_current_cred();
1432 }
1433}
1434
1435/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 * Send AF_UNIX data.
1437 */
1438
1439static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1440 struct msghdr *msg, size_t len)
1441{
1442 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1443 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001444 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001446 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 struct sock *other = NULL;
1448 int namelen = 0; /* fake GCC */
1449 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001450 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001451 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 long timeo;
1453 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001454 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001455 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 if (NULL == siocb->scm)
1458 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001459 wait_for_unix_gc();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 err = scm_send(sock, msg, siocb->scm);
1461 if (err < 0)
1462 return err;
1463
1464 err = -EOPNOTSUPP;
1465 if (msg->msg_flags&MSG_OOB)
1466 goto out;
1467
1468 if (msg->msg_namelen) {
1469 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1470 if (err < 0)
1471 goto out;
1472 namelen = err;
1473 } else {
1474 sunaddr = NULL;
1475 err = -ENOTCONN;
1476 other = unix_peer_get(sk);
1477 if (!other)
1478 goto out;
1479 }
1480
Joe Perchesf64f9e72009-11-29 16:55:45 -08001481 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1482 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 goto out;
1484
1485 err = -EMSGSIZE;
1486 if (len > sk->sk_sndbuf - 32)
1487 goto out;
1488
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001489 if (len > SKB_MAX_ALLOC)
1490 data_len = min_t(size_t,
1491 len - SKB_MAX_ALLOC,
1492 MAX_SKB_FRAGS * PAGE_SIZE);
1493
1494 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1495 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001496 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 goto out;
1498
David S. Millerf78a5fd2011-09-16 19:34:00 -04001499 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001500 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001501 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001502 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001503 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001504
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001505 skb_put(skb, len - data_len);
1506 skb->data_len = data_len;
1507 skb->len = len;
1508 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 if (err)
1510 goto out_free;
1511
1512 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1513
1514restart:
1515 if (!other) {
1516 err = -ECONNRESET;
1517 if (sunaddr == NULL)
1518 goto out_free;
1519
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001520 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001522 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 goto out_free;
1524 }
1525
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001526 if (sk_filter(other, skb) < 0) {
1527 /* Toss the packet but do not return any error to the sender */
1528 err = len;
1529 goto out_free;
1530 }
1531
David S. Miller1c92b4e2007-05-31 13:24:26 -07001532 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 err = -EPERM;
1534 if (!unix_may_send(sk, other))
1535 goto out_unlock;
1536
1537 if (sock_flag(other, SOCK_DEAD)) {
1538 /*
1539 * Check with 1003.1g - what should
1540 * datagram error
1541 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001542 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 sock_put(other);
1544
1545 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001546 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001548 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001549 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
1551 unix_dgram_disconnected(sk, other);
1552 sock_put(other);
1553 err = -ECONNREFUSED;
1554 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001555 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 }
1557
1558 other = NULL;
1559 if (err)
1560 goto out_free;
1561 goto restart;
1562 }
1563
1564 err = -EPIPE;
1565 if (other->sk_shutdown & RCV_SHUTDOWN)
1566 goto out_unlock;
1567
1568 if (sk->sk_type != SOCK_SEQPACKET) {
1569 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1570 if (err)
1571 goto out_unlock;
1572 }
1573
Rainer Weikusat3c734192008-06-17 22:28:05 -07001574 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 if (!timeo) {
1576 err = -EAGAIN;
1577 goto out_unlock;
1578 }
1579
1580 timeo = unix_wait_for_peer(other, timeo);
1581
1582 err = sock_intr_errno(timeo);
1583 if (signal_pending(current))
1584 goto out_free;
1585
1586 goto restart;
1587 }
1588
Alban Crequy3f661162010-10-04 08:48:28 +00001589 if (sock_flag(other, SOCK_RCVTSTAMP))
1590 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001591 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001593 if (max_level > unix_sk(other)->recursion_level)
1594 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001595 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 other->sk_data_ready(other, len);
1597 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001598 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 return len;
1600
1601out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001602 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603out_free:
1604 kfree_skb(skb);
1605out:
1606 if (other)
1607 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001608 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 return err;
1610}
1611
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1614 struct msghdr *msg, size_t len)
1615{
1616 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1617 struct sock *sk = sock->sk;
1618 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001619 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001620 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001621 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001623 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001624 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
1626 if (NULL == siocb->scm)
1627 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001628 wait_for_unix_gc();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 err = scm_send(sock, msg, siocb->scm);
1630 if (err < 0)
1631 return err;
1632
1633 err = -EOPNOTSUPP;
1634 if (msg->msg_flags&MSG_OOB)
1635 goto out_err;
1636
1637 if (msg->msg_namelen) {
1638 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1639 goto out_err;
1640 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001642 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 if (!other)
1644 goto out_err;
1645 }
1646
1647 if (sk->sk_shutdown & SEND_SHUTDOWN)
1648 goto pipe_err;
1649
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001650 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 /*
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001652 * Optimisation for the fact that under 0.01% of X
1653 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 */
1655
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001656 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001659 if (size > ((sk->sk_sndbuf >> 1) - 64))
1660 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 if (size > SKB_MAX_ALLOC)
1663 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001664
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 /*
1666 * Grab a buffer
1667 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001668
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001669 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1670 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
Jianjun Konge27dfce2008-11-01 21:38:31 -07001672 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 goto out_err;
1674
1675 /*
1676 * If you pass two values to the sock_alloc_send_skb
1677 * it tries to grab the large buffer with GFP_NOFS
1678 * (which can fail easily), and if it fails grab the
1679 * fallback size buffer which is under a page and will
1680 * succeed. [Alan]
1681 */
1682 size = min_t(int, size, skb_tailroom(skb));
1683
Eric W. Biederman7361c362010-06-13 03:34:33 +00001684
David S. Millerf78a5fd2011-09-16 19:34:00 -04001685 /* Only send the fds in the first buffer */
1686 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001687 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001688 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001689 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001690 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001691 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001692 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001694 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1695 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001697 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 }
1699
David S. Miller1c92b4e2007-05-31 13:24:26 -07001700 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 if (sock_flag(other, SOCK_DEAD) ||
1703 (other->sk_shutdown & RCV_SHUTDOWN))
1704 goto pipe_err_free;
1705
Eric Dumazet16e57262011-09-19 05:52:27 +00001706 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001708 if (max_level > unix_sk(other)->recursion_level)
1709 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001710 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001712 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
David S. Millerf78a5fd2011-09-16 19:34:00 -04001715 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 siocb->scm = NULL;
1717
1718 return sent;
1719
1720pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001721 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 kfree_skb(skb);
1723pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001724 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1725 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 err = -EPIPE;
1727out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001728 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 siocb->scm = NULL;
1730 return sent ? : err;
1731}
1732
1733static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1734 struct msghdr *msg, size_t len)
1735{
1736 int err;
1737 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 err = sock_error(sk);
1740 if (err)
1741 return err;
1742
1743 if (sk->sk_state != TCP_ESTABLISHED)
1744 return -ENOTCONN;
1745
1746 if (msg->msg_namelen)
1747 msg->msg_namelen = 0;
1748
1749 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1750}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001751
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001752static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1753 struct msghdr *msg, size_t size,
1754 int flags)
1755{
1756 struct sock *sk = sock->sk;
1757
1758 if (sk->sk_state != TCP_ESTABLISHED)
1759 return -ENOTCONN;
1760
1761 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1762}
1763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1765{
1766 struct unix_sock *u = unix_sk(sk);
1767
1768 msg->msg_namelen = 0;
1769 if (u->addr) {
1770 msg->msg_namelen = u->addr->len;
1771 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1772 }
1773}
1774
1775static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1776 struct msghdr *msg, size_t size,
1777 int flags)
1778{
1779 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1780 struct scm_cookie tmp_scm;
1781 struct sock *sk = sock->sk;
1782 struct unix_sock *u = unix_sk(sk);
1783 int noblock = flags & MSG_DONTWAIT;
1784 struct sk_buff *skb;
1785 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001786 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
1788 err = -EOPNOTSUPP;
1789 if (flags&MSG_OOB)
1790 goto out;
1791
1792 msg->msg_namelen = 0;
1793
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001794 err = mutex_lock_interruptible(&u->readlock);
1795 if (err) {
1796 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1797 goto out;
1798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001800 skip = sk_peek_offset(sk, flags);
1801
1802 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001803 if (!skb) {
1804 unix_state_lock(sk);
1805 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1806 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1807 (sk->sk_shutdown & RCV_SHUTDOWN))
1808 err = 0;
1809 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Eric Dumazet67426b72010-10-29 20:44:44 +00001813 wake_up_interruptible_sync_poll(&u->peer_wait,
1814 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816 if (msg->msg_name)
1817 unix_copy_addr(msg, skb->sk);
1818
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001819 if (size > skb->len - skip)
1820 size = skb->len - skip;
1821 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 msg->msg_flags |= MSG_TRUNC;
1823
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001824 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 if (err)
1826 goto out_free;
1827
Alban Crequy3f661162010-10-04 08:48:28 +00001828 if (sock_flag(sk, SOCK_RCVTSTAMP))
1829 __sock_recv_timestamp(msg, sk, skb);
1830
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 if (!siocb->scm) {
1832 siocb->scm = &tmp_scm;
1833 memset(&tmp_scm, 0, sizeof(tmp_scm));
1834 }
David S. Millerf78a5fd2011-09-16 19:34:00 -04001835 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001836 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001838 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 if (UNIXCB(skb).fp)
1840 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001841
1842 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001843 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 /* It is questionable: on PEEK we could:
1845 - do not return fds - good, but too simple 8)
1846 - return fds, and do not return them on read (old strategy,
1847 apparently wrong)
1848 - clone fds (I chose it for now, it is the most universal
1849 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001850
1851 POSIX 1003.1g does not actually define this clearly
1852 at all. POSIX 1003.1g doesn't define a lot of things
1853 clearly however!
1854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001856
1857 sk_peek_offset_fwd(sk, size);
1858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 if (UNIXCB(skb).fp)
1860 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1861 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001862 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 scm_recv(sock, msg, siocb->scm, flags);
1865
1866out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001867 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001869 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870out:
1871 return err;
1872}
1873
1874/*
1875 * Sleep until data has arrive. But check for races..
1876 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001877
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001878static long unix_stream_data_wait(struct sock *sk, long timeo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879{
1880 DEFINE_WAIT(wait);
1881
David S. Miller1c92b4e2007-05-31 13:24:26 -07001882 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
1884 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001885 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886
David S. Millerb03efcf2005-07-08 14:57:23 -07001887 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 sk->sk_err ||
1889 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1890 signal_pending(current) ||
1891 !timeo)
1892 break;
1893
1894 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001895 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 timeo = schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001897 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1899 }
1900
Eric Dumazetaa395142010-04-20 13:03:51 +00001901 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001902 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 return timeo;
1904}
1905
1906
1907
1908static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1909 struct msghdr *msg, size_t size,
1910 int flags)
1911{
1912 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1913 struct scm_cookie tmp_scm;
1914 struct sock *sk = sock->sk;
1915 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001916 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 int copied = 0;
1918 int check_creds = 0;
1919 int target;
1920 int err = 0;
1921 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001922 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923
1924 err = -EINVAL;
1925 if (sk->sk_state != TCP_ESTABLISHED)
1926 goto out;
1927
1928 err = -EOPNOTSUPP;
1929 if (flags&MSG_OOB)
1930 goto out;
1931
1932 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1933 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1934
1935 msg->msg_namelen = 0;
1936
1937 /* Lock the socket to prevent queue disordering
1938 * while sleeps in memcpy_tomsg
1939 */
1940
1941 if (!siocb->scm) {
1942 siocb->scm = &tmp_scm;
1943 memset(&tmp_scm, 0, sizeof(tmp_scm));
1944 }
1945
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001946 err = mutex_lock_interruptible(&u->readlock);
1947 if (err) {
1948 err = sock_intr_errno(timeo);
1949 goto out;
1950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001952 skip = sk_peek_offset(sk, flags);
1953
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001954 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 int chunk;
1956 struct sk_buff *skb;
1957
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001958 unix_state_lock(sk);
Eric Dumazet6f01fd62012-01-28 16:11:03 +00001959 skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001960again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001961 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001962 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001964 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
1966 /*
1967 * POSIX 1003.1g mandates this order.
1968 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001969
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001970 err = sock_error(sk);
1971 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001972 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001974 goto unlock;
1975
1976 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 err = -EAGAIN;
1978 if (!timeo)
1979 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001980 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
1982 timeo = unix_stream_data_wait(sk, timeo);
1983
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001984 if (signal_pending(current)
1985 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 err = sock_intr_errno(timeo);
1987 goto out;
1988 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001989
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001991 unlock:
1992 unix_state_unlock(sk);
1993 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001995
1996 if (skip >= skb->len) {
1997 skip -= skb->len;
1998 skb = skb_peek_next(skb, &sk->sk_receive_queue);
1999 goto again;
2000 }
2001
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07002002 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
2004 if (check_creds) {
2005 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00002006 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002007 (UNIXCB(skb).cred != siocb->scm->cred))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 } else {
2010 /* Copy credentials */
David S. Millerf78a5fd2011-09-16 19:34:00 -04002011 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 check_creds = 1;
2013 }
2014
2015 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002016 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 unix_copy_addr(msg, skb->sk);
2018 sunaddr = NULL;
2019 }
2020
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002021 chunk = min_t(unsigned int, skb->len - skip, size);
2022 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (copied == 0)
2024 copied = -EFAULT;
2025 break;
2026 }
2027 copied += chunk;
2028 size -= chunk;
2029
2030 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002031 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 skb_pull(skb, chunk);
2033
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002034 sk_peek_offset_bwd(sk, chunk);
2035
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 if (UNIXCB(skb).fp)
2037 unix_detach_fds(siocb->scm, skb);
2038
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002039 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002042 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002043 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
2045 if (siocb->scm->fp)
2046 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002047 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 /* It is questionable, see note in unix_dgram_recvmsg.
2049 */
2050 if (UNIXCB(skb).fp)
2051 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2052
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002053 sk_peek_offset_fwd(sk, chunk);
2054
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 break;
2056 }
2057 } while (size);
2058
Ingo Molnar57b47a52006-03-20 22:35:41 -08002059 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 scm_recv(sock, msg, siocb->scm, flags);
2061out:
2062 return copied ? : err;
2063}
2064
2065static int unix_shutdown(struct socket *sock, int mode)
2066{
2067 struct sock *sk = sock->sk;
2068 struct sock *other;
2069
2070 mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
2071
Alban Crequy7180a032011-01-19 04:56:36 +00002072 if (!mode)
2073 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Alban Crequy7180a032011-01-19 04:56:36 +00002075 unix_state_lock(sk);
2076 sk->sk_shutdown |= mode;
2077 other = unix_peer(sk);
2078 if (other)
2079 sock_hold(other);
2080 unix_state_unlock(sk);
2081 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Alban Crequy7180a032011-01-19 04:56:36 +00002083 if (other &&
2084 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Alban Crequy7180a032011-01-19 04:56:36 +00002086 int peer_mode = 0;
2087
2088 if (mode&RCV_SHUTDOWN)
2089 peer_mode |= SEND_SHUTDOWN;
2090 if (mode&SEND_SHUTDOWN)
2091 peer_mode |= RCV_SHUTDOWN;
2092 unix_state_lock(other);
2093 other->sk_shutdown |= peer_mode;
2094 unix_state_unlock(other);
2095 other->sk_state_change(other);
2096 if (peer_mode == SHUTDOWN_MASK)
2097 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2098 else if (peer_mode & RCV_SHUTDOWN)
2099 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 }
Alban Crequy7180a032011-01-19 04:56:36 +00002101 if (other)
2102 sock_put(other);
2103
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 return 0;
2105}
2106
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002107long unix_inq_len(struct sock *sk)
2108{
2109 struct sk_buff *skb;
2110 long amount = 0;
2111
2112 if (sk->sk_state == TCP_LISTEN)
2113 return -EINVAL;
2114
2115 spin_lock(&sk->sk_receive_queue.lock);
2116 if (sk->sk_type == SOCK_STREAM ||
2117 sk->sk_type == SOCK_SEQPACKET) {
2118 skb_queue_walk(&sk->sk_receive_queue, skb)
2119 amount += skb->len;
2120 } else {
2121 skb = skb_peek(&sk->sk_receive_queue);
2122 if (skb)
2123 amount = skb->len;
2124 }
2125 spin_unlock(&sk->sk_receive_queue.lock);
2126
2127 return amount;
2128}
2129EXPORT_SYMBOL_GPL(unix_inq_len);
2130
2131long unix_outq_len(struct sock *sk)
2132{
2133 return sk_wmem_alloc_get(sk);
2134}
2135EXPORT_SYMBOL_GPL(unix_outq_len);
2136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2138{
2139 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002140 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 int err;
2142
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002143 switch (cmd) {
2144 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002145 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002146 err = put_user(amount, (int __user *)arg);
2147 break;
2148 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002149 amount = unix_inq_len(sk);
2150 if (amount < 0)
2151 err = amount;
2152 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002154 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002155 default:
2156 err = -ENOIOCTLCMD;
2157 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159 return err;
2160}
2161
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002162static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
2164 struct sock *sk = sock->sk;
2165 unsigned int mask;
2166
Eric Dumazetaa395142010-04-20 13:03:51 +00002167 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 mask = 0;
2169
2170 /* exceptional events? */
2171 if (sk->sk_err)
2172 mask |= POLLERR;
2173 if (sk->sk_shutdown == SHUTDOWN_MASK)
2174 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002175 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002176 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
2178 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002179 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 mask |= POLLIN | POLLRDNORM;
2181
2182 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002183 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2184 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 mask |= POLLHUP;
2186
2187 /*
2188 * we set writable also when the other side has shut down the
2189 * connection. This prevents stuck sockets.
2190 */
2191 if (unix_writable(sk))
2192 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2193
2194 return mask;
2195}
2196
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002197static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2198 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002199{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002200 struct sock *sk = sock->sk, *other;
2201 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002202
Eric Dumazetaa395142010-04-20 13:03:51 +00002203 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002204 mask = 0;
2205
2206 /* exceptional events? */
2207 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
2208 mask |= POLLERR;
2209 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazet5456f092010-10-31 05:36:23 +00002210 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002211 if (sk->sk_shutdown == SHUTDOWN_MASK)
2212 mask |= POLLHUP;
2213
2214 /* readable? */
Eric Dumazet5456f092010-10-31 05:36:23 +00002215 if (!skb_queue_empty(&sk->sk_receive_queue))
Rainer Weikusat3c734192008-06-17 22:28:05 -07002216 mask |= POLLIN | POLLRDNORM;
2217
2218 /* Connection-based need to check for termination and startup */
2219 if (sk->sk_type == SOCK_SEQPACKET) {
2220 if (sk->sk_state == TCP_CLOSE)
2221 mask |= POLLHUP;
2222 /* connection hasn't started yet? */
2223 if (sk->sk_state == TCP_SYN_SENT)
2224 return mask;
2225 }
2226
Eric Dumazet973a34a2010-10-31 05:38:25 +00002227 /* No write status requested, avoid expensive OUT tests. */
Hans Verkuil626cf232012-03-23 15:02:27 -07002228 if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
Eric Dumazet973a34a2010-10-31 05:38:25 +00002229 return mask;
2230
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002231 writable = unix_writable(sk);
Eric Dumazet5456f092010-10-31 05:36:23 +00002232 other = unix_peer_get(sk);
2233 if (other) {
2234 if (unix_peer(other) != sk) {
2235 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2236 if (unix_recvq_full(other))
2237 writable = 0;
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002238 }
Eric Dumazet5456f092010-10-31 05:36:23 +00002239 sock_put(other);
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002240 }
2241
2242 if (writable)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002243 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2244 else
2245 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
2246
Rainer Weikusat3c734192008-06-17 22:28:05 -07002247 return mask;
2248}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250#ifdef CONFIG_PROC_FS
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002251
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002252#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
2253
2254#define get_bucket(x) ((x) >> BUCKET_SPACE)
2255#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
2256#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002257
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002258static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259{
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002260 unsigned long offset = get_offset(*pos);
2261 unsigned long bucket = get_bucket(*pos);
2262 struct sock *sk;
2263 unsigned long count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002265 for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
2266 if (sock_net(sk) != seq_file_net(seq))
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002267 continue;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002268 if (++count == offset)
2269 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002271
2272 return sk;
2273}
2274
2275static struct sock *unix_next_socket(struct seq_file *seq,
2276 struct sock *sk,
2277 loff_t *pos)
2278{
2279 unsigned long bucket;
2280
2281 while (sk > (struct sock *)SEQ_START_TOKEN) {
2282 sk = sk_next(sk);
2283 if (!sk)
2284 goto next_bucket;
2285 if (sock_net(sk) == seq_file_net(seq))
2286 return sk;
2287 }
2288
2289 do {
2290 sk = unix_from_bucket(seq, pos);
2291 if (sk)
2292 return sk;
2293
2294next_bucket:
2295 bucket = get_bucket(*pos) + 1;
2296 *pos = set_bucket_offset(bucket, 1);
2297 } while (bucket < ARRAY_SIZE(unix_socket_table));
2298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 return NULL;
2300}
2301
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002303 __acquires(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002305 spin_lock(&unix_table_lock);
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002306
2307 if (!*pos)
2308 return SEQ_START_TOKEN;
2309
2310 if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
2311 return NULL;
2312
2313 return unix_next_socket(seq, NULL, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314}
2315
2316static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2317{
2318 ++*pos;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002319 return unix_next_socket(seq, v, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320}
2321
2322static void unix_seq_stop(struct seq_file *seq, void *v)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002323 __releases(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002325 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326}
2327
2328static int unix_seq_show(struct seq_file *seq, void *v)
2329{
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002330
Joe Perchesb9f31242008-04-12 19:04:38 -07002331 if (v == SEQ_START_TOKEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 seq_puts(seq, "Num RefCount Protocol Flags Type St "
2333 "Inode Path\n");
2334 else {
2335 struct sock *s = v;
2336 struct unix_sock *u = unix_sk(s);
David S. Miller1c92b4e2007-05-31 13:24:26 -07002337 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
Dan Rosenberg71338aa2011-05-23 12:17:35 +00002339 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 s,
2341 atomic_read(&s->sk_refcnt),
2342 0,
2343 s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
2344 s->sk_type,
2345 s->sk_socket ?
2346 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
2347 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
2348 sock_i_ino(s));
2349
2350 if (u->addr) {
2351 int i, len;
2352 seq_putc(seq, ' ');
2353
2354 i = 0;
2355 len = u->addr->len - sizeof(short);
2356 if (!UNIX_ABSTRACT(s))
2357 len--;
2358 else {
2359 seq_putc(seq, '@');
2360 i++;
2361 }
2362 for ( ; i < len; i++)
2363 seq_putc(seq, u->addr->name->sun_path[i]);
2364 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07002365 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 seq_putc(seq, '\n');
2367 }
2368
2369 return 0;
2370}
2371
Philippe De Muyter56b3d972007-07-10 23:07:31 -07002372static const struct seq_operations unix_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 .start = unix_seq_start,
2374 .next = unix_seq_next,
2375 .stop = unix_seq_stop,
2376 .show = unix_seq_show,
2377};
2378
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379static int unix_seq_open(struct inode *inode, struct file *file)
2380{
Denis V. Luneve372c412007-11-19 22:31:54 -08002381 return seq_open_net(inode, file, &unix_seq_ops,
Eric Dumazet8b51b062012-06-08 22:10:20 +00002382 sizeof(struct seq_net_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383}
2384
Arjan van de Venda7071d2007-02-12 00:55:36 -08002385static const struct file_operations unix_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 .owner = THIS_MODULE,
2387 .open = unix_seq_open,
2388 .read = seq_read,
2389 .llseek = seq_lseek,
Denis V. Luneve372c412007-11-19 22:31:54 -08002390 .release = seq_release_net,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391};
2392
2393#endif
2394
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00002395static const struct net_proto_family unix_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 .family = PF_UNIX,
2397 .create = unix_create,
2398 .owner = THIS_MODULE,
2399};
2400
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002401
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002402static int __net_init unix_net_init(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002403{
2404 int error = -ENOMEM;
2405
Denis V. Luneva0a53c82007-12-11 04:19:17 -08002406 net->unx.sysctl_max_dgram_qlen = 10;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002407 if (unix_sysctl_register(net))
2408 goto out;
Pavel Emelyanovd392e492007-12-01 23:44:15 +11002409
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002410#ifdef CONFIG_PROC_FS
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002411 if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops)) {
2412 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002413 goto out;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002414 }
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002415#endif
2416 error = 0;
2417out:
Jianjun Kong48dcc33e2008-11-01 21:37:27 -07002418 return error;
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002419}
2420
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002421static void __net_exit unix_net_exit(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002422{
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002423 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002424 proc_net_remove(net, "unix");
2425}
2426
2427static struct pernet_operations unix_net_ops = {
2428 .init = unix_net_init,
2429 .exit = unix_net_exit,
2430};
2431
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432static int __init af_unix_init(void)
2433{
2434 int rc = -1;
2435 struct sk_buff *dummy_skb;
2436
YOSHIFUJI Hideakief047f52006-09-01 00:29:06 -07002437 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
2439 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002440 if (rc != 0) {
2441 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002442 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 goto out;
2444 }
2445
2446 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002447 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448out:
2449 return rc;
2450}
2451
2452static void __exit af_unix_exit(void)
2453{
2454 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002456 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457}
2458
David Woodhouse3d366962008-04-24 00:59:25 -07002459/* Earlier than device_initcall() so that other drivers invoking
2460 request_module() don't end up in a loop when modprobe tries
2461 to use a UNIX socket. But later than subsys_initcall() because
2462 we depend on stuff initialised there */
2463fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464module_exit(af_unix_exit);
2465
2466MODULE_LICENSE("GPL");
2467MODULE_ALIAS_NETPROTO(PF_UNIX);