blob: c5ee4ff613641b3f8439f1c9cb6b22d55a1ff7f2 [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
Al Virofaf02012012-07-20 02:37:29 +0400826static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
827{
828 struct dentry *dentry;
829 struct path path;
830 int err = 0;
831 /*
832 * Get the parent directory, calculate the hash for last
833 * component.
834 */
835 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
836 err = PTR_ERR(dentry);
837 if (IS_ERR(dentry))
838 return err;
839
840 /*
841 * All right, let's create it.
842 */
843 err = security_path_mknod(&path, dentry, mode, 0);
844 if (!err) {
845 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
846 if (!err) {
847 res->mnt = mntget(path.mnt);
848 res->dentry = dget(dentry);
849 }
850 }
851 done_path_create(&path, dentry);
852 return err;
853}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
855static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
856{
857 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900858 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700860 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400861 char *sun_path = sunaddr->sun_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000863 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 struct unix_address *addr;
865 struct hlist_head *list;
866
867 err = -EINVAL;
868 if (sunaddr->sun_family != AF_UNIX)
869 goto out;
870
Jianjun Konge27dfce2008-11-01 21:38:31 -0700871 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 err = unix_autobind(sock);
873 goto out;
874 }
875
876 err = unix_mkname(sunaddr, addr_len, &hash);
877 if (err < 0)
878 goto out;
879 addr_len = err;
880
Ingo Molnar57b47a52006-03-20 22:35:41 -0800881 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883 err = -EINVAL;
884 if (u->addr)
885 goto out_up;
886
887 err = -ENOMEM;
888 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
889 if (!addr)
890 goto out_up;
891
892 memcpy(addr->name, sunaddr, addr_len);
893 addr->len = addr_len;
894 addr->hash = hash ^ sk->sk_type;
895 atomic_set(&addr->refcnt, 1);
896
Al Virodae6ad82011-06-26 11:50:15 -0400897 if (sun_path[0]) {
Al Virofaf02012012-07-20 02:37:29 +0400898 struct path path;
899 umode_t mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400900 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virofaf02012012-07-20 02:37:29 +0400901 err = unix_mknod(sun_path, mode, &path);
902 if (err) {
903 if (err == -EEXIST)
904 err = -EADDRINUSE;
905 unix_release_addr(addr);
906 goto out_up;
907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 addr->hash = UNIX_HASH_SIZE;
Al Virofaf02012012-07-20 02:37:29 +0400909 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
910 spin_lock(&unix_table_lock);
911 u->path = path;
912 list = &unix_socket_table[hash];
913 } else {
914 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800916 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 sk->sk_type, hash)) {
918 unix_release_addr(addr);
919 goto out_unlock;
920 }
921
922 list = &unix_socket_table[addr->hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 }
924
925 err = 0;
926 __unix_remove_socket(sk);
927 u->addr = addr;
928 __unix_insert_socket(list, sk);
929
930out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800931 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800933 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934out:
935 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936}
937
David S. Miller278a3de2007-05-31 15:19:20 -0700938static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
939{
940 if (unlikely(sk1 == sk2) || !sk2) {
941 unix_state_lock(sk1);
942 return;
943 }
944 if (sk1 < sk2) {
945 unix_state_lock(sk1);
946 unix_state_lock_nested(sk2);
947 } else {
948 unix_state_lock(sk2);
949 unix_state_lock_nested(sk1);
950 }
951}
952
953static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
954{
955 if (unlikely(sk1 == sk2) || !sk2) {
956 unix_state_unlock(sk1);
957 return;
958 }
959 unix_state_unlock(sk1);
960 unix_state_unlock(sk2);
961}
962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
964 int alen, int flags)
965{
966 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900967 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700968 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000970 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 int err;
972
973 if (addr->sa_family != AF_UNSPEC) {
974 err = unix_mkname(sunaddr, alen, &hash);
975 if (err < 0)
976 goto out;
977 alen = err;
978
979 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
980 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
981 goto out;
982
David S. Miller278a3de2007-05-31 15:19:20 -0700983restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700984 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 if (!other)
986 goto out;
987
David S. Miller278a3de2007-05-31 15:19:20 -0700988 unix_state_double_lock(sk, other);
989
990 /* Apparently VFS overslept socket death. Retry. */
991 if (sock_flag(other, SOCK_DEAD)) {
992 unix_state_double_unlock(sk, other);
993 sock_put(other);
994 goto restart;
995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 err = -EPERM;
998 if (!unix_may_send(sk, other))
999 goto out_unlock;
1000
1001 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1002 if (err)
1003 goto out_unlock;
1004
1005 } else {
1006 /*
1007 * 1003.1g breaking connected state with AF_UNSPEC
1008 */
1009 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001010 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
1012
1013 /*
1014 * If it was connected, reconnect.
1015 */
1016 if (unix_peer(sk)) {
1017 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001018 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001019 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
1021 if (other != old_peer)
1022 unix_dgram_disconnected(sk, old_peer);
1023 sock_put(old_peer);
1024 } else {
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 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001028 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001031 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 sock_put(other);
1033out:
1034 return err;
1035}
1036
1037static long unix_wait_for_peer(struct sock *other, long timeo)
1038{
1039 struct unix_sock *u = unix_sk(other);
1040 int sched;
1041 DEFINE_WAIT(wait);
1042
1043 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1044
1045 sched = !sock_flag(other, SOCK_DEAD) &&
1046 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001047 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
David S. Miller1c92b4e2007-05-31 13:24:26 -07001049 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 if (sched)
1052 timeo = schedule_timeout(timeo);
1053
1054 finish_wait(&u->peer_wait, &wait);
1055 return timeo;
1056}
1057
1058static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1059 int addr_len, int flags)
1060{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001061 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001063 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1065 struct sock *newsk = NULL;
1066 struct sock *other = NULL;
1067 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001068 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 int st;
1070 int err;
1071 long timeo;
1072
1073 err = unix_mkname(sunaddr, addr_len, &hash);
1074 if (err < 0)
1075 goto out;
1076 addr_len = err;
1077
Joe Perchesf64f9e72009-11-29 16:55:45 -08001078 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1079 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 goto out;
1081
1082 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1083
1084 /* First of all allocate resources.
1085 If we will make it after state is locked,
1086 we will have to recheck all again in any case.
1087 */
1088
1089 err = -ENOMEM;
1090
1091 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001092 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 if (newsk == NULL)
1094 goto out;
1095
1096 /* Allocate skb for sending to listening sock */
1097 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1098 if (skb == NULL)
1099 goto out;
1100
1101restart:
1102 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001103 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (!other)
1105 goto out;
1106
1107 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001108 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 /* Apparently VFS overslept socket death. Retry. */
1111 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001112 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 sock_put(other);
1114 goto restart;
1115 }
1116
1117 err = -ECONNREFUSED;
1118 if (other->sk_state != TCP_LISTEN)
1119 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001120 if (other->sk_shutdown & RCV_SHUTDOWN)
1121 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Rainer Weikusat3c734192008-06-17 22:28:05 -07001123 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 err = -EAGAIN;
1125 if (!timeo)
1126 goto out_unlock;
1127
1128 timeo = unix_wait_for_peer(other, timeo);
1129
1130 err = sock_intr_errno(timeo);
1131 if (signal_pending(current))
1132 goto out;
1133 sock_put(other);
1134 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137 /* Latch our state.
1138
Daniel Balutae5537bf2011-03-14 15:25:33 -07001139 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 drop lock on peer. It is dangerous because deadlock is
1141 possible. Connect to self case and simultaneous
1142 attempt to connect are eliminated by checking socket
1143 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1144 check this before attempt to grab lock.
1145
1146 Well, and we have to recheck the state after socket locked.
1147 */
1148 st = sk->sk_state;
1149
1150 switch (st) {
1151 case TCP_CLOSE:
1152 /* This is ok... continue with connect */
1153 break;
1154 case TCP_ESTABLISHED:
1155 /* Socket is already connected */
1156 err = -EISCONN;
1157 goto out_unlock;
1158 default:
1159 err = -EINVAL;
1160 goto out_unlock;
1161 }
1162
David S. Miller1c92b4e2007-05-31 13:24:26 -07001163 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001166 unix_state_unlock(sk);
1167 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 sock_put(other);
1169 goto restart;
1170 }
1171
David S. Miller3610cda2011-01-05 15:38:53 -08001172 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001174 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 goto out_unlock;
1176 }
1177
1178 /* The way is open! Fastly set all the necessary fields... */
1179
1180 sock_hold(sk);
1181 unix_peer(newsk) = sk;
1182 newsk->sk_state = TCP_ESTABLISHED;
1183 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001184 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001186 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 otheru = unix_sk(other);
1188
1189 /* copy address information from listening to new sock*/
1190 if (otheru->addr) {
1191 atomic_inc(&otheru->addr->refcnt);
1192 newu->addr = otheru->addr;
1193 }
Al Viro40ffe672012-03-14 21:54:32 -04001194 if (otheru->path.dentry) {
1195 path_get(&otheru->path);
1196 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
1198
1199 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001200 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 sock->state = SS_CONNECTED;
1203 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001204 sock_hold(newsk);
1205
1206 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1207 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
David S. Miller1c92b4e2007-05-31 13:24:26 -07001209 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 /* take ten and and send info to listening sock */
1212 spin_lock(&other->sk_receive_queue.lock);
1213 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001215 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 other->sk_data_ready(other, 0);
1217 sock_put(other);
1218 return 0;
1219
1220out_unlock:
1221 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001222 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001225 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 if (newsk)
1227 unix_release_sock(newsk, 0);
1228 if (other)
1229 sock_put(other);
1230 return err;
1231}
1232
1233static int unix_socketpair(struct socket *socka, struct socket *sockb)
1234{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001235 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 /* Join our sockets back to back */
1238 sock_hold(ska);
1239 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001240 unix_peer(ska) = skb;
1241 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001242 init_peercred(ska);
1243 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245 if (ska->sk_type != SOCK_DGRAM) {
1246 ska->sk_state = TCP_ESTABLISHED;
1247 skb->sk_state = TCP_ESTABLISHED;
1248 socka->state = SS_CONNECTED;
1249 sockb->state = SS_CONNECTED;
1250 }
1251 return 0;
1252}
1253
1254static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1255{
1256 struct sock *sk = sock->sk;
1257 struct sock *tsk;
1258 struct sk_buff *skb;
1259 int err;
1260
1261 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001262 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 goto out;
1264
1265 err = -EINVAL;
1266 if (sk->sk_state != TCP_LISTEN)
1267 goto out;
1268
1269 /* If socket state is TCP_LISTEN it cannot change (for now...),
1270 * so that no locks are necessary.
1271 */
1272
1273 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1274 if (!skb) {
1275 /* This means receive shutdown. */
1276 if (err == 0)
1277 err = -EINVAL;
1278 goto out;
1279 }
1280
1281 tsk = skb->sk;
1282 skb_free_datagram(sk, skb);
1283 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1284
1285 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001286 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 newsock->state = SS_CONNECTED;
1288 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001289 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 return 0;
1291
1292out:
1293 return err;
1294}
1295
1296
1297static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1298{
1299 struct sock *sk = sock->sk;
1300 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001301 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 int err = 0;
1303
1304 if (peer) {
1305 sk = unix_peer_get(sk);
1306
1307 err = -ENOTCONN;
1308 if (!sk)
1309 goto out;
1310 err = 0;
1311 } else {
1312 sock_hold(sk);
1313 }
1314
1315 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001316 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 if (!u->addr) {
1318 sunaddr->sun_family = AF_UNIX;
1319 sunaddr->sun_path[0] = 0;
1320 *uaddr_len = sizeof(short);
1321 } else {
1322 struct unix_address *addr = u->addr;
1323
1324 *uaddr_len = addr->len;
1325 memcpy(sunaddr, addr->name, *uaddr_len);
1326 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001327 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 sock_put(sk);
1329out:
1330 return err;
1331}
1332
1333static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1334{
1335 int i;
1336
1337 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 UNIXCB(skb).fp = NULL;
1339
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001340 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 unix_notinflight(scm->fp->fp[i]);
1342}
1343
Eric W. Biederman7361c362010-06-13 03:34:33 +00001344static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
1346 struct scm_cookie scm;
1347 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001348 scm.pid = UNIXCB(skb).pid;
1349 scm.cred = UNIXCB(skb).cred;
1350 if (UNIXCB(skb).fp)
1351 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
1353 /* Alas, it calls VFS */
1354 /* So fscking what? fput() had been SMP-safe since the last Summer */
1355 scm_destroy(&scm);
1356 sock_wfree(skb);
1357}
1358
Eric Dumazet25888e32010-11-25 04:11:39 +00001359#define MAX_RECURSION_LEVEL 4
1360
Miklos Szeredi62093442008-11-09 15:23:57 +01001361static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
1363 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001364 unsigned char max_level = 0;
1365 int unix_sock_count = 0;
1366
1367 for (i = scm->fp->count - 1; i >= 0; i--) {
1368 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1369
1370 if (sk) {
1371 unix_sock_count++;
1372 max_level = max(max_level,
1373 unix_sk(sk)->recursion_level);
1374 }
1375 }
1376 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1377 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001378
1379 /*
1380 * Need to duplicate file references for the sake of garbage
1381 * collection. Otherwise a socket in the fps might become a
1382 * candidate for GC while the skb is not yet queued.
1383 */
1384 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1385 if (!UNIXCB(skb).fp)
1386 return -ENOMEM;
1387
Eric Dumazet25888e32010-11-25 04:11:39 +00001388 if (unix_sock_count) {
1389 for (i = scm->fp->count - 1; i >= 0; i--)
1390 unix_inflight(scm->fp->fp[i]);
1391 }
1392 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393}
1394
David S. Millerf78a5fd2011-09-16 19:34:00 -04001395static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001396{
1397 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001398
David S. Millerf78a5fd2011-09-16 19:34:00 -04001399 UNIXCB(skb).pid = get_pid(scm->pid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001400 if (scm->cred)
1401 UNIXCB(skb).cred = get_cred(scm->cred);
Eric W. Biederman7361c362010-06-13 03:34:33 +00001402 UNIXCB(skb).fp = NULL;
1403 if (scm->fp && send_fds)
1404 err = unix_attach_fds(scm, skb);
1405
1406 skb->destructor = unix_destruct_scm;
1407 return err;
1408}
1409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001411 * Some apps rely on write() giving SCM_CREDENTIALS
1412 * We include credentials if source or destination socket
1413 * asserted SOCK_PASSCRED.
1414 */
1415static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1416 const struct sock *other)
1417{
1418 if (UNIXCB(skb).cred)
1419 return;
1420 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
1421 !other->sk_socket ||
1422 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
1423 UNIXCB(skb).pid = get_pid(task_tgid(current));
1424 UNIXCB(skb).cred = get_current_cred();
1425 }
1426}
1427
1428/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 * Send AF_UNIX data.
1430 */
1431
1432static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1433 struct msghdr *msg, size_t len)
1434{
1435 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1436 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001437 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001439 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 struct sock *other = NULL;
1441 int namelen = 0; /* fake GCC */
1442 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001443 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001444 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 long timeo;
1446 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001447 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001448 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 if (NULL == siocb->scm)
1451 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001452 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001453 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 if (err < 0)
1455 return err;
1456
1457 err = -EOPNOTSUPP;
1458 if (msg->msg_flags&MSG_OOB)
1459 goto out;
1460
1461 if (msg->msg_namelen) {
1462 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1463 if (err < 0)
1464 goto out;
1465 namelen = err;
1466 } else {
1467 sunaddr = NULL;
1468 err = -ENOTCONN;
1469 other = unix_peer_get(sk);
1470 if (!other)
1471 goto out;
1472 }
1473
Joe Perchesf64f9e72009-11-29 16:55:45 -08001474 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1475 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 goto out;
1477
1478 err = -EMSGSIZE;
1479 if (len > sk->sk_sndbuf - 32)
1480 goto out;
1481
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001482 if (len > SKB_MAX_ALLOC)
1483 data_len = min_t(size_t,
1484 len - SKB_MAX_ALLOC,
1485 MAX_SKB_FRAGS * PAGE_SIZE);
1486
1487 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1488 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001489 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 goto out;
1491
David S. Millerf78a5fd2011-09-16 19:34:00 -04001492 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001493 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001494 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001495 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001496 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001497
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001498 skb_put(skb, len - data_len);
1499 skb->data_len = data_len;
1500 skb->len = len;
1501 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 if (err)
1503 goto out_free;
1504
1505 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1506
1507restart:
1508 if (!other) {
1509 err = -ECONNRESET;
1510 if (sunaddr == NULL)
1511 goto out_free;
1512
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001513 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001515 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 goto out_free;
1517 }
1518
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001519 if (sk_filter(other, skb) < 0) {
1520 /* Toss the packet but do not return any error to the sender */
1521 err = len;
1522 goto out_free;
1523 }
1524
David S. Miller1c92b4e2007-05-31 13:24:26 -07001525 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 err = -EPERM;
1527 if (!unix_may_send(sk, other))
1528 goto out_unlock;
1529
1530 if (sock_flag(other, SOCK_DEAD)) {
1531 /*
1532 * Check with 1003.1g - what should
1533 * datagram error
1534 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001535 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 sock_put(other);
1537
1538 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001539 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001541 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001542 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
1544 unix_dgram_disconnected(sk, other);
1545 sock_put(other);
1546 err = -ECONNREFUSED;
1547 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001548 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 }
1550
1551 other = NULL;
1552 if (err)
1553 goto out_free;
1554 goto restart;
1555 }
1556
1557 err = -EPIPE;
1558 if (other->sk_shutdown & RCV_SHUTDOWN)
1559 goto out_unlock;
1560
1561 if (sk->sk_type != SOCK_SEQPACKET) {
1562 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1563 if (err)
1564 goto out_unlock;
1565 }
1566
Rainer Weikusat3c734192008-06-17 22:28:05 -07001567 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 if (!timeo) {
1569 err = -EAGAIN;
1570 goto out_unlock;
1571 }
1572
1573 timeo = unix_wait_for_peer(other, timeo);
1574
1575 err = sock_intr_errno(timeo);
1576 if (signal_pending(current))
1577 goto out_free;
1578
1579 goto restart;
1580 }
1581
Alban Crequy3f661162010-10-04 08:48:28 +00001582 if (sock_flag(other, SOCK_RCVTSTAMP))
1583 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001584 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001586 if (max_level > unix_sk(other)->recursion_level)
1587 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001588 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 other->sk_data_ready(other, len);
1590 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001591 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 return len;
1593
1594out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001595 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596out_free:
1597 kfree_skb(skb);
1598out:
1599 if (other)
1600 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001601 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 return err;
1603}
1604
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001605
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1607 struct msghdr *msg, size_t len)
1608{
1609 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1610 struct sock *sk = sock->sk;
1611 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001612 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001613 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001614 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001616 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001617 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
1619 if (NULL == siocb->scm)
1620 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001621 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001622 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 if (err < 0)
1624 return err;
1625
1626 err = -EOPNOTSUPP;
1627 if (msg->msg_flags&MSG_OOB)
1628 goto out_err;
1629
1630 if (msg->msg_namelen) {
1631 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1632 goto out_err;
1633 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001635 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 if (!other)
1637 goto out_err;
1638 }
1639
1640 if (sk->sk_shutdown & SEND_SHUTDOWN)
1641 goto pipe_err;
1642
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001643 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 /*
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001645 * Optimisation for the fact that under 0.01% of X
1646 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 */
1648
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001649 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
1651 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001652 if (size > ((sk->sk_sndbuf >> 1) - 64))
1653 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
1655 if (size > SKB_MAX_ALLOC)
1656 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 /*
1659 * Grab a buffer
1660 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001661
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001662 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1663 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
Jianjun Konge27dfce2008-11-01 21:38:31 -07001665 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 goto out_err;
1667
1668 /*
1669 * If you pass two values to the sock_alloc_send_skb
1670 * it tries to grab the large buffer with GFP_NOFS
1671 * (which can fail easily), and if it fails grab the
1672 * fallback size buffer which is under a page and will
1673 * succeed. [Alan]
1674 */
1675 size = min_t(int, size, skb_tailroom(skb));
1676
Eric W. Biederman7361c362010-06-13 03:34:33 +00001677
David S. Millerf78a5fd2011-09-16 19:34:00 -04001678 /* Only send the fds in the first buffer */
1679 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001680 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001681 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001682 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001683 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001684 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001685 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001687 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1688 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001690 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 }
1692
David S. Miller1c92b4e2007-05-31 13:24:26 -07001693 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
1695 if (sock_flag(other, SOCK_DEAD) ||
1696 (other->sk_shutdown & RCV_SHUTDOWN))
1697 goto pipe_err_free;
1698
Eric Dumazet16e57262011-09-19 05:52:27 +00001699 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001701 if (max_level > unix_sk(other)->recursion_level)
1702 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001703 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001705 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
David S. Millerf78a5fd2011-09-16 19:34:00 -04001708 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 siocb->scm = NULL;
1710
1711 return sent;
1712
1713pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001714 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 kfree_skb(skb);
1716pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001717 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1718 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 err = -EPIPE;
1720out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001721 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 siocb->scm = NULL;
1723 return sent ? : err;
1724}
1725
1726static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1727 struct msghdr *msg, size_t len)
1728{
1729 int err;
1730 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 err = sock_error(sk);
1733 if (err)
1734 return err;
1735
1736 if (sk->sk_state != TCP_ESTABLISHED)
1737 return -ENOTCONN;
1738
1739 if (msg->msg_namelen)
1740 msg->msg_namelen = 0;
1741
1742 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1743}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001744
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001745static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1746 struct msghdr *msg, size_t size,
1747 int flags)
1748{
1749 struct sock *sk = sock->sk;
1750
1751 if (sk->sk_state != TCP_ESTABLISHED)
1752 return -ENOTCONN;
1753
1754 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1755}
1756
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1758{
1759 struct unix_sock *u = unix_sk(sk);
1760
1761 msg->msg_namelen = 0;
1762 if (u->addr) {
1763 msg->msg_namelen = u->addr->len;
1764 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1765 }
1766}
1767
1768static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1769 struct msghdr *msg, size_t size,
1770 int flags)
1771{
1772 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1773 struct scm_cookie tmp_scm;
1774 struct sock *sk = sock->sk;
1775 struct unix_sock *u = unix_sk(sk);
1776 int noblock = flags & MSG_DONTWAIT;
1777 struct sk_buff *skb;
1778 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001779 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
1781 err = -EOPNOTSUPP;
1782 if (flags&MSG_OOB)
1783 goto out;
1784
1785 msg->msg_namelen = 0;
1786
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001787 err = mutex_lock_interruptible(&u->readlock);
1788 if (err) {
1789 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1790 goto out;
1791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001793 skip = sk_peek_offset(sk, flags);
1794
1795 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001796 if (!skb) {
1797 unix_state_lock(sk);
1798 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1799 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1800 (sk->sk_shutdown & RCV_SHUTDOWN))
1801 err = 0;
1802 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Eric Dumazet67426b72010-10-29 20:44:44 +00001806 wake_up_interruptible_sync_poll(&u->peer_wait,
1807 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
1809 if (msg->msg_name)
1810 unix_copy_addr(msg, skb->sk);
1811
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001812 if (size > skb->len - skip)
1813 size = skb->len - skip;
1814 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 msg->msg_flags |= MSG_TRUNC;
1816
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001817 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 if (err)
1819 goto out_free;
1820
Alban Crequy3f661162010-10-04 08:48:28 +00001821 if (sock_flag(sk, SOCK_RCVTSTAMP))
1822 __sock_recv_timestamp(msg, sk, skb);
1823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 if (!siocb->scm) {
1825 siocb->scm = &tmp_scm;
1826 memset(&tmp_scm, 0, sizeof(tmp_scm));
1827 }
David S. Millerf78a5fd2011-09-16 19:34:00 -04001828 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001829 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001831 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 if (UNIXCB(skb).fp)
1833 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001834
1835 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001836 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 /* It is questionable: on PEEK we could:
1838 - do not return fds - good, but too simple 8)
1839 - return fds, and do not return them on read (old strategy,
1840 apparently wrong)
1841 - clone fds (I chose it for now, it is the most universal
1842 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001843
1844 POSIX 1003.1g does not actually define this clearly
1845 at all. POSIX 1003.1g doesn't define a lot of things
1846 clearly however!
1847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001849
1850 sk_peek_offset_fwd(sk, size);
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 if (UNIXCB(skb).fp)
1853 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1854 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001855 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
1857 scm_recv(sock, msg, siocb->scm, flags);
1858
1859out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001860 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001862 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863out:
1864 return err;
1865}
1866
1867/*
1868 * Sleep until data has arrive. But check for races..
1869 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001870
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001871static long unix_stream_data_wait(struct sock *sk, long timeo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872{
1873 DEFINE_WAIT(wait);
1874
David S. Miller1c92b4e2007-05-31 13:24:26 -07001875 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
1877 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001878 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
David S. Millerb03efcf2005-07-08 14:57:23 -07001880 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 sk->sk_err ||
1882 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1883 signal_pending(current) ||
1884 !timeo)
1885 break;
1886
1887 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001888 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 timeo = schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001890 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1892 }
1893
Eric Dumazetaa395142010-04-20 13:03:51 +00001894 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001895 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return timeo;
1897}
1898
1899
1900
1901static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1902 struct msghdr *msg, size_t size,
1903 int flags)
1904{
1905 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1906 struct scm_cookie tmp_scm;
1907 struct sock *sk = sock->sk;
1908 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001909 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 int copied = 0;
1911 int check_creds = 0;
1912 int target;
1913 int err = 0;
1914 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001915 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 err = -EINVAL;
1918 if (sk->sk_state != TCP_ESTABLISHED)
1919 goto out;
1920
1921 err = -EOPNOTSUPP;
1922 if (flags&MSG_OOB)
1923 goto out;
1924
1925 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1926 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1927
1928 msg->msg_namelen = 0;
1929
1930 /* Lock the socket to prevent queue disordering
1931 * while sleeps in memcpy_tomsg
1932 */
1933
1934 if (!siocb->scm) {
1935 siocb->scm = &tmp_scm;
1936 memset(&tmp_scm, 0, sizeof(tmp_scm));
1937 }
1938
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001939 err = mutex_lock_interruptible(&u->readlock);
1940 if (err) {
1941 err = sock_intr_errno(timeo);
1942 goto out;
1943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001945 skip = sk_peek_offset(sk, flags);
1946
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001947 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 int chunk;
1949 struct sk_buff *skb;
1950
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001951 unix_state_lock(sk);
Eric Dumazet6f01fd62012-01-28 16:11:03 +00001952 skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001953again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001954 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001955 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001957 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958
1959 /*
1960 * POSIX 1003.1g mandates this order.
1961 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001962
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001963 err = sock_error(sk);
1964 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001965 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001967 goto unlock;
1968
1969 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 err = -EAGAIN;
1971 if (!timeo)
1972 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001973 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
1975 timeo = unix_stream_data_wait(sk, timeo);
1976
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001977 if (signal_pending(current)
1978 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 err = sock_intr_errno(timeo);
1980 goto out;
1981 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001984 unlock:
1985 unix_state_unlock(sk);
1986 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001988
1989 if (skip >= skb->len) {
1990 skip -= skb->len;
1991 skb = skb_peek_next(skb, &sk->sk_receive_queue);
1992 goto again;
1993 }
1994
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001995 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
1997 if (check_creds) {
1998 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00001999 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002000 (UNIXCB(skb).cred != siocb->scm->cred))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 } else {
2003 /* Copy credentials */
David S. Millerf78a5fd2011-09-16 19:34:00 -04002004 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 check_creds = 1;
2006 }
2007
2008 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002009 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 unix_copy_addr(msg, skb->sk);
2011 sunaddr = NULL;
2012 }
2013
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002014 chunk = min_t(unsigned int, skb->len - skip, size);
2015 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 if (copied == 0)
2017 copied = -EFAULT;
2018 break;
2019 }
2020 copied += chunk;
2021 size -= chunk;
2022
2023 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002024 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 skb_pull(skb, chunk);
2026
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002027 sk_peek_offset_bwd(sk, chunk);
2028
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 if (UNIXCB(skb).fp)
2030 unix_detach_fds(siocb->scm, skb);
2031
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002032 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002035 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002036 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037
2038 if (siocb->scm->fp)
2039 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002040 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 /* It is questionable, see note in unix_dgram_recvmsg.
2042 */
2043 if (UNIXCB(skb).fp)
2044 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2045
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002046 sk_peek_offset_fwd(sk, chunk);
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 break;
2049 }
2050 } while (size);
2051
Ingo Molnar57b47a52006-03-20 22:35:41 -08002052 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 scm_recv(sock, msg, siocb->scm, flags);
2054out:
2055 return copied ? : err;
2056}
2057
2058static int unix_shutdown(struct socket *sock, int mode)
2059{
2060 struct sock *sk = sock->sk;
2061 struct sock *other;
2062
2063 mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
2064
Alban Crequy7180a032011-01-19 04:56:36 +00002065 if (!mode)
2066 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
Alban Crequy7180a032011-01-19 04:56:36 +00002068 unix_state_lock(sk);
2069 sk->sk_shutdown |= mode;
2070 other = unix_peer(sk);
2071 if (other)
2072 sock_hold(other);
2073 unix_state_unlock(sk);
2074 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
Alban Crequy7180a032011-01-19 04:56:36 +00002076 if (other &&
2077 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Alban Crequy7180a032011-01-19 04:56:36 +00002079 int peer_mode = 0;
2080
2081 if (mode&RCV_SHUTDOWN)
2082 peer_mode |= SEND_SHUTDOWN;
2083 if (mode&SEND_SHUTDOWN)
2084 peer_mode |= RCV_SHUTDOWN;
2085 unix_state_lock(other);
2086 other->sk_shutdown |= peer_mode;
2087 unix_state_unlock(other);
2088 other->sk_state_change(other);
2089 if (peer_mode == SHUTDOWN_MASK)
2090 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2091 else if (peer_mode & RCV_SHUTDOWN)
2092 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 }
Alban Crequy7180a032011-01-19 04:56:36 +00002094 if (other)
2095 sock_put(other);
2096
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 return 0;
2098}
2099
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002100long unix_inq_len(struct sock *sk)
2101{
2102 struct sk_buff *skb;
2103 long amount = 0;
2104
2105 if (sk->sk_state == TCP_LISTEN)
2106 return -EINVAL;
2107
2108 spin_lock(&sk->sk_receive_queue.lock);
2109 if (sk->sk_type == SOCK_STREAM ||
2110 sk->sk_type == SOCK_SEQPACKET) {
2111 skb_queue_walk(&sk->sk_receive_queue, skb)
2112 amount += skb->len;
2113 } else {
2114 skb = skb_peek(&sk->sk_receive_queue);
2115 if (skb)
2116 amount = skb->len;
2117 }
2118 spin_unlock(&sk->sk_receive_queue.lock);
2119
2120 return amount;
2121}
2122EXPORT_SYMBOL_GPL(unix_inq_len);
2123
2124long unix_outq_len(struct sock *sk)
2125{
2126 return sk_wmem_alloc_get(sk);
2127}
2128EXPORT_SYMBOL_GPL(unix_outq_len);
2129
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2131{
2132 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002133 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 int err;
2135
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002136 switch (cmd) {
2137 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002138 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002139 err = put_user(amount, (int __user *)arg);
2140 break;
2141 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002142 amount = unix_inq_len(sk);
2143 if (amount < 0)
2144 err = amount;
2145 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002147 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002148 default:
2149 err = -ENOIOCTLCMD;
2150 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 }
2152 return err;
2153}
2154
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002155static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
2157 struct sock *sk = sock->sk;
2158 unsigned int mask;
2159
Eric Dumazetaa395142010-04-20 13:03:51 +00002160 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 mask = 0;
2162
2163 /* exceptional events? */
2164 if (sk->sk_err)
2165 mask |= POLLERR;
2166 if (sk->sk_shutdown == SHUTDOWN_MASK)
2167 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002168 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002169 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170
2171 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002172 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 mask |= POLLIN | POLLRDNORM;
2174
2175 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002176 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2177 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 mask |= POLLHUP;
2179
2180 /*
2181 * we set writable also when the other side has shut down the
2182 * connection. This prevents stuck sockets.
2183 */
2184 if (unix_writable(sk))
2185 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2186
2187 return mask;
2188}
2189
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002190static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2191 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002192{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002193 struct sock *sk = sock->sk, *other;
2194 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002195
Eric Dumazetaa395142010-04-20 13:03:51 +00002196 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002197 mask = 0;
2198
2199 /* exceptional events? */
2200 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
2201 mask |= POLLERR;
2202 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazet5456f092010-10-31 05:36:23 +00002203 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002204 if (sk->sk_shutdown == SHUTDOWN_MASK)
2205 mask |= POLLHUP;
2206
2207 /* readable? */
Eric Dumazet5456f092010-10-31 05:36:23 +00002208 if (!skb_queue_empty(&sk->sk_receive_queue))
Rainer Weikusat3c734192008-06-17 22:28:05 -07002209 mask |= POLLIN | POLLRDNORM;
2210
2211 /* Connection-based need to check for termination and startup */
2212 if (sk->sk_type == SOCK_SEQPACKET) {
2213 if (sk->sk_state == TCP_CLOSE)
2214 mask |= POLLHUP;
2215 /* connection hasn't started yet? */
2216 if (sk->sk_state == TCP_SYN_SENT)
2217 return mask;
2218 }
2219
Eric Dumazet973a34a2010-10-31 05:38:25 +00002220 /* No write status requested, avoid expensive OUT tests. */
Hans Verkuil626cf232012-03-23 15:02:27 -07002221 if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
Eric Dumazet973a34a2010-10-31 05:38:25 +00002222 return mask;
2223
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002224 writable = unix_writable(sk);
Eric Dumazet5456f092010-10-31 05:36:23 +00002225 other = unix_peer_get(sk);
2226 if (other) {
2227 if (unix_peer(other) != sk) {
2228 sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
2229 if (unix_recvq_full(other))
2230 writable = 0;
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002231 }
Eric Dumazet5456f092010-10-31 05:36:23 +00002232 sock_put(other);
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002233 }
2234
2235 if (writable)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002236 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2237 else
2238 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
2239
Rainer Weikusat3c734192008-06-17 22:28:05 -07002240 return mask;
2241}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243#ifdef CONFIG_PROC_FS
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002244
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002245#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
2246
2247#define get_bucket(x) ((x) >> BUCKET_SPACE)
2248#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
2249#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
Pavel Emelyanova53eb3f2007-11-23 20:30:01 +08002250
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002251static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252{
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002253 unsigned long offset = get_offset(*pos);
2254 unsigned long bucket = get_bucket(*pos);
2255 struct sock *sk;
2256 unsigned long count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002258 for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
2259 if (sock_net(sk) != seq_file_net(seq))
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002260 continue;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002261 if (++count == offset)
2262 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002264
2265 return sk;
2266}
2267
2268static struct sock *unix_next_socket(struct seq_file *seq,
2269 struct sock *sk,
2270 loff_t *pos)
2271{
2272 unsigned long bucket;
2273
2274 while (sk > (struct sock *)SEQ_START_TOKEN) {
2275 sk = sk_next(sk);
2276 if (!sk)
2277 goto next_bucket;
2278 if (sock_net(sk) == seq_file_net(seq))
2279 return sk;
2280 }
2281
2282 do {
2283 sk = unix_from_bucket(seq, pos);
2284 if (sk)
2285 return sk;
2286
2287next_bucket:
2288 bucket = get_bucket(*pos) + 1;
2289 *pos = set_bucket_offset(bucket, 1);
2290 } while (bucket < ARRAY_SIZE(unix_socket_table));
2291
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 return NULL;
2293}
2294
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002296 __acquires(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002298 spin_lock(&unix_table_lock);
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002299
2300 if (!*pos)
2301 return SEQ_START_TOKEN;
2302
2303 if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
2304 return NULL;
2305
2306 return unix_next_socket(seq, NULL, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307}
2308
2309static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2310{
2311 ++*pos;
Eric Dumazet7123aaa2012-06-08 05:03:21 +00002312 return unix_next_socket(seq, v, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313}
2314
2315static void unix_seq_stop(struct seq_file *seq, void *v)
Eric Dumazet9a429c42008-01-01 21:58:02 -08002316 __releases(unix_table_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317{
David S. Millerfbe9cc42005-12-13 23:26:29 -08002318 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319}
2320
2321static int unix_seq_show(struct seq_file *seq, void *v)
2322{
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002323
Joe Perchesb9f31242008-04-12 19:04:38 -07002324 if (v == SEQ_START_TOKEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 seq_puts(seq, "Num RefCount Protocol Flags Type St "
2326 "Inode Path\n");
2327 else {
2328 struct sock *s = v;
2329 struct unix_sock *u = unix_sk(s);
David S. Miller1c92b4e2007-05-31 13:24:26 -07002330 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Dan Rosenberg71338aa2011-05-23 12:17:35 +00002332 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 s,
2334 atomic_read(&s->sk_refcnt),
2335 0,
2336 s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
2337 s->sk_type,
2338 s->sk_socket ?
2339 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
2340 (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
2341 sock_i_ino(s));
2342
2343 if (u->addr) {
2344 int i, len;
2345 seq_putc(seq, ' ');
2346
2347 i = 0;
2348 len = u->addr->len - sizeof(short);
2349 if (!UNIX_ABSTRACT(s))
2350 len--;
2351 else {
2352 seq_putc(seq, '@');
2353 i++;
2354 }
2355 for ( ; i < len; i++)
2356 seq_putc(seq, u->addr->name->sun_path[i]);
2357 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07002358 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 seq_putc(seq, '\n');
2360 }
2361
2362 return 0;
2363}
2364
Philippe De Muyter56b3d972007-07-10 23:07:31 -07002365static const struct seq_operations unix_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 .start = unix_seq_start,
2367 .next = unix_seq_next,
2368 .stop = unix_seq_stop,
2369 .show = unix_seq_show,
2370};
2371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372static int unix_seq_open(struct inode *inode, struct file *file)
2373{
Denis V. Luneve372c412007-11-19 22:31:54 -08002374 return seq_open_net(inode, file, &unix_seq_ops,
Eric Dumazet8b51b062012-06-08 22:10:20 +00002375 sizeof(struct seq_net_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376}
2377
Arjan van de Venda7071d2007-02-12 00:55:36 -08002378static const struct file_operations unix_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 .owner = THIS_MODULE,
2380 .open = unix_seq_open,
2381 .read = seq_read,
2382 .llseek = seq_lseek,
Denis V. Luneve372c412007-11-19 22:31:54 -08002383 .release = seq_release_net,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384};
2385
2386#endif
2387
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00002388static const struct net_proto_family unix_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 .family = PF_UNIX,
2390 .create = unix_create,
2391 .owner = THIS_MODULE,
2392};
2393
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002394
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002395static int __net_init unix_net_init(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002396{
2397 int error = -ENOMEM;
2398
Denis V. Luneva0a53c82007-12-11 04:19:17 -08002399 net->unx.sysctl_max_dgram_qlen = 10;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002400 if (unix_sysctl_register(net))
2401 goto out;
Pavel Emelyanovd392e492007-12-01 23:44:15 +11002402
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002403#ifdef CONFIG_PROC_FS
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002404 if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops)) {
2405 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002406 goto out;
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002407 }
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002408#endif
2409 error = 0;
2410out:
Jianjun Kong48dcc33e2008-11-01 21:37:27 -07002411 return error;
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002412}
2413
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002414static void __net_exit unix_net_exit(struct net *net)
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002415{
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002416 unix_sysctl_unregister(net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002417 proc_net_remove(net, "unix");
2418}
2419
2420static struct pernet_operations unix_net_ops = {
2421 .init = unix_net_init,
2422 .exit = unix_net_exit,
2423};
2424
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425static int __init af_unix_init(void)
2426{
2427 int rc = -1;
2428 struct sk_buff *dummy_skb;
2429
YOSHIFUJI Hideakief047f52006-09-01 00:29:06 -07002430 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
2432 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002433 if (rc != 0) {
2434 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002435 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 goto out;
2437 }
2438
2439 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002440 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441out:
2442 return rc;
2443}
2444
2445static void __exit af_unix_exit(void)
2446{
2447 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002449 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450}
2451
David Woodhouse3d366962008-04-24 00:59:25 -07002452/* Earlier than device_initcall() so that other drivers invoking
2453 request_module() don't end up in a loop when modprobe tries
2454 to use a UNIX socket. But later than subsys_initcall() because
2455 we depend on stuff initialised there */
2456fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457module_exit(af_unix_exit);
2458
2459MODULE_LICENSE("GPL");
2460MODULE_ALIAS_NETPROTO(PF_UNIX);