blob: 9efe01113c5c5bc898dd6b26a4e0ced9733e1c01 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NET4: Implementation of BSD Unix domain sockets.
3 *
Alan Cox113aa832008-10-13 19:01:08 -07004 * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * Fixes:
12 * Linus Torvalds : Assorted bug cures.
13 * Niibe Yutaka : async I/O support.
14 * Carsten Paeth : PF_UNIX check, address fixes.
15 * Alan Cox : Limit size of allocated blocks.
16 * Alan Cox : Fixed the stupid socketpair bug.
17 * Alan Cox : BSD compatibility fine tuning.
18 * Alan Cox : Fixed a bug in connect when interrupted.
19 * Alan Cox : Sorted out a proper draft version of
20 * file descriptor passing hacked up from
21 * Mike Shaver's work.
22 * Marty Leisner : Fixes to fd passing
23 * Nick Nevin : recvmsg bugfix.
24 * Alan Cox : Started proper garbage collector
25 * Heiko EiBfeldt : Missing verify_area check
26 * Alan Cox : Started POSIXisms
27 * Andreas Schwab : Replace inode by dentry for proper
28 * reference counting
29 * Kirk Petersen : Made this a module
30 * Christoph Rohland : Elegant non-blocking accept/connect algorithm.
31 * Lots of bug fixes.
32 * Alexey Kuznetosv : Repaired (I hope) bugs introduces
33 * by above two patches.
34 * Andrea Arcangeli : If possible we block in connect(2)
35 * if the max backlog of the listen socket
36 * is been reached. This won't break
37 * old apps and it will avoid huge amount
38 * of socks hashed (this for unix_gc()
39 * performances reasons).
40 * Security fix that limits the max
41 * number of socks to 2*max_files and
42 * the number of skb queueable in the
43 * dgram receiver.
44 * Artur Skawina : Hash function optimizations
45 * Alexey Kuznetsov : Full scale SMP. Lot of bugs are introduced 8)
46 * Malcolm Beattie : Set peercred for socketpair
47 * Michal Ostrowski : Module initialization cleanup.
48 * Arnaldo C. Melo : Remove MOD_{INC,DEC}_USE_COUNT,
49 * the core infrastructure is doing that
50 * for all net proto families now (2.5.69+)
51 *
52 *
53 * Known differences from reference BSD that was tested:
54 *
55 * [TO FIX]
56 * ECONNREFUSED is not returned from one end of a connected() socket to the
57 * other the moment one end closes.
58 * fstat() doesn't return st_dev=0, and give the blksize as high water mark
59 * and a fake inode identifier (nor the BSD first socket fstat twice bug).
60 * [NOT TO FIX]
61 * accept() returns a path name even if the connecting socket has closed
62 * in the meantime (BSD loses the path and gives up).
63 * accept() returns 0 length path for an unbound connector. BSD returns 16
64 * and a null first byte in the path (but not for gethost/peername - BSD bug ??)
65 * socketpair(...SOCK_RAW..) doesn't panic the kernel.
66 * BSD af_unix apparently has connect forgetting to block properly.
67 * (need to check this with the POSIX spec in detail)
68 *
69 * Differences from 2.0.0-11-... (ANK)
70 * Bug fixes and improvements.
71 * - client shutdown killed server socket.
72 * - removed all useless cli/sti pairs.
73 *
74 * Semantic changes/extensions.
75 * - generic control message passing.
76 * - SCM_CREDENTIALS control message.
77 * - "Abstract" (not FS based) socket bindings.
78 * Abstract names are sequences of bytes (not zero terminated)
79 * started by 0, so that this name space does not intersect
80 * with BSD names.
81 */
82
83#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/signal.h>
86#include <linux/sched.h>
87#include <linux/errno.h>
88#include <linux/string.h>
89#include <linux/stat.h>
90#include <linux/dcache.h>
91#include <linux/namei.h>
92#include <linux/socket.h>
93#include <linux/un.h>
94#include <linux/fcntl.h>
95#include <linux/termios.h>
96#include <linux/sockios.h>
97#include <linux/net.h>
98#include <linux/in.h>
99#include <linux/fs.h>
100#include <linux/slab.h>
101#include <asm/uaccess.h>
102#include <linux/skbuff.h>
103#include <linux/netdevice.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +0200104#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105#include <net/sock.h>
Arnaldo Carvalho de Meloc752f072005-08-09 20:08:28 -0700106#include <net/tcp_states.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#include <net/af_unix.h>
108#include <linux/proc_fs.h>
109#include <linux/seq_file.h>
110#include <net/scm.h>
111#include <linux/init.h>
112#include <linux/poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#include <linux/rtnetlink.h>
114#include <linux/mount.h>
115#include <net/checksum.h>
116#include <linux/security.h>
117
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000118struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000119EXPORT_SYMBOL_GPL(unix_socket_table);
120DEFINE_SPINLOCK(unix_table_lock);
121EXPORT_SYMBOL_GPL(unix_table_lock);
Eric Dumazet518de9b2010-10-26 14:22:44 -0700122static atomic_long_t unix_nr_socks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000125static struct hlist_head *unix_sockets_unbound(void *addr)
126{
127 unsigned long hash = (unsigned long)addr;
128
129 hash ^= hash >> 16;
130 hash ^= hash >> 8;
131 hash %= UNIX_HASH_SIZE;
132 return &unix_socket_table[UNIX_HASH_SIZE + hash];
133}
134
135#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700137#ifdef CONFIG_SECURITY_NETWORK
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700138static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700139{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700140 memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700141}
142
143static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
144{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700145 scm->secid = *UNIXSID(skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700146}
147#else
Catherine Zhangdc49c1f2006-08-02 14:12:06 -0700148static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
Catherine Zhang877ce7c2006-06-29 12:27:47 -0700149{ }
150
151static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
152{ }
153#endif /* CONFIG_SECURITY_NETWORK */
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155/*
156 * SMP locking strategy:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800157 * hash table is protected with spinlock unix_table_lock
Stephen Hemminger663717f2010-02-18 14:12:06 -0800158 * each socket state is protected by separate spin lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 */
160
Eric Dumazet95c96172012-04-15 05:58:06 +0000161static inline unsigned int unix_hash_fold(__wsum n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Eric Dumazet95c96172012-04-15 05:58:06 +0000163 unsigned int hash = (__force unsigned int)n;
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 hash ^= hash>>16;
166 hash ^= hash>>8;
167 return hash&(UNIX_HASH_SIZE-1);
168}
169
170#define unix_peer(sk) (unix_sk(sk)->peer)
171
172static inline int unix_our_peer(struct sock *sk, struct sock *osk)
173{
174 return unix_peer(osk) == sk;
175}
176
177static inline int unix_may_send(struct sock *sk, struct sock *osk)
178{
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800179 return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180}
181
Rainer Weikusat3c734192008-06-17 22:28:05 -0700182static inline int unix_recvq_full(struct sock const *sk)
183{
184 return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
185}
186
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000187struct sock *unix_peer_get(struct sock *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
189 struct sock *peer;
190
David S. Miller1c92b4e2007-05-31 13:24:26 -0700191 unix_state_lock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 peer = unix_peer(s);
193 if (peer)
194 sock_hold(peer);
David S. Miller1c92b4e2007-05-31 13:24:26 -0700195 unix_state_unlock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 return peer;
197}
Pavel Emelyanovfa7ff562011-12-15 02:44:03 +0000198EXPORT_SYMBOL_GPL(unix_peer_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200static inline void unix_release_addr(struct unix_address *addr)
201{
202 if (atomic_dec_and_test(&addr->refcnt))
203 kfree(addr);
204}
205
206/*
207 * Check unix socket name:
208 * - should be not zero length.
209 * - if started by not zero, should be NULL terminated (FS object)
210 * - if started by zero, it is abstract name.
211 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900212
Eric Dumazet95c96172012-04-15 05:58:06 +0000213static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 if (len <= sizeof(short) || len > sizeof(*sunaddr))
216 return -EINVAL;
217 if (!sunaddr || sunaddr->sun_family != AF_UNIX)
218 return -EINVAL;
219 if (sunaddr->sun_path[0]) {
220 /*
221 * This may look like an off by one error but it is a bit more
222 * subtle. 108 is the longest valid AF_UNIX path for a binding.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300223 * sun_path[108] doesn't as such exist. However in kernel space
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 * we are guaranteed that it is a valid memory location in our
225 * kernel address buffer.
226 */
Jianjun Konge27dfce2008-11-01 21:38:31 -0700227 ((char *)sunaddr)[len] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 len = strlen(sunaddr->sun_path)+1+sizeof(short);
229 return len;
230 }
231
Joe Perches07f07572008-11-19 15:44:53 -0800232 *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 return len;
234}
235
236static void __unix_remove_socket(struct sock *sk)
237{
238 sk_del_node_init(sk);
239}
240
241static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
242{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700243 WARN_ON(!sk_unhashed(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 sk_add_node(sk, list);
245}
246
247static inline void unix_remove_socket(struct sock *sk)
248{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800249 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 __unix_remove_socket(sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800251 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
254static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
255{
David S. Millerfbe9cc42005-12-13 23:26:29 -0800256 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 __unix_insert_socket(list, sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800258 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800261static struct sock *__unix_find_socket_byname(struct net *net,
262 struct sockaddr_un *sunname,
Eric Dumazet95c96172012-04-15 05:58:06 +0000263 int len, int type, unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Sasha Levinb67bfe02013-02-27 17:06:00 -0800267 sk_for_each(s, &unix_socket_table[hash ^ type]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 struct unix_sock *u = unix_sk(s);
269
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900270 if (!net_eq(sock_net(s), net))
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800271 continue;
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 if (u->addr->len == len &&
274 !memcmp(u->addr->name, sunname, len))
275 goto found;
276 }
277 s = NULL;
278found:
279 return s;
280}
281
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800282static inline struct sock *unix_find_socket_byname(struct net *net,
283 struct sockaddr_un *sunname,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 int len, int type,
Eric Dumazet95c96172012-04-15 05:58:06 +0000285 unsigned int hash)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
287 struct sock *s;
288
David S. Millerfbe9cc42005-12-13 23:26:29 -0800289 spin_lock(&unix_table_lock);
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800290 s = __unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 if (s)
292 sock_hold(s);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800293 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 return s;
295}
296
Eric W. Biederman6616f782010-06-13 03:35:48 +0000297static struct sock *unix_find_socket_byinode(struct inode *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 struct sock *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
David S. Millerfbe9cc42005-12-13 23:26:29 -0800301 spin_lock(&unix_table_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800302 sk_for_each(s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
Al Viro40ffe672012-03-14 21:54:32 -0400304 struct dentry *dentry = unix_sk(s)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800306 if (dentry && dentry->d_inode == i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 sock_hold(s);
308 goto found;
309 }
310 }
311 s = NULL;
312found:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800313 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return s;
315}
316
317static inline int unix_writable(struct sock *sk)
318{
319 return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
320}
321
322static void unix_write_space(struct sock *sk)
323{
Eric Dumazet43815482010-04-29 11:01:49 +0000324 struct socket_wq *wq;
325
326 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 if (unix_writable(sk)) {
Eric Dumazet43815482010-04-29 11:01:49 +0000328 wq = rcu_dereference(sk->sk_wq);
329 if (wq_has_sleeper(wq))
Eric Dumazet67426b72010-10-29 20:44:44 +0000330 wake_up_interruptible_sync_poll(&wq->wait,
331 POLLOUT | POLLWRNORM | POLLWRBAND);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800332 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Eric Dumazet43815482010-04-29 11:01:49 +0000334 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335}
336
337/* When dgram socket disconnects (or changes its peer), we clear its receive
338 * queue of packets arrived from previous peer. First, it allows to do
339 * flow control based only on wmem_alloc; second, sk connected to peer
340 * may receive messages only from that peer. */
341static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
342{
David S. Millerb03efcf2005-07-08 14:57:23 -0700343 if (!skb_queue_empty(&sk->sk_receive_queue)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 skb_queue_purge(&sk->sk_receive_queue);
345 wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
346
347 /* If one link of bidirectional dgram pipe is disconnected,
348 * we signal error. Messages are lost. Do not make this,
349 * when peer was not connected to us.
350 */
351 if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
352 other->sk_err = ECONNRESET;
353 other->sk_error_report(other);
354 }
355 }
356}
357
358static void unix_sock_destructor(struct sock *sk)
359{
360 struct unix_sock *u = unix_sk(sk);
361
362 skb_queue_purge(&sk->sk_receive_queue);
363
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700364 WARN_ON(atomic_read(&sk->sk_wmem_alloc));
365 WARN_ON(!sk_unhashed(sk));
366 WARN_ON(sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (!sock_flag(sk, SOCK_DEAD)) {
Eric Dumazet6b41e7d2008-11-19 15:48:09 -0800368 printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 return;
370 }
371
372 if (u->addr)
373 unix_release_addr(u->addr);
374
Eric Dumazet518de9b2010-10-26 14:22:44 -0700375 atomic_long_dec(&unix_nr_socks);
David S. Miller6f756a82008-11-23 17:34:03 -0800376 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800377 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
David S. Miller6f756a82008-11-23 17:34:03 -0800378 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379#ifdef UNIX_REFCNT_DEBUG
Eric Dumazet518de9b2010-10-26 14:22:44 -0700380 printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
381 atomic_long_read(&unix_nr_socks));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382#endif
383}
384
Paul Mooreded34e02013-03-25 03:18:33 +0000385static void unix_release_sock(struct sock *sk, int embrion)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
387 struct unix_sock *u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400388 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 struct sock *skpair;
390 struct sk_buff *skb;
391 int state;
392
393 unix_remove_socket(sk);
394
395 /* Clear state */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700396 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 sock_orphan(sk);
398 sk->sk_shutdown = SHUTDOWN_MASK;
Al Viro40ffe672012-03-14 21:54:32 -0400399 path = u->path;
400 u->path.dentry = NULL;
401 u->path.mnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 state = sk->sk_state;
403 sk->sk_state = TCP_CLOSE;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700404 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406 wake_up_interruptible_all(&u->peer_wait);
407
Jianjun Konge27dfce2008-11-01 21:38:31 -0700408 skpair = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Jianjun Konge27dfce2008-11-01 21:38:31 -0700410 if (skpair != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
David S. Miller1c92b4e2007-05-31 13:24:26 -0700412 unix_state_lock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* No more writes */
414 skpair->sk_shutdown = SHUTDOWN_MASK;
415 if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
416 skpair->sk_err = ECONNRESET;
David S. Miller1c92b4e2007-05-31 13:24:26 -0700417 unix_state_unlock(skpair);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 skpair->sk_state_change(skpair);
Pavel Emelyanov8d8ad9d2007-11-26 20:10:50 +0800419 sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 }
421 sock_put(skpair); /* It may now die */
422 unix_peer(sk) = NULL;
423 }
424
425 /* Try to flush out this socket. Throw out buffers at least */
426
427 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
Jianjun Konge27dfce2008-11-01 21:38:31 -0700428 if (state == TCP_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 unix_release_sock(skb->sk, 1);
430 /* passed fds are erased in the kfree_skb hook */
431 kfree_skb(skb);
432 }
433
Al Viro40ffe672012-03-14 21:54:32 -0400434 if (path.dentry)
435 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 sock_put(sk);
438
439 /* ---- Socket is dead now and most probably destroyed ---- */
440
441 /*
Alan Coxe04dae82012-09-17 00:52:41 +0000442 * Fixme: BSD difference: In BSD all sockets connected to us get
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 * ECONNRESET and we die on the spot. In Linux we behave
444 * like files and pipes do and wait for the last
445 * dereference.
446 *
447 * Can't we simply set sock->err?
448 *
449 * What the above comment does talk about? --ANK(980817)
450 */
451
Pavel Emelyanov9305cfa2007-11-10 22:06:01 -0800452 if (unix_tot_inflight)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900453 unix_gc(); /* Garbage collect fds */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000456static void init_peercred(struct sock *sk)
457{
458 put_pid(sk->sk_peer_pid);
459 if (sk->sk_peer_cred)
460 put_cred(sk->sk_peer_cred);
461 sk->sk_peer_pid = get_pid(task_tgid(current));
462 sk->sk_peer_cred = get_current_cred();
463}
464
465static void copy_peercred(struct sock *sk, struct sock *peersk)
466{
467 put_pid(sk->sk_peer_pid);
468 if (sk->sk_peer_cred)
469 put_cred(sk->sk_peer_cred);
470 sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
471 sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
472}
473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474static int unix_listen(struct socket *sock, int backlog)
475{
476 int err;
477 struct sock *sk = sock->sk;
478 struct unix_sock *u = unix_sk(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000479 struct pid *old_pid = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800482 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
483 goto out; /* Only stream/seqpacket sockets accept */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 err = -EINVAL;
485 if (!u->addr)
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800486 goto out; /* No listens on an unbound socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -0700487 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
489 goto out_unlock;
490 if (backlog > sk->sk_max_ack_backlog)
491 wake_up_interruptible_all(&u->peer_wait);
492 sk->sk_max_ack_backlog = backlog;
493 sk->sk_state = TCP_LISTEN;
494 /* set credentials so connect can copy them */
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000495 init_peercred(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 err = 0;
497
498out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -0700499 unix_state_unlock(sk);
Eric W. Biederman109f6e32010-06-13 03:30:14 +0000500 put_pid(old_pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501out:
502 return err;
503}
504
505static int unix_release(struct socket *);
506static int unix_bind(struct socket *, struct sockaddr *, int);
507static int unix_stream_connect(struct socket *, struct sockaddr *,
508 int addr_len, int flags);
509static int unix_socketpair(struct socket *, struct socket *);
510static int unix_accept(struct socket *, struct socket *, int);
511static int unix_getname(struct socket *, struct sockaddr *, int *, int);
512static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700513static unsigned int unix_dgram_poll(struct file *, struct socket *,
514 poll_table *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515static int unix_ioctl(struct socket *, unsigned int, unsigned long);
516static int unix_shutdown(struct socket *, int);
517static int unix_stream_sendmsg(struct kiocb *, struct socket *,
518 struct msghdr *, size_t);
519static int unix_stream_recvmsg(struct kiocb *, struct socket *,
520 struct msghdr *, size_t, int);
521static int unix_dgram_sendmsg(struct kiocb *, struct socket *,
522 struct msghdr *, size_t);
523static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
524 struct msghdr *, size_t, int);
525static int unix_dgram_connect(struct socket *, struct sockaddr *,
526 int, int);
527static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
528 struct msghdr *, size_t);
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000529static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
530 struct msghdr *, size_t, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000532static void unix_set_peek_off(struct sock *sk, int val)
533{
534 struct unix_sock *u = unix_sk(sk);
535
536 mutex_lock(&u->readlock);
537 sk->sk_peek_off = val;
538 mutex_unlock(&u->readlock);
539}
540
541
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800542static const struct proto_ops unix_stream_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 .family = PF_UNIX,
544 .owner = THIS_MODULE,
545 .release = unix_release,
546 .bind = unix_bind,
547 .connect = unix_stream_connect,
548 .socketpair = unix_socketpair,
549 .accept = unix_accept,
550 .getname = unix_getname,
551 .poll = unix_poll,
552 .ioctl = unix_ioctl,
553 .listen = unix_listen,
554 .shutdown = unix_shutdown,
555 .setsockopt = sock_no_setsockopt,
556 .getsockopt = sock_no_getsockopt,
557 .sendmsg = unix_stream_sendmsg,
558 .recvmsg = unix_stream_recvmsg,
559 .mmap = sock_no_mmap,
560 .sendpage = sock_no_sendpage,
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +0000561 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562};
563
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800564static const struct proto_ops unix_dgram_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 .family = PF_UNIX,
566 .owner = THIS_MODULE,
567 .release = unix_release,
568 .bind = unix_bind,
569 .connect = unix_dgram_connect,
570 .socketpair = unix_socketpair,
571 .accept = sock_no_accept,
572 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700573 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 .ioctl = unix_ioctl,
575 .listen = sock_no_listen,
576 .shutdown = unix_shutdown,
577 .setsockopt = sock_no_setsockopt,
578 .getsockopt = sock_no_getsockopt,
579 .sendmsg = unix_dgram_sendmsg,
580 .recvmsg = unix_dgram_recvmsg,
581 .mmap = sock_no_mmap,
582 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000583 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584};
585
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800586static const struct proto_ops unix_seqpacket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 .family = PF_UNIX,
588 .owner = THIS_MODULE,
589 .release = unix_release,
590 .bind = unix_bind,
591 .connect = unix_stream_connect,
592 .socketpair = unix_socketpair,
593 .accept = unix_accept,
594 .getname = unix_getname,
Rainer Weikusatec0d2152008-06-27 19:34:18 -0700595 .poll = unix_dgram_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 .ioctl = unix_ioctl,
597 .listen = unix_listen,
598 .shutdown = unix_shutdown,
599 .setsockopt = sock_no_setsockopt,
600 .getsockopt = sock_no_getsockopt,
601 .sendmsg = unix_seqpacket_sendmsg,
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +0000602 .recvmsg = unix_seqpacket_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 .mmap = sock_no_mmap,
604 .sendpage = sock_no_sendpage,
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +0000605 .set_peek_off = unix_set_peek_off,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606};
607
608static struct proto unix_proto = {
Eric Dumazet248969a2008-11-17 00:00:30 -0800609 .name = "UNIX",
610 .owner = THIS_MODULE,
Eric Dumazet248969a2008-11-17 00:00:30 -0800611 .obj_size = sizeof(struct unix_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612};
613
Ingo Molnara09785a2006-07-03 00:25:12 -0700614/*
615 * AF_UNIX sockets do not interact with hardware, hence they
616 * dont trigger interrupts - so it's safe for them to have
617 * bh-unsafe locking for their sk_receive_queue.lock. Split off
618 * this special lock-class by reinitializing the spinlock key:
619 */
620static struct lock_class_key af_unix_sk_receive_queue_lock_key;
621
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800622static struct sock *unix_create1(struct net *net, struct socket *sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 struct sock *sk = NULL;
625 struct unix_sock *u;
626
Eric Dumazet518de9b2010-10-26 14:22:44 -0700627 atomic_long_inc(&unix_nr_socks);
628 if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 goto out;
630
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700631 sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (!sk)
633 goto out;
634
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800635 sock_init_data(sock, sk);
Ingo Molnara09785a2006-07-03 00:25:12 -0700636 lockdep_set_class(&sk->sk_receive_queue.lock,
637 &af_unix_sk_receive_queue_lock_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 sk->sk_write_space = unix_write_space;
Denis V. Luneva0a53c82007-12-11 04:19:17 -0800640 sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 sk->sk_destruct = unix_sock_destructor;
642 u = unix_sk(sk);
Al Viro40ffe672012-03-14 21:54:32 -0400643 u->path.dentry = NULL;
644 u->path.mnt = NULL;
Benjamin LaHaisefd19f322006-01-03 14:10:46 -0800645 spin_lock_init(&u->lock);
Al Viro516e0cc2008-07-26 00:39:17 -0400646 atomic_long_set(&u->inflight, 0);
Miklos Szeredi1fd05ba2007-07-11 14:22:39 -0700647 INIT_LIST_HEAD(&u->link);
Ingo Molnar57b47a52006-03-20 22:35:41 -0800648 mutex_init(&u->readlock); /* single task reading lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 init_waitqueue_head(&u->peer_wait);
Eric Dumazet7123aaa2012-06-08 05:03:21 +0000650 unix_insert_socket(unix_sockets_unbound(sk), sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651out:
Pavel Emelyanov284b3272007-11-10 22:08:30 -0800652 if (sk == NULL)
Eric Dumazet518de9b2010-10-26 14:22:44 -0700653 atomic_long_dec(&unix_nr_socks);
Eric Dumazet920de802008-11-24 00:09:29 -0800654 else {
655 local_bh_disable();
Eric Dumazeta8076d82008-11-17 02:38:49 -0800656 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
Eric Dumazet920de802008-11-24 00:09:29 -0800657 local_bh_enable();
658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 return sk;
660}
661
Eric Paris3f378b62009-11-05 22:18:14 -0800662static int unix_create(struct net *net, struct socket *sock, int protocol,
663 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
665 if (protocol && protocol != PF_UNIX)
666 return -EPROTONOSUPPORT;
667
668 sock->state = SS_UNCONNECTED;
669
670 switch (sock->type) {
671 case SOCK_STREAM:
672 sock->ops = &unix_stream_ops;
673 break;
674 /*
675 * Believe it or not BSD has AF_UNIX, SOCK_RAW though
676 * nothing uses it.
677 */
678 case SOCK_RAW:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700679 sock->type = SOCK_DGRAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 case SOCK_DGRAM:
681 sock->ops = &unix_dgram_ops;
682 break;
683 case SOCK_SEQPACKET:
684 sock->ops = &unix_seqpacket_ops;
685 break;
686 default:
687 return -ESOCKTNOSUPPORT;
688 }
689
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700690 return unix_create1(net, sock) ? 0 : -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692
693static int unix_release(struct socket *sock)
694{
695 struct sock *sk = sock->sk;
696
697 if (!sk)
698 return 0;
699
Paul Mooreded34e02013-03-25 03:18:33 +0000700 unix_release_sock(sk, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 sock->sk = NULL;
702
Paul Mooreded34e02013-03-25 03:18:33 +0000703 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704}
705
706static int unix_autobind(struct socket *sock)
707{
708 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900709 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 struct unix_sock *u = unix_sk(sk);
711 static u32 ordernum = 1;
Eric Dumazet6eba6a32008-11-16 22:58:44 -0800712 struct unix_address *addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 int err;
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000714 unsigned int retries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Ingo Molnar57b47a52006-03-20 22:35:41 -0800716 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
718 err = 0;
719 if (u->addr)
720 goto out;
721
722 err = -ENOMEM;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700723 addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 if (!addr)
725 goto out;
726
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 addr->name->sun_family = AF_UNIX;
728 atomic_set(&addr->refcnt, 1);
729
730retry:
731 addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
Joe Perches07f07572008-11-19 15:44:53 -0800732 addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
David S. Millerfbe9cc42005-12-13 23:26:29 -0800734 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 ordernum = (ordernum+1)&0xFFFFF;
736
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800737 if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 addr->hash)) {
David S. Millerfbe9cc42005-12-13 23:26:29 -0800739 spin_unlock(&unix_table_lock);
Tetsuo Handa8df73ff2010-09-04 01:34:28 +0000740 /*
741 * __unix_find_socket_byname() may take long time if many names
742 * are already in use.
743 */
744 cond_resched();
745 /* Give up if all names seems to be in use. */
746 if (retries++ == 0xFFFFF) {
747 err = -ENOSPC;
748 kfree(addr);
749 goto out;
750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 goto retry;
752 }
753 addr->hash ^= sk->sk_type;
754
755 __unix_remove_socket(sk);
756 u->addr = addr;
757 __unix_insert_socket(&unix_socket_table[addr->hash], sk);
David S. Millerfbe9cc42005-12-13 23:26:29 -0800758 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 err = 0;
760
Ingo Molnar57b47a52006-03-20 22:35:41 -0800761out: mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 return err;
763}
764
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800765static struct sock *unix_find_other(struct net *net,
766 struct sockaddr_un *sunname, int len,
Eric Dumazet95c96172012-04-15 05:58:06 +0000767 int type, unsigned int hash, int *error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
769 struct sock *u;
Al Viro421748e2008-08-02 01:04:36 -0400770 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 int err = 0;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +0900772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 if (sunname->sun_path[0]) {
Al Viro421748e2008-08-02 01:04:36 -0400774 struct inode *inode;
775 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 if (err)
777 goto fail;
Al Viro421748e2008-08-02 01:04:36 -0400778 inode = path.dentry->d_inode;
779 err = inode_permission(inode, MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (err)
781 goto put_fail;
782
783 err = -ECONNREFUSED;
Al Viro421748e2008-08-02 01:04:36 -0400784 if (!S_ISSOCK(inode->i_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 goto put_fail;
Eric W. Biederman6616f782010-06-13 03:35:48 +0000786 u = unix_find_socket_byinode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (!u)
788 goto put_fail;
789
790 if (u->sk_type == type)
Al Viro68ac1232012-03-15 08:21:57 -0400791 touch_atime(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Al Viro421748e2008-08-02 01:04:36 -0400793 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
Jianjun Konge27dfce2008-11-01 21:38:31 -0700795 err = -EPROTOTYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 if (u->sk_type != type) {
797 sock_put(u);
798 goto fail;
799 }
800 } else {
801 err = -ECONNREFUSED;
Jianjun Konge27dfce2008-11-01 21:38:31 -0700802 u = unix_find_socket_byname(net, sunname, len, type, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 if (u) {
804 struct dentry *dentry;
Al Viro40ffe672012-03-14 21:54:32 -0400805 dentry = unix_sk(u)->path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 if (dentry)
Al Viro68ac1232012-03-15 08:21:57 -0400807 touch_atime(&unix_sk(u)->path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 } else
809 goto fail;
810 }
811 return u;
812
813put_fail:
Al Viro421748e2008-08-02 01:04:36 -0400814 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815fail:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700816 *error = err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 return NULL;
818}
819
Al Virofaf02012012-07-20 02:37:29 +0400820static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
821{
822 struct dentry *dentry;
823 struct path path;
824 int err = 0;
825 /*
826 * Get the parent directory, calculate the hash for last
827 * component.
828 */
829 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
830 err = PTR_ERR(dentry);
831 if (IS_ERR(dentry))
832 return err;
833
834 /*
835 * All right, let's create it.
836 */
837 err = security_path_mknod(&path, dentry, mode, 0);
838 if (!err) {
839 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
840 if (!err) {
841 res->mnt = mntget(path.mnt);
842 res->dentry = dget(dentry);
843 }
844 }
845 done_path_create(&path, dentry);
846 return err;
847}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
850{
851 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900852 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700854 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Al Virodae6ad82011-06-26 11:50:15 -0400855 char *sun_path = sunaddr->sun_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +0000857 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct unix_address *addr;
859 struct hlist_head *list;
860
861 err = -EINVAL;
862 if (sunaddr->sun_family != AF_UNIX)
863 goto out;
864
Jianjun Konge27dfce2008-11-01 21:38:31 -0700865 if (addr_len == sizeof(short)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 err = unix_autobind(sock);
867 goto out;
868 }
869
870 err = unix_mkname(sunaddr, addr_len, &hash);
871 if (err < 0)
872 goto out;
873 addr_len = err;
874
Ingo Molnar57b47a52006-03-20 22:35:41 -0800875 mutex_lock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
877 err = -EINVAL;
878 if (u->addr)
879 goto out_up;
880
881 err = -ENOMEM;
882 addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
883 if (!addr)
884 goto out_up;
885
886 memcpy(addr->name, sunaddr, addr_len);
887 addr->len = addr_len;
888 addr->hash = hash ^ sk->sk_type;
889 atomic_set(&addr->refcnt, 1);
890
Al Virodae6ad82011-06-26 11:50:15 -0400891 if (sun_path[0]) {
Al Virofaf02012012-07-20 02:37:29 +0400892 struct path path;
893 umode_t mode = S_IFSOCK |
Al Viroce3b0f82009-03-29 19:08:22 -0400894 (SOCK_INODE(sock)->i_mode & ~current_umask());
Al Virofaf02012012-07-20 02:37:29 +0400895 err = unix_mknod(sun_path, mode, &path);
896 if (err) {
897 if (err == -EEXIST)
898 err = -EADDRINUSE;
899 unix_release_addr(addr);
900 goto out_up;
901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 addr->hash = UNIX_HASH_SIZE;
Al Virofaf02012012-07-20 02:37:29 +0400903 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
904 spin_lock(&unix_table_lock);
905 u->path = path;
906 list = &unix_socket_table[hash];
907 } else {
908 spin_lock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 err = -EADDRINUSE;
Denis V. Lunev097e66c2007-11-19 22:29:30 -0800910 if (__unix_find_socket_byname(net, sunaddr, addr_len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 sk->sk_type, hash)) {
912 unix_release_addr(addr);
913 goto out_unlock;
914 }
915
916 list = &unix_socket_table[addr->hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 }
918
919 err = 0;
920 __unix_remove_socket(sk);
921 u->addr = addr;
922 __unix_insert_socket(list, sk);
923
924out_unlock:
David S. Millerfbe9cc42005-12-13 23:26:29 -0800925 spin_unlock(&unix_table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926out_up:
Ingo Molnar57b47a52006-03-20 22:35:41 -0800927 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928out:
929 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930}
931
David S. Miller278a3de2007-05-31 15:19:20 -0700932static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
933{
934 if (unlikely(sk1 == sk2) || !sk2) {
935 unix_state_lock(sk1);
936 return;
937 }
938 if (sk1 < sk2) {
939 unix_state_lock(sk1);
940 unix_state_lock_nested(sk2);
941 } else {
942 unix_state_lock(sk2);
943 unix_state_lock_nested(sk1);
944 }
945}
946
947static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
948{
949 if (unlikely(sk1 == sk2) || !sk2) {
950 unix_state_unlock(sk1);
951 return;
952 }
953 unix_state_unlock(sk1);
954 unix_state_unlock(sk2);
955}
956
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
958 int alen, int flags)
959{
960 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900961 struct net *net = sock_net(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -0700962 struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 struct sock *other;
Eric Dumazet95c96172012-04-15 05:58:06 +0000964 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 int err;
966
967 if (addr->sa_family != AF_UNSPEC) {
968 err = unix_mkname(sunaddr, alen, &hash);
969 if (err < 0)
970 goto out;
971 alen = err;
972
973 if (test_bit(SOCK_PASSCRED, &sock->flags) &&
974 !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
975 goto out;
976
David S. Miller278a3de2007-05-31 15:19:20 -0700977restart:
Jianjun Konge27dfce2008-11-01 21:38:31 -0700978 other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 if (!other)
980 goto out;
981
David S. Miller278a3de2007-05-31 15:19:20 -0700982 unix_state_double_lock(sk, other);
983
984 /* Apparently VFS overslept socket death. Retry. */
985 if (sock_flag(other, SOCK_DEAD)) {
986 unix_state_double_unlock(sk, other);
987 sock_put(other);
988 goto restart;
989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
991 err = -EPERM;
992 if (!unix_may_send(sk, other))
993 goto out_unlock;
994
995 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
996 if (err)
997 goto out_unlock;
998
999 } else {
1000 /*
1001 * 1003.1g breaking connected state with AF_UNSPEC
1002 */
1003 other = NULL;
David S. Miller278a3de2007-05-31 15:19:20 -07001004 unix_state_double_lock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006
1007 /*
1008 * If it was connected, reconnect.
1009 */
1010 if (unix_peer(sk)) {
1011 struct sock *old_peer = unix_peer(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001012 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001013 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
1015 if (other != old_peer)
1016 unix_dgram_disconnected(sk, old_peer);
1017 sock_put(old_peer);
1018 } else {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001019 unix_peer(sk) = other;
David S. Miller278a3de2007-05-31 15:19:20 -07001020 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001022 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
1024out_unlock:
David S. Miller278a3de2007-05-31 15:19:20 -07001025 unix_state_double_unlock(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 sock_put(other);
1027out:
1028 return err;
1029}
1030
1031static long unix_wait_for_peer(struct sock *other, long timeo)
1032{
1033 struct unix_sock *u = unix_sk(other);
1034 int sched;
1035 DEFINE_WAIT(wait);
1036
1037 prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
1038
1039 sched = !sock_flag(other, SOCK_DEAD) &&
1040 !(other->sk_shutdown & RCV_SHUTDOWN) &&
Rainer Weikusat3c734192008-06-17 22:28:05 -07001041 unix_recvq_full(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
David S. Miller1c92b4e2007-05-31 13:24:26 -07001043 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 if (sched)
1046 timeo = schedule_timeout(timeo);
1047
1048 finish_wait(&u->peer_wait, &wait);
1049 return timeo;
1050}
1051
1052static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1053 int addr_len, int flags)
1054{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001055 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001057 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1059 struct sock *newsk = NULL;
1060 struct sock *other = NULL;
1061 struct sk_buff *skb = NULL;
Eric Dumazet95c96172012-04-15 05:58:06 +00001062 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 int st;
1064 int err;
1065 long timeo;
1066
1067 err = unix_mkname(sunaddr, addr_len, &hash);
1068 if (err < 0)
1069 goto out;
1070 addr_len = err;
1071
Joe Perchesf64f9e72009-11-29 16:55:45 -08001072 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
1073 (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 goto out;
1075
1076 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
1077
1078 /* First of all allocate resources.
1079 If we will make it after state is locked,
1080 we will have to recheck all again in any case.
1081 */
1082
1083 err = -ENOMEM;
1084
1085 /* create new sock for complete connection */
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001086 newsk = unix_create1(sock_net(sk), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 if (newsk == NULL)
1088 goto out;
1089
1090 /* Allocate skb for sending to listening sock */
1091 skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
1092 if (skb == NULL)
1093 goto out;
1094
1095restart:
1096 /* Find listening sock. */
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001097 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (!other)
1099 goto out;
1100
1101 /* Latch state of peer */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001102 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 /* Apparently VFS overslept socket death. Retry. */
1105 if (sock_flag(other, SOCK_DEAD)) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001106 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 sock_put(other);
1108 goto restart;
1109 }
1110
1111 err = -ECONNREFUSED;
1112 if (other->sk_state != TCP_LISTEN)
1113 goto out_unlock;
Tomoki Sekiyama77238f22009-10-18 23:17:37 -07001114 if (other->sk_shutdown & RCV_SHUTDOWN)
1115 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Rainer Weikusat3c734192008-06-17 22:28:05 -07001117 if (unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 err = -EAGAIN;
1119 if (!timeo)
1120 goto out_unlock;
1121
1122 timeo = unix_wait_for_peer(other, timeo);
1123
1124 err = sock_intr_errno(timeo);
1125 if (signal_pending(current))
1126 goto out;
1127 sock_put(other);
1128 goto restart;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
1131 /* Latch our state.
1132
Daniel Balutae5537bf2011-03-14 15:25:33 -07001133 It is tricky place. We need to grab our state lock and cannot
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 drop lock on peer. It is dangerous because deadlock is
1135 possible. Connect to self case and simultaneous
1136 attempt to connect are eliminated by checking socket
1137 state. other is TCP_LISTEN, if sk is TCP_LISTEN we
1138 check this before attempt to grab lock.
1139
1140 Well, and we have to recheck the state after socket locked.
1141 */
1142 st = sk->sk_state;
1143
1144 switch (st) {
1145 case TCP_CLOSE:
1146 /* This is ok... continue with connect */
1147 break;
1148 case TCP_ESTABLISHED:
1149 /* Socket is already connected */
1150 err = -EISCONN;
1151 goto out_unlock;
1152 default:
1153 err = -EINVAL;
1154 goto out_unlock;
1155 }
1156
David S. Miller1c92b4e2007-05-31 13:24:26 -07001157 unix_state_lock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
1159 if (sk->sk_state != st) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001160 unix_state_unlock(sk);
1161 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 sock_put(other);
1163 goto restart;
1164 }
1165
David S. Miller3610cda2011-01-05 15:38:53 -08001166 err = security_unix_stream_connect(sk, other, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 if (err) {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001168 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 goto out_unlock;
1170 }
1171
1172 /* The way is open! Fastly set all the necessary fields... */
1173
1174 sock_hold(sk);
1175 unix_peer(newsk) = sk;
1176 newsk->sk_state = TCP_ESTABLISHED;
1177 newsk->sk_type = sk->sk_type;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001178 init_peercred(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 newu = unix_sk(newsk);
Eric Dumazeteaefd112011-02-18 03:26:36 +00001180 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 otheru = unix_sk(other);
1182
1183 /* copy address information from listening to new sock*/
1184 if (otheru->addr) {
1185 atomic_inc(&otheru->addr->refcnt);
1186 newu->addr = otheru->addr;
1187 }
Al Viro40ffe672012-03-14 21:54:32 -04001188 if (otheru->path.dentry) {
1189 path_get(&otheru->path);
1190 newu->path = otheru->path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
1192
1193 /* Set credentials */
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001194 copy_peercred(sk, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 sock->state = SS_CONNECTED;
1197 sk->sk_state = TCP_ESTABLISHED;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001198 sock_hold(newsk);
1199
1200 smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
1201 unix_peer(sk) = newsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
David S. Miller1c92b4e2007-05-31 13:24:26 -07001203 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
1205 /* take ten and and send info to listening sock */
1206 spin_lock(&other->sk_receive_queue.lock);
1207 __skb_queue_tail(&other->sk_receive_queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 spin_unlock(&other->sk_receive_queue.lock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001209 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 other->sk_data_ready(other, 0);
1211 sock_put(other);
1212 return 0;
1213
1214out_unlock:
1215 if (other)
David S. Miller1c92b4e2007-05-31 13:24:26 -07001216 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218out:
Wei Yongjun40d44442009-02-25 00:32:45 +00001219 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 if (newsk)
1221 unix_release_sock(newsk, 0);
1222 if (other)
1223 sock_put(other);
1224 return err;
1225}
1226
1227static int unix_socketpair(struct socket *socka, struct socket *sockb)
1228{
Jianjun Konge27dfce2008-11-01 21:38:31 -07001229 struct sock *ska = socka->sk, *skb = sockb->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 /* Join our sockets back to back */
1232 sock_hold(ska);
1233 sock_hold(skb);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001234 unix_peer(ska) = skb;
1235 unix_peer(skb) = ska;
Eric W. Biederman109f6e32010-06-13 03:30:14 +00001236 init_peercred(ska);
1237 init_peercred(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239 if (ska->sk_type != SOCK_DGRAM) {
1240 ska->sk_state = TCP_ESTABLISHED;
1241 skb->sk_state = TCP_ESTABLISHED;
1242 socka->state = SS_CONNECTED;
1243 sockb->state = SS_CONNECTED;
1244 }
1245 return 0;
1246}
1247
1248static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
1249{
1250 struct sock *sk = sock->sk;
1251 struct sock *tsk;
1252 struct sk_buff *skb;
1253 int err;
1254
1255 err = -EOPNOTSUPP;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001256 if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 goto out;
1258
1259 err = -EINVAL;
1260 if (sk->sk_state != TCP_LISTEN)
1261 goto out;
1262
1263 /* If socket state is TCP_LISTEN it cannot change (for now...),
1264 * so that no locks are necessary.
1265 */
1266
1267 skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
1268 if (!skb) {
1269 /* This means receive shutdown. */
1270 if (err == 0)
1271 err = -EINVAL;
1272 goto out;
1273 }
1274
1275 tsk = skb->sk;
1276 skb_free_datagram(sk, skb);
1277 wake_up_interruptible(&unix_sk(sk)->peer_wait);
1278
1279 /* attach accepted sock to socket */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001280 unix_state_lock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 newsock->state = SS_CONNECTED;
1282 sock_graft(tsk, newsock);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001283 unix_state_unlock(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return 0;
1285
1286out:
1287 return err;
1288}
1289
1290
1291static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
1292{
1293 struct sock *sk = sock->sk;
1294 struct unix_sock *u;
Cyrill Gorcunov13cfa972009-11-08 05:51:19 +00001295 DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 int err = 0;
1297
1298 if (peer) {
1299 sk = unix_peer_get(sk);
1300
1301 err = -ENOTCONN;
1302 if (!sk)
1303 goto out;
1304 err = 0;
1305 } else {
1306 sock_hold(sk);
1307 }
1308
1309 u = unix_sk(sk);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001310 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 if (!u->addr) {
1312 sunaddr->sun_family = AF_UNIX;
1313 sunaddr->sun_path[0] = 0;
1314 *uaddr_len = sizeof(short);
1315 } else {
1316 struct unix_address *addr = u->addr;
1317
1318 *uaddr_len = addr->len;
1319 memcpy(sunaddr, addr->name, *uaddr_len);
1320 }
David S. Miller1c92b4e2007-05-31 13:24:26 -07001321 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 sock_put(sk);
1323out:
1324 return err;
1325}
1326
1327static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
1328{
1329 int i;
1330
1331 scm->fp = UNIXCB(skb).fp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 UNIXCB(skb).fp = NULL;
1333
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001334 for (i = scm->fp->count-1; i >= 0; i--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 unix_notinflight(scm->fp->fp[i]);
1336}
1337
Eric W. Biederman7361c362010-06-13 03:34:33 +00001338static void unix_destruct_scm(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339{
1340 struct scm_cookie scm;
1341 memset(&scm, 0, sizeof(scm));
Eric W. Biederman7361c362010-06-13 03:34:33 +00001342 scm.pid = UNIXCB(skb).pid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001343 if (UNIXCB(skb).fp)
1344 unix_detach_fds(&scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
1346 /* Alas, it calls VFS */
1347 /* So fscking what? fput() had been SMP-safe since the last Summer */
1348 scm_destroy(&scm);
1349 sock_wfree(skb);
1350}
1351
Eric Dumazet25888e32010-11-25 04:11:39 +00001352#define MAX_RECURSION_LEVEL 4
1353
Miklos Szeredi62093442008-11-09 15:23:57 +01001354static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355{
1356 int i;
Eric Dumazet25888e32010-11-25 04:11:39 +00001357 unsigned char max_level = 0;
1358 int unix_sock_count = 0;
1359
1360 for (i = scm->fp->count - 1; i >= 0; i--) {
1361 struct sock *sk = unix_get_socket(scm->fp->fp[i]);
1362
1363 if (sk) {
1364 unix_sock_count++;
1365 max_level = max(max_level,
1366 unix_sk(sk)->recursion_level);
1367 }
1368 }
1369 if (unlikely(max_level > MAX_RECURSION_LEVEL))
1370 return -ETOOMANYREFS;
Miklos Szeredi62093442008-11-09 15:23:57 +01001371
1372 /*
1373 * Need to duplicate file references for the sake of garbage
1374 * collection. Otherwise a socket in the fps might become a
1375 * candidate for GC while the skb is not yet queued.
1376 */
1377 UNIXCB(skb).fp = scm_fp_dup(scm->fp);
1378 if (!UNIXCB(skb).fp)
1379 return -ENOMEM;
1380
Eric Dumazet25888e32010-11-25 04:11:39 +00001381 if (unix_sock_count) {
1382 for (i = scm->fp->count - 1; i >= 0; i--)
1383 unix_inflight(scm->fp->fp[i]);
1384 }
1385 return max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386}
1387
David S. Millerf78a5fd2011-09-16 19:34:00 -04001388static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001389{
1390 int err = 0;
Eric Dumazet16e57262011-09-19 05:52:27 +00001391
David S. Millerf78a5fd2011-09-16 19:34:00 -04001392 UNIXCB(skb).pid = get_pid(scm->pid);
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001393 UNIXCB(skb).uid = scm->creds.uid;
1394 UNIXCB(skb).gid = scm->creds.gid;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001395 UNIXCB(skb).fp = NULL;
1396 if (scm->fp && send_fds)
1397 err = unix_attach_fds(scm, skb);
1398
1399 skb->destructor = unix_destruct_scm;
1400 return err;
1401}
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403/*
Eric Dumazet16e57262011-09-19 05:52:27 +00001404 * Some apps rely on write() giving SCM_CREDENTIALS
1405 * We include credentials if source or destination socket
1406 * asserted SOCK_PASSCRED.
1407 */
1408static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
1409 const struct sock *other)
1410{
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001411 if (UNIXCB(skb).pid)
Eric Dumazet16e57262011-09-19 05:52:27 +00001412 return;
1413 if (test_bit(SOCK_PASSCRED, &sock->flags) ||
Eric W. Biederman25da0e32013-04-03 16:13:35 +00001414 !other->sk_socket ||
1415 test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
Eric Dumazet16e57262011-09-19 05:52:27 +00001416 UNIXCB(skb).pid = get_pid(task_tgid(current));
David S. Miller6e0895c2013-04-22 20:32:51 -04001417 current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
Eric Dumazet16e57262011-09-19 05:52:27 +00001418 }
1419}
1420
1421/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 * Send AF_UNIX data.
1423 */
1424
1425static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1426 struct msghdr *msg, size_t len)
1427{
1428 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1429 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001430 struct net *net = sock_net(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001432 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 struct sock *other = NULL;
1434 int namelen = 0; /* fake GCC */
1435 int err;
Eric Dumazet95c96172012-04-15 05:58:06 +00001436 unsigned int hash;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001437 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 long timeo;
1439 struct scm_cookie tmp_scm;
Eric Dumazet25888e32010-11-25 04:11:39 +00001440 int max_level;
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001441 int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
1443 if (NULL == siocb->scm)
1444 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001445 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001446 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 if (err < 0)
1448 return err;
1449
1450 err = -EOPNOTSUPP;
1451 if (msg->msg_flags&MSG_OOB)
1452 goto out;
1453
1454 if (msg->msg_namelen) {
1455 err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
1456 if (err < 0)
1457 goto out;
1458 namelen = err;
1459 } else {
1460 sunaddr = NULL;
1461 err = -ENOTCONN;
1462 other = unix_peer_get(sk);
1463 if (!other)
1464 goto out;
1465 }
1466
Joe Perchesf64f9e72009-11-29 16:55:45 -08001467 if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
1468 && (err = unix_autobind(sock)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 goto out;
1470
1471 err = -EMSGSIZE;
1472 if (len > sk->sk_sndbuf - 32)
1473 goto out;
1474
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001475 if (len > SKB_MAX_ALLOC)
1476 data_len = min_t(size_t,
1477 len - SKB_MAX_ALLOC,
1478 MAX_SKB_FRAGS * PAGE_SIZE);
1479
1480 skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
1481 msg->msg_flags & MSG_DONTWAIT, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001482 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 goto out;
1484
David S. Millerf78a5fd2011-09-16 19:34:00 -04001485 err = unix_scm_to_skb(siocb->scm, skb, true);
Eric Dumazet25888e32010-11-25 04:11:39 +00001486 if (err < 0)
Eric W. Biederman7361c362010-06-13 03:34:33 +00001487 goto out_free;
Eric Dumazet25888e32010-11-25 04:11:39 +00001488 max_level = err + 1;
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07001489 unix_get_secdata(siocb->scm, skb);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001490
Eric Dumazeteb6a2482012-04-03 05:28:28 +00001491 skb_put(skb, len - data_len);
1492 skb->data_len = data_len;
1493 skb->len = len;
1494 err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 if (err)
1496 goto out_free;
1497
1498 timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
1499
1500restart:
1501 if (!other) {
1502 err = -ECONNRESET;
1503 if (sunaddr == NULL)
1504 goto out_free;
1505
Denis V. Lunev097e66c2007-11-19 22:29:30 -08001506 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 hash, &err);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001508 if (other == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 goto out_free;
1510 }
1511
Alban Crequyd6ae3ba2011-01-18 06:39:15 +00001512 if (sk_filter(other, skb) < 0) {
1513 /* Toss the packet but do not return any error to the sender */
1514 err = len;
1515 goto out_free;
1516 }
1517
David S. Miller1c92b4e2007-05-31 13:24:26 -07001518 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 err = -EPERM;
1520 if (!unix_may_send(sk, other))
1521 goto out_unlock;
1522
1523 if (sock_flag(other, SOCK_DEAD)) {
1524 /*
1525 * Check with 1003.1g - what should
1526 * datagram error
1527 */
David S. Miller1c92b4e2007-05-31 13:24:26 -07001528 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 sock_put(other);
1530
1531 err = 0;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001532 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 if (unix_peer(sk) == other) {
Jianjun Konge27dfce2008-11-01 21:38:31 -07001534 unix_peer(sk) = NULL;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001535 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537 unix_dgram_disconnected(sk, other);
1538 sock_put(other);
1539 err = -ECONNREFUSED;
1540 } else {
David S. Miller1c92b4e2007-05-31 13:24:26 -07001541 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 }
1543
1544 other = NULL;
1545 if (err)
1546 goto out_free;
1547 goto restart;
1548 }
1549
1550 err = -EPIPE;
1551 if (other->sk_shutdown & RCV_SHUTDOWN)
1552 goto out_unlock;
1553
1554 if (sk->sk_type != SOCK_SEQPACKET) {
1555 err = security_unix_may_send(sk->sk_socket, other->sk_socket);
1556 if (err)
1557 goto out_unlock;
1558 }
1559
Rainer Weikusat3c734192008-06-17 22:28:05 -07001560 if (unix_peer(other) != sk && unix_recvq_full(other)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 if (!timeo) {
1562 err = -EAGAIN;
1563 goto out_unlock;
1564 }
1565
1566 timeo = unix_wait_for_peer(other, timeo);
1567
1568 err = sock_intr_errno(timeo);
1569 if (signal_pending(current))
1570 goto out_free;
1571
1572 goto restart;
1573 }
1574
Alban Crequy3f661162010-10-04 08:48:28 +00001575 if (sock_flag(other, SOCK_RCVTSTAMP))
1576 __net_timestamp(skb);
Eric Dumazet16e57262011-09-19 05:52:27 +00001577 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001579 if (max_level > unix_sk(other)->recursion_level)
1580 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001581 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 other->sk_data_ready(other, len);
1583 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001584 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return len;
1586
1587out_unlock:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001588 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589out_free:
1590 kfree_skb(skb);
1591out:
1592 if (other)
1593 sock_put(other);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001594 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 return err;
1596}
1597
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001598
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1600 struct msghdr *msg, size_t len)
1601{
1602 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1603 struct sock *sk = sock->sk;
1604 struct sock *other = NULL;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001605 int err, size;
David S. Millerf78a5fd2011-09-16 19:34:00 -04001606 struct sk_buff *skb;
Jianjun Konge27dfce2008-11-01 21:38:31 -07001607 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 struct scm_cookie tmp_scm;
Miklos Szeredi8ba69ba2009-09-11 11:31:45 -07001609 bool fds_sent = false;
Eric Dumazet25888e32010-11-25 04:11:39 +00001610 int max_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 if (NULL == siocb->scm)
1613 siocb->scm = &tmp_scm;
dann frazier5f23b732008-11-26 15:32:27 -08001614 wait_for_unix_gc();
Eric Dumazete0e3cea2012-08-21 06:21:17 +00001615 err = scm_send(sock, msg, siocb->scm, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 if (err < 0)
1617 return err;
1618
1619 err = -EOPNOTSUPP;
1620 if (msg->msg_flags&MSG_OOB)
1621 goto out_err;
1622
1623 if (msg->msg_namelen) {
1624 err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
1625 goto out_err;
1626 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 err = -ENOTCONN;
Benjamin LaHaise830a1e52005-12-13 23:22:32 -08001628 other = unix_peer(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 if (!other)
1630 goto out_err;
1631 }
1632
1633 if (sk->sk_shutdown & SEND_SHUTDOWN)
1634 goto pipe_err;
1635
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001636 while (sent < len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 /*
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001638 * Optimisation for the fact that under 0.01% of X
1639 * messages typically need breaking up.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 */
1641
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001642 size = len-sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 /* Keep two messages in the pipe so it schedules better */
Benjamin LaHaisee9df7d7f2006-03-20 21:29:05 -08001645 if (size > ((sk->sk_sndbuf >> 1) - 64))
1646 size = (sk->sk_sndbuf >> 1) - 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648 if (size > SKB_MAX_ALLOC)
1649 size = SKB_MAX_ALLOC;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001650
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 /*
1652 * Grab a buffer
1653 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001654
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001655 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT,
1656 &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
Jianjun Konge27dfce2008-11-01 21:38:31 -07001658 if (skb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 goto out_err;
1660
1661 /*
1662 * If you pass two values to the sock_alloc_send_skb
1663 * it tries to grab the large buffer with GFP_NOFS
1664 * (which can fail easily), and if it fails grab the
1665 * fallback size buffer which is under a page and will
1666 * succeed. [Alan]
1667 */
1668 size = min_t(int, size, skb_tailroom(skb));
1669
Eric W. Biederman7361c362010-06-13 03:34:33 +00001670
David S. Millerf78a5fd2011-09-16 19:34:00 -04001671 /* Only send the fds in the first buffer */
1672 err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
Eric Dumazet25888e32010-11-25 04:11:39 +00001673 if (err < 0) {
Eric W. Biederman7361c362010-06-13 03:34:33 +00001674 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001675 goto out_err;
Miklos Szeredi62093442008-11-09 15:23:57 +01001676 }
Eric Dumazet25888e32010-11-25 04:11:39 +00001677 max_level = err + 1;
Eric W. Biederman7361c362010-06-13 03:34:33 +00001678 fds_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001680 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1681 if (err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 kfree_skb(skb);
David S. Millerf78a5fd2011-09-16 19:34:00 -04001683 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 }
1685
David S. Miller1c92b4e2007-05-31 13:24:26 -07001686 unix_state_lock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 if (sock_flag(other, SOCK_DEAD) ||
1689 (other->sk_shutdown & RCV_SHUTDOWN))
1690 goto pipe_err_free;
1691
Eric Dumazet16e57262011-09-19 05:52:27 +00001692 maybe_add_creds(skb, sock, other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 skb_queue_tail(&other->sk_receive_queue, skb);
Eric Dumazet25888e32010-11-25 04:11:39 +00001694 if (max_level > unix_sk(other)->recursion_level)
1695 unix_sk(other)->recursion_level = max_level;
David S. Miller1c92b4e2007-05-31 13:24:26 -07001696 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 other->sk_data_ready(other, size);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001698 sent += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
David S. Millerf78a5fd2011-09-16 19:34:00 -04001701 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 siocb->scm = NULL;
1703
1704 return sent;
1705
1706pipe_err_free:
David S. Miller1c92b4e2007-05-31 13:24:26 -07001707 unix_state_unlock(other);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 kfree_skb(skb);
1709pipe_err:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001710 if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
1711 send_sig(SIGPIPE, current, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 err = -EPIPE;
1713out_err:
David S. Millerf78a5fd2011-09-16 19:34:00 -04001714 scm_destroy(siocb->scm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 siocb->scm = NULL;
1716 return sent ? : err;
1717}
1718
1719static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
1720 struct msghdr *msg, size_t len)
1721{
1722 int err;
1723 struct sock *sk = sock->sk;
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001724
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 err = sock_error(sk);
1726 if (err)
1727 return err;
1728
1729 if (sk->sk_state != TCP_ESTABLISHED)
1730 return -ENOTCONN;
1731
1732 if (msg->msg_namelen)
1733 msg->msg_namelen = 0;
1734
1735 return unix_dgram_sendmsg(kiocb, sock, msg, len);
1736}
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001737
Eric W. Biedermana05d2ad2011-04-24 01:54:57 +00001738static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
1739 struct msghdr *msg, size_t size,
1740 int flags)
1741{
1742 struct sock *sk = sock->sk;
1743
1744 if (sk->sk_state != TCP_ESTABLISHED)
1745 return -ENOTCONN;
1746
1747 return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
1748}
1749
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
1751{
1752 struct unix_sock *u = unix_sk(sk);
1753
1754 msg->msg_namelen = 0;
1755 if (u->addr) {
1756 msg->msg_namelen = u->addr->len;
1757 memcpy(msg->msg_name, u->addr->name, u->addr->len);
1758 }
1759}
1760
1761static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1762 struct msghdr *msg, size_t size,
1763 int flags)
1764{
1765 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1766 struct scm_cookie tmp_scm;
1767 struct sock *sk = sock->sk;
1768 struct unix_sock *u = unix_sk(sk);
1769 int noblock = flags & MSG_DONTWAIT;
1770 struct sk_buff *skb;
1771 int err;
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001772 int peeked, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 err = -EOPNOTSUPP;
1775 if (flags&MSG_OOB)
1776 goto out;
1777
1778 msg->msg_namelen = 0;
1779
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001780 err = mutex_lock_interruptible(&u->readlock);
1781 if (err) {
1782 err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
1783 goto out;
1784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001786 skip = sk_peek_offset(sk, flags);
1787
1788 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001789 if (!skb) {
1790 unix_state_lock(sk);
1791 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
1792 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
1793 (sk->sk_shutdown & RCV_SHUTDOWN))
1794 err = 0;
1795 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 goto out_unlock;
Florian Zumbiehl0a112252007-11-29 23:19:23 +11001797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Eric Dumazet67426b72010-10-29 20:44:44 +00001799 wake_up_interruptible_sync_poll(&u->peer_wait,
1800 POLLOUT | POLLWRNORM | POLLWRBAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
1802 if (msg->msg_name)
1803 unix_copy_addr(msg, skb->sk);
1804
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001805 if (size > skb->len - skip)
1806 size = skb->len - skip;
1807 else if (size < skb->len - skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 msg->msg_flags |= MSG_TRUNC;
1809
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001810 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 if (err)
1812 goto out_free;
1813
Alban Crequy3f661162010-10-04 08:48:28 +00001814 if (sock_flag(sk, SOCK_RCVTSTAMP))
1815 __sock_recv_timestamp(msg, sk, skb);
1816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 if (!siocb->scm) {
1818 siocb->scm = &tmp_scm;
1819 memset(&tmp_scm, 0, sizeof(tmp_scm));
1820 }
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001821 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Catherine Zhang877ce7c2006-06-29 12:27:47 -07001822 unix_set_secdata(siocb->scm, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001824 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 if (UNIXCB(skb).fp)
1826 unix_detach_fds(siocb->scm, skb);
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001827
1828 sk_peek_offset_bwd(sk, skb->len);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001829 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 /* It is questionable: on PEEK we could:
1831 - do not return fds - good, but too simple 8)
1832 - return fds, and do not return them on read (old strategy,
1833 apparently wrong)
1834 - clone fds (I chose it for now, it is the most universal
1835 solution)
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001836
1837 POSIX 1003.1g does not actually define this clearly
1838 at all. POSIX 1003.1g doesn't define a lot of things
1839 clearly however!
1840
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 */
Pavel Emelyanovf55bb7f2012-02-21 07:31:51 +00001842
1843 sk_peek_offset_fwd(sk, size);
1844
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 if (UNIXCB(skb).fp)
1846 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1847 }
Eric Dumazet9f6f9af2012-02-21 23:24:55 +00001848 err = (flags & MSG_TRUNC) ? skb->len - skip : size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
1850 scm_recv(sock, msg, siocb->scm, flags);
1851
1852out_free:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001853 skb_free_datagram(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854out_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001855 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856out:
1857 return err;
1858}
1859
1860/*
1861 * Sleep until data has arrive. But check for races..
1862 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001863
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001864static long unix_stream_data_wait(struct sock *sk, long timeo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
1866 DEFINE_WAIT(wait);
1867
David S. Miller1c92b4e2007-05-31 13:24:26 -07001868 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870 for (;;) {
Eric Dumazetaa395142010-04-20 13:03:51 +00001871 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
David S. Millerb03efcf2005-07-08 14:57:23 -07001873 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 sk->sk_err ||
1875 (sk->sk_shutdown & RCV_SHUTDOWN) ||
1876 signal_pending(current) ||
1877 !timeo)
1878 break;
1879
1880 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001881 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 timeo = schedule_timeout(timeo);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001883 unix_state_lock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
1885 }
1886
Eric Dumazetaa395142010-04-20 13:03:51 +00001887 finish_wait(sk_sleep(sk), &wait);
David S. Miller1c92b4e2007-05-31 13:24:26 -07001888 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 return timeo;
1890}
1891
1892
1893
1894static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1895 struct msghdr *msg, size_t size,
1896 int flags)
1897{
1898 struct sock_iocb *siocb = kiocb_to_siocb(iocb);
1899 struct scm_cookie tmp_scm;
1900 struct sock *sk = sock->sk;
1901 struct unix_sock *u = unix_sk(sk);
Jianjun Konge27dfce2008-11-01 21:38:31 -07001902 struct sockaddr_un *sunaddr = msg->msg_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 int copied = 0;
1904 int check_creds = 0;
1905 int target;
1906 int err = 0;
1907 long timeo;
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001908 int skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 err = -EINVAL;
1911 if (sk->sk_state != TCP_ESTABLISHED)
1912 goto out;
1913
1914 err = -EOPNOTSUPP;
1915 if (flags&MSG_OOB)
1916 goto out;
1917
1918 target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
1919 timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
1920
1921 msg->msg_namelen = 0;
1922
1923 /* Lock the socket to prevent queue disordering
1924 * while sleeps in memcpy_tomsg
1925 */
1926
1927 if (!siocb->scm) {
1928 siocb->scm = &tmp_scm;
1929 memset(&tmp_scm, 0, sizeof(tmp_scm));
1930 }
1931
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001932 err = mutex_lock_interruptible(&u->readlock);
1933 if (err) {
1934 err = sock_intr_errno(timeo);
1935 goto out;
1936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001938 skip = sk_peek_offset(sk, flags);
1939
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001940 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 int chunk;
1942 struct sk_buff *skb;
1943
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001944 unix_state_lock(sk);
Eric Dumazet6f01fd62012-01-28 16:11:03 +00001945 skb = skb_peek(&sk->sk_receive_queue);
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001946again:
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001947 if (skb == NULL) {
Eric Dumazet25888e32010-11-25 04:11:39 +00001948 unix_sk(sk)->recursion_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 if (copied >= target)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001950 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
1952 /*
1953 * POSIX 1003.1g mandates this order.
1954 */
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09001955
Eric Dumazet6eba6a32008-11-16 22:58:44 -08001956 err = sock_error(sk);
1957 if (err)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001958 goto unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 if (sk->sk_shutdown & RCV_SHUTDOWN)
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001960 goto unlock;
1961
1962 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 err = -EAGAIN;
1964 if (!timeo)
1965 break;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001966 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
1968 timeo = unix_stream_data_wait(sk, timeo);
1969
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001970 if (signal_pending(current)
1971 || mutex_lock_interruptible(&u->readlock)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 err = sock_intr_errno(timeo);
1973 goto out;
1974 }
Rainer Weikusatb3ca9b02011-02-28 04:50:55 +00001975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 continue;
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001977 unlock:
1978 unix_state_unlock(sk);
1979 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 }
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00001981
1982 if (skip >= skb->len) {
1983 skip -= skb->len;
1984 skb = skb_peek_next(skb, &sk->sk_receive_queue);
1985 goto again;
1986 }
1987
Miklos Szeredi3c0d2f32007-06-05 13:10:29 -07001988 unix_state_unlock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
1990 if (check_creds) {
1991 /* Never glue messages from different writers */
Eric W. Biederman7361c362010-06-13 03:34:33 +00001992 if ((UNIXCB(skb).pid != siocb->scm->pid) ||
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001993 !uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) ||
1994 !gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 break;
Eric W. Biederman0e82e7f6d2013-04-03 16:14:47 +00001996 } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 /* Copy credentials */
Eric W. Biederman6b0ee8c02013-04-03 17:28:16 +00001998 scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 check_creds = 1;
2000 }
2001
2002 /* Copy address just once */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002003 if (sunaddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 unix_copy_addr(msg, skb->sk);
2005 sunaddr = NULL;
2006 }
2007
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002008 chunk = min_t(unsigned int, skb->len - skip, size);
2009 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 if (copied == 0)
2011 copied = -EFAULT;
2012 break;
2013 }
2014 copied += chunk;
2015 size -= chunk;
2016
2017 /* Mark read part of skb as used */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002018 if (!(flags & MSG_PEEK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 skb_pull(skb, chunk);
2020
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002021 sk_peek_offset_bwd(sk, chunk);
2022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (UNIXCB(skb).fp)
2024 unix_detach_fds(siocb->scm, skb);
2025
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002026 if (skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
Eric Dumazet6f01fd62012-01-28 16:11:03 +00002029 skb_unlink(skb, &sk->sk_receive_queue);
Neil Horman70d4bf62010-07-20 06:45:56 +00002030 consume_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
2032 if (siocb->scm->fp)
2033 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002034 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 /* It is questionable, see note in unix_dgram_recvmsg.
2036 */
2037 if (UNIXCB(skb).fp)
2038 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2039
Pavel Emelyanovfc0d7532012-02-21 07:32:06 +00002040 sk_peek_offset_fwd(sk, chunk);
2041
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 break;
2043 }
2044 } while (size);
2045
Ingo Molnar57b47a52006-03-20 22:35:41 -08002046 mutex_unlock(&u->readlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 scm_recv(sock, msg, siocb->scm, flags);
2048out:
2049 return copied ? : err;
2050}
2051
2052static int unix_shutdown(struct socket *sock, int mode)
2053{
2054 struct sock *sk = sock->sk;
2055 struct sock *other;
2056
Xi Wangfc61b922012-08-26 16:47:13 +00002057 if (mode < SHUT_RD || mode > SHUT_RDWR)
2058 return -EINVAL;
2059 /* This maps:
2060 * SHUT_RD (0) -> RCV_SHUTDOWN (1)
2061 * SHUT_WR (1) -> SEND_SHUTDOWN (2)
2062 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
2063 */
2064 ++mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
Alban Crequy7180a032011-01-19 04:56:36 +00002066 unix_state_lock(sk);
2067 sk->sk_shutdown |= mode;
2068 other = unix_peer(sk);
2069 if (other)
2070 sock_hold(other);
2071 unix_state_unlock(sk);
2072 sk->sk_state_change(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Alban Crequy7180a032011-01-19 04:56:36 +00002074 if (other &&
2075 (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Alban Crequy7180a032011-01-19 04:56:36 +00002077 int peer_mode = 0;
2078
2079 if (mode&RCV_SHUTDOWN)
2080 peer_mode |= SEND_SHUTDOWN;
2081 if (mode&SEND_SHUTDOWN)
2082 peer_mode |= RCV_SHUTDOWN;
2083 unix_state_lock(other);
2084 other->sk_shutdown |= peer_mode;
2085 unix_state_unlock(other);
2086 other->sk_state_change(other);
2087 if (peer_mode == SHUTDOWN_MASK)
2088 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
2089 else if (peer_mode & RCV_SHUTDOWN)
2090 sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 }
Alban Crequy7180a032011-01-19 04:56:36 +00002092 if (other)
2093 sock_put(other);
2094
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 return 0;
2096}
2097
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002098long unix_inq_len(struct sock *sk)
2099{
2100 struct sk_buff *skb;
2101 long amount = 0;
2102
2103 if (sk->sk_state == TCP_LISTEN)
2104 return -EINVAL;
2105
2106 spin_lock(&sk->sk_receive_queue.lock);
2107 if (sk->sk_type == SOCK_STREAM ||
2108 sk->sk_type == SOCK_SEQPACKET) {
2109 skb_queue_walk(&sk->sk_receive_queue, skb)
2110 amount += skb->len;
2111 } else {
2112 skb = skb_peek(&sk->sk_receive_queue);
2113 if (skb)
2114 amount = skb->len;
2115 }
2116 spin_unlock(&sk->sk_receive_queue.lock);
2117
2118 return amount;
2119}
2120EXPORT_SYMBOL_GPL(unix_inq_len);
2121
2122long unix_outq_len(struct sock *sk)
2123{
2124 return sk_wmem_alloc_get(sk);
2125}
2126EXPORT_SYMBOL_GPL(unix_outq_len);
2127
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2129{
2130 struct sock *sk = sock->sk;
Jianjun Konge27dfce2008-11-01 21:38:31 -07002131 long amount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 int err;
2133
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002134 switch (cmd) {
2135 case SIOCOUTQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002136 amount = unix_outq_len(sk);
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002137 err = put_user(amount, (int __user *)arg);
2138 break;
2139 case SIOCINQ:
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002140 amount = unix_inq_len(sk);
2141 if (amount < 0)
2142 err = amount;
2143 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 err = put_user(amount, (int __user *)arg);
Pavel Emelyanov885ee742011-12-30 00:54:11 +00002145 break;
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002146 default:
2147 err = -ENOIOCTLCMD;
2148 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 }
2150 return err;
2151}
2152
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002153static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154{
2155 struct sock *sk = sock->sk;
2156 unsigned int mask;
2157
Eric Dumazetaa395142010-04-20 13:03:51 +00002158 sock_poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 mask = 0;
2160
2161 /* exceptional events? */
2162 if (sk->sk_err)
2163 mask |= POLLERR;
2164 if (sk->sk_shutdown == SHUTDOWN_MASK)
2165 mask |= POLLHUP;
Davide Libenzif348d702006-03-25 03:07:39 -08002166 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +00002167 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
2169 /* readable? */
Eric Dumazetdb409802010-09-06 11:13:50 +00002170 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 mask |= POLLIN | POLLRDNORM;
2172
2173 /* Connection-based need to check for termination and startup */
Eric Dumazet6eba6a32008-11-16 22:58:44 -08002174 if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
2175 sk->sk_state == TCP_CLOSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 mask |= POLLHUP;
2177
2178 /*
2179 * we set writable also when the other side has shut down the
2180 * connection. This prevents stuck sockets.
2181 */
2182 if (unix_writable(sk))
2183 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
2184
2185 return mask;
2186}
2187
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002188static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
2189 poll_table *wait)
Rainer Weikusat3c734192008-06-17 22:28:05 -07002190{
Rainer Weikusatec0d2152008-06-27 19:34:18 -07002191 struct sock *sk = sock->sk, *other;
2192 unsigned int mask, writable;
Rainer Weikusat3c734192008-06-17 22:28:05 -07002193
Eric Dumazetaa395142010-04-20 13:03:51 +00002194 sock_poll_wait(file, sk_sleep(sk), wait);
Rainer Weikusat3c734192008-06-17 22:28:05 -07002195 mask = 0;
2196
2197 /* exceptional events? */
2198 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002199 mask |= POLLERR |
Jacob Keller8facd5f2013-04-02 13:55:40 -07002200 (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
Keller, Jacob E7d4c04f2013-03-28 11:19:25 +00002201
Rainer Weikusat3c734192008-06-17 22:28:05 -07002202 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
Gao fengd4beaa62013-02-18 01:34:54 +00002404 if (!proc_create("unix", 0, net->proc_net, &unix_seq_fops)) {
Pavel Emelyanov1597fbc2007-12-01 23:51:01 +11002405 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);
Gao fengece31ff2013-02-18 01:34:56 +00002417 remove_proc_entry("unix", net->proc_net);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002418}
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
YOSHIFUJI Hideaki / 吉藤英明b4fff5f2013-01-09 07:20:07 +00002429 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
2431 rc = proto_register(&unix_proto, 1);
YOSHIFUJI Hideakiac7bfa62007-02-09 23:25:23 +09002432 if (rc != 0) {
2433 printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
Harvey Harrison0dc47872008-03-05 20:47:47 -08002434 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 goto out;
2436 }
2437
2438 sock_register(&unix_family_ops);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002439 register_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440out:
2441 return rc;
2442}
2443
2444static void __exit af_unix_exit(void)
2445{
2446 sock_unregister(PF_UNIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 proto_unregister(&unix_proto);
Denis V. Lunev097e66c2007-11-19 22:29:30 -08002448 unregister_pernet_subsys(&unix_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449}
2450
David Woodhouse3d366962008-04-24 00:59:25 -07002451/* Earlier than device_initcall() so that other drivers invoking
2452 request_module() don't end up in a loop when modprobe tries
2453 to use a UNIX socket. But later than subsys_initcall() because
2454 we depend on stuff initialised there */
2455fs_initcall(af_unix_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456module_exit(af_unix_exit);
2457
2458MODULE_LICENSE("GPL");
2459MODULE_ALIAS_NETPROTO(PF_UNIX);