Blame view
net/unix/af_unix.c
67.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * NET4: Implementation of BSD Unix domain sockets. * |
113aa838e net: Rationalise ... |
4 |
* Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 8 9 10 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * |
1da177e4c Linux-2.6.12-rc2 |
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
* Fixes: * Linus Torvalds : Assorted bug cures. * Niibe Yutaka : async I/O support. * Carsten Paeth : PF_UNIX check, address fixes. * Alan Cox : Limit size of allocated blocks. * Alan Cox : Fixed the stupid socketpair bug. * Alan Cox : BSD compatibility fine tuning. * Alan Cox : Fixed a bug in connect when interrupted. * Alan Cox : Sorted out a proper draft version of * file descriptor passing hacked up from * Mike Shaver's work. * Marty Leisner : Fixes to fd passing * Nick Nevin : recvmsg bugfix. * Alan Cox : Started proper garbage collector * Heiko EiBfeldt : Missing verify_area check * Alan Cox : Started POSIXisms * Andreas Schwab : Replace inode by dentry for proper * reference counting * Kirk Petersen : Made this a module * Christoph Rohland : Elegant non-blocking accept/connect algorithm. * Lots of bug fixes. * Alexey Kuznetosv : Repaired (I hope) bugs introduces * by above two patches. * Andrea Arcangeli : If possible we block in connect(2) * if the max backlog of the listen socket * is been reached. This won't break * old apps and it will avoid huge amount * of socks hashed (this for unix_gc() * performances reasons). * Security fix that limits the max * number of socks to 2*max_files and * the number of skb queueable in the * dgram receiver. * Artur Skawina : Hash function optimizations * Alexey Kuznetsov : Full scale SMP. Lot of bugs are introduced 8) * Malcolm Beattie : Set peercred for socketpair * Michal Ostrowski : Module initialization cleanup. * Arnaldo C. Melo : Remove MOD_{INC,DEC}_USE_COUNT, * the core infrastructure is doing that * for all net proto families now (2.5.69+) * * * Known differences from reference BSD that was tested: * * [TO FIX] * ECONNREFUSED is not returned from one end of a connected() socket to the * other the moment one end closes. * fstat() doesn't return st_dev=0, and give the blksize as high water mark * and a fake inode identifier (nor the BSD first socket fstat twice bug). * [NOT TO FIX] * accept() returns a path name even if the connecting socket has closed * in the meantime (BSD loses the path and gives up). * accept() returns 0 length path for an unbound connector. BSD returns 16 * and a null first byte in the path (but not for gethost/peername - BSD bug ??) * socketpair(...SOCK_RAW..) doesn't panic the kernel. * BSD af_unix apparently has connect forgetting to block properly. * (need to check this with the POSIX spec in detail) * * Differences from 2.0.0-11-... (ANK) * Bug fixes and improvements. * - client shutdown killed server socket. * - removed all useless cli/sti pairs. * * Semantic changes/extensions. * - generic control message passing. * - SCM_CREDENTIALS control message. * - "Abstract" (not FS based) socket bindings. * Abstract names are sequences of bytes (not zero terminated) * started by 0, so that this name space does not intersect * with BSD names. */ |
5cc208bec unix: convert pri... |
82 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4c Linux-2.6.12-rc2 |
83 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
84 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
85 |
#include <linux/signal.h> |
3f07c0144 sched/headers: Pr... |
86 |
#include <linux/sched/signal.h> |
1da177e4c Linux-2.6.12-rc2 |
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
#include <linux/errno.h> #include <linux/string.h> #include <linux/stat.h> #include <linux/dcache.h> #include <linux/namei.h> #include <linux/socket.h> #include <linux/un.h> #include <linux/fcntl.h> #include <linux/termios.h> #include <linux/sockios.h> #include <linux/net.h> #include <linux/in.h> #include <linux/fs.h> #include <linux/slab.h> |
7c0f6ba68 Replace <asm/uacc... |
101 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
#include <linux/skbuff.h> #include <linux/netdevice.h> |
457c4cbc5 [NET]: Make /proc... |
104 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
105 |
#include <net/sock.h> |
c752f0739 [TCP]: Move the t... |
106 |
#include <net/tcp_states.h> |
1da177e4c Linux-2.6.12-rc2 |
107 108 109 110 111 112 |
#include <net/af_unix.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <net/scm.h> #include <linux/init.h> #include <linux/poll.h> |
1da177e4c Linux-2.6.12-rc2 |
113 114 115 116 |
#include <linux/rtnetlink.h> #include <linux/mount.h> #include <net/checksum.h> #include <linux/security.h> |
2b15af6f9 af_unix: use free... |
117 |
#include <linux/freezer.h> |
ba94f3088 unix: add ioctl t... |
118 |
#include <linux/file.h> |
1da177e4c Linux-2.6.12-rc2 |
119 |
|
7123aaa3a af_unix: speedup ... |
120 |
struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; |
fa7ff56f7 af_unix: Export s... |
121 122 123 |
EXPORT_SYMBOL_GPL(unix_socket_table); DEFINE_SPINLOCK(unix_table_lock); EXPORT_SYMBOL_GPL(unix_table_lock); |
518de9b39 fs: allow for mor... |
124 |
static atomic_long_t unix_nr_socks; |
1da177e4c Linux-2.6.12-rc2 |
125 |
|
1da177e4c Linux-2.6.12-rc2 |
126 |
|
7123aaa3a af_unix: speedup ... |
127 128 129 130 131 132 133 134 135 136 137 |
static struct hlist_head *unix_sockets_unbound(void *addr) { unsigned long hash = (unsigned long)addr; hash ^= hash >> 16; hash ^= hash >> 8; hash %= UNIX_HASH_SIZE; return &unix_socket_table[UNIX_HASH_SIZE + hash]; } #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE) |
1da177e4c Linux-2.6.12-rc2 |
138 |
|
877ce7c1b [AF_UNIX]: Datagr... |
139 |
#ifdef CONFIG_SECURITY_NETWORK |
dc49c1f94 [AF_UNIX]: Kernel... |
140 |
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
877ce7c1b [AF_UNIX]: Datagr... |
141 |
{ |
37a9a8df8 net/unix: support... |
142 |
UNIXCB(skb).secid = scm->secid; |
877ce7c1b [AF_UNIX]: Datagr... |
143 144 145 146 |
} static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) { |
37a9a8df8 net/unix: support... |
147 148 149 150 151 152 |
scm->secid = UNIXCB(skb).secid; } static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) { return (scm->secid == UNIXCB(skb).secid); |
877ce7c1b [AF_UNIX]: Datagr... |
153 154 |
} #else |
dc49c1f94 [AF_UNIX]: Kernel... |
155 |
static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
877ce7c1b [AF_UNIX]: Datagr... |
156 157 158 159 |
{ } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) { } |
37a9a8df8 net/unix: support... |
160 161 162 163 164 |
static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) { return true; } |
877ce7c1b [AF_UNIX]: Datagr... |
165 |
#endif /* CONFIG_SECURITY_NETWORK */ |
1da177e4c Linux-2.6.12-rc2 |
166 167 |
/* * SMP locking strategy: |
fbe9cc4a8 [AF_UNIX]: Use sp... |
168 |
* hash table is protected with spinlock unix_table_lock |
663717f65 AF_UNIX: update l... |
169 |
* each socket state is protected by separate spin lock. |
1da177e4c Linux-2.6.12-rc2 |
170 |
*/ |
95c961747 net: cleanup unsi... |
171 |
static inline unsigned int unix_hash_fold(__wsum n) |
1da177e4c Linux-2.6.12-rc2 |
172 |
{ |
0a13404dd net: unix socket ... |
173 |
unsigned int hash = (__force unsigned int)csum_fold(n); |
95c961747 net: cleanup unsi... |
174 |
|
1da177e4c Linux-2.6.12-rc2 |
175 176 177 178 179 180 181 182 183 184 185 186 187 |
hash ^= hash>>8; return hash&(UNIX_HASH_SIZE-1); } #define unix_peer(sk) (unix_sk(sk)->peer) static inline int unix_our_peer(struct sock *sk, struct sock *osk) { return unix_peer(osk) == sk; } static inline int unix_may_send(struct sock *sk, struct sock *osk) { |
6eba6a372 net: Cleanup of a... |
188 |
return unix_peer(osk) == NULL || unix_our_peer(sk, osk); |
1da177e4c Linux-2.6.12-rc2 |
189 |
} |
3c73419c0 af_unix: fix 'pol... |
190 191 192 193 |
static inline int unix_recvq_full(struct sock const *sk) { return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog; } |
fa7ff56f7 af_unix: Export s... |
194 |
struct sock *unix_peer_get(struct sock *s) |
1da177e4c Linux-2.6.12-rc2 |
195 196 |
{ struct sock *peer; |
1c92b4e50 [AF_UNIX]: Make s... |
197 |
unix_state_lock(s); |
1da177e4c Linux-2.6.12-rc2 |
198 199 200 |
peer = unix_peer(s); if (peer) sock_hold(peer); |
1c92b4e50 [AF_UNIX]: Make s... |
201 |
unix_state_unlock(s); |
1da177e4c Linux-2.6.12-rc2 |
202 203 |
return peer; } |
fa7ff56f7 af_unix: Export s... |
204 |
EXPORT_SYMBOL_GPL(unix_peer_get); |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 |
static inline void unix_release_addr(struct unix_address *addr) { |
8c9814b97 net: convert unix... |
208 |
if (refcount_dec_and_test(&addr->refcnt)) |
1da177e4c Linux-2.6.12-rc2 |
209 210 211 212 213 214 215 216 217 |
kfree(addr); } /* * Check unix socket name: * - should be not zero length. * - if started by not zero, should be NULL terminated (FS object) * - if started by zero, it is abstract name. */ |
ac7bfa62f [NET] UNIX: Fix w... |
218 |
|
95c961747 net: cleanup unsi... |
219 |
static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp) |
1da177e4c Linux-2.6.12-rc2 |
220 221 222 223 224 225 226 227 228 |
{ if (len <= sizeof(short) || len > sizeof(*sunaddr)) return -EINVAL; if (!sunaddr || sunaddr->sun_family != AF_UNIX) return -EINVAL; if (sunaddr->sun_path[0]) { /* * This may look like an off by one error but it is a bit more * subtle. 108 is the longest valid AF_UNIX path for a binding. |
25985edce Fix common misspe... |
229 |
* sun_path[108] doesn't as such exist. However in kernel space |
1da177e4c Linux-2.6.12-rc2 |
230 231 232 |
* we are guaranteed that it is a valid memory location in our * kernel address buffer. */ |
e27dfcea4 af_unix: clean up... |
233 |
((char *)sunaddr)[len] = 0; |
1da177e4c Linux-2.6.12-rc2 |
234 235 236 |
len = strlen(sunaddr->sun_path)+1+sizeof(short); return len; } |
07f0757a6 include/net net/ ... |
237 |
*hashp = unix_hash_fold(csum_partial(sunaddr, len, 0)); |
1da177e4c Linux-2.6.12-rc2 |
238 239 240 241 242 243 244 245 246 247 |
return len; } static void __unix_remove_socket(struct sock *sk) { sk_del_node_init(sk); } static void __unix_insert_socket(struct hlist_head *list, struct sock *sk) { |
547b792ca net: convert BUG_... |
248 |
WARN_ON(!sk_unhashed(sk)); |
1da177e4c Linux-2.6.12-rc2 |
249 250 251 252 253 |
sk_add_node(sk, list); } static inline void unix_remove_socket(struct sock *sk) { |
fbe9cc4a8 [AF_UNIX]: Use sp... |
254 |
spin_lock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
255 |
__unix_remove_socket(sk); |
fbe9cc4a8 [AF_UNIX]: Use sp... |
256 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
257 258 259 260 |
} static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk) { |
fbe9cc4a8 [AF_UNIX]: Use sp... |
261 |
spin_lock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
262 |
__unix_insert_socket(list, sk); |
fbe9cc4a8 [AF_UNIX]: Use sp... |
263 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
264 |
} |
097e66c57 [NET]: Make AF_UN... |
265 266 |
static struct sock *__unix_find_socket_byname(struct net *net, struct sockaddr_un *sunname, |
95c961747 net: cleanup unsi... |
267 |
int len, int type, unsigned int hash) |
1da177e4c Linux-2.6.12-rc2 |
268 269 |
{ struct sock *s; |
1da177e4c Linux-2.6.12-rc2 |
270 |
|
b67bfe0d4 hlist: drop the n... |
271 |
sk_for_each(s, &unix_socket_table[hash ^ type]) { |
1da177e4c Linux-2.6.12-rc2 |
272 |
struct unix_sock *u = unix_sk(s); |
878628fbf [NET] NETNS: Omit... |
273 |
if (!net_eq(sock_net(s), net)) |
097e66c57 [NET]: Make AF_UN... |
274 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
275 276 277 278 279 280 281 282 |
if (u->addr->len == len && !memcmp(u->addr->name, sunname, len)) goto found; } s = NULL; found: return s; } |
097e66c57 [NET]: Make AF_UN... |
283 284 |
static inline struct sock *unix_find_socket_byname(struct net *net, struct sockaddr_un *sunname, |
1da177e4c Linux-2.6.12-rc2 |
285 |
int len, int type, |
95c961747 net: cleanup unsi... |
286 |
unsigned int hash) |
1da177e4c Linux-2.6.12-rc2 |
287 288 |
{ struct sock *s; |
fbe9cc4a8 [AF_UNIX]: Use sp... |
289 |
spin_lock(&unix_table_lock); |
097e66c57 [NET]: Make AF_UN... |
290 |
s = __unix_find_socket_byname(net, sunname, len, type, hash); |
1da177e4c Linux-2.6.12-rc2 |
291 292 |
if (s) sock_hold(s); |
fbe9cc4a8 [AF_UNIX]: Use sp... |
293 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
294 295 |
return s; } |
6616f7888 af_unix: Allow co... |
296 |
static struct sock *unix_find_socket_byinode(struct inode *i) |
1da177e4c Linux-2.6.12-rc2 |
297 298 |
{ struct sock *s; |
1da177e4c Linux-2.6.12-rc2 |
299 |
|
fbe9cc4a8 [AF_UNIX]: Use sp... |
300 |
spin_lock(&unix_table_lock); |
b67bfe0d4 hlist: drop the n... |
301 |
sk_for_each(s, |
1da177e4c Linux-2.6.12-rc2 |
302 |
&unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
40ffe67d2 switch unix_sock ... |
303 |
struct dentry *dentry = unix_sk(s)->path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
304 |
|
beef5121f Revert "af_unix: ... |
305 |
if (dentry && d_backing_inode(dentry) == i) { |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 309 310 311 |
sock_hold(s); goto found; } } s = NULL; found: |
fbe9cc4a8 [AF_UNIX]: Use sp... |
312 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
313 314 |
return s; } |
7d267278a unix: avoid use-a... |
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
/* Support code for asymmetrically connected dgram sockets * * If a datagram socket is connected to a socket not itself connected * to the first socket (eg, /dev/log), clients may only enqueue more * messages if the present receive queue of the server socket is not * "too large". This means there's a second writeability condition * poll and sendmsg need to test. The dgram recv code will do a wake * up on the peer_wait wait queue of a socket upon reception of a * datagram which needs to be propagated to sleeping would-be writers * since these might not have sent anything so far. This can't be * accomplished via poll_wait because the lifetime of the server * socket might be less than that of its clients if these break their * association with it or if the server socket is closed while clients * are still connected to it and there's no way to inform "a polling * implementation" that it should let go of a certain wait queue * |
ac6424b98 sched/wait: Renam... |
331 |
* In order to propagate a wake up, a wait_queue_entry_t of the client |
7d267278a unix: avoid use-a... |
332 333 334 335 336 337 338 |
* socket is enqueued on the peer_wait queue of the server socket * whose wake function does a wake_up on the ordinary client socket * wait queue. This connection is established whenever a write (or * poll for write) hit the flow control condition and broken when the * association to the server socket is dissolved or after a wake up * was relayed. */ |
ac6424b98 sched/wait: Renam... |
339 |
static int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int flags, |
7d267278a unix: avoid use-a... |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
void *key) { struct unix_sock *u; wait_queue_head_t *u_sleep; u = container_of(q, struct unix_sock, peer_wake); __remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait, q); u->peer_wake.private = NULL; /* relaying can only happen while the wq still exists */ u_sleep = sk_sleep(&u->sk); if (u_sleep) wake_up_interruptible_poll(u_sleep, key); return 0; } static int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other) { struct unix_sock *u, *u_other; int rc; u = unix_sk(sk); u_other = unix_sk(other); rc = 0; spin_lock(&u_other->peer_wait.lock); if (!u->peer_wake.private) { u->peer_wake.private = other; __add_wait_queue(&u_other->peer_wait, &u->peer_wake); rc = 1; } spin_unlock(&u_other->peer_wait.lock); return rc; } static void unix_dgram_peer_wake_disconnect(struct sock *sk, struct sock *other) { struct unix_sock *u, *u_other; u = unix_sk(sk); u_other = unix_sk(other); spin_lock(&u_other->peer_wait.lock); if (u->peer_wake.private == other) { __remove_wait_queue(&u_other->peer_wait, &u->peer_wake); u->peer_wake.private = NULL; } spin_unlock(&u_other->peer_wait.lock); } static void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk, struct sock *other) { unix_dgram_peer_wake_disconnect(sk, other); wake_up_interruptible_poll(sk_sleep(sk), POLLOUT | POLLWRNORM | POLLWRBAND); } /* preconditions: * - unix_peer(sk) == other * - association is stable */ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other) { int connected; connected = unix_dgram_peer_wake_connect(sk, other); if (unix_recvq_full(other)) return 1; if (connected) unix_dgram_peer_wake_disconnect(sk, other); return 0; } |
1586a5877 af_unix: do not r... |
425 |
static int unix_writable(const struct sock *sk) |
1da177e4c Linux-2.6.12-rc2 |
426 |
{ |
1586a5877 af_unix: do not r... |
427 |
return sk->sk_state != TCP_LISTEN && |
14afee4b6 net: convert sock... |
428 |
(refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf; |
1da177e4c Linux-2.6.12-rc2 |
429 430 431 432 |
} static void unix_write_space(struct sock *sk) { |
438154823 net: sock_def_rea... |
433 434 435 |
struct socket_wq *wq; rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
436 |
if (unix_writable(sk)) { |
438154823 net: sock_def_rea... |
437 |
wq = rcu_dereference(sk->sk_wq); |
1ce0bf50a net: Generalise w... |
438 |
if (skwq_has_sleeper(wq)) |
67426b756 af_unix: use keye... |
439 440 |
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | POLLWRNORM | POLLWRBAND); |
8d8ad9d7c [NET]: Name magic... |
441 |
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
1da177e4c Linux-2.6.12-rc2 |
442 |
} |
438154823 net: sock_def_rea... |
443 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
444 445 446 447 448 449 450 451 |
} /* When dgram socket disconnects (or changes its peer), we clear its receive * queue of packets arrived from previous peer. First, it allows to do * flow control based only on wmem_alloc; second, sk connected to peer * may receive messages only from that peer. */ static void unix_dgram_disconnected(struct sock *sk, struct sock *other) { |
b03efcfb2 [NET]: Transform ... |
452 |
if (!skb_queue_empty(&sk->sk_receive_queue)) { |
1da177e4c Linux-2.6.12-rc2 |
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
skb_queue_purge(&sk->sk_receive_queue); wake_up_interruptible_all(&unix_sk(sk)->peer_wait); /* If one link of bidirectional dgram pipe is disconnected, * we signal error. Messages are lost. Do not make this, * when peer was not connected to us. */ if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) { other->sk_err = ECONNRESET; other->sk_error_report(other); } } } static void unix_sock_destructor(struct sock *sk) { struct unix_sock *u = unix_sk(sk); skb_queue_purge(&sk->sk_receive_queue); |
14afee4b6 net: convert sock... |
472 |
WARN_ON(refcount_read(&sk->sk_wmem_alloc)); |
547b792ca net: convert BUG_... |
473 474 |
WARN_ON(!sk_unhashed(sk)); WARN_ON(sk->sk_socket); |
1da177e4c Linux-2.6.12-rc2 |
475 |
if (!sock_flag(sk, SOCK_DEAD)) { |
5cc208bec unix: convert pri... |
476 477 |
pr_info("Attempt to release alive unix socket: %p ", sk); |
1da177e4c Linux-2.6.12-rc2 |
478 479 480 481 482 |
return; } if (u->addr) unix_release_addr(u->addr); |
518de9b39 fs: allow for mor... |
483 |
atomic_long_dec(&unix_nr_socks); |
6f756a8c3 net: Make sure BH... |
484 |
local_bh_disable(); |
a8076d8db net: af_unix shou... |
485 |
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
6f756a8c3 net: Make sure BH... |
486 |
local_bh_enable(); |
1da177e4c Linux-2.6.12-rc2 |
487 |
#ifdef UNIX_REFCNT_DEBUG |
5cc208bec unix: convert pri... |
488 489 |
pr_debug("UNIX %p is destroyed, %ld are still alive. ", sk, |
518de9b39 fs: allow for mor... |
490 |
atomic_long_read(&unix_nr_socks)); |
1da177e4c Linux-2.6.12-rc2 |
491 492 |
#endif } |
ded34e0fe unix: fix a race ... |
493 |
static void unix_release_sock(struct sock *sk, int embrion) |
1da177e4c Linux-2.6.12-rc2 |
494 495 |
{ struct unix_sock *u = unix_sk(sk); |
40ffe67d2 switch unix_sock ... |
496 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
497 498 499 500 501 502 503 |
struct sock *skpair; struct sk_buff *skb; int state; unix_remove_socket(sk); /* Clear state */ |
1c92b4e50 [AF_UNIX]: Make s... |
504 |
unix_state_lock(sk); |
1da177e4c Linux-2.6.12-rc2 |
505 506 |
sock_orphan(sk); sk->sk_shutdown = SHUTDOWN_MASK; |
40ffe67d2 switch unix_sock ... |
507 508 509 |
path = u->path; u->path.dentry = NULL; u->path.mnt = NULL; |
1da177e4c Linux-2.6.12-rc2 |
510 511 |
state = sk->sk_state; sk->sk_state = TCP_CLOSE; |
1c92b4e50 [AF_UNIX]: Make s... |
512 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
513 514 |
wake_up_interruptible_all(&u->peer_wait); |
e27dfcea4 af_unix: clean up... |
515 |
skpair = unix_peer(sk); |
1da177e4c Linux-2.6.12-rc2 |
516 |
|
e27dfcea4 af_unix: clean up... |
517 |
if (skpair != NULL) { |
1da177e4c Linux-2.6.12-rc2 |
518 |
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { |
1c92b4e50 [AF_UNIX]: Make s... |
519 |
unix_state_lock(skpair); |
1da177e4c Linux-2.6.12-rc2 |
520 521 522 523 |
/* No more writes */ skpair->sk_shutdown = SHUTDOWN_MASK; if (!skb_queue_empty(&sk->sk_receive_queue) || embrion) skpair->sk_err = ECONNRESET; |
1c92b4e50 [AF_UNIX]: Make s... |
524 |
unix_state_unlock(skpair); |
1da177e4c Linux-2.6.12-rc2 |
525 |
skpair->sk_state_change(skpair); |
8d8ad9d7c [NET]: Name magic... |
526 |
sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
1da177e4c Linux-2.6.12-rc2 |
527 |
} |
7d267278a unix: avoid use-a... |
528 529 |
unix_dgram_peer_wake_disconnect(sk, skpair); |
1da177e4c Linux-2.6.12-rc2 |
530 531 532 533 534 535 536 |
sock_put(skpair); /* It may now die */ unix_peer(sk) = NULL; } /* Try to flush out this socket. Throw out buffers at least */ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
e27dfcea4 af_unix: clean up... |
537 |
if (state == TCP_LISTEN) |
1da177e4c Linux-2.6.12-rc2 |
538 539 |
unix_release_sock(skb->sk, 1); /* passed fds are erased in the kfree_skb hook */ |
73ed5d25d af-unix: fix use-... |
540 |
UNIXCB(skb).consumed = skb->len; |
1da177e4c Linux-2.6.12-rc2 |
541 542 |
kfree_skb(skb); } |
40ffe67d2 switch unix_sock ... |
543 544 |
if (path.dentry) path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
545 546 547 548 549 550 |
sock_put(sk); /* ---- Socket is dead now and most probably destroyed ---- */ /* |
e04dae840 af_unix: old_cred... |
551 |
* Fixme: BSD difference: In BSD all sockets connected to us get |
1da177e4c Linux-2.6.12-rc2 |
552 553 554 555 556 557 558 559 |
* ECONNRESET and we die on the spot. In Linux we behave * like files and pipes do and wait for the last * dereference. * * Can't we simply set sock->err? * * What the above comment does talk about? --ANK(980817) */ |
9305cfa44 [AF_UNIX]: Make u... |
560 |
if (unix_tot_inflight) |
ac7bfa62f [NET] UNIX: Fix w... |
561 |
unix_gc(); /* Garbage collect fds */ |
1da177e4c Linux-2.6.12-rc2 |
562 |
} |
109f6e39f af_unix: Allow SO... |
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
static void init_peercred(struct sock *sk) { put_pid(sk->sk_peer_pid); if (sk->sk_peer_cred) put_cred(sk->sk_peer_cred); sk->sk_peer_pid = get_pid(task_tgid(current)); sk->sk_peer_cred = get_current_cred(); } static void copy_peercred(struct sock *sk, struct sock *peersk) { put_pid(sk->sk_peer_pid); if (sk->sk_peer_cred) put_cred(sk->sk_peer_cred); sk->sk_peer_pid = get_pid(peersk->sk_peer_pid); sk->sk_peer_cred = get_cred(peersk->sk_peer_cred); } |
1da177e4c Linux-2.6.12-rc2 |
580 581 582 583 584 |
static int unix_listen(struct socket *sock, int backlog) { int err; struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); |
109f6e39f af_unix: Allow SO... |
585 |
struct pid *old_pid = NULL; |
1da177e4c Linux-2.6.12-rc2 |
586 587 |
err = -EOPNOTSUPP; |
6eba6a372 net: Cleanup of a... |
588 589 |
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) goto out; /* Only stream/seqpacket sockets accept */ |
1da177e4c Linux-2.6.12-rc2 |
590 591 |
err = -EINVAL; if (!u->addr) |
6eba6a372 net: Cleanup of a... |
592 |
goto out; /* No listens on an unbound socket */ |
1c92b4e50 [AF_UNIX]: Make s... |
593 |
unix_state_lock(sk); |
1da177e4c Linux-2.6.12-rc2 |
594 595 596 597 598 599 600 |
if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) goto out_unlock; if (backlog > sk->sk_max_ack_backlog) wake_up_interruptible_all(&u->peer_wait); sk->sk_max_ack_backlog = backlog; sk->sk_state = TCP_LISTEN; /* set credentials so connect can copy them */ |
109f6e39f af_unix: Allow SO... |
601 |
init_peercred(sk); |
1da177e4c Linux-2.6.12-rc2 |
602 603 604 |
err = 0; out_unlock: |
1c92b4e50 [AF_UNIX]: Make s... |
605 |
unix_state_unlock(sk); |
109f6e39f af_unix: Allow SO... |
606 |
put_pid(old_pid); |
1da177e4c Linux-2.6.12-rc2 |
607 608 609 610 611 612 613 614 615 |
out: return err; } static int unix_release(struct socket *); static int unix_bind(struct socket *, struct sockaddr *, int); static int unix_stream_connect(struct socket *, struct sockaddr *, int addr_len, int flags); static int unix_socketpair(struct socket *, struct socket *); |
cdfbabfb2 net: Work around ... |
616 |
static int unix_accept(struct socket *, struct socket *, int, bool); |
1da177e4c Linux-2.6.12-rc2 |
617 618 |
static int unix_getname(struct socket *, struct sockaddr *, int *, int); static unsigned int unix_poll(struct file *, struct socket *, poll_table *); |
ec0d215f9 af_unix: fix 'pol... |
619 620 |
static unsigned int unix_dgram_poll(struct file *, struct socket *, poll_table *); |
1da177e4c Linux-2.6.12-rc2 |
621 622 |
static int unix_ioctl(struct socket *, unsigned int, unsigned long); static int unix_shutdown(struct socket *, int); |
1b7841404 net: Remove iocb ... |
623 624 |
static int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t); static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int); |
869e7c624 net: af_unix: imp... |
625 626 |
static ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset, size_t size, int flags); |
2b514574f net: af_unix: imp... |
627 628 629 |
static ssize_t unix_stream_splice_read(struct socket *, loff_t *ppos, struct pipe_inode_info *, size_t size, unsigned int flags); |
1b7841404 net: Remove iocb ... |
630 631 |
static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t); static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int); |
1da177e4c Linux-2.6.12-rc2 |
632 633 |
static int unix_dgram_connect(struct socket *, struct sockaddr *, int, int); |
1b7841404 net: Remove iocb ... |
634 635 636 |
static int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t); static int unix_seqpacket_recvmsg(struct socket *, struct msghdr *, size_t, int); |
1da177e4c Linux-2.6.12-rc2 |
637 |
|
12663bfc9 net: unix: allow ... |
638 |
static int unix_set_peek_off(struct sock *sk, int val) |
f55bb7f9c unix: Support pee... |
639 640 |
{ struct unix_sock *u = unix_sk(sk); |
6e1ce3c34 af_unix: split 'u... |
641 |
if (mutex_lock_interruptible(&u->iolock)) |
12663bfc9 net: unix: allow ... |
642 |
return -EINTR; |
f55bb7f9c unix: Support pee... |
643 |
sk->sk_peek_off = val; |
6e1ce3c34 af_unix: split 'u... |
644 |
mutex_unlock(&u->iolock); |
12663bfc9 net: unix: allow ... |
645 646 |
return 0; |
f55bb7f9c unix: Support pee... |
647 |
} |
90ddc4f04 [NET]: move struc... |
648 |
static const struct proto_ops unix_stream_ops = { |
1da177e4c Linux-2.6.12-rc2 |
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 |
.family = PF_UNIX, .owner = THIS_MODULE, .release = unix_release, .bind = unix_bind, .connect = unix_stream_connect, .socketpair = unix_socketpair, .accept = unix_accept, .getname = unix_getname, .poll = unix_poll, .ioctl = unix_ioctl, .listen = unix_listen, .shutdown = unix_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = unix_stream_sendmsg, .recvmsg = unix_stream_recvmsg, .mmap = sock_no_mmap, |
869e7c624 net: af_unix: imp... |
666 |
.sendpage = unix_stream_sendpage, |
2b514574f net: af_unix: imp... |
667 |
.splice_read = unix_stream_splice_read, |
fc0d75364 unix: Support pee... |
668 |
.set_peek_off = unix_set_peek_off, |
1da177e4c Linux-2.6.12-rc2 |
669 |
}; |
90ddc4f04 [NET]: move struc... |
670 |
static const struct proto_ops unix_dgram_ops = { |
1da177e4c Linux-2.6.12-rc2 |
671 672 673 674 675 676 677 678 |
.family = PF_UNIX, .owner = THIS_MODULE, .release = unix_release, .bind = unix_bind, .connect = unix_dgram_connect, .socketpair = unix_socketpair, .accept = sock_no_accept, .getname = unix_getname, |
ec0d215f9 af_unix: fix 'pol... |
679 |
.poll = unix_dgram_poll, |
1da177e4c Linux-2.6.12-rc2 |
680 681 682 683 684 685 686 687 688 |
.ioctl = unix_ioctl, .listen = sock_no_listen, .shutdown = unix_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = unix_dgram_sendmsg, .recvmsg = unix_dgram_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, |
f55bb7f9c unix: Support pee... |
689 |
.set_peek_off = unix_set_peek_off, |
1da177e4c Linux-2.6.12-rc2 |
690 |
}; |
90ddc4f04 [NET]: move struc... |
691 |
static const struct proto_ops unix_seqpacket_ops = { |
1da177e4c Linux-2.6.12-rc2 |
692 693 694 695 696 697 698 699 |
.family = PF_UNIX, .owner = THIS_MODULE, .release = unix_release, .bind = unix_bind, .connect = unix_stream_connect, .socketpair = unix_socketpair, .accept = unix_accept, .getname = unix_getname, |
ec0d215f9 af_unix: fix 'pol... |
700 |
.poll = unix_dgram_poll, |
1da177e4c Linux-2.6.12-rc2 |
701 702 703 704 705 706 |
.ioctl = unix_ioctl, .listen = unix_listen, .shutdown = unix_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = unix_seqpacket_sendmsg, |
a05d2ad1c af_unix: Only all... |
707 |
.recvmsg = unix_seqpacket_recvmsg, |
1da177e4c Linux-2.6.12-rc2 |
708 709 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage, |
f55bb7f9c unix: Support pee... |
710 |
.set_peek_off = unix_set_peek_off, |
1da177e4c Linux-2.6.12-rc2 |
711 712 713 |
}; static struct proto unix_proto = { |
248969ae3 net: af_unix can ... |
714 715 |
.name = "UNIX", .owner = THIS_MODULE, |
248969ae3 net: af_unix can ... |
716 |
.obj_size = sizeof(struct unix_sock), |
1da177e4c Linux-2.6.12-rc2 |
717 |
}; |
a09785a24 [PATCH] lockdep: ... |
718 719 720 721 722 723 724 |
/* * AF_UNIX sockets do not interact with hardware, hence they * dont trigger interrupts - so it's safe for them to have * bh-unsafe locking for their sk_receive_queue.lock. Split off * this special lock-class by reinitializing the spinlock key: */ static struct lock_class_key af_unix_sk_receive_queue_lock_key; |
11aa9c28b net: Pass kern fr... |
725 |
static struct sock *unix_create1(struct net *net, struct socket *sock, int kern) |
1da177e4c Linux-2.6.12-rc2 |
726 727 728 |
{ struct sock *sk = NULL; struct unix_sock *u; |
518de9b39 fs: allow for mor... |
729 730 |
atomic_long_inc(&unix_nr_socks); if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) |
1da177e4c Linux-2.6.12-rc2 |
731 |
goto out; |
11aa9c28b net: Pass kern fr... |
732 |
sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, kern); |
1da177e4c Linux-2.6.12-rc2 |
733 734 |
if (!sk) goto out; |
6eba6a372 net: Cleanup of a... |
735 |
sock_init_data(sock, sk); |
a09785a24 [PATCH] lockdep: ... |
736 737 |
lockdep_set_class(&sk->sk_receive_queue.lock, &af_unix_sk_receive_queue_lock_key); |
1da177e4c Linux-2.6.12-rc2 |
738 |
|
3aa9799e1 af_unix: charge b... |
739 |
sk->sk_allocation = GFP_KERNEL_ACCOUNT; |
1da177e4c Linux-2.6.12-rc2 |
740 |
sk->sk_write_space = unix_write_space; |
a0a53c8ba [NETNS]: struct n... |
741 |
sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; |
1da177e4c Linux-2.6.12-rc2 |
742 743 |
sk->sk_destruct = unix_sock_destructor; u = unix_sk(sk); |
40ffe67d2 switch unix_sock ... |
744 745 |
u->path.dentry = NULL; u->path.mnt = NULL; |
fd19f329a [AF_UNIX]: Conver... |
746 |
spin_lock_init(&u->lock); |
516e0cc56 [PATCH] f_count m... |
747 |
atomic_long_set(&u->inflight, 0); |
1fd05ba5a [AF_UNIX]: Rewrit... |
748 |
INIT_LIST_HEAD(&u->link); |
6e1ce3c34 af_unix: split 'u... |
749 750 |
mutex_init(&u->iolock); /* single task reading lock */ mutex_init(&u->bindlock); /* single task binding lock */ |
1da177e4c Linux-2.6.12-rc2 |
751 |
init_waitqueue_head(&u->peer_wait); |
7d267278a unix: avoid use-a... |
752 |
init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); |
7123aaa3a af_unix: speedup ... |
753 |
unix_insert_socket(unix_sockets_unbound(sk), sk); |
1da177e4c Linux-2.6.12-rc2 |
754 |
out: |
284b327be [UNIX]: The unix_... |
755 |
if (sk == NULL) |
518de9b39 fs: allow for mor... |
756 |
atomic_long_dec(&unix_nr_socks); |
920de804b net: Make sure BH... |
757 758 |
else { local_bh_disable(); |
a8076d8db net: af_unix shou... |
759 |
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
920de804b net: Make sure BH... |
760 761 |
local_bh_enable(); } |
1da177e4c Linux-2.6.12-rc2 |
762 763 |
return sk; } |
3f378b684 net: pass kern to... |
764 765 |
static int unix_create(struct net *net, struct socket *sock, int protocol, int kern) |
1da177e4c Linux-2.6.12-rc2 |
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 |
{ if (protocol && protocol != PF_UNIX) return -EPROTONOSUPPORT; sock->state = SS_UNCONNECTED; switch (sock->type) { case SOCK_STREAM: sock->ops = &unix_stream_ops; break; /* * Believe it or not BSD has AF_UNIX, SOCK_RAW though * nothing uses it. */ case SOCK_RAW: |
e27dfcea4 af_unix: clean up... |
781 |
sock->type = SOCK_DGRAM; |
1da177e4c Linux-2.6.12-rc2 |
782 783 784 785 786 787 788 789 790 |
case SOCK_DGRAM: sock->ops = &unix_dgram_ops; break; case SOCK_SEQPACKET: sock->ops = &unix_seqpacket_ops; break; default: return -ESOCKTNOSUPPORT; } |
11aa9c28b net: Pass kern fr... |
791 |
return unix_create1(net, sock, kern) ? 0 : -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
792 793 794 795 796 797 798 799 |
} static int unix_release(struct socket *sock) { struct sock *sk = sock->sk; if (!sk) return 0; |
ded34e0fe unix: fix a race ... |
800 |
unix_release_sock(sk, 0); |
1da177e4c Linux-2.6.12-rc2 |
801 |
sock->sk = NULL; |
ded34e0fe unix: fix a race ... |
802 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
803 804 805 806 807 |
} static int unix_autobind(struct socket *sock) { struct sock *sk = sock->sk; |
3b1e0a655 [NET] NETNS: Omit... |
808 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
809 810 |
struct unix_sock *u = unix_sk(sk); static u32 ordernum = 1; |
6eba6a372 net: Cleanup of a... |
811 |
struct unix_address *addr; |
1da177e4c Linux-2.6.12-rc2 |
812 |
int err; |
8df73ff90 UNIX: Do not loop... |
813 |
unsigned int retries = 0; |
1da177e4c Linux-2.6.12-rc2 |
814 |
|
6e1ce3c34 af_unix: split 'u... |
815 |
err = mutex_lock_interruptible(&u->bindlock); |
37ab4fa78 net: unix: allow ... |
816 817 |
if (err) return err; |
1da177e4c Linux-2.6.12-rc2 |
818 819 820 821 822 823 |
err = 0; if (u->addr) goto out; err = -ENOMEM; |
0da974f4f [NET]: Conversion... |
824 |
addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
825 826 |
if (!addr) goto out; |
1da177e4c Linux-2.6.12-rc2 |
827 |
addr->name->sun_family = AF_UNIX; |
8c9814b97 net: convert unix... |
828 |
refcount_set(&addr->refcnt, 1); |
1da177e4c Linux-2.6.12-rc2 |
829 830 831 |
retry: addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short); |
07f0757a6 include/net net/ ... |
832 |
addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0)); |
1da177e4c Linux-2.6.12-rc2 |
833 |
|
fbe9cc4a8 [AF_UNIX]: Use sp... |
834 |
spin_lock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
835 |
ordernum = (ordernum+1)&0xFFFFF; |
097e66c57 [NET]: Make AF_UN... |
836 |
if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, |
1da177e4c Linux-2.6.12-rc2 |
837 |
addr->hash)) { |
fbe9cc4a8 [AF_UNIX]: Use sp... |
838 |
spin_unlock(&unix_table_lock); |
8df73ff90 UNIX: Do not loop... |
839 840 841 842 843 844 845 846 847 848 849 |
/* * __unix_find_socket_byname() may take long time if many names * are already in use. */ cond_resched(); /* Give up if all names seems to be in use. */ if (retries++ == 0xFFFFF) { err = -ENOSPC; kfree(addr); goto out; } |
1da177e4c Linux-2.6.12-rc2 |
850 851 852 853 854 855 856 |
goto retry; } addr->hash ^= sk->sk_type; __unix_remove_socket(sk); u->addr = addr; __unix_insert_socket(&unix_socket_table[addr->hash], sk); |
fbe9cc4a8 [AF_UNIX]: Use sp... |
857 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
858 |
err = 0; |
6e1ce3c34 af_unix: split 'u... |
859 |
out: mutex_unlock(&u->bindlock); |
1da177e4c Linux-2.6.12-rc2 |
860 861 |
return err; } |
097e66c57 [NET]: Make AF_UN... |
862 863 |
static struct sock *unix_find_other(struct net *net, struct sockaddr_un *sunname, int len, |
95c961747 net: cleanup unsi... |
864 |
int type, unsigned int hash, int *error) |
1da177e4c Linux-2.6.12-rc2 |
865 866 |
{ struct sock *u; |
421748ecd [PATCH] assorted ... |
867 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
868 |
int err = 0; |
ac7bfa62f [NET] UNIX: Fix w... |
869 |
|
1da177e4c Linux-2.6.12-rc2 |
870 |
if (sunname->sun_path[0]) { |
421748ecd [PATCH] assorted ... |
871 872 |
struct inode *inode; err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); |
1da177e4c Linux-2.6.12-rc2 |
873 874 |
if (err) goto fail; |
beef5121f Revert "af_unix: ... |
875 |
inode = d_backing_inode(path.dentry); |
421748ecd [PATCH] assorted ... |
876 |
err = inode_permission(inode, MAY_WRITE); |
1da177e4c Linux-2.6.12-rc2 |
877 878 879 880 |
if (err) goto put_fail; err = -ECONNREFUSED; |
421748ecd [PATCH] assorted ... |
881 |
if (!S_ISSOCK(inode->i_mode)) |
1da177e4c Linux-2.6.12-rc2 |
882 |
goto put_fail; |
6616f7888 af_unix: Allow co... |
883 |
u = unix_find_socket_byinode(inode); |
1da177e4c Linux-2.6.12-rc2 |
884 885 886 887 |
if (!u) goto put_fail; if (u->sk_type == type) |
68ac1234f switch touch_atim... |
888 |
touch_atime(&path); |
1da177e4c Linux-2.6.12-rc2 |
889 |
|
421748ecd [PATCH] assorted ... |
890 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
891 |
|
e27dfcea4 af_unix: clean up... |
892 |
err = -EPROTOTYPE; |
1da177e4c Linux-2.6.12-rc2 |
893 894 895 896 897 898 |
if (u->sk_type != type) { sock_put(u); goto fail; } } else { err = -ECONNREFUSED; |
e27dfcea4 af_unix: clean up... |
899 |
u = unix_find_socket_byname(net, sunname, len, type, hash); |
1da177e4c Linux-2.6.12-rc2 |
900 901 |
if (u) { struct dentry *dentry; |
40ffe67d2 switch unix_sock ... |
902 |
dentry = unix_sk(u)->path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
903 |
if (dentry) |
68ac1234f switch touch_atim... |
904 |
touch_atime(&unix_sk(u)->path); |
1da177e4c Linux-2.6.12-rc2 |
905 906 907 908 909 910 |
} else goto fail; } return u; put_fail: |
421748ecd [PATCH] assorted ... |
911 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
912 |
fail: |
e27dfcea4 af_unix: clean up... |
913 |
*error = err; |
1da177e4c Linux-2.6.12-rc2 |
914 915 |
return NULL; } |
38f7bd94a Revert "af_unix: ... |
916 |
static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) |
faf020102 clean unix_bind()... |
917 |
{ |
38f7bd94a Revert "af_unix: ... |
918 919 920 921 922 923 924 925 926 927 928 |
struct dentry *dentry; struct path path; int err = 0; /* * Get the parent directory, calculate the hash for last * component. */ dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); err = PTR_ERR(dentry); if (IS_ERR(dentry)) return err; |
faf020102 clean unix_bind()... |
929 |
|
38f7bd94a Revert "af_unix: ... |
930 931 932 933 |
/* * All right, let's create it. */ err = security_path_mknod(&path, dentry, mode, 0); |
faf020102 clean unix_bind()... |
934 |
if (!err) { |
38f7bd94a Revert "af_unix: ... |
935 |
err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); |
faf020102 clean unix_bind()... |
936 |
if (!err) { |
38f7bd94a Revert "af_unix: ... |
937 |
res->mnt = mntget(path.mnt); |
faf020102 clean unix_bind()... |
938 939 940 |
res->dentry = dget(dentry); } } |
38f7bd94a Revert "af_unix: ... |
941 |
done_path_create(&path, dentry); |
faf020102 clean unix_bind()... |
942 943 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
944 945 946 947 |
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; |
3b1e0a655 [NET] NETNS: Omit... |
948 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
949 |
struct unix_sock *u = unix_sk(sk); |
e27dfcea4 af_unix: clean up... |
950 |
struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
dae6ad8f3 new helpers: kern... |
951 |
char *sun_path = sunaddr->sun_path; |
38f7bd94a Revert "af_unix: ... |
952 |
int err; |
95c961747 net: cleanup unsi... |
953 |
unsigned int hash; |
1da177e4c Linux-2.6.12-rc2 |
954 955 |
struct unix_address *addr; struct hlist_head *list; |
82fe0d2b4 af_unix: Use desi... |
956 |
struct path path = { }; |
1da177e4c Linux-2.6.12-rc2 |
957 958 |
err = -EINVAL; |
defbcf2de af_unix: Add sock... |
959 960 |
if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) |
1da177e4c Linux-2.6.12-rc2 |
961 |
goto out; |
e27dfcea4 af_unix: clean up... |
962 |
if (addr_len == sizeof(short)) { |
1da177e4c Linux-2.6.12-rc2 |
963 964 965 966 967 968 969 970 |
err = unix_autobind(sock); goto out; } err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) goto out; addr_len = err; |
0fb44559f af_unix: move uni... |
971 972 973 974 975 976 977 978 979 980 |
if (sun_path[0]) { umode_t mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current_umask()); err = unix_mknod(sun_path, mode, &path); if (err) { if (err == -EEXIST) err = -EADDRINUSE; goto out; } } |
6e1ce3c34 af_unix: split 'u... |
981 |
err = mutex_lock_interruptible(&u->bindlock); |
37ab4fa78 net: unix: allow ... |
982 |
if (err) |
0fb44559f af_unix: move uni... |
983 |
goto out_put; |
1da177e4c Linux-2.6.12-rc2 |
984 985 986 987 988 989 990 991 992 993 994 995 996 |
err = -EINVAL; if (u->addr) goto out_up; err = -ENOMEM; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) goto out_up; memcpy(addr->name, sunaddr, addr_len); addr->len = addr_len; addr->hash = hash ^ sk->sk_type; |
8c9814b97 net: convert unix... |
997 |
refcount_set(&addr->refcnt, 1); |
1da177e4c Linux-2.6.12-rc2 |
998 |
|
38f7bd94a Revert "af_unix: ... |
999 |
if (sun_path[0]) { |
1da177e4c Linux-2.6.12-rc2 |
1000 |
addr->hash = UNIX_HASH_SIZE; |
beef5121f Revert "af_unix: ... |
1001 |
hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
faf020102 clean unix_bind()... |
1002 |
spin_lock(&unix_table_lock); |
38f7bd94a Revert "af_unix: ... |
1003 |
u->path = path; |
faf020102 clean unix_bind()... |
1004 1005 1006 |
list = &unix_socket_table[hash]; } else { spin_lock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
1007 |
err = -EADDRINUSE; |
097e66c57 [NET]: Make AF_UN... |
1008 |
if (__unix_find_socket_byname(net, sunaddr, addr_len, |
1da177e4c Linux-2.6.12-rc2 |
1009 1010 1011 1012 1013 1014 |
sk->sk_type, hash)) { unix_release_addr(addr); goto out_unlock; } list = &unix_socket_table[addr->hash]; |
1da177e4c Linux-2.6.12-rc2 |
1015 1016 1017 1018 1019 1020 1021 1022 |
} err = 0; __unix_remove_socket(sk); u->addr = addr; __unix_insert_socket(list, sk); out_unlock: |
fbe9cc4a8 [AF_UNIX]: Use sp... |
1023 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
1024 |
out_up: |
6e1ce3c34 af_unix: split 'u... |
1025 |
mutex_unlock(&u->bindlock); |
0fb44559f af_unix: move uni... |
1026 1027 1028 |
out_put: if (err) path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
1029 1030 |
out: return err; |
1da177e4c Linux-2.6.12-rc2 |
1031 |
} |
278a3de5a [AF_UNIX]: Fix da... |
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 |
static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) { if (unlikely(sk1 == sk2) || !sk2) { unix_state_lock(sk1); return; } if (sk1 < sk2) { unix_state_lock(sk1); unix_state_lock_nested(sk2); } else { unix_state_lock(sk2); unix_state_lock_nested(sk1); } } static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) { if (unlikely(sk1 == sk2) || !sk2) { unix_state_unlock(sk1); return; } unix_state_unlock(sk1); unix_state_unlock(sk2); } |
1da177e4c Linux-2.6.12-rc2 |
1056 1057 1058 1059 |
static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sock *sk = sock->sk; |
3b1e0a655 [NET] NETNS: Omit... |
1060 |
struct net *net = sock_net(sk); |
e27dfcea4 af_unix: clean up... |
1061 |
struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; |
1da177e4c Linux-2.6.12-rc2 |
1062 |
struct sock *other; |
95c961747 net: cleanup unsi... |
1063 |
unsigned int hash; |
1da177e4c Linux-2.6.12-rc2 |
1064 |
int err; |
defbcf2de af_unix: Add sock... |
1065 1066 1067 |
err = -EINVAL; if (alen < offsetofend(struct sockaddr, sa_family)) goto out; |
1da177e4c Linux-2.6.12-rc2 |
1068 1069 1070 1071 1072 1073 1074 1075 1076 |
if (addr->sa_family != AF_UNSPEC) { err = unix_mkname(sunaddr, alen, &hash); if (err < 0) goto out; alen = err; if (test_bit(SOCK_PASSCRED, &sock->flags) && !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0) goto out; |
278a3de5a [AF_UNIX]: Fix da... |
1077 |
restart: |
e27dfcea4 af_unix: clean up... |
1078 |
other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err); |
1da177e4c Linux-2.6.12-rc2 |
1079 1080 |
if (!other) goto out; |
278a3de5a [AF_UNIX]: Fix da... |
1081 1082 1083 1084 1085 1086 1087 1088 |
unix_state_double_lock(sk, other); /* Apparently VFS overslept socket death. Retry. */ if (sock_flag(other, SOCK_DEAD)) { unix_state_double_unlock(sk, other); sock_put(other); goto restart; } |
1da177e4c Linux-2.6.12-rc2 |
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 |
err = -EPERM; if (!unix_may_send(sk, other)) goto out_unlock; err = security_unix_may_send(sk->sk_socket, other->sk_socket); if (err) goto out_unlock; } else { /* * 1003.1g breaking connected state with AF_UNSPEC */ other = NULL; |
278a3de5a [AF_UNIX]: Fix da... |
1103 |
unix_state_double_lock(sk, other); |
1da177e4c Linux-2.6.12-rc2 |
1104 1105 1106 1107 1108 1109 1110 |
} /* * If it was connected, reconnect. */ if (unix_peer(sk)) { struct sock *old_peer = unix_peer(sk); |
e27dfcea4 af_unix: clean up... |
1111 |
unix_peer(sk) = other; |
7d267278a unix: avoid use-a... |
1112 |
unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer); |
278a3de5a [AF_UNIX]: Fix da... |
1113 |
unix_state_double_unlock(sk, other); |
1da177e4c Linux-2.6.12-rc2 |
1114 1115 1116 1117 1118 |
if (other != old_peer) unix_dgram_disconnected(sk, old_peer); sock_put(old_peer); } else { |
e27dfcea4 af_unix: clean up... |
1119 |
unix_peer(sk) = other; |
278a3de5a [AF_UNIX]: Fix da... |
1120 |
unix_state_double_unlock(sk, other); |
1da177e4c Linux-2.6.12-rc2 |
1121 |
} |
ac7bfa62f [NET] UNIX: Fix w... |
1122 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1123 1124 |
out_unlock: |
278a3de5a [AF_UNIX]: Fix da... |
1125 |
unix_state_double_unlock(sk, other); |
1da177e4c Linux-2.6.12-rc2 |
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 |
sock_put(other); out: return err; } static long unix_wait_for_peer(struct sock *other, long timeo) { struct unix_sock *u = unix_sk(other); int sched; DEFINE_WAIT(wait); prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE); sched = !sock_flag(other, SOCK_DEAD) && !(other->sk_shutdown & RCV_SHUTDOWN) && |
3c73419c0 af_unix: fix 'pol... |
1141 |
unix_recvq_full(other); |
1da177e4c Linux-2.6.12-rc2 |
1142 |
|
1c92b4e50 [AF_UNIX]: Make s... |
1143 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 |
if (sched) timeo = schedule_timeout(timeo); finish_wait(&u->peer_wait, &wait); return timeo; } static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { |
e27dfcea4 af_unix: clean up... |
1155 |
struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
1da177e4c Linux-2.6.12-rc2 |
1156 |
struct sock *sk = sock->sk; |
3b1e0a655 [NET] NETNS: Omit... |
1157 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
1158 1159 1160 1161 |
struct unix_sock *u = unix_sk(sk), *newu, *otheru; struct sock *newsk = NULL; struct sock *other = NULL; struct sk_buff *skb = NULL; |
95c961747 net: cleanup unsi... |
1162 |
unsigned int hash; |
1da177e4c Linux-2.6.12-rc2 |
1163 1164 1165 1166 1167 1168 1169 1170 |
int st; int err; long timeo; err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) goto out; addr_len = err; |
f64f9e719 net: Move && and ... |
1171 1172 |
if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr && (err = unix_autobind(sock)) != 0) |
1da177e4c Linux-2.6.12-rc2 |
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 |
goto out; timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); /* First of all allocate resources. If we will make it after state is locked, we will have to recheck all again in any case. */ err = -ENOMEM; /* create new sock for complete connection */ |
11aa9c28b net: Pass kern fr... |
1185 |
newsk = unix_create1(sock_net(sk), NULL, 0); |
1da177e4c Linux-2.6.12-rc2 |
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
if (newsk == NULL) goto out; /* Allocate skb for sending to listening sock */ skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL); if (skb == NULL) goto out; restart: /* Find listening sock. */ |
097e66c57 [NET]: Make AF_UN... |
1196 |
other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err); |
1da177e4c Linux-2.6.12-rc2 |
1197 1198 1199 1200 |
if (!other) goto out; /* Latch state of peer */ |
1c92b4e50 [AF_UNIX]: Make s... |
1201 |
unix_state_lock(other); |
1da177e4c Linux-2.6.12-rc2 |
1202 1203 1204 |
/* Apparently VFS overslept socket death. Retry. */ if (sock_flag(other, SOCK_DEAD)) { |
1c92b4e50 [AF_UNIX]: Make s... |
1205 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1206 1207 1208 1209 1210 1211 1212 |
sock_put(other); goto restart; } err = -ECONNREFUSED; if (other->sk_state != TCP_LISTEN) goto out_unlock; |
77238f2b9 AF_UNIX: Fix dead... |
1213 1214 |
if (other->sk_shutdown & RCV_SHUTDOWN) goto out_unlock; |
1da177e4c Linux-2.6.12-rc2 |
1215 |
|
3c73419c0 af_unix: fix 'pol... |
1216 |
if (unix_recvq_full(other)) { |
1da177e4c Linux-2.6.12-rc2 |
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 |
err = -EAGAIN; if (!timeo) goto out_unlock; timeo = unix_wait_for_peer(other, timeo); err = sock_intr_errno(timeo); if (signal_pending(current)) goto out; sock_put(other); goto restart; |
ac7bfa62f [NET] UNIX: Fix w... |
1228 |
} |
1da177e4c Linux-2.6.12-rc2 |
1229 1230 |
/* Latch our state. |
e5537bfc9 af_unix: update l... |
1231 |
It is tricky place. We need to grab our state lock and cannot |
1da177e4c Linux-2.6.12-rc2 |
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 |
drop lock on peer. It is dangerous because deadlock is possible. Connect to self case and simultaneous attempt to connect are eliminated by checking socket state. other is TCP_LISTEN, if sk is TCP_LISTEN we check this before attempt to grab lock. Well, and we have to recheck the state after socket locked. */ st = sk->sk_state; switch (st) { case TCP_CLOSE: /* This is ok... continue with connect */ break; case TCP_ESTABLISHED: /* Socket is already connected */ err = -EISCONN; goto out_unlock; default: err = -EINVAL; goto out_unlock; } |
1c92b4e50 [AF_UNIX]: Make s... |
1254 |
unix_state_lock_nested(sk); |
1da177e4c Linux-2.6.12-rc2 |
1255 1256 |
if (sk->sk_state != st) { |
1c92b4e50 [AF_UNIX]: Make s... |
1257 1258 |
unix_state_unlock(sk); unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1259 1260 1261 |
sock_put(other); goto restart; } |
3610cda53 af_unix: Avoid so... |
1262 |
err = security_unix_stream_connect(sk, other, newsk); |
1da177e4c Linux-2.6.12-rc2 |
1263 |
if (err) { |
1c92b4e50 [AF_UNIX]: Make s... |
1264 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1265 1266 1267 1268 1269 1270 1271 1272 1273 |
goto out_unlock; } /* The way is open! Fastly set all the necessary fields... */ sock_hold(sk); unix_peer(newsk) = sk; newsk->sk_state = TCP_ESTABLISHED; newsk->sk_type = sk->sk_type; |
109f6e39f af_unix: Allow SO... |
1274 |
init_peercred(newsk); |
1da177e4c Linux-2.6.12-rc2 |
1275 |
newu = unix_sk(newsk); |
eaefd1105 net: add __rcu an... |
1276 |
RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); |
1da177e4c Linux-2.6.12-rc2 |
1277 1278 1279 1280 |
otheru = unix_sk(other); /* copy address information from listening to new sock*/ if (otheru->addr) { |
8c9814b97 net: convert unix... |
1281 |
refcount_inc(&otheru->addr->refcnt); |
1da177e4c Linux-2.6.12-rc2 |
1282 1283 |
newu->addr = otheru->addr; } |
40ffe67d2 switch unix_sock ... |
1284 1285 1286 |
if (otheru->path.dentry) { path_get(&otheru->path); newu->path = otheru->path; |
1da177e4c Linux-2.6.12-rc2 |
1287 1288 1289 |
} /* Set credentials */ |
109f6e39f af_unix: Allow SO... |
1290 |
copy_peercred(sk, other); |
1da177e4c Linux-2.6.12-rc2 |
1291 |
|
1da177e4c Linux-2.6.12-rc2 |
1292 1293 |
sock->state = SS_CONNECTED; sk->sk_state = TCP_ESTABLISHED; |
830a1e5c2 [AF_UNIX]: Remove... |
1294 |
sock_hold(newsk); |
4e857c58e arch: Mass conver... |
1295 |
smp_mb__after_atomic(); /* sock_hold() does an atomic_inc() */ |
830a1e5c2 [AF_UNIX]: Remove... |
1296 |
unix_peer(sk) = newsk; |
1da177e4c Linux-2.6.12-rc2 |
1297 |
|
1c92b4e50 [AF_UNIX]: Make s... |
1298 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1299 1300 1301 1302 |
/* take ten and and send info to listening sock */ spin_lock(&other->sk_receive_queue.lock); __skb_queue_tail(&other->sk_receive_queue, skb); |
1da177e4c Linux-2.6.12-rc2 |
1303 |
spin_unlock(&other->sk_receive_queue.lock); |
1c92b4e50 [AF_UNIX]: Make s... |
1304 |
unix_state_unlock(other); |
676d23690 net: Fix use afte... |
1305 |
other->sk_data_ready(other); |
1da177e4c Linux-2.6.12-rc2 |
1306 1307 1308 1309 1310 |
sock_put(other); return 0; out_unlock: if (other) |
1c92b4e50 [AF_UNIX]: Make s... |
1311 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1312 1313 |
out: |
40d44446c unix: remove some... |
1314 |
kfree_skb(skb); |
1da177e4c Linux-2.6.12-rc2 |
1315 1316 1317 1318 1319 1320 1321 1322 1323 |
if (newsk) unix_release_sock(newsk, 0); if (other) sock_put(other); return err; } static int unix_socketpair(struct socket *socka, struct socket *sockb) { |
e27dfcea4 af_unix: clean up... |
1324 |
struct sock *ska = socka->sk, *skb = sockb->sk; |
1da177e4c Linux-2.6.12-rc2 |
1325 1326 1327 1328 |
/* Join our sockets back to back */ sock_hold(ska); sock_hold(skb); |
e27dfcea4 af_unix: clean up... |
1329 1330 |
unix_peer(ska) = skb; unix_peer(skb) = ska; |
109f6e39f af_unix: Allow SO... |
1331 1332 |
init_peercred(ska); init_peercred(skb); |
1da177e4c Linux-2.6.12-rc2 |
1333 1334 1335 1336 1337 1338 1339 1340 1341 |
if (ska->sk_type != SOCK_DGRAM) { ska->sk_state = TCP_ESTABLISHED; skb->sk_state = TCP_ESTABLISHED; socka->state = SS_CONNECTED; sockb->state = SS_CONNECTED; } return 0; } |
90c6bd34f net: unix: inheri... |
1342 1343 1344 1345 1346 1347 1348 1349 |
static void unix_sock_inherit_flags(const struct socket *old, struct socket *new) { if (test_bit(SOCK_PASSCRED, &old->flags)) set_bit(SOCK_PASSCRED, &new->flags); if (test_bit(SOCK_PASSSEC, &old->flags)) set_bit(SOCK_PASSSEC, &new->flags); } |
cdfbabfb2 net: Work around ... |
1350 1351 |
static int unix_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) |
1da177e4c Linux-2.6.12-rc2 |
1352 1353 1354 1355 1356 1357 1358 |
{ struct sock *sk = sock->sk; struct sock *tsk; struct sk_buff *skb; int err; err = -EOPNOTSUPP; |
6eba6a372 net: Cleanup of a... |
1359 |
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) |
1da177e4c Linux-2.6.12-rc2 |
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 |
goto out; err = -EINVAL; if (sk->sk_state != TCP_LISTEN) goto out; /* If socket state is TCP_LISTEN it cannot change (for now...), * so that no locks are necessary. */ skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err); if (!skb) { /* This means receive shutdown. */ if (err == 0) err = -EINVAL; goto out; } tsk = skb->sk; skb_free_datagram(sk, skb); wake_up_interruptible(&unix_sk(sk)->peer_wait); /* attach accepted sock to socket */ |
1c92b4e50 [AF_UNIX]: Make s... |
1383 |
unix_state_lock(tsk); |
1da177e4c Linux-2.6.12-rc2 |
1384 |
newsock->state = SS_CONNECTED; |
90c6bd34f net: unix: inheri... |
1385 |
unix_sock_inherit_flags(sock, newsock); |
1da177e4c Linux-2.6.12-rc2 |
1386 |
sock_graft(tsk, newsock); |
1c92b4e50 [AF_UNIX]: Make s... |
1387 |
unix_state_unlock(tsk); |
1da177e4c Linux-2.6.12-rc2 |
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 |
return 0; out: return err; } static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; struct unix_sock *u; |
13cfa97be net: netlink_getn... |
1399 |
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr); |
1da177e4c Linux-2.6.12-rc2 |
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 |
int err = 0; if (peer) { sk = unix_peer_get(sk); err = -ENOTCONN; if (!sk) goto out; err = 0; } else { sock_hold(sk); } u = unix_sk(sk); |
1c92b4e50 [AF_UNIX]: Make s... |
1414 |
unix_state_lock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 |
if (!u->addr) { sunaddr->sun_family = AF_UNIX; sunaddr->sun_path[0] = 0; *uaddr_len = sizeof(short); } else { struct unix_address *addr = u->addr; *uaddr_len = addr->len; memcpy(sunaddr, addr->name, *uaddr_len); } |
1c92b4e50 [AF_UNIX]: Make s... |
1425 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 |
sock_put(sk); out: return err; } static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) { int i; scm->fp = UNIXCB(skb).fp; |
1da177e4c Linux-2.6.12-rc2 |
1436 |
UNIXCB(skb).fp = NULL; |
6eba6a372 net: Cleanup of a... |
1437 |
for (i = scm->fp->count-1; i >= 0; i--) |
415e3d3e9 unix: correctly t... |
1438 |
unix_notinflight(scm->fp->user, scm->fp->fp[i]); |
1da177e4c Linux-2.6.12-rc2 |
1439 |
} |
7361c36c5 af_unix: Allow cr... |
1440 |
static void unix_destruct_scm(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
1441 1442 1443 |
{ struct scm_cookie scm; memset(&scm, 0, sizeof(scm)); |
7361c36c5 af_unix: Allow cr... |
1444 |
scm.pid = UNIXCB(skb).pid; |
7361c36c5 af_unix: Allow cr... |
1445 1446 |
if (UNIXCB(skb).fp) unix_detach_fds(&scm, skb); |
1da177e4c Linux-2.6.12-rc2 |
1447 1448 1449 1450 1451 1452 |
/* Alas, it calls VFS */ /* So fscking what? fput() had been SMP-safe since the last Summer */ scm_destroy(&scm); sock_wfree(skb); } |
712f4aad4 unix: properly ac... |
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 |
/* * The "user->unix_inflight" variable is protected by the garbage * collection lock, and we just read it locklessly here. If you go * over the limit, there might be a tiny race in actually noticing * it across threads. Tough. */ static inline bool too_many_unix_fds(struct task_struct *p) { struct user_struct *user = current_user(); if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); return false; } |
6209344f5 net: unix: fix in... |
1467 |
static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
1468 1469 |
{ int i; |
25888e303 af_unix: limit re... |
1470 |
|
712f4aad4 unix: properly ac... |
1471 1472 |
if (too_many_unix_fds(current)) return -ETOOMANYREFS; |
6209344f5 net: unix: fix in... |
1473 1474 1475 1476 1477 1478 1479 1480 |
/* * Need to duplicate file references for the sake of garbage * collection. Otherwise a socket in the fps might become a * candidate for GC while the skb is not yet queued. */ UNIXCB(skb).fp = scm_fp_dup(scm->fp); if (!UNIXCB(skb).fp) return -ENOMEM; |
712f4aad4 unix: properly ac... |
1481 |
for (i = scm->fp->count - 1; i >= 0; i--) |
415e3d3e9 unix: correctly t... |
1482 |
unix_inflight(scm->fp->user, scm->fp->fp[i]); |
27eac47b0 net/unix: drop ob... |
1483 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1484 |
} |
f78a5fda9 Revert "Scm: Remo... |
1485 |
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) |
7361c36c5 af_unix: Allow cr... |
1486 1487 |
{ int err = 0; |
16e572626 af_unix: dont sen... |
1488 |
|
f78a5fda9 Revert "Scm: Remo... |
1489 |
UNIXCB(skb).pid = get_pid(scm->pid); |
6b0ee8c03 scm: Stop passing... |
1490 1491 |
UNIXCB(skb).uid = scm->creds.uid; UNIXCB(skb).gid = scm->creds.gid; |
7361c36c5 af_unix: Allow cr... |
1492 |
UNIXCB(skb).fp = NULL; |
37a9a8df8 net/unix: support... |
1493 |
unix_get_secdata(scm, skb); |
7361c36c5 af_unix: Allow cr... |
1494 1495 1496 1497 1498 1499 |
if (scm->fp && send_fds) err = unix_attach_fds(scm, skb); skb->destructor = unix_destruct_scm; return err; } |
9490f886b af-unix: passcred... |
1500 1501 1502 1503 1504 1505 1506 |
static bool unix_passcred_enabled(const struct socket *sock, const struct sock *other) { return test_bit(SOCK_PASSCRED, &sock->flags) || !other->sk_socket || test_bit(SOCK_PASSCRED, &other->sk_socket->flags); } |
1da177e4c Linux-2.6.12-rc2 |
1507 |
/* |
16e572626 af_unix: dont sen... |
1508 1509 1510 1511 1512 1513 1514 |
* Some apps rely on write() giving SCM_CREDENTIALS * We include credentials if source or destination socket * asserted SOCK_PASSCRED. */ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, const struct sock *other) { |
6b0ee8c03 scm: Stop passing... |
1515 |
if (UNIXCB(skb).pid) |
16e572626 af_unix: dont sen... |
1516 |
return; |
9490f886b af-unix: passcred... |
1517 |
if (unix_passcred_enabled(sock, other)) { |
16e572626 af_unix: dont sen... |
1518 |
UNIXCB(skb).pid = get_pid(task_tgid(current)); |
6e0895c2e Merge git://git.k... |
1519 |
current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); |
16e572626 af_unix: dont sen... |
1520 1521 |
} } |
9490f886b af-unix: passcred... |
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 |
static int maybe_init_creds(struct scm_cookie *scm, struct socket *socket, const struct sock *other) { int err; struct msghdr msg = { .msg_controllen = 0 }; err = scm_send(socket, &msg, scm, false); if (err) return err; if (unix_passcred_enabled(socket, other)) { scm->pid = get_pid(task_tgid(current)); current_uid_gid(&scm->creds.uid, &scm->creds.gid); } return err; } static bool unix_skb_scm_eq(struct sk_buff *skb, struct scm_cookie *scm) { const struct unix_skb_parms *u = &UNIXCB(skb); return u->pid == scm->pid && uid_eq(u->uid, scm->creds.uid) && gid_eq(u->gid, scm->creds.gid) && unix_secdata_eq(scm, skb); } |
16e572626 af_unix: dont sen... |
1550 |
/* |
1da177e4c Linux-2.6.12-rc2 |
1551 1552 |
* Send AF_UNIX data. */ |
1b7841404 net: Remove iocb ... |
1553 1554 |
static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
1da177e4c Linux-2.6.12-rc2 |
1555 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1556 |
struct sock *sk = sock->sk; |
3b1e0a655 [NET] NETNS: Omit... |
1557 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
1558 |
struct unix_sock *u = unix_sk(sk); |
342dfc306 net: add build-ti... |
1559 |
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name); |
1da177e4c Linux-2.6.12-rc2 |
1560 1561 1562 |
struct sock *other = NULL; int namelen = 0; /* fake GCC */ int err; |
95c961747 net: cleanup unsi... |
1563 |
unsigned int hash; |
f78a5fda9 Revert "Scm: Remo... |
1564 |
struct sk_buff *skb; |
1da177e4c Linux-2.6.12-rc2 |
1565 |
long timeo; |
7cc056626 net: remove sock_... |
1566 |
struct scm_cookie scm; |
eb6a24816 af_unix: reduce h... |
1567 |
int data_len = 0; |
7d267278a unix: avoid use-a... |
1568 |
int sk_locked; |
1da177e4c Linux-2.6.12-rc2 |
1569 |
|
5f23b7349 net: Fix soft loc... |
1570 |
wait_for_unix_gc(); |
7cc056626 net: remove sock_... |
1571 |
err = scm_send(sock, msg, &scm, false); |
1da177e4c Linux-2.6.12-rc2 |
1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 |
if (err < 0) return err; err = -EOPNOTSUPP; if (msg->msg_flags&MSG_OOB) goto out; if (msg->msg_namelen) { err = unix_mkname(sunaddr, msg->msg_namelen, &hash); if (err < 0) goto out; namelen = err; } else { sunaddr = NULL; err = -ENOTCONN; other = unix_peer_get(sk); if (!other) goto out; } |
f64f9e719 net: Move && and ... |
1591 1592 |
if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr && (err = unix_autobind(sock)) != 0) |
1da177e4c Linux-2.6.12-rc2 |
1593 1594 1595 1596 1597 |
goto out; err = -EMSGSIZE; if (len > sk->sk_sndbuf - 32) goto out; |
31ff6aa5c net: unix: Align ... |
1598 |
if (len > SKB_MAX_ALLOC) { |
eb6a24816 af_unix: reduce h... |
1599 1600 1601 |
data_len = min_t(size_t, len - SKB_MAX_ALLOC, MAX_SKB_FRAGS * PAGE_SIZE); |
31ff6aa5c net: unix: Align ... |
1602 1603 1604 1605 |
data_len = PAGE_ALIGN(data_len); BUILD_BUG_ON(SKB_MAX_ALLOC < PAGE_SIZE); } |
eb6a24816 af_unix: reduce h... |
1606 1607 |
skb = sock_alloc_send_pskb(sk, len - data_len, data_len, |
28d642710 net: attempt high... |
1608 1609 |
msg->msg_flags & MSG_DONTWAIT, &err, PAGE_ALLOC_COSTLY_ORDER); |
e27dfcea4 af_unix: clean up... |
1610 |
if (skb == NULL) |
1da177e4c Linux-2.6.12-rc2 |
1611 |
goto out; |
7cc056626 net: remove sock_... |
1612 |
err = unix_scm_to_skb(&scm, skb, true); |
25888e303 af_unix: limit re... |
1613 |
if (err < 0) |
7361c36c5 af_unix: Allow cr... |
1614 |
goto out_free; |
877ce7c1b [AF_UNIX]: Datagr... |
1615 |
|
eb6a24816 af_unix: reduce h... |
1616 1617 1618 |
skb_put(skb, len - data_len); skb->data_len = data_len; skb->len = len; |
c0371da60 put iov_iter into... |
1619 |
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len); |
1da177e4c Linux-2.6.12-rc2 |
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 |
if (err) goto out_free; timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); restart: if (!other) { err = -ECONNRESET; if (sunaddr == NULL) goto out_free; |
097e66c57 [NET]: Make AF_UN... |
1630 |
other = unix_find_other(net, sunaddr, namelen, sk->sk_type, |
1da177e4c Linux-2.6.12-rc2 |
1631 |
hash, &err); |
e27dfcea4 af_unix: clean up... |
1632 |
if (other == NULL) |
1da177e4c Linux-2.6.12-rc2 |
1633 1634 |
goto out_free; } |
d6ae3bae3 af_unix: implemen... |
1635 1636 1637 1638 1639 |
if (sk_filter(other, skb) < 0) { /* Toss the packet but do not return any error to the sender */ err = len; goto out_free; } |
7d267278a unix: avoid use-a... |
1640 |
sk_locked = 0; |
1c92b4e50 [AF_UNIX]: Make s... |
1641 |
unix_state_lock(other); |
7d267278a unix: avoid use-a... |
1642 |
restart_locked: |
1da177e4c Linux-2.6.12-rc2 |
1643 1644 1645 |
err = -EPERM; if (!unix_may_send(sk, other)) goto out_unlock; |
7d267278a unix: avoid use-a... |
1646 |
if (unlikely(sock_flag(other, SOCK_DEAD))) { |
1da177e4c Linux-2.6.12-rc2 |
1647 1648 1649 1650 |
/* * Check with 1003.1g - what should * datagram error */ |
1c92b4e50 [AF_UNIX]: Make s... |
1651 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1652 |
sock_put(other); |
7d267278a unix: avoid use-a... |
1653 1654 |
if (!sk_locked) unix_state_lock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1655 |
err = 0; |
1da177e4c Linux-2.6.12-rc2 |
1656 |
if (unix_peer(sk) == other) { |
e27dfcea4 af_unix: clean up... |
1657 |
unix_peer(sk) = NULL; |
7d267278a unix: avoid use-a... |
1658 |
unix_dgram_peer_wake_disconnect_wakeup(sk, other); |
1c92b4e50 [AF_UNIX]: Make s... |
1659 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1660 1661 1662 1663 1664 |
unix_dgram_disconnected(sk, other); sock_put(other); err = -ECONNREFUSED; } else { |
1c92b4e50 [AF_UNIX]: Make s... |
1665 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 |
} other = NULL; if (err) goto out_free; goto restart; } err = -EPIPE; if (other->sk_shutdown & RCV_SHUTDOWN) goto out_unlock; if (sk->sk_type != SOCK_SEQPACKET) { err = security_unix_may_send(sk->sk_socket, other->sk_socket); if (err) goto out_unlock; } |
a5527dda3 af_unix: Guard ag... |
1683 1684 1685 1686 1687 1688 |
/* other == sk && unix_peer(other) != sk if * - unix_peer(sk) == NULL, destination address bound to sk * - unix_peer(sk) == sk by time of get but disconnected before lock */ if (other != sk && unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { |
7d267278a unix: avoid use-a... |
1689 1690 1691 1692 1693 1694 1695 1696 |
if (timeo) { timeo = unix_wait_for_peer(other, timeo); err = sock_intr_errno(timeo); if (signal_pending(current)) goto out_free; goto restart; |
1da177e4c Linux-2.6.12-rc2 |
1697 |
} |
7d267278a unix: avoid use-a... |
1698 1699 1700 1701 |
if (!sk_locked) { unix_state_unlock(other); unix_state_double_lock(sk, other); } |
1da177e4c Linux-2.6.12-rc2 |
1702 |
|
7d267278a unix: avoid use-a... |
1703 1704 1705 1706 1707 1708 |
if (unix_peer(sk) != other || unix_dgram_peer_wake_me(sk, other)) { err = -EAGAIN; sk_locked = 1; goto out_unlock; } |
1da177e4c Linux-2.6.12-rc2 |
1709 |
|
7d267278a unix: avoid use-a... |
1710 1711 1712 1713 |
if (!sk_locked) { sk_locked = 1; goto restart_locked; } |
1da177e4c Linux-2.6.12-rc2 |
1714 |
} |
7d267278a unix: avoid use-a... |
1715 1716 |
if (unlikely(sk_locked)) unix_state_unlock(sk); |
3f66116e8 AF_UNIX: Implemen... |
1717 1718 |
if (sock_flag(other, SOCK_RCVTSTAMP)) __net_timestamp(skb); |
16e572626 af_unix: dont sen... |
1719 |
maybe_add_creds(skb, sock, other); |
1da177e4c Linux-2.6.12-rc2 |
1720 |
skb_queue_tail(&other->sk_receive_queue, skb); |
1c92b4e50 [AF_UNIX]: Make s... |
1721 |
unix_state_unlock(other); |
676d23690 net: Fix use afte... |
1722 |
other->sk_data_ready(other); |
1da177e4c Linux-2.6.12-rc2 |
1723 |
sock_put(other); |
7cc056626 net: remove sock_... |
1724 |
scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
1725 1726 1727 |
return len; out_unlock: |
7d267278a unix: avoid use-a... |
1728 1729 |
if (sk_locked) unix_state_unlock(sk); |
1c92b4e50 [AF_UNIX]: Make s... |
1730 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1731 1732 1733 1734 1735 |
out_free: kfree_skb(skb); out: if (other) sock_put(other); |
7cc056626 net: remove sock_... |
1736 |
scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
1737 1738 |
return err; } |
e370a7236 af_unix: improve ... |
1739 1740 1741 1742 |
/* We use paged skbs for stream sockets, and limit occupancy to 32768 * bytes, and a minimun of a full page. */ #define UNIX_SKB_FRAGS_SZ (PAGE_SIZE << get_order(32768)) |
ac7bfa62f [NET] UNIX: Fix w... |
1743 |
|
1b7841404 net: Remove iocb ... |
1744 1745 |
static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
1da177e4c Linux-2.6.12-rc2 |
1746 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1747 1748 |
struct sock *sk = sock->sk; struct sock *other = NULL; |
6eba6a372 net: Cleanup of a... |
1749 |
int err, size; |
f78a5fda9 Revert "Scm: Remo... |
1750 |
struct sk_buff *skb; |
e27dfcea4 af_unix: clean up... |
1751 |
int sent = 0; |
7cc056626 net: remove sock_... |
1752 |
struct scm_cookie scm; |
8ba69ba6a net: unix: fix se... |
1753 |
bool fds_sent = false; |
e370a7236 af_unix: improve ... |
1754 |
int data_len; |
1da177e4c Linux-2.6.12-rc2 |
1755 |
|
5f23b7349 net: Fix soft loc... |
1756 |
wait_for_unix_gc(); |
7cc056626 net: remove sock_... |
1757 |
err = scm_send(sock, msg, &scm, false); |
1da177e4c Linux-2.6.12-rc2 |
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 |
if (err < 0) return err; err = -EOPNOTSUPP; if (msg->msg_flags&MSG_OOB) goto out_err; if (msg->msg_namelen) { err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; goto out_err; } else { |
1da177e4c Linux-2.6.12-rc2 |
1769 |
err = -ENOTCONN; |
830a1e5c2 [AF_UNIX]: Remove... |
1770 |
other = unix_peer(sk); |
1da177e4c Linux-2.6.12-rc2 |
1771 1772 1773 1774 1775 1776 |
if (!other) goto out_err; } if (sk->sk_shutdown & SEND_SHUTDOWN) goto pipe_err; |
6eba6a372 net: Cleanup of a... |
1777 |
while (sent < len) { |
e370a7236 af_unix: improve ... |
1778 |
size = len - sent; |
1da177e4c Linux-2.6.12-rc2 |
1779 1780 |
/* Keep two messages in the pipe so it schedules better */ |
e370a7236 af_unix: improve ... |
1781 |
size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64); |
1da177e4c Linux-2.6.12-rc2 |
1782 |
|
e370a7236 af_unix: improve ... |
1783 1784 |
/* allow fallback to order-0 allocations */ size = min_t(int, size, SKB_MAX_HEAD(0) + UNIX_SKB_FRAGS_SZ); |
ac7bfa62f [NET] UNIX: Fix w... |
1785 |
|
e370a7236 af_unix: improve ... |
1786 |
data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); |
1da177e4c Linux-2.6.12-rc2 |
1787 |
|
31ff6aa5c net: unix: Align ... |
1788 |
data_len = min_t(size_t, size, PAGE_ALIGN(data_len)); |
e370a7236 af_unix: improve ... |
1789 |
skb = sock_alloc_send_pskb(sk, size - data_len, data_len, |
28d642710 net: attempt high... |
1790 1791 |
msg->msg_flags & MSG_DONTWAIT, &err, get_order(UNIX_SKB_FRAGS_SZ)); |
e370a7236 af_unix: improve ... |
1792 |
if (!skb) |
1da177e4c Linux-2.6.12-rc2 |
1793 |
goto out_err; |
f78a5fda9 Revert "Scm: Remo... |
1794 |
/* Only send the fds in the first buffer */ |
7cc056626 net: remove sock_... |
1795 |
err = unix_scm_to_skb(&scm, skb, !fds_sent); |
25888e303 af_unix: limit re... |
1796 |
if (err < 0) { |
7361c36c5 af_unix: Allow cr... |
1797 |
kfree_skb(skb); |
f78a5fda9 Revert "Scm: Remo... |
1798 |
goto out_err; |
6209344f5 net: unix: fix in... |
1799 |
} |
7361c36c5 af_unix: Allow cr... |
1800 |
fds_sent = true; |
1da177e4c Linux-2.6.12-rc2 |
1801 |
|
e370a7236 af_unix: improve ... |
1802 1803 1804 |
skb_put(skb, size - data_len); skb->data_len = data_len; skb->len = size; |
c0371da60 put iov_iter into... |
1805 |
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size); |
6eba6a372 net: Cleanup of a... |
1806 |
if (err) { |
1da177e4c Linux-2.6.12-rc2 |
1807 |
kfree_skb(skb); |
f78a5fda9 Revert "Scm: Remo... |
1808 |
goto out_err; |
1da177e4c Linux-2.6.12-rc2 |
1809 |
} |
1c92b4e50 [AF_UNIX]: Make s... |
1810 |
unix_state_lock(other); |
1da177e4c Linux-2.6.12-rc2 |
1811 1812 1813 1814 |
if (sock_flag(other, SOCK_DEAD) || (other->sk_shutdown & RCV_SHUTDOWN)) goto pipe_err_free; |
16e572626 af_unix: dont sen... |
1815 |
maybe_add_creds(skb, sock, other); |
1da177e4c Linux-2.6.12-rc2 |
1816 |
skb_queue_tail(&other->sk_receive_queue, skb); |
1c92b4e50 [AF_UNIX]: Make s... |
1817 |
unix_state_unlock(other); |
676d23690 net: Fix use afte... |
1818 |
other->sk_data_ready(other); |
e27dfcea4 af_unix: clean up... |
1819 |
sent += size; |
1da177e4c Linux-2.6.12-rc2 |
1820 |
} |
1da177e4c Linux-2.6.12-rc2 |
1821 |
|
7cc056626 net: remove sock_... |
1822 |
scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
1823 1824 1825 1826 |
return sent; pipe_err_free: |
1c92b4e50 [AF_UNIX]: Make s... |
1827 |
unix_state_unlock(other); |
1da177e4c Linux-2.6.12-rc2 |
1828 1829 |
kfree_skb(skb); pipe_err: |
6eba6a372 net: Cleanup of a... |
1830 1831 |
if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) send_sig(SIGPIPE, current, 0); |
1da177e4c Linux-2.6.12-rc2 |
1832 1833 |
err = -EPIPE; out_err: |
7cc056626 net: remove sock_... |
1834 |
scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
1835 1836 |
return sent ? : err; } |
869e7c624 net: af_unix: imp... |
1837 1838 1839 |
static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, int offset, size_t size, int flags) { |
9490f886b af-unix: passcred... |
1840 1841 1842 1843 |
int err; bool send_sigpipe = false; bool init_scm = true; struct scm_cookie scm; |
869e7c624 net: af_unix: imp... |
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 |
struct sock *other, *sk = socket->sk; struct sk_buff *skb, *newskb = NULL, *tail = NULL; if (flags & MSG_OOB) return -EOPNOTSUPP; other = unix_peer(sk); if (!other || sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; if (false) { alloc_skb: unix_state_unlock(other); |
6e1ce3c34 af_unix: split 'u... |
1857 |
mutex_unlock(&unix_sk(other)->iolock); |
869e7c624 net: af_unix: imp... |
1858 1859 1860 |
newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, &err, 0); if (!newskb) |
9490f886b af-unix: passcred... |
1861 |
goto err; |
869e7c624 net: af_unix: imp... |
1862 |
} |
6e1ce3c34 af_unix: split 'u... |
1863 |
/* we must acquire iolock as we modify already present |
869e7c624 net: af_unix: imp... |
1864 1865 |
* skbs in the sk_receive_queue and mess with skb->len */ |
6e1ce3c34 af_unix: split 'u... |
1866 |
err = mutex_lock_interruptible(&unix_sk(other)->iolock); |
869e7c624 net: af_unix: imp... |
1867 1868 |
if (err) { err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS; |
869e7c624 net: af_unix: imp... |
1869 1870 1871 1872 1873 |
goto err; } if (sk->sk_shutdown & SEND_SHUTDOWN) { err = -EPIPE; |
9490f886b af-unix: passcred... |
1874 |
send_sigpipe = true; |
869e7c624 net: af_unix: imp... |
1875 1876 1877 1878 1879 1880 1881 1882 |
goto err_unlock; } unix_state_lock(other); if (sock_flag(other, SOCK_DEAD) || other->sk_shutdown & RCV_SHUTDOWN) { err = -EPIPE; |
9490f886b af-unix: passcred... |
1883 |
send_sigpipe = true; |
869e7c624 net: af_unix: imp... |
1884 1885 |
goto err_state_unlock; } |
9490f886b af-unix: passcred... |
1886 1887 1888 1889 1890 1891 |
if (init_scm) { err = maybe_init_creds(&scm, socket, other); if (err) goto err_state_unlock; init_scm = false; } |
869e7c624 net: af_unix: imp... |
1892 1893 1894 |
skb = skb_peek_tail(&other->sk_receive_queue); if (tail && tail == skb) { skb = newskb; |
9490f886b af-unix: passcred... |
1895 1896 |
} else if (!skb || !unix_skb_scm_eq(skb, &scm)) { if (newskb) { |
869e7c624 net: af_unix: imp... |
1897 |
skb = newskb; |
9490f886b af-unix: passcred... |
1898 1899 |
} else { tail = skb; |
869e7c624 net: af_unix: imp... |
1900 |
goto alloc_skb; |
9490f886b af-unix: passcred... |
1901 |
} |
869e7c624 net: af_unix: imp... |
1902 1903 1904 1905 1906 1907 |
} else if (newskb) { /* this is fast path, we don't necessarily need to * call to kfree_skb even though with newskb == NULL * this - does no harm */ consume_skb(newskb); |
8844f9723 af_unix: don't ap... |
1908 |
newskb = NULL; |
869e7c624 net: af_unix: imp... |
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 |
} if (skb_append_pagefrags(skb, page, offset, size)) { tail = skb; goto alloc_skb; } skb->len += size; skb->data_len += size; skb->truesize += size; |
14afee4b6 net: convert sock... |
1919 |
refcount_add(size, &sk->sk_wmem_alloc); |
869e7c624 net: af_unix: imp... |
1920 |
|
a3a116e04 af_unix: take rec... |
1921 |
if (newskb) { |
9490f886b af-unix: passcred... |
1922 1923 1924 |
err = unix_scm_to_skb(&scm, skb, false); if (err) goto err_state_unlock; |
a3a116e04 af_unix: take rec... |
1925 |
spin_lock(&other->sk_receive_queue.lock); |
869e7c624 net: af_unix: imp... |
1926 |
__skb_queue_tail(&other->sk_receive_queue, newskb); |
a3a116e04 af_unix: take rec... |
1927 1928 |
spin_unlock(&other->sk_receive_queue.lock); } |
869e7c624 net: af_unix: imp... |
1929 1930 |
unix_state_unlock(other); |
6e1ce3c34 af_unix: split 'u... |
1931 |
mutex_unlock(&unix_sk(other)->iolock); |
869e7c624 net: af_unix: imp... |
1932 1933 |
other->sk_data_ready(other); |
9490f886b af-unix: passcred... |
1934 |
scm_destroy(&scm); |
869e7c624 net: af_unix: imp... |
1935 1936 1937 1938 1939 |
return size; err_state_unlock: unix_state_unlock(other); err_unlock: |
6e1ce3c34 af_unix: split 'u... |
1940 |
mutex_unlock(&unix_sk(other)->iolock); |
869e7c624 net: af_unix: imp... |
1941 1942 1943 1944 |
err: kfree_skb(newskb); if (send_sigpipe && !(flags & MSG_NOSIGNAL)) send_sig(SIGPIPE, current, 0); |
9490f886b af-unix: passcred... |
1945 1946 |
if (!init_scm) scm_destroy(&scm); |
869e7c624 net: af_unix: imp... |
1947 1948 |
return err; } |
1b7841404 net: Remove iocb ... |
1949 1950 |
static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
1da177e4c Linux-2.6.12-rc2 |
1951 1952 1953 |
{ int err; struct sock *sk = sock->sk; |
ac7bfa62f [NET] UNIX: Fix w... |
1954 |
|
1da177e4c Linux-2.6.12-rc2 |
1955 1956 1957 1958 1959 1960 1961 1962 1963 |
err = sock_error(sk); if (err) return err; if (sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; if (msg->msg_namelen) msg->msg_namelen = 0; |
1b7841404 net: Remove iocb ... |
1964 |
return unix_dgram_sendmsg(sock, msg, len); |
1da177e4c Linux-2.6.12-rc2 |
1965 |
} |
ac7bfa62f [NET] UNIX: Fix w... |
1966 |
|
1b7841404 net: Remove iocb ... |
1967 1968 |
static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) |
a05d2ad1c af_unix: Only all... |
1969 1970 1971 1972 1973 |
{ struct sock *sk = sock->sk; if (sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; |
1b7841404 net: Remove iocb ... |
1974 |
return unix_dgram_recvmsg(sock, msg, size, flags); |
a05d2ad1c af_unix: Only all... |
1975 |
} |
1da177e4c Linux-2.6.12-rc2 |
1976 1977 1978 |
static void unix_copy_addr(struct msghdr *msg, struct sock *sk) { struct unix_sock *u = unix_sk(sk); |
1da177e4c Linux-2.6.12-rc2 |
1979 1980 1981 1982 1983 |
if (u->addr) { msg->msg_namelen = u->addr->len; memcpy(msg->msg_name, u->addr->name, u->addr->len); } } |
1b7841404 net: Remove iocb ... |
1984 1985 |
static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) |
1da177e4c Linux-2.6.12-rc2 |
1986 |
{ |
7cc056626 net: remove sock_... |
1987 |
struct scm_cookie scm; |
1da177e4c Linux-2.6.12-rc2 |
1988 1989 |
struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); |
648742808 af_unix: fix unix... |
1990 1991 |
struct sk_buff *skb, *last; long timeo; |
1da177e4c Linux-2.6.12-rc2 |
1992 |
int err; |
f55bb7f9c unix: Support pee... |
1993 |
int peeked, skip; |
1da177e4c Linux-2.6.12-rc2 |
1994 1995 1996 1997 |
err = -EOPNOTSUPP; if (flags&MSG_OOB) goto out; |
648742808 af_unix: fix unix... |
1998 |
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
1da177e4c Linux-2.6.12-rc2 |
1999 |
|
648742808 af_unix: fix unix... |
2000 |
do { |
6e1ce3c34 af_unix: split 'u... |
2001 |
mutex_lock(&u->iolock); |
f55bb7f9c unix: Support pee... |
2002 |
|
648742808 af_unix: fix unix... |
2003 |
skip = sk_peek_offset(sk, flags); |
7c13f97ff udp: do fwd memor... |
2004 2005 |
skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip, &err, &last); |
648742808 af_unix: fix unix... |
2006 2007 |
if (skb) break; |
6e1ce3c34 af_unix: split 'u... |
2008 |
mutex_unlock(&u->iolock); |
648742808 af_unix: fix unix... |
2009 2010 2011 2012 2013 |
if (err != -EAGAIN) break; } while (timeo && !__skb_wait_for_more_packets(sk, &err, &timeo, last)); |
6e1ce3c34 af_unix: split 'u... |
2014 |
if (!skb) { /* implies iolock unlocked */ |
0a1122588 [UNIX]: EOF on no... |
2015 2016 2017 2018 2019 2020 |
unix_state_lock(sk); /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) err = 0; unix_state_unlock(sk); |
648742808 af_unix: fix unix... |
2021 |
goto out; |
0a1122588 [UNIX]: EOF on no... |
2022 |
} |
1da177e4c Linux-2.6.12-rc2 |
2023 |
|
77b75f4d8 unix: use wq_has_... |
2024 2025 2026 2027 |
if (wq_has_sleeper(&u->peer_wait)) wake_up_interruptible_sync_poll(&u->peer_wait, POLLOUT | POLLWRNORM | POLLWRBAND); |
1da177e4c Linux-2.6.12-rc2 |
2028 2029 2030 |
if (msg->msg_name) unix_copy_addr(msg, skb->sk); |
f55bb7f9c unix: Support pee... |
2031 2032 2033 |
if (size > skb->len - skip) size = skb->len - skip; else if (size < skb->len - skip) |
1da177e4c Linux-2.6.12-rc2 |
2034 |
msg->msg_flags |= MSG_TRUNC; |
51f3d02b9 net: Add and use ... |
2035 |
err = skb_copy_datagram_msg(skb, skip, msg, size); |
1da177e4c Linux-2.6.12-rc2 |
2036 2037 |
if (err) goto out_free; |
3f66116e8 AF_UNIX: Implemen... |
2038 2039 |
if (sock_flag(sk, SOCK_RCVTSTAMP)) __sock_recv_timestamp(msg, sk, skb); |
7cc056626 net: remove sock_... |
2040 2041 2042 2043 |
memset(&scm, 0, sizeof(scm)); scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); unix_set_secdata(&scm, skb); |
1da177e4c Linux-2.6.12-rc2 |
2044 |
|
6eba6a372 net: Cleanup of a... |
2045 |
if (!(flags & MSG_PEEK)) { |
1da177e4c Linux-2.6.12-rc2 |
2046 |
if (UNIXCB(skb).fp) |
7cc056626 net: remove sock_... |
2047 |
unix_detach_fds(&scm, skb); |
f55bb7f9c unix: Support pee... |
2048 2049 |
sk_peek_offset_bwd(sk, skb->len); |
6eba6a372 net: Cleanup of a... |
2050 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
2051 2052 2053 2054 2055 2056 |
/* It is questionable: on PEEK we could: - do not return fds - good, but too simple 8) - return fds, and do not return them on read (old strategy, apparently wrong) - clone fds (I chose it for now, it is the most universal solution) |
ac7bfa62f [NET] UNIX: Fix w... |
2057 2058 2059 2060 |
POSIX 1003.1g does not actually define this clearly at all. POSIX 1003.1g doesn't define a lot of things clearly however! |
1da177e4c Linux-2.6.12-rc2 |
2061 |
*/ |
f55bb7f9c unix: Support pee... |
2062 2063 |
sk_peek_offset_fwd(sk, size); |
1da177e4c Linux-2.6.12-rc2 |
2064 |
if (UNIXCB(skb).fp) |
7cc056626 net: remove sock_... |
2065 |
scm.fp = scm_fp_dup(UNIXCB(skb).fp); |
1da177e4c Linux-2.6.12-rc2 |
2066 |
} |
9f6f9af76 af_unix: MSG_TRUN... |
2067 |
err = (flags & MSG_TRUNC) ? skb->len - skip : size; |
1da177e4c Linux-2.6.12-rc2 |
2068 |
|
7cc056626 net: remove sock_... |
2069 |
scm_recv(sock, msg, &scm, flags); |
1da177e4c Linux-2.6.12-rc2 |
2070 2071 |
out_free: |
6eba6a372 net: Cleanup of a... |
2072 |
skb_free_datagram(sk, skb); |
6e1ce3c34 af_unix: split 'u... |
2073 |
mutex_unlock(&u->iolock); |
1da177e4c Linux-2.6.12-rc2 |
2074 2075 2076 2077 2078 |
out: return err; } /* |
79f632c71 unix/stream: fix ... |
2079 |
* Sleep until more data has arrived. But check for races.. |
1da177e4c Linux-2.6.12-rc2 |
2080 |
*/ |
79f632c71 unix/stream: fix ... |
2081 |
static long unix_stream_data_wait(struct sock *sk, long timeo, |
06a77b07e af_unix: conditio... |
2082 2083 |
struct sk_buff *last, unsigned int last_len, bool freezable) |
1da177e4c Linux-2.6.12-rc2 |
2084 |
{ |
2b514574f net: af_unix: imp... |
2085 |
struct sk_buff *tail; |
1da177e4c Linux-2.6.12-rc2 |
2086 |
DEFINE_WAIT(wait); |
1c92b4e50 [AF_UNIX]: Make s... |
2087 |
unix_state_lock(sk); |
1da177e4c Linux-2.6.12-rc2 |
2088 2089 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
2090 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
2091 |
|
2b514574f net: af_unix: imp... |
2092 2093 2094 |
tail = skb_peek_tail(&sk->sk_receive_queue); if (tail != last || (tail && tail->len != last_len) || |
1da177e4c Linux-2.6.12-rc2 |
2095 2096 2097 2098 2099 |
sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) || signal_pending(current) || !timeo) break; |
9cd3e072b net: rename SOCK_... |
2100 |
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
1c92b4e50 [AF_UNIX]: Make s... |
2101 |
unix_state_unlock(sk); |
06a77b07e af_unix: conditio... |
2102 2103 2104 2105 |
if (freezable) timeo = freezable_schedule_timeout(timeo); else timeo = schedule_timeout(timeo); |
1c92b4e50 [AF_UNIX]: Make s... |
2106 |
unix_state_lock(sk); |
b48732e4a unix/caif: sk_soc... |
2107 2108 2109 |
if (sock_flag(sk, SOCK_DEAD)) break; |
9cd3e072b net: rename SOCK_... |
2110 |
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
1da177e4c Linux-2.6.12-rc2 |
2111 |
} |
aa3951451 net: sk_sleep() h... |
2112 |
finish_wait(sk_sleep(sk), &wait); |
1c92b4e50 [AF_UNIX]: Make s... |
2113 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
2114 2115 |
return timeo; } |
e370a7236 af_unix: improve ... |
2116 2117 2118 2119 |
static unsigned int unix_skb_len(const struct sk_buff *skb) { return skb->len - UNIXCB(skb).consumed; } |
2b514574f net: af_unix: imp... |
2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 |
struct unix_stream_read_state { int (*recv_actor)(struct sk_buff *, int, int, struct unix_stream_read_state *); struct socket *socket; struct msghdr *msg; struct pipe_inode_info *pipe; size_t size; int flags; unsigned int splice_flags; }; |
06a77b07e af_unix: conditio... |
2130 2131 |
static int unix_stream_read_generic(struct unix_stream_read_state *state, bool freezable) |
1da177e4c Linux-2.6.12-rc2 |
2132 |
{ |
7cc056626 net: remove sock_... |
2133 |
struct scm_cookie scm; |
2b514574f net: af_unix: imp... |
2134 |
struct socket *sock = state->socket; |
1da177e4c Linux-2.6.12-rc2 |
2135 2136 |
struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); |
1da177e4c Linux-2.6.12-rc2 |
2137 |
int copied = 0; |
2b514574f net: af_unix: imp... |
2138 |
int flags = state->flags; |
de1443916 net: unix: non bl... |
2139 |
int noblock = flags & MSG_DONTWAIT; |
2b514574f net: af_unix: imp... |
2140 |
bool check_creds = false; |
1da177e4c Linux-2.6.12-rc2 |
2141 2142 2143 |
int target; int err = 0; long timeo; |
fc0d75364 unix: Support pee... |
2144 |
int skip; |
2b514574f net: af_unix: imp... |
2145 2146 |
size_t size = state->size; unsigned int last_len; |
1da177e4c Linux-2.6.12-rc2 |
2147 |
|
1b92ee3d0 af_unix: Don't se... |
2148 2149 |
if (unlikely(sk->sk_state != TCP_ESTABLISHED)) { err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
2150 |
goto out; |
1b92ee3d0 af_unix: Don't se... |
2151 |
} |
1da177e4c Linux-2.6.12-rc2 |
2152 |
|
1b92ee3d0 af_unix: Don't se... |
2153 2154 |
if (unlikely(flags & MSG_OOB)) { err = -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
2155 |
goto out; |
1b92ee3d0 af_unix: Don't se... |
2156 |
} |
1da177e4c Linux-2.6.12-rc2 |
2157 |
|
2b514574f net: af_unix: imp... |
2158 |
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); |
de1443916 net: unix: non bl... |
2159 |
timeo = sock_rcvtimeo(sk, noblock); |
1da177e4c Linux-2.6.12-rc2 |
2160 |
|
2b514574f net: af_unix: imp... |
2161 |
memset(&scm, 0, sizeof(scm)); |
1da177e4c Linux-2.6.12-rc2 |
2162 2163 2164 |
/* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg */ |
6e1ce3c34 af_unix: split 'u... |
2165 |
mutex_lock(&u->iolock); |
1da177e4c Linux-2.6.12-rc2 |
2166 |
|
a0917e0bc datagram: When pe... |
2167 |
skip = max(sk_peek_offset(sk, flags), 0); |
e9193d60d net/unix: fix log... |
2168 |
|
6eba6a372 net: Cleanup of a... |
2169 |
do { |
1da177e4c Linux-2.6.12-rc2 |
2170 |
int chunk; |
73ed5d25d af-unix: fix use-... |
2171 |
bool drop_skb; |
79f632c71 unix/stream: fix ... |
2172 |
struct sk_buff *skb, *last; |
1da177e4c Linux-2.6.12-rc2 |
2173 |
|
18eceb818 af_unix: Don't us... |
2174 |
redo: |
3c0d2f378 [AF_UNIX]: Fix st... |
2175 |
unix_state_lock(sk); |
b48732e4a unix/caif: sk_soc... |
2176 2177 2178 2179 |
if (sock_flag(sk, SOCK_DEAD)) { err = -ECONNRESET; goto unlock; } |
79f632c71 unix/stream: fix ... |
2180 |
last = skb = skb_peek(&sk->sk_receive_queue); |
2b514574f net: af_unix: imp... |
2181 |
last_len = last ? last->len : 0; |
fc0d75364 unix: Support pee... |
2182 |
again: |
6eba6a372 net: Cleanup of a... |
2183 |
if (skb == NULL) { |
1da177e4c Linux-2.6.12-rc2 |
2184 |
if (copied >= target) |
3c0d2f378 [AF_UNIX]: Fix st... |
2185 |
goto unlock; |
1da177e4c Linux-2.6.12-rc2 |
2186 2187 2188 2189 |
/* * POSIX 1003.1g mandates this order. */ |
ac7bfa62f [NET] UNIX: Fix w... |
2190 |
|
6eba6a372 net: Cleanup of a... |
2191 2192 |
err = sock_error(sk); if (err) |
3c0d2f378 [AF_UNIX]: Fix st... |
2193 |
goto unlock; |
1da177e4c Linux-2.6.12-rc2 |
2194 |
if (sk->sk_shutdown & RCV_SHUTDOWN) |
3c0d2f378 [AF_UNIX]: Fix st... |
2195 2196 2197 |
goto unlock; unix_state_unlock(sk); |
1b92ee3d0 af_unix: Don't se... |
2198 2199 |
if (!timeo) { err = -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
2200 |
break; |
1b92ee3d0 af_unix: Don't se... |
2201 |
} |
6e1ce3c34 af_unix: split 'u... |
2202 |
mutex_unlock(&u->iolock); |
1da177e4c Linux-2.6.12-rc2 |
2203 |
|
2b514574f net: af_unix: imp... |
2204 |
timeo = unix_stream_data_wait(sk, timeo, last, |
06a77b07e af_unix: conditio... |
2205 |
last_len, freezable); |
1da177e4c Linux-2.6.12-rc2 |
2206 |
|
3822b5c2f af_unix: Revert '... |
2207 |
if (signal_pending(current)) { |
1da177e4c Linux-2.6.12-rc2 |
2208 |
err = sock_intr_errno(timeo); |
fa0dc04df af_unix: fix stru... |
2209 |
scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
2210 2211 |
goto out; } |
b3ca9b02b net: fix multithr... |
2212 |
|
6e1ce3c34 af_unix: split 'u... |
2213 |
mutex_lock(&u->iolock); |
18eceb818 af_unix: Don't us... |
2214 |
goto redo; |
2b514574f net: af_unix: imp... |
2215 |
unlock: |
3c0d2f378 [AF_UNIX]: Fix st... |
2216 2217 |
unix_state_unlock(sk); break; |
1da177e4c Linux-2.6.12-rc2 |
2218 |
} |
fc0d75364 unix: Support pee... |
2219 |
|
e370a7236 af_unix: improve ... |
2220 2221 |
while (skip >= unix_skb_len(skb)) { skip -= unix_skb_len(skb); |
79f632c71 unix/stream: fix ... |
2222 |
last = skb; |
2b514574f net: af_unix: imp... |
2223 |
last_len = skb->len; |
fc0d75364 unix: Support pee... |
2224 |
skb = skb_peek_next(skb, &sk->sk_receive_queue); |
79f632c71 unix/stream: fix ... |
2225 2226 |
if (!skb) goto again; |
fc0d75364 unix: Support pee... |
2227 |
} |
3c0d2f378 [AF_UNIX]: Fix st... |
2228 |
unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
2229 2230 2231 |
if (check_creds) { /* Never glue messages from different writers */ |
9490f886b af-unix: passcred... |
2232 |
if (!unix_skb_scm_eq(skb, &scm)) |
1da177e4c Linux-2.6.12-rc2 |
2233 |
break; |
0e82e7f6d af_unix: If we do... |
2234 |
} else if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
2235 |
/* Copy credentials */ |
7cc056626 net: remove sock_... |
2236 |
scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); |
37a9a8df8 net/unix: support... |
2237 |
unix_set_secdata(&scm, skb); |
2b514574f net: af_unix: imp... |
2238 |
check_creds = true; |
1da177e4c Linux-2.6.12-rc2 |
2239 2240 2241 |
} /* Copy address just once */ |
2b514574f net: af_unix: imp... |
2242 2243 2244 2245 |
if (state->msg && state->msg->msg_name) { DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, state->msg->msg_name); unix_copy_addr(state->msg, skb->sk); |
1da177e4c Linux-2.6.12-rc2 |
2246 2247 |
sunaddr = NULL; } |
e370a7236 af_unix: improve ... |
2248 |
chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size); |
73ed5d25d af-unix: fix use-... |
2249 |
skb_get(skb); |
2b514574f net: af_unix: imp... |
2250 |
chunk = state->recv_actor(skb, skip, chunk, state); |
73ed5d25d af-unix: fix use-... |
2251 2252 2253 |
drop_skb = !unix_skb_len(skb); /* skb is only safe to use if !drop_skb */ consume_skb(skb); |
2b514574f net: af_unix: imp... |
2254 |
if (chunk < 0) { |
1da177e4c Linux-2.6.12-rc2 |
2255 2256 2257 2258 2259 2260 |
if (copied == 0) copied = -EFAULT; break; } copied += chunk; size -= chunk; |
73ed5d25d af-unix: fix use-... |
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 |
if (drop_skb) { /* the skb was touched by a concurrent reader; * we should not expect anything from this skb * anymore and assume it invalid - we can be * sure it was dropped from the socket queue * * let's report a short read */ err = 0; break; } |
1da177e4c Linux-2.6.12-rc2 |
2272 |
/* Mark read part of skb as used */ |
6eba6a372 net: Cleanup of a... |
2273 |
if (!(flags & MSG_PEEK)) { |
e370a7236 af_unix: improve ... |
2274 |
UNIXCB(skb).consumed += chunk; |
1da177e4c Linux-2.6.12-rc2 |
2275 |
|
fc0d75364 unix: Support pee... |
2276 |
sk_peek_offset_bwd(sk, chunk); |
1da177e4c Linux-2.6.12-rc2 |
2277 |
if (UNIXCB(skb).fp) |
7cc056626 net: remove sock_... |
2278 |
unix_detach_fds(&scm, skb); |
1da177e4c Linux-2.6.12-rc2 |
2279 |
|
e370a7236 af_unix: improve ... |
2280 |
if (unix_skb_len(skb)) |
1da177e4c Linux-2.6.12-rc2 |
2281 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2282 |
|
6f01fd6e6 af_unix: fix EPOL... |
2283 |
skb_unlink(skb, &sk->sk_receive_queue); |
70d4bf6d4 drop_monitor: con... |
2284 |
consume_skb(skb); |
1da177e4c Linux-2.6.12-rc2 |
2285 |
|
7cc056626 net: remove sock_... |
2286 |
if (scm.fp) |
1da177e4c Linux-2.6.12-rc2 |
2287 |
break; |
6eba6a372 net: Cleanup of a... |
2288 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
2289 2290 2291 |
/* It is questionable, see note in unix_dgram_recvmsg. */ if (UNIXCB(skb).fp) |
7cc056626 net: remove sock_... |
2292 |
scm.fp = scm_fp_dup(UNIXCB(skb).fp); |
1da177e4c Linux-2.6.12-rc2 |
2293 |
|
e9193d60d net/unix: fix log... |
2294 |
sk_peek_offset_fwd(sk, chunk); |
fc0d75364 unix: Support pee... |
2295 |
|
9f389e356 af_unix: return d... |
2296 2297 |
if (UNIXCB(skb).fp) break; |
e9193d60d net/unix: fix log... |
2298 |
skip = 0; |
9f389e356 af_unix: return d... |
2299 2300 2301 2302 2303 2304 2305 |
last = skb; last_len = skb->len; unix_state_lock(sk); skb = skb_peek_next(skb, &sk->sk_receive_queue); if (skb) goto again; unix_state_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
2306 2307 2308 |
break; } } while (size); |
6e1ce3c34 af_unix: split 'u... |
2309 |
mutex_unlock(&u->iolock); |
2b514574f net: af_unix: imp... |
2310 2311 2312 2313 |
if (state->msg) scm_recv(sock, state->msg, &scm, flags); else scm_destroy(&scm); |
1da177e4c Linux-2.6.12-rc2 |
2314 2315 2316 |
out: return copied ? : err; } |
2b514574f net: af_unix: imp... |
2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 |
static int unix_stream_read_actor(struct sk_buff *skb, int skip, int chunk, struct unix_stream_read_state *state) { int ret; ret = skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip, state->msg, chunk); return ret ?: chunk; } static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct unix_stream_read_state state = { .recv_actor = unix_stream_read_actor, .socket = sock, .msg = msg, .size = size, .flags = flags }; |
06a77b07e af_unix: conditio... |
2338 |
return unix_stream_read_generic(&state, true); |
2b514574f net: af_unix: imp... |
2339 |
} |
2b514574f net: af_unix: imp... |
2340 2341 2342 2343 2344 2345 |
static int unix_stream_splice_actor(struct sk_buff *skb, int skip, int chunk, struct unix_stream_read_state *state) { return skb_splice_bits(skb, state->socket->sk, UNIXCB(skb).consumed + skip, |
25869262e skb_splice_bits()... |
2346 |
state->pipe, chunk, state->splice_flags); |
2b514574f net: af_unix: imp... |
2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 |
} static ssize_t unix_stream_splice_read(struct socket *sock, loff_t *ppos, struct pipe_inode_info *pipe, size_t size, unsigned int flags) { struct unix_stream_read_state state = { .recv_actor = unix_stream_splice_actor, .socket = sock, .pipe = pipe, .size = size, .splice_flags = flags, }; if (unlikely(*ppos)) return -ESPIPE; if (sock->file->f_flags & O_NONBLOCK || flags & SPLICE_F_NONBLOCK) state.flags = MSG_DONTWAIT; |
06a77b07e af_unix: conditio... |
2367 |
return unix_stream_read_generic(&state, false); |
2b514574f net: af_unix: imp... |
2368 |
} |
1da177e4c Linux-2.6.12-rc2 |
2369 2370 2371 2372 |
static int unix_shutdown(struct socket *sock, int mode) { struct sock *sk = sock->sk; struct sock *other; |
fc61b928d af_unix: fix shut... |
2373 2374 2375 2376 2377 2378 2379 2380 |
if (mode < SHUT_RD || mode > SHUT_RDWR) return -EINVAL; /* This maps: * SHUT_RD (0) -> RCV_SHUTDOWN (1) * SHUT_WR (1) -> SEND_SHUTDOWN (2) * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) */ ++mode; |
7180a0311 af_unix: coding s... |
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 |
unix_state_lock(sk); sk->sk_shutdown |= mode; other = unix_peer(sk); if (other) sock_hold(other); unix_state_unlock(sk); sk->sk_state_change(sk); if (other && (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { int peer_mode = 0; if (mode&RCV_SHUTDOWN) peer_mode |= SEND_SHUTDOWN; if (mode&SEND_SHUTDOWN) peer_mode |= RCV_SHUTDOWN; unix_state_lock(other); other->sk_shutdown |= peer_mode; unix_state_unlock(other); other->sk_state_change(other); if (peer_mode == SHUTDOWN_MASK) sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); else if (peer_mode & RCV_SHUTDOWN) sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
1da177e4c Linux-2.6.12-rc2 |
2407 |
} |
7180a0311 af_unix: coding s... |
2408 2409 |
if (other) sock_put(other); |
1da177e4c Linux-2.6.12-rc2 |
2410 2411 |
return 0; } |
885ee74d5 af_unix: Move CIN... |
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 |
long unix_inq_len(struct sock *sk) { struct sk_buff *skb; long amount = 0; if (sk->sk_state == TCP_LISTEN) return -EINVAL; spin_lock(&sk->sk_receive_queue.lock); if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { skb_queue_walk(&sk->sk_receive_queue, skb) |
e370a7236 af_unix: improve ... |
2424 |
amount += unix_skb_len(skb); |
885ee74d5 af_unix: Move CIN... |
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 |
} else { skb = skb_peek(&sk->sk_receive_queue); if (skb) amount = skb->len; } spin_unlock(&sk->sk_receive_queue.lock); return amount; } EXPORT_SYMBOL_GPL(unix_inq_len); long unix_outq_len(struct sock *sk) { return sk_wmem_alloc_get(sk); } EXPORT_SYMBOL_GPL(unix_outq_len); |
ba94f3088 unix: add ioctl t... |
2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 |
static int unix_open_file(struct sock *sk) { struct path path; struct file *f; int fd; if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) return -EPERM; unix_state_lock(sk); path = unix_sk(sk)->path; if (!path.dentry) { unix_state_unlock(sk); return -ENOENT; } path_get(&path); unix_state_unlock(sk); fd = get_unused_fd_flags(O_CLOEXEC); if (fd < 0) goto out; f = dentry_open(&path, O_PATH, current_cred()); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); goto out; } fd_install(fd, f); out: path_put(&path); return fd; } |
1da177e4c Linux-2.6.12-rc2 |
2477 2478 2479 |
static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; |
e27dfcea4 af_unix: clean up... |
2480 |
long amount = 0; |
1da177e4c Linux-2.6.12-rc2 |
2481 |
int err; |
6eba6a372 net: Cleanup of a... |
2482 2483 |
switch (cmd) { case SIOCOUTQ: |
885ee74d5 af_unix: Move CIN... |
2484 |
amount = unix_outq_len(sk); |
6eba6a372 net: Cleanup of a... |
2485 2486 2487 |
err = put_user(amount, (int __user *)arg); break; case SIOCINQ: |
885ee74d5 af_unix: Move CIN... |
2488 2489 2490 2491 |
amount = unix_inq_len(sk); if (amount < 0) err = amount; else |
1da177e4c Linux-2.6.12-rc2 |
2492 |
err = put_user(amount, (int __user *)arg); |
885ee74d5 af_unix: Move CIN... |
2493 |
break; |
ba94f3088 unix: add ioctl t... |
2494 2495 2496 |
case SIOCUNIXFILE: err = unix_open_file(sk); break; |
6eba6a372 net: Cleanup of a... |
2497 2498 2499 |
default: err = -ENOIOCTLCMD; break; |
1da177e4c Linux-2.6.12-rc2 |
2500 2501 2502 |
} return err; } |
6eba6a372 net: Cleanup of a... |
2503 |
static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait) |
1da177e4c Linux-2.6.12-rc2 |
2504 2505 2506 |
{ struct sock *sk = sock->sk; unsigned int mask; |
aa3951451 net: sk_sleep() h... |
2507 |
sock_poll_wait(file, sk_sleep(sk), wait); |
1da177e4c Linux-2.6.12-rc2 |
2508 2509 2510 2511 2512 2513 2514 |
mask = 0; /* exceptional events? */ if (sk->sk_err) mask |= POLLERR; if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; |
f348d70a3 [PATCH] POLLRDHUP... |
2515 |
if (sk->sk_shutdown & RCV_SHUTDOWN) |
db40980fc net: poll() optim... |
2516 |
mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
1da177e4c Linux-2.6.12-rc2 |
2517 2518 |
/* readable? */ |
db40980fc net: poll() optim... |
2519 |
if (!skb_queue_empty(&sk->sk_receive_queue)) |
1da177e4c Linux-2.6.12-rc2 |
2520 2521 2522 |
mask |= POLLIN | POLLRDNORM; /* Connection-based need to check for termination and startup */ |
6eba6a372 net: Cleanup of a... |
2523 2524 |
if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && sk->sk_state == TCP_CLOSE) |
1da177e4c Linux-2.6.12-rc2 |
2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 |
mask |= POLLHUP; /* * we set writable also when the other side has shut down the * connection. This prevents stuck sockets. */ if (unix_writable(sk)) mask |= POLLOUT | POLLWRNORM | POLLWRBAND; return mask; } |
ec0d215f9 af_unix: fix 'pol... |
2536 2537 |
static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, poll_table *wait) |
3c73419c0 af_unix: fix 'pol... |
2538 |
{ |
ec0d215f9 af_unix: fix 'pol... |
2539 2540 |
struct sock *sk = sock->sk, *other; unsigned int mask, writable; |
3c73419c0 af_unix: fix 'pol... |
2541 |
|
aa3951451 net: sk_sleep() h... |
2542 |
sock_poll_wait(file, sk_sleep(sk), wait); |
3c73419c0 af_unix: fix 'pol... |
2543 2544 2545 2546 |
mask = 0; /* exceptional events? */ if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
7d4c04fc1 net: add option t... |
2547 |
mask |= POLLERR | |
8facd5fb7 net: fix smatch w... |
2548 |
(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); |
7d4c04fc1 net: add option t... |
2549 |
|
3c73419c0 af_unix: fix 'pol... |
2550 |
if (sk->sk_shutdown & RCV_SHUTDOWN) |
5456f09aa af_unix: fix unix... |
2551 |
mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
3c73419c0 af_unix: fix 'pol... |
2552 2553 2554 2555 |
if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; /* readable? */ |
5456f09aa af_unix: fix unix... |
2556 |
if (!skb_queue_empty(&sk->sk_receive_queue)) |
3c73419c0 af_unix: fix 'pol... |
2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 |
mask |= POLLIN | POLLRDNORM; /* Connection-based need to check for termination and startup */ if (sk->sk_type == SOCK_SEQPACKET) { if (sk->sk_state == TCP_CLOSE) mask |= POLLHUP; /* connection hasn't started yet? */ if (sk->sk_state == TCP_SYN_SENT) return mask; } |
973a34aa8 af_unix: optimize... |
2567 |
/* No write status requested, avoid expensive OUT tests. */ |
626cf2366 poll: add poll_re... |
2568 |
if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) |
973a34aa8 af_unix: optimize... |
2569 |
return mask; |
ec0d215f9 af_unix: fix 'pol... |
2570 |
writable = unix_writable(sk); |
7d267278a unix: avoid use-a... |
2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 |
if (writable) { unix_state_lock(sk); other = unix_peer(sk); if (other && unix_peer(other) != sk && unix_recvq_full(other) && unix_dgram_peer_wake_me(sk, other)) writable = 0; unix_state_unlock(sk); |
ec0d215f9 af_unix: fix 'pol... |
2581 2582 2583 |
} if (writable) |
3c73419c0 af_unix: fix 'pol... |
2584 2585 |
mask |= POLLOUT | POLLWRNORM | POLLWRBAND; else |
9cd3e072b net: rename SOCK_... |
2586 |
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
3c73419c0 af_unix: fix 'pol... |
2587 |
|
3c73419c0 af_unix: fix 'pol... |
2588 2589 |
return mask; } |
1da177e4c Linux-2.6.12-rc2 |
2590 2591 |
#ifdef CONFIG_PROC_FS |
a53eb3feb [UNIX] Move the u... |
2592 |
|
7123aaa3a af_unix: speedup ... |
2593 2594 2595 2596 2597 |
#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1) #define get_bucket(x) ((x) >> BUCKET_SPACE) #define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1)) #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) |
a53eb3feb [UNIX] Move the u... |
2598 |
|
7123aaa3a af_unix: speedup ... |
2599 |
static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos) |
1da177e4c Linux-2.6.12-rc2 |
2600 |
{ |
7123aaa3a af_unix: speedup ... |
2601 2602 2603 2604 |
unsigned long offset = get_offset(*pos); unsigned long bucket = get_bucket(*pos); struct sock *sk; unsigned long count = 0; |
1da177e4c Linux-2.6.12-rc2 |
2605 |
|
7123aaa3a af_unix: speedup ... |
2606 2607 |
for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) { if (sock_net(sk) != seq_file_net(seq)) |
097e66c57 [NET]: Make AF_UN... |
2608 |
continue; |
7123aaa3a af_unix: speedup ... |
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 |
if (++count == offset) break; } return sk; } static struct sock *unix_next_socket(struct seq_file *seq, struct sock *sk, loff_t *pos) { unsigned long bucket; while (sk > (struct sock *)SEQ_START_TOKEN) { sk = sk_next(sk); if (!sk) goto next_bucket; if (sock_net(sk) == seq_file_net(seq)) return sk; |
1da177e4c Linux-2.6.12-rc2 |
2628 |
} |
7123aaa3a af_unix: speedup ... |
2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 |
do { sk = unix_from_bucket(seq, pos); if (sk) return sk; next_bucket: bucket = get_bucket(*pos) + 1; *pos = set_bucket_offset(bucket, 1); } while (bucket < ARRAY_SIZE(unix_socket_table)); |
1da177e4c Linux-2.6.12-rc2 |
2639 2640 |
return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
2641 |
static void *unix_seq_start(struct seq_file *seq, loff_t *pos) |
9a429c498 [NET]: Add some a... |
2642 |
__acquires(unix_table_lock) |
1da177e4c Linux-2.6.12-rc2 |
2643 |
{ |
fbe9cc4a8 [AF_UNIX]: Use sp... |
2644 |
spin_lock(&unix_table_lock); |
7123aaa3a af_unix: speedup ... |
2645 2646 2647 2648 2649 2650 2651 2652 |
if (!*pos) return SEQ_START_TOKEN; if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table)) return NULL; return unix_next_socket(seq, NULL, pos); |
1da177e4c Linux-2.6.12-rc2 |
2653 2654 2655 2656 2657 |
} static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; |
7123aaa3a af_unix: speedup ... |
2658 |
return unix_next_socket(seq, v, pos); |
1da177e4c Linux-2.6.12-rc2 |
2659 2660 2661 |
} static void unix_seq_stop(struct seq_file *seq, void *v) |
9a429c498 [NET]: Add some a... |
2662 |
__releases(unix_table_lock) |
1da177e4c Linux-2.6.12-rc2 |
2663 |
{ |
fbe9cc4a8 [AF_UNIX]: Use sp... |
2664 |
spin_unlock(&unix_table_lock); |
1da177e4c Linux-2.6.12-rc2 |
2665 2666 2667 2668 |
} static int unix_seq_show(struct seq_file *seq, void *v) { |
ac7bfa62f [NET] UNIX: Fix w... |
2669 |
|
b9f3124f0 [AF_UNIX]: Use SE... |
2670 |
if (v == SEQ_START_TOKEN) |
1da177e4c Linux-2.6.12-rc2 |
2671 2672 2673 2674 2675 2676 |
seq_puts(seq, "Num RefCount Protocol Flags Type St " "Inode Path "); else { struct sock *s = v; struct unix_sock *u = unix_sk(s); |
1c92b4e50 [AF_UNIX]: Make s... |
2677 |
unix_state_lock(s); |
1da177e4c Linux-2.6.12-rc2 |
2678 |
|
71338aa7d net: convert %p u... |
2679 |
seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu", |
1da177e4c Linux-2.6.12-rc2 |
2680 |
s, |
41c6d650f net: convert sock... |
2681 |
refcount_read(&s->sk_refcnt), |
1da177e4c Linux-2.6.12-rc2 |
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 |
0, s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0, s->sk_type, s->sk_socket ? (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) : (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING), sock_i_ino(s)); if (u->addr) { int i, len; seq_putc(seq, ' '); i = 0; len = u->addr->len - sizeof(short); if (!UNIX_ABSTRACT(s)) len--; else { seq_putc(seq, '@'); i++; } for ( ; i < len; i++) |
e7947ea77 unix: escape all ... |
2703 2704 |
seq_putc(seq, u->addr->name->sun_path[i] ?: '@'); |
1da177e4c Linux-2.6.12-rc2 |
2705 |
} |
1c92b4e50 [AF_UNIX]: Make s... |
2706 |
unix_state_unlock(s); |
1da177e4c Linux-2.6.12-rc2 |
2707 2708 2709 2710 2711 2712 |
seq_putc(seq, ' '); } return 0; } |
56b3d975b [NET]: Make all i... |
2713 |
static const struct seq_operations unix_seq_ops = { |
1da177e4c Linux-2.6.12-rc2 |
2714 2715 2716 2717 2718 |
.start = unix_seq_start, .next = unix_seq_next, .stop = unix_seq_stop, .show = unix_seq_show, }; |
1da177e4c Linux-2.6.12-rc2 |
2719 2720 |
static int unix_seq_open(struct inode *inode, struct file *file) { |
e372c4140 [NET]: Consolidat... |
2721 |
return seq_open_net(inode, file, &unix_seq_ops, |
8b51b064a af_unix: remove u... |
2722 |
sizeof(struct seq_net_private)); |
1da177e4c Linux-2.6.12-rc2 |
2723 |
} |
da7071d7e [PATCH] mark stru... |
2724 |
static const struct file_operations unix_seq_fops = { |
1da177e4c Linux-2.6.12-rc2 |
2725 2726 2727 2728 |
.owner = THIS_MODULE, .open = unix_seq_open, .read = seq_read, .llseek = seq_lseek, |
e372c4140 [NET]: Consolidat... |
2729 |
.release = seq_release_net, |
1da177e4c Linux-2.6.12-rc2 |
2730 2731 2732 |
}; #endif |
ec1b4cf74 net: mark net_pro... |
2733 |
static const struct net_proto_family unix_family_ops = { |
1da177e4c Linux-2.6.12-rc2 |
2734 2735 2736 2737 |
.family = PF_UNIX, .create = unix_create, .owner = THIS_MODULE, }; |
097e66c57 [NET]: Make AF_UN... |
2738 |
|
2c8c1e729 net: spread __net... |
2739 |
static int __net_init unix_net_init(struct net *net) |
097e66c57 [NET]: Make AF_UN... |
2740 2741 |
{ int error = -ENOMEM; |
a0a53c8ba [NETNS]: struct n... |
2742 |
net->unx.sysctl_max_dgram_qlen = 10; |
1597fbc0f [UNIX]: Make the ... |
2743 2744 |
if (unix_sysctl_register(net)) goto out; |
d392e4975 [UNIX]: Move the ... |
2745 |
|
097e66c57 [NET]: Make AF_UN... |
2746 |
#ifdef CONFIG_PROC_FS |
d4beaa66a net: proc: change... |
2747 |
if (!proc_create("unix", 0, net->proc_net, &unix_seq_fops)) { |
1597fbc0f [UNIX]: Make the ... |
2748 |
unix_sysctl_unregister(net); |
097e66c57 [NET]: Make AF_UN... |
2749 |
goto out; |
1597fbc0f [UNIX]: Make the ... |
2750 |
} |
097e66c57 [NET]: Make AF_UN... |
2751 2752 2753 |
#endif error = 0; out: |
48dcc33e5 af_unix: netns: f... |
2754 |
return error; |
097e66c57 [NET]: Make AF_UN... |
2755 |
} |
2c8c1e729 net: spread __net... |
2756 |
static void __net_exit unix_net_exit(struct net *net) |
097e66c57 [NET]: Make AF_UN... |
2757 |
{ |
1597fbc0f [UNIX]: Make the ... |
2758 |
unix_sysctl_unregister(net); |
ece31ffd5 net: proc: change... |
2759 |
remove_proc_entry("unix", net->proc_net); |
097e66c57 [NET]: Make AF_UN... |
2760 2761 2762 2763 2764 2765 |
} static struct pernet_operations unix_net_ops = { .init = unix_net_init, .exit = unix_net_exit, }; |
1da177e4c Linux-2.6.12-rc2 |
2766 2767 2768 |
static int __init af_unix_init(void) { int rc = -1; |
1da177e4c Linux-2.6.12-rc2 |
2769 |
|
b4fff5f8b unix: Use FIELD_S... |
2770 |
BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb)); |
1da177e4c Linux-2.6.12-rc2 |
2771 2772 |
rc = proto_register(&unix_proto, 1); |
ac7bfa62f [NET] UNIX: Fix w... |
2773 |
if (rc != 0) { |
5cc208bec unix: convert pri... |
2774 2775 |
pr_crit("%s: Cannot create unix_sock SLAB cache! ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
2776 2777 2778 2779 |
goto out; } sock_register(&unix_family_ops); |
097e66c57 [NET]: Make AF_UN... |
2780 |
register_pernet_subsys(&unix_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
2781 2782 2783 2784 2785 2786 2787 |
out: return rc; } static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); |
1da177e4c Linux-2.6.12-rc2 |
2788 |
proto_unregister(&unix_proto); |
097e66c57 [NET]: Make AF_UN... |
2789 |
unregister_pernet_subsys(&unix_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
2790 |
} |
3d3669602 [AF_UNIX] Initial... |
2791 2792 2793 2794 2795 |
/* Earlier than device_initcall() so that other drivers invoking request_module() don't end up in a loop when modprobe tries to use a UNIX socket. But later than subsys_initcall() because we depend on stuff initialised there */ fs_initcall(af_unix_init); |
1da177e4c Linux-2.6.12-rc2 |
2796 2797 2798 2799 |
module_exit(af_unix_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_NETPROTO(PF_UNIX); |