diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 06:54:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 06:54:01 -0500 |
commit | 0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch) | |
tree | 62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/unix | |
parent | 21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff) | |
parent | 85040bcb4643cba578839e953f25e2d1965d83d0 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits)
[IPV6] ADDRLABEL: Fix double free on label deletion.
[PPP]: Sparse warning fixes.
[IPV4] fib_trie: remove unneeded NULL check
[IPV4] fib_trie: More whitespace cleanup.
[NET_SCHED]: Use nla_policy for attribute validation in ematches
[NET_SCHED]: Use nla_policy for attribute validation in actions
[NET_SCHED]: Use nla_policy for attribute validation in classifiers
[NET_SCHED]: Use nla_policy for attribute validation in packet schedulers
[NET_SCHED]: sch_api: introduce constant for rate table size
[NET_SCHED]: Use typeful attribute parsing helpers
[NET_SCHED]: Use typeful attribute construction helpers
[NET_SCHED]: Use NLA_PUT_STRING for string dumping
[NET_SCHED]: Use nla_nest_start/nla_nest_end
[NET_SCHED]: Propagate nla_parse return value
[NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get
[NET_SCHED]: act_api: use nlmsg_parse
[NET_SCHED]: act_api: fix netlink API conversion bug
[NET_SCHED]: sch_netem: use nla_parse_nested_compat
[NET_SCHED]: sch_atm: fix format string warning
[NETNS]: Add namespace for ICMP replying code.
...
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 171 | ||||
-rw-r--r-- | net/unix/sysctl_net_unix.c | 52 |
2 files changed, 138 insertions, 85 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 060bba4567d2..eea75888805e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -117,8 +117,6 @@ | |||
117 | #include <net/checksum.h> | 117 | #include <net/checksum.h> |
118 | #include <linux/security.h> | 118 | #include <linux/security.h> |
119 | 119 | ||
120 | int sysctl_unix_max_dgram_qlen __read_mostly = 10; | ||
121 | |||
122 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; | 120 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; |
123 | static DEFINE_SPINLOCK(unix_table_lock); | 121 | static DEFINE_SPINLOCK(unix_table_lock); |
124 | static atomic_t unix_nr_socks = ATOMIC_INIT(0); | 122 | static atomic_t unix_nr_socks = ATOMIC_INIT(0); |
@@ -127,32 +125,6 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0); | |||
127 | 125 | ||
128 | #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) | 126 | #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) |
129 | 127 | ||
130 | static struct sock *first_unix_socket(int *i) | ||
131 | { | ||
132 | for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) { | ||
133 | if (!hlist_empty(&unix_socket_table[*i])) | ||
134 | return __sk_head(&unix_socket_table[*i]); | ||
135 | } | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | static struct sock *next_unix_socket(int *i, struct sock *s) | ||
140 | { | ||
141 | struct sock *next = sk_next(s); | ||
142 | /* More in this chain? */ | ||
143 | if (next) | ||
144 | return next; | ||
145 | /* Look for next non-empty chain. */ | ||
146 | for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) { | ||
147 | if (!hlist_empty(&unix_socket_table[*i])) | ||
148 | return __sk_head(&unix_socket_table[*i]); | ||
149 | } | ||
150 | return NULL; | ||
151 | } | ||
152 | |||
153 | #define forall_unix_sockets(i, s) \ | ||
154 | for (s = first_unix_socket(&(i)); s; s = next_unix_socket(&(i),(s))) | ||
155 | |||
156 | #ifdef CONFIG_SECURITY_NETWORK | 128 | #ifdef CONFIG_SECURITY_NETWORK |
157 | static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) | 129 | static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
158 | { | 130 | { |
@@ -270,7 +242,8 @@ static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk) | |||
270 | spin_unlock(&unix_table_lock); | 242 | spin_unlock(&unix_table_lock); |
271 | } | 243 | } |
272 | 244 | ||
273 | static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname, | 245 | static struct sock *__unix_find_socket_byname(struct net *net, |
246 | struct sockaddr_un *sunname, | ||
274 | int len, int type, unsigned hash) | 247 | int len, int type, unsigned hash) |
275 | { | 248 | { |
276 | struct sock *s; | 249 | struct sock *s; |
@@ -279,6 +252,9 @@ static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname, | |||
279 | sk_for_each(s, node, &unix_socket_table[hash ^ type]) { | 252 | sk_for_each(s, node, &unix_socket_table[hash ^ type]) { |
280 | struct unix_sock *u = unix_sk(s); | 253 | struct unix_sock *u = unix_sk(s); |
281 | 254 | ||
255 | if (s->sk_net != net) | ||
256 | continue; | ||
257 | |||
282 | if (u->addr->len == len && | 258 | if (u->addr->len == len && |
283 | !memcmp(u->addr->name, sunname, len)) | 259 | !memcmp(u->addr->name, sunname, len)) |
284 | goto found; | 260 | goto found; |
@@ -288,21 +264,22 @@ found: | |||
288 | return s; | 264 | return s; |
289 | } | 265 | } |
290 | 266 | ||
291 | static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname, | 267 | static inline struct sock *unix_find_socket_byname(struct net *net, |
268 | struct sockaddr_un *sunname, | ||
292 | int len, int type, | 269 | int len, int type, |
293 | unsigned hash) | 270 | unsigned hash) |
294 | { | 271 | { |
295 | struct sock *s; | 272 | struct sock *s; |
296 | 273 | ||
297 | spin_lock(&unix_table_lock); | 274 | spin_lock(&unix_table_lock); |
298 | s = __unix_find_socket_byname(sunname, len, type, hash); | 275 | s = __unix_find_socket_byname(net, sunname, len, type, hash); |
299 | if (s) | 276 | if (s) |
300 | sock_hold(s); | 277 | sock_hold(s); |
301 | spin_unlock(&unix_table_lock); | 278 | spin_unlock(&unix_table_lock); |
302 | return s; | 279 | return s; |
303 | } | 280 | } |
304 | 281 | ||
305 | static struct sock *unix_find_socket_byinode(struct inode *i) | 282 | static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i) |
306 | { | 283 | { |
307 | struct sock *s; | 284 | struct sock *s; |
308 | struct hlist_node *node; | 285 | struct hlist_node *node; |
@@ -312,6 +289,9 @@ static struct sock *unix_find_socket_byinode(struct inode *i) | |||
312 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { | 289 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
313 | struct dentry *dentry = unix_sk(s)->dentry; | 290 | struct dentry *dentry = unix_sk(s)->dentry; |
314 | 291 | ||
292 | if (s->sk_net != net) | ||
293 | continue; | ||
294 | |||
315 | if(dentry && dentry->d_inode == i) | 295 | if(dentry && dentry->d_inode == i) |
316 | { | 296 | { |
317 | sock_hold(s); | 297 | sock_hold(s); |
@@ -335,7 +315,7 @@ static void unix_write_space(struct sock *sk) | |||
335 | if (unix_writable(sk)) { | 315 | if (unix_writable(sk)) { |
336 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 316 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
337 | wake_up_interruptible_sync(sk->sk_sleep); | 317 | wake_up_interruptible_sync(sk->sk_sleep); |
338 | sk_wake_async(sk, 2, POLL_OUT); | 318 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
339 | } | 319 | } |
340 | read_unlock(&sk->sk_callback_lock); | 320 | read_unlock(&sk->sk_callback_lock); |
341 | } | 321 | } |
@@ -421,7 +401,7 @@ static int unix_release_sock (struct sock *sk, int embrion) | |||
421 | unix_state_unlock(skpair); | 401 | unix_state_unlock(skpair); |
422 | skpair->sk_state_change(skpair); | 402 | skpair->sk_state_change(skpair); |
423 | read_lock(&skpair->sk_callback_lock); | 403 | read_lock(&skpair->sk_callback_lock); |
424 | sk_wake_async(skpair,1,POLL_HUP); | 404 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
425 | read_unlock(&skpair->sk_callback_lock); | 405 | read_unlock(&skpair->sk_callback_lock); |
426 | } | 406 | } |
427 | sock_put(skpair); /* It may now die */ | 407 | sock_put(skpair); /* It may now die */ |
@@ -612,7 +592,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) | |||
612 | &af_unix_sk_receive_queue_lock_key); | 592 | &af_unix_sk_receive_queue_lock_key); |
613 | 593 | ||
614 | sk->sk_write_space = unix_write_space; | 594 | sk->sk_write_space = unix_write_space; |
615 | sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen; | 595 | sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; |
616 | sk->sk_destruct = unix_sock_destructor; | 596 | sk->sk_destruct = unix_sock_destructor; |
617 | u = unix_sk(sk); | 597 | u = unix_sk(sk); |
618 | u->dentry = NULL; | 598 | u->dentry = NULL; |
@@ -631,9 +611,6 @@ out: | |||
631 | 611 | ||
632 | static int unix_create(struct net *net, struct socket *sock, int protocol) | 612 | static int unix_create(struct net *net, struct socket *sock, int protocol) |
633 | { | 613 | { |
634 | if (net != &init_net) | ||
635 | return -EAFNOSUPPORT; | ||
636 | |||
637 | if (protocol && protocol != PF_UNIX) | 614 | if (protocol && protocol != PF_UNIX) |
638 | return -EPROTONOSUPPORT; | 615 | return -EPROTONOSUPPORT; |
639 | 616 | ||
@@ -677,6 +654,7 @@ static int unix_release(struct socket *sock) | |||
677 | static int unix_autobind(struct socket *sock) | 654 | static int unix_autobind(struct socket *sock) |
678 | { | 655 | { |
679 | struct sock *sk = sock->sk; | 656 | struct sock *sk = sock->sk; |
657 | struct net *net = sk->sk_net; | ||
680 | struct unix_sock *u = unix_sk(sk); | 658 | struct unix_sock *u = unix_sk(sk); |
681 | static u32 ordernum = 1; | 659 | static u32 ordernum = 1; |
682 | struct unix_address * addr; | 660 | struct unix_address * addr; |
@@ -703,7 +681,7 @@ retry: | |||
703 | spin_lock(&unix_table_lock); | 681 | spin_lock(&unix_table_lock); |
704 | ordernum = (ordernum+1)&0xFFFFF; | 682 | ordernum = (ordernum+1)&0xFFFFF; |
705 | 683 | ||
706 | if (__unix_find_socket_byname(addr->name, addr->len, sock->type, | 684 | if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, |
707 | addr->hash)) { | 685 | addr->hash)) { |
708 | spin_unlock(&unix_table_lock); | 686 | spin_unlock(&unix_table_lock); |
709 | /* Sanity yield. It is unusual case, but yet... */ | 687 | /* Sanity yield. It is unusual case, but yet... */ |
@@ -723,7 +701,8 @@ out: mutex_unlock(&u->readlock); | |||
723 | return err; | 701 | return err; |
724 | } | 702 | } |
725 | 703 | ||
726 | static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, | 704 | static struct sock *unix_find_other(struct net *net, |
705 | struct sockaddr_un *sunname, int len, | ||
727 | int type, unsigned hash, int *error) | 706 | int type, unsigned hash, int *error) |
728 | { | 707 | { |
729 | struct sock *u; | 708 | struct sock *u; |
@@ -741,7 +720,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, | |||
741 | err = -ECONNREFUSED; | 720 | err = -ECONNREFUSED; |
742 | if (!S_ISSOCK(nd.dentry->d_inode->i_mode)) | 721 | if (!S_ISSOCK(nd.dentry->d_inode->i_mode)) |
743 | goto put_fail; | 722 | goto put_fail; |
744 | u=unix_find_socket_byinode(nd.dentry->d_inode); | 723 | u=unix_find_socket_byinode(net, nd.dentry->d_inode); |
745 | if (!u) | 724 | if (!u) |
746 | goto put_fail; | 725 | goto put_fail; |
747 | 726 | ||
@@ -757,7 +736,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, | |||
757 | } | 736 | } |
758 | } else { | 737 | } else { |
759 | err = -ECONNREFUSED; | 738 | err = -ECONNREFUSED; |
760 | u=unix_find_socket_byname(sunname, len, type, hash); | 739 | u=unix_find_socket_byname(net, sunname, len, type, hash); |
761 | if (u) { | 740 | if (u) { |
762 | struct dentry *dentry; | 741 | struct dentry *dentry; |
763 | dentry = unix_sk(u)->dentry; | 742 | dentry = unix_sk(u)->dentry; |
@@ -779,6 +758,7 @@ fail: | |||
779 | static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 758 | static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
780 | { | 759 | { |
781 | struct sock *sk = sock->sk; | 760 | struct sock *sk = sock->sk; |
761 | struct net *net = sk->sk_net; | ||
782 | struct unix_sock *u = unix_sk(sk); | 762 | struct unix_sock *u = unix_sk(sk); |
783 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; | 763 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; |
784 | struct dentry * dentry = NULL; | 764 | struct dentry * dentry = NULL; |
@@ -853,7 +833,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
853 | 833 | ||
854 | if (!sunaddr->sun_path[0]) { | 834 | if (!sunaddr->sun_path[0]) { |
855 | err = -EADDRINUSE; | 835 | err = -EADDRINUSE; |
856 | if (__unix_find_socket_byname(sunaddr, addr_len, | 836 | if (__unix_find_socket_byname(net, sunaddr, addr_len, |
857 | sk->sk_type, hash)) { | 837 | sk->sk_type, hash)) { |
858 | unix_release_addr(addr); | 838 | unix_release_addr(addr); |
859 | goto out_unlock; | 839 | goto out_unlock; |
@@ -919,6 +899,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, | |||
919 | int alen, int flags) | 899 | int alen, int flags) |
920 | { | 900 | { |
921 | struct sock *sk = sock->sk; | 901 | struct sock *sk = sock->sk; |
902 | struct net *net = sk->sk_net; | ||
922 | struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr; | 903 | struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr; |
923 | struct sock *other; | 904 | struct sock *other; |
924 | unsigned hash; | 905 | unsigned hash; |
@@ -935,7 +916,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, | |||
935 | goto out; | 916 | goto out; |
936 | 917 | ||
937 | restart: | 918 | restart: |
938 | other=unix_find_other(sunaddr, alen, sock->type, hash, &err); | 919 | other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err); |
939 | if (!other) | 920 | if (!other) |
940 | goto out; | 921 | goto out; |
941 | 922 | ||
@@ -1015,6 +996,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1015 | { | 996 | { |
1016 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; | 997 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; |
1017 | struct sock *sk = sock->sk; | 998 | struct sock *sk = sock->sk; |
999 | struct net *net = sk->sk_net; | ||
1018 | struct unix_sock *u = unix_sk(sk), *newu, *otheru; | 1000 | struct unix_sock *u = unix_sk(sk), *newu, *otheru; |
1019 | struct sock *newsk = NULL; | 1001 | struct sock *newsk = NULL; |
1020 | struct sock *other = NULL; | 1002 | struct sock *other = NULL; |
@@ -1054,7 +1036,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1054 | 1036 | ||
1055 | restart: | 1037 | restart: |
1056 | /* Find listening sock. */ | 1038 | /* Find listening sock. */ |
1057 | other = unix_find_other(sunaddr, addr_len, sk->sk_type, hash, &err); | 1039 | other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err); |
1058 | if (!other) | 1040 | if (!other) |
1059 | goto out; | 1041 | goto out; |
1060 | 1042 | ||
@@ -1330,6 +1312,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1330 | { | 1312 | { |
1331 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1313 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1332 | struct sock *sk = sock->sk; | 1314 | struct sock *sk = sock->sk; |
1315 | struct net *net = sk->sk_net; | ||
1333 | struct unix_sock *u = unix_sk(sk); | 1316 | struct unix_sock *u = unix_sk(sk); |
1334 | struct sockaddr_un *sunaddr=msg->msg_name; | 1317 | struct sockaddr_un *sunaddr=msg->msg_name; |
1335 | struct sock *other = NULL; | 1318 | struct sock *other = NULL; |
@@ -1393,7 +1376,7 @@ restart: | |||
1393 | if (sunaddr == NULL) | 1376 | if (sunaddr == NULL) |
1394 | goto out_free; | 1377 | goto out_free; |
1395 | 1378 | ||
1396 | other = unix_find_other(sunaddr, namelen, sk->sk_type, | 1379 | other = unix_find_other(net, sunaddr, namelen, sk->sk_type, |
1397 | hash, &err); | 1380 | hash, &err); |
1398 | if (other==NULL) | 1381 | if (other==NULL) |
1399 | goto out_free; | 1382 | goto out_free; |
@@ -1915,9 +1898,9 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1915 | other->sk_state_change(other); | 1898 | other->sk_state_change(other); |
1916 | read_lock(&other->sk_callback_lock); | 1899 | read_lock(&other->sk_callback_lock); |
1917 | if (peer_mode == SHUTDOWN_MASK) | 1900 | if (peer_mode == SHUTDOWN_MASK) |
1918 | sk_wake_async(other,1,POLL_HUP); | 1901 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
1919 | else if (peer_mode & RCV_SHUTDOWN) | 1902 | else if (peer_mode & RCV_SHUTDOWN) |
1920 | sk_wake_async(other,1,POLL_IN); | 1903 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
1921 | read_unlock(&other->sk_callback_lock); | 1904 | read_unlock(&other->sk_callback_lock); |
1922 | } | 1905 | } |
1923 | if (other) | 1906 | if (other) |
@@ -2006,12 +1989,41 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl | |||
2006 | 1989 | ||
2007 | 1990 | ||
2008 | #ifdef CONFIG_PROC_FS | 1991 | #ifdef CONFIG_PROC_FS |
2009 | static struct sock *unix_seq_idx(int *iter, loff_t pos) | 1992 | static struct sock *first_unix_socket(int *i) |
1993 | { | ||
1994 | for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) { | ||
1995 | if (!hlist_empty(&unix_socket_table[*i])) | ||
1996 | return __sk_head(&unix_socket_table[*i]); | ||
1997 | } | ||
1998 | return NULL; | ||
1999 | } | ||
2000 | |||
2001 | static struct sock *next_unix_socket(int *i, struct sock *s) | ||
2002 | { | ||
2003 | struct sock *next = sk_next(s); | ||
2004 | /* More in this chain? */ | ||
2005 | if (next) | ||
2006 | return next; | ||
2007 | /* Look for next non-empty chain. */ | ||
2008 | for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) { | ||
2009 | if (!hlist_empty(&unix_socket_table[*i])) | ||
2010 | return __sk_head(&unix_socket_table[*i]); | ||
2011 | } | ||
2012 | return NULL; | ||
2013 | } | ||
2014 | |||
2015 | struct unix_iter_state { | ||
2016 | struct seq_net_private p; | ||
2017 | int i; | ||
2018 | }; | ||
2019 | static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos) | ||
2010 | { | 2020 | { |
2011 | loff_t off = 0; | 2021 | loff_t off = 0; |
2012 | struct sock *s; | 2022 | struct sock *s; |
2013 | 2023 | ||
2014 | for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) { | 2024 | for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) { |
2025 | if (s->sk_net != iter->p.net) | ||
2026 | continue; | ||
2015 | if (off == pos) | 2027 | if (off == pos) |
2016 | return s; | 2028 | return s; |
2017 | ++off; | 2029 | ++off; |
@@ -2021,21 +2033,30 @@ static struct sock *unix_seq_idx(int *iter, loff_t pos) | |||
2021 | 2033 | ||
2022 | 2034 | ||
2023 | static void *unix_seq_start(struct seq_file *seq, loff_t *pos) | 2035 | static void *unix_seq_start(struct seq_file *seq, loff_t *pos) |
2036 | __acquires(unix_table_lock) | ||
2024 | { | 2037 | { |
2038 | struct unix_iter_state *iter = seq->private; | ||
2025 | spin_lock(&unix_table_lock); | 2039 | spin_lock(&unix_table_lock); |
2026 | return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1); | 2040 | return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1); |
2027 | } | 2041 | } |
2028 | 2042 | ||
2029 | static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 2043 | static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
2030 | { | 2044 | { |
2045 | struct unix_iter_state *iter = seq->private; | ||
2046 | struct sock *sk = v; | ||
2031 | ++*pos; | 2047 | ++*pos; |
2032 | 2048 | ||
2033 | if (v == (void *)1) | 2049 | if (v == (void *)1) |
2034 | return first_unix_socket(seq->private); | 2050 | sk = first_unix_socket(&iter->i); |
2035 | return next_unix_socket(seq->private, v); | 2051 | else |
2052 | sk = next_unix_socket(&iter->i, sk); | ||
2053 | while (sk && (sk->sk_net != iter->p.net)) | ||
2054 | sk = next_unix_socket(&iter->i, sk); | ||
2055 | return sk; | ||
2036 | } | 2056 | } |
2037 | 2057 | ||
2038 | static void unix_seq_stop(struct seq_file *seq, void *v) | 2058 | static void unix_seq_stop(struct seq_file *seq, void *v) |
2059 | __releases(unix_table_lock) | ||
2039 | { | 2060 | { |
2040 | spin_unlock(&unix_table_lock); | 2061 | spin_unlock(&unix_table_lock); |
2041 | } | 2062 | } |
@@ -2094,7 +2115,8 @@ static const struct seq_operations unix_seq_ops = { | |||
2094 | 2115 | ||
2095 | static int unix_seq_open(struct inode *inode, struct file *file) | 2116 | static int unix_seq_open(struct inode *inode, struct file *file) |
2096 | { | 2117 | { |
2097 | return seq_open_private(file, &unix_seq_ops, sizeof(int)); | 2118 | return seq_open_net(inode, file, &unix_seq_ops, |
2119 | sizeof(struct unix_iter_state)); | ||
2098 | } | 2120 | } |
2099 | 2121 | ||
2100 | static const struct file_operations unix_seq_fops = { | 2122 | static const struct file_operations unix_seq_fops = { |
@@ -2102,7 +2124,7 @@ static const struct file_operations unix_seq_fops = { | |||
2102 | .open = unix_seq_open, | 2124 | .open = unix_seq_open, |
2103 | .read = seq_read, | 2125 | .read = seq_read, |
2104 | .llseek = seq_lseek, | 2126 | .llseek = seq_lseek, |
2105 | .release = seq_release_private, | 2127 | .release = seq_release_net, |
2106 | }; | 2128 | }; |
2107 | 2129 | ||
2108 | #endif | 2130 | #endif |
@@ -2113,6 +2135,37 @@ static struct net_proto_family unix_family_ops = { | |||
2113 | .owner = THIS_MODULE, | 2135 | .owner = THIS_MODULE, |
2114 | }; | 2136 | }; |
2115 | 2137 | ||
2138 | |||
2139 | static int unix_net_init(struct net *net) | ||
2140 | { | ||
2141 | int error = -ENOMEM; | ||
2142 | |||
2143 | net->unx.sysctl_max_dgram_qlen = 10; | ||
2144 | if (unix_sysctl_register(net)) | ||
2145 | goto out; | ||
2146 | |||
2147 | #ifdef CONFIG_PROC_FS | ||
2148 | if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops)) { | ||
2149 | unix_sysctl_unregister(net); | ||
2150 | goto out; | ||
2151 | } | ||
2152 | #endif | ||
2153 | error = 0; | ||
2154 | out: | ||
2155 | return 0; | ||
2156 | } | ||
2157 | |||
2158 | static void unix_net_exit(struct net *net) | ||
2159 | { | ||
2160 | unix_sysctl_unregister(net); | ||
2161 | proc_net_remove(net, "unix"); | ||
2162 | } | ||
2163 | |||
2164 | static struct pernet_operations unix_net_ops = { | ||
2165 | .init = unix_net_init, | ||
2166 | .exit = unix_net_exit, | ||
2167 | }; | ||
2168 | |||
2116 | static int __init af_unix_init(void) | 2169 | static int __init af_unix_init(void) |
2117 | { | 2170 | { |
2118 | int rc = -1; | 2171 | int rc = -1; |
@@ -2128,10 +2181,7 @@ static int __init af_unix_init(void) | |||
2128 | } | 2181 | } |
2129 | 2182 | ||
2130 | sock_register(&unix_family_ops); | 2183 | sock_register(&unix_family_ops); |
2131 | #ifdef CONFIG_PROC_FS | 2184 | register_pernet_subsys(&unix_net_ops); |
2132 | proc_net_fops_create(&init_net, "unix", 0, &unix_seq_fops); | ||
2133 | #endif | ||
2134 | unix_sysctl_register(); | ||
2135 | out: | 2185 | out: |
2136 | return rc; | 2186 | return rc; |
2137 | } | 2187 | } |
@@ -2139,9 +2189,8 @@ out: | |||
2139 | static void __exit af_unix_exit(void) | 2189 | static void __exit af_unix_exit(void) |
2140 | { | 2190 | { |
2141 | sock_unregister(PF_UNIX); | 2191 | sock_unregister(PF_UNIX); |
2142 | unix_sysctl_unregister(); | ||
2143 | proc_net_remove(&init_net, "unix"); | ||
2144 | proto_unregister(&unix_proto); | 2192 | proto_unregister(&unix_proto); |
2193 | unregister_pernet_subsys(&unix_net_ops); | ||
2145 | } | 2194 | } |
2146 | 2195 | ||
2147 | module_init(af_unix_init); | 2196 | module_init(af_unix_init); |
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index eb0bd57ebada..77513d7e35f2 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c | |||
@@ -18,7 +18,7 @@ static ctl_table unix_table[] = { | |||
18 | { | 18 | { |
19 | .ctl_name = NET_UNIX_MAX_DGRAM_QLEN, | 19 | .ctl_name = NET_UNIX_MAX_DGRAM_QLEN, |
20 | .procname = "max_dgram_qlen", | 20 | .procname = "max_dgram_qlen", |
21 | .data = &sysctl_unix_max_dgram_qlen, | 21 | .data = &init_net.unx.sysctl_max_dgram_qlen, |
22 | .maxlen = sizeof(int), | 22 | .maxlen = sizeof(int), |
23 | .mode = 0644, | 23 | .mode = 0644, |
24 | .proc_handler = &proc_dointvec | 24 | .proc_handler = &proc_dointvec |
@@ -26,35 +26,39 @@ static ctl_table unix_table[] = { | |||
26 | { .ctl_name = 0 } | 26 | { .ctl_name = 0 } |
27 | }; | 27 | }; |
28 | 28 | ||
29 | static ctl_table unix_net_table[] = { | 29 | static struct ctl_path unix_path[] = { |
30 | { | 30 | { .procname = "net", .ctl_name = CTL_NET, }, |
31 | .ctl_name = NET_UNIX, | 31 | { .procname = "unix", .ctl_name = NET_UNIX, }, |
32 | .procname = "unix", | 32 | { }, |
33 | .mode = 0555, | ||
34 | .child = unix_table | ||
35 | }, | ||
36 | { .ctl_name = 0 } | ||
37 | }; | 33 | }; |
38 | 34 | ||
39 | static ctl_table unix_root_table[] = { | 35 | int unix_sysctl_register(struct net *net) |
40 | { | 36 | { |
41 | .ctl_name = CTL_NET, | 37 | struct ctl_table *table; |
42 | .procname = "net", | ||
43 | .mode = 0555, | ||
44 | .child = unix_net_table | ||
45 | }, | ||
46 | { .ctl_name = 0 } | ||
47 | }; | ||
48 | 38 | ||
49 | static struct ctl_table_header * unix_sysctl_header; | 39 | table = kmemdup(unix_table, sizeof(unix_table), GFP_KERNEL); |
40 | if (table == NULL) | ||
41 | goto err_alloc; | ||
50 | 42 | ||
51 | void unix_sysctl_register(void) | 43 | table[0].data = &net->unx.sysctl_max_dgram_qlen; |
52 | { | 44 | net->unx.ctl = register_net_sysctl_table(net, unix_path, table); |
53 | unix_sysctl_header = register_sysctl_table(unix_root_table); | 45 | if (net->unx.ctl == NULL) |
46 | goto err_reg; | ||
47 | |||
48 | return 0; | ||
49 | |||
50 | err_reg: | ||
51 | kfree(table); | ||
52 | err_alloc: | ||
53 | return -ENOMEM; | ||
54 | } | 54 | } |
55 | 55 | ||
56 | void unix_sysctl_unregister(void) | 56 | void unix_sysctl_unregister(struct net *net) |
57 | { | 57 | { |
58 | unregister_sysctl_table(unix_sysctl_header); | 58 | struct ctl_table *table; |
59 | |||
60 | table = net->unx.ctl->ctl_table_arg; | ||
61 | unregister_sysctl_table(net->unx.ctl); | ||
62 | kfree(table); | ||
59 | } | 63 | } |
60 | 64 | ||