aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2007-11-20 01:29:30 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:54:27 -0500
commit097e66c578459f79e3a2128c54e9df5194e1419a (patch)
treebdc164e849dc33a4321ea51d965a113917bb287b /net/unix/af_unix.c
parentd12d01d6b4d197115c4d7736172b5b1ec8b1eb71 (diff)
[NET]: Make AF_UNIX per network namespace safe [v2]
Because of the global nature of garbage collection, and because of the cost of per namespace hash tables unix_socket_table has been kept global. With a filter added on lookups so we don't see sockets from the wrong namespace. Currently I don't fold the namesapce into the hash so multiple namespaces using the same socket name will be guaranteed a hash collision. Changes from v1: - fixed unix_seq_open Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c118
1 files changed, 92 insertions, 26 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 060bba4567d2..ecad42b72ad6 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -270,7 +270,8 @@ static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
270 spin_unlock(&unix_table_lock); 270 spin_unlock(&unix_table_lock);
271} 271}
272 272
273static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname, 273static struct sock *__unix_find_socket_byname(struct net *net,
274 struct sockaddr_un *sunname,
274 int len, int type, unsigned hash) 275 int len, int type, unsigned hash)
275{ 276{
276 struct sock *s; 277 struct sock *s;
@@ -279,6 +280,9 @@ static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
279 sk_for_each(s, node, &unix_socket_table[hash ^ type]) { 280 sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
280 struct unix_sock *u = unix_sk(s); 281 struct unix_sock *u = unix_sk(s);
281 282
283 if (s->sk_net != net)
284 continue;
285
282 if (u->addr->len == len && 286 if (u->addr->len == len &&
283 !memcmp(u->addr->name, sunname, len)) 287 !memcmp(u->addr->name, sunname, len))
284 goto found; 288 goto found;
@@ -288,21 +292,22 @@ found:
288 return s; 292 return s;
289} 293}
290 294
291static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname, 295static inline struct sock *unix_find_socket_byname(struct net *net,
296 struct sockaddr_un *sunname,
292 int len, int type, 297 int len, int type,
293 unsigned hash) 298 unsigned hash)
294{ 299{
295 struct sock *s; 300 struct sock *s;
296 301
297 spin_lock(&unix_table_lock); 302 spin_lock(&unix_table_lock);
298 s = __unix_find_socket_byname(sunname, len, type, hash); 303 s = __unix_find_socket_byname(net, sunname, len, type, hash);
299 if (s) 304 if (s)
300 sock_hold(s); 305 sock_hold(s);
301 spin_unlock(&unix_table_lock); 306 spin_unlock(&unix_table_lock);
302 return s; 307 return s;
303} 308}
304 309
305static struct sock *unix_find_socket_byinode(struct inode *i) 310static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
306{ 311{
307 struct sock *s; 312 struct sock *s;
308 struct hlist_node *node; 313 struct hlist_node *node;
@@ -312,6 +317,9 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
312 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { 317 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
313 struct dentry *dentry = unix_sk(s)->dentry; 318 struct dentry *dentry = unix_sk(s)->dentry;
314 319
320 if (s->sk_net != net)
321 continue;
322
315 if(dentry && dentry->d_inode == i) 323 if(dentry && dentry->d_inode == i)
316 { 324 {
317 sock_hold(s); 325 sock_hold(s);
@@ -631,9 +639,6 @@ out:
631 639
632static int unix_create(struct net *net, struct socket *sock, int protocol) 640static int unix_create(struct net *net, struct socket *sock, int protocol)
633{ 641{
634 if (net != &init_net)
635 return -EAFNOSUPPORT;
636
637 if (protocol && protocol != PF_UNIX) 642 if (protocol && protocol != PF_UNIX)
638 return -EPROTONOSUPPORT; 643 return -EPROTONOSUPPORT;
639 644
@@ -677,6 +682,7 @@ static int unix_release(struct socket *sock)
677static int unix_autobind(struct socket *sock) 682static int unix_autobind(struct socket *sock)
678{ 683{
679 struct sock *sk = sock->sk; 684 struct sock *sk = sock->sk;
685 struct net *net = sk->sk_net;
680 struct unix_sock *u = unix_sk(sk); 686 struct unix_sock *u = unix_sk(sk);
681 static u32 ordernum = 1; 687 static u32 ordernum = 1;
682 struct unix_address * addr; 688 struct unix_address * addr;
@@ -703,7 +709,7 @@ retry:
703 spin_lock(&unix_table_lock); 709 spin_lock(&unix_table_lock);
704 ordernum = (ordernum+1)&0xFFFFF; 710 ordernum = (ordernum+1)&0xFFFFF;
705 711
706 if (__unix_find_socket_byname(addr->name, addr->len, sock->type, 712 if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
707 addr->hash)) { 713 addr->hash)) {
708 spin_unlock(&unix_table_lock); 714 spin_unlock(&unix_table_lock);
709 /* Sanity yield. It is unusual case, but yet... */ 715 /* Sanity yield. It is unusual case, but yet... */
@@ -723,7 +729,8 @@ out: mutex_unlock(&u->readlock);
723 return err; 729 return err;
724} 730}
725 731
726static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, 732static struct sock *unix_find_other(struct net *net,
733 struct sockaddr_un *sunname, int len,
727 int type, unsigned hash, int *error) 734 int type, unsigned hash, int *error)
728{ 735{
729 struct sock *u; 736 struct sock *u;
@@ -741,7 +748,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
741 err = -ECONNREFUSED; 748 err = -ECONNREFUSED;
742 if (!S_ISSOCK(nd.dentry->d_inode->i_mode)) 749 if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
743 goto put_fail; 750 goto put_fail;
744 u=unix_find_socket_byinode(nd.dentry->d_inode); 751 u=unix_find_socket_byinode(net, nd.dentry->d_inode);
745 if (!u) 752 if (!u)
746 goto put_fail; 753 goto put_fail;
747 754
@@ -757,7 +764,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
757 } 764 }
758 } else { 765 } else {
759 err = -ECONNREFUSED; 766 err = -ECONNREFUSED;
760 u=unix_find_socket_byname(sunname, len, type, hash); 767 u=unix_find_socket_byname(net, sunname, len, type, hash);
761 if (u) { 768 if (u) {
762 struct dentry *dentry; 769 struct dentry *dentry;
763 dentry = unix_sk(u)->dentry; 770 dentry = unix_sk(u)->dentry;
@@ -779,6 +786,7 @@ fail:
779static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 786static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
780{ 787{
781 struct sock *sk = sock->sk; 788 struct sock *sk = sock->sk;
789 struct net *net = sk->sk_net;
782 struct unix_sock *u = unix_sk(sk); 790 struct unix_sock *u = unix_sk(sk);
783 struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; 791 struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
784 struct dentry * dentry = NULL; 792 struct dentry * dentry = NULL;
@@ -853,7 +861,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
853 861
854 if (!sunaddr->sun_path[0]) { 862 if (!sunaddr->sun_path[0]) {
855 err = -EADDRINUSE; 863 err = -EADDRINUSE;
856 if (__unix_find_socket_byname(sunaddr, addr_len, 864 if (__unix_find_socket_byname(net, sunaddr, addr_len,
857 sk->sk_type, hash)) { 865 sk->sk_type, hash)) {
858 unix_release_addr(addr); 866 unix_release_addr(addr);
859 goto out_unlock; 867 goto out_unlock;
@@ -919,6 +927,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
919 int alen, int flags) 927 int alen, int flags)
920{ 928{
921 struct sock *sk = sock->sk; 929 struct sock *sk = sock->sk;
930 struct net *net = sk->sk_net;
922 struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr; 931 struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
923 struct sock *other; 932 struct sock *other;
924 unsigned hash; 933 unsigned hash;
@@ -935,7 +944,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
935 goto out; 944 goto out;
936 945
937restart: 946restart:
938 other=unix_find_other(sunaddr, alen, sock->type, hash, &err); 947 other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
939 if (!other) 948 if (!other)
940 goto out; 949 goto out;
941 950
@@ -1015,6 +1024,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1015{ 1024{
1016 struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; 1025 struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
1017 struct sock *sk = sock->sk; 1026 struct sock *sk = sock->sk;
1027 struct net *net = sk->sk_net;
1018 struct unix_sock *u = unix_sk(sk), *newu, *otheru; 1028 struct unix_sock *u = unix_sk(sk), *newu, *otheru;
1019 struct sock *newsk = NULL; 1029 struct sock *newsk = NULL;
1020 struct sock *other = NULL; 1030 struct sock *other = NULL;
@@ -1054,7 +1064,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
1054 1064
1055restart: 1065restart:
1056 /* Find listening sock. */ 1066 /* Find listening sock. */
1057 other = unix_find_other(sunaddr, addr_len, sk->sk_type, hash, &err); 1067 other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
1058 if (!other) 1068 if (!other)
1059 goto out; 1069 goto out;
1060 1070
@@ -1330,6 +1340,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1330{ 1340{
1331 struct sock_iocb *siocb = kiocb_to_siocb(kiocb); 1341 struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
1332 struct sock *sk = sock->sk; 1342 struct sock *sk = sock->sk;
1343 struct net *net = sk->sk_net;
1333 struct unix_sock *u = unix_sk(sk); 1344 struct unix_sock *u = unix_sk(sk);
1334 struct sockaddr_un *sunaddr=msg->msg_name; 1345 struct sockaddr_un *sunaddr=msg->msg_name;
1335 struct sock *other = NULL; 1346 struct sock *other = NULL;
@@ -1393,7 +1404,7 @@ restart:
1393 if (sunaddr == NULL) 1404 if (sunaddr == NULL)
1394 goto out_free; 1405 goto out_free;
1395 1406
1396 other = unix_find_other(sunaddr, namelen, sk->sk_type, 1407 other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
1397 hash, &err); 1408 hash, &err);
1398 if (other==NULL) 1409 if (other==NULL)
1399 goto out_free; 1410 goto out_free;
@@ -2006,12 +2017,18 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl
2006 2017
2007 2018
2008#ifdef CONFIG_PROC_FS 2019#ifdef CONFIG_PROC_FS
2009static struct sock *unix_seq_idx(int *iter, loff_t pos) 2020struct unix_iter_state {
2021 struct net *net;
2022 int i;
2023};
2024static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
2010{ 2025{
2011 loff_t off = 0; 2026 loff_t off = 0;
2012 struct sock *s; 2027 struct sock *s;
2013 2028
2014 for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) { 2029 for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
2030 if (s->sk_net != iter->net)
2031 continue;
2015 if (off == pos) 2032 if (off == pos)
2016 return s; 2033 return s;
2017 ++off; 2034 ++off;
@@ -2022,17 +2039,24 @@ static struct sock *unix_seq_idx(int *iter, loff_t pos)
2022 2039
2023static void *unix_seq_start(struct seq_file *seq, loff_t *pos) 2040static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
2024{ 2041{
2042 struct unix_iter_state *iter = seq->private;
2025 spin_lock(&unix_table_lock); 2043 spin_lock(&unix_table_lock);
2026 return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1); 2044 return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
2027} 2045}
2028 2046
2029static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) 2047static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2030{ 2048{
2049 struct unix_iter_state *iter = seq->private;
2050 struct sock *sk = v;
2031 ++*pos; 2051 ++*pos;
2032 2052
2033 if (v == (void *)1) 2053 if (v == (void *)1)
2034 return first_unix_socket(seq->private); 2054 sk = first_unix_socket(&iter->i);
2035 return next_unix_socket(seq->private, v); 2055 else
2056 sk = next_unix_socket(&iter->i, sk);
2057 while (sk && (sk->sk_net != iter->net))
2058 sk = next_unix_socket(&iter->i, sk);
2059 return sk;
2036} 2060}
2037 2061
2038static void unix_seq_stop(struct seq_file *seq, void *v) 2062static void unix_seq_stop(struct seq_file *seq, void *v)
@@ -2094,7 +2118,27 @@ static const struct seq_operations unix_seq_ops = {
2094 2118
2095static int unix_seq_open(struct inode *inode, struct file *file) 2119static int unix_seq_open(struct inode *inode, struct file *file)
2096{ 2120{
2097 return seq_open_private(file, &unix_seq_ops, sizeof(int)); 2121 struct unix_iter_state *it;
2122
2123 it = __seq_open_private(file, &unix_seq_ops,
2124 sizeof(struct unix_iter_state));
2125 if (it == NULL)
2126 return -ENOMEM;
2127
2128 it->net = get_proc_net(inode);
2129 if (it->net == NULL) {
2130 seq_release_private(inode, file);
2131 return -ENXIO;
2132 }
2133 return 0;
2134}
2135
2136static int unix_seq_release(struct inode *inode, struct file *file)
2137{
2138 struct seq_file *seq = file->private_data;
2139 struct unix_iter_state *iter = seq->private;
2140 put_net(iter->net);
2141 return seq_release_private(inode, file);
2098} 2142}
2099 2143
2100static const struct file_operations unix_seq_fops = { 2144static const struct file_operations unix_seq_fops = {
@@ -2102,7 +2146,7 @@ static const struct file_operations unix_seq_fops = {
2102 .open = unix_seq_open, 2146 .open = unix_seq_open,
2103 .read = seq_read, 2147 .read = seq_read,
2104 .llseek = seq_lseek, 2148 .llseek = seq_lseek,
2105 .release = seq_release_private, 2149 .release = unix_seq_release,
2106}; 2150};
2107 2151
2108#endif 2152#endif
@@ -2113,6 +2157,30 @@ static struct net_proto_family unix_family_ops = {
2113 .owner = THIS_MODULE, 2157 .owner = THIS_MODULE,
2114}; 2158};
2115 2159
2160
2161static int unix_net_init(struct net *net)
2162{
2163 int error = -ENOMEM;
2164
2165#ifdef CONFIG_PROC_FS
2166 if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops))
2167 goto out;
2168#endif
2169 error = 0;
2170out:
2171 return 0;
2172}
2173
2174static void unix_net_exit(struct net *net)
2175{
2176 proc_net_remove(net, "unix");
2177}
2178
2179static struct pernet_operations unix_net_ops = {
2180 .init = unix_net_init,
2181 .exit = unix_net_exit,
2182};
2183
2116static int __init af_unix_init(void) 2184static int __init af_unix_init(void)
2117{ 2185{
2118 int rc = -1; 2186 int rc = -1;
@@ -2128,9 +2196,7 @@ static int __init af_unix_init(void)
2128 } 2196 }
2129 2197
2130 sock_register(&unix_family_ops); 2198 sock_register(&unix_family_ops);
2131#ifdef CONFIG_PROC_FS 2199 register_pernet_subsys(&unix_net_ops);
2132 proc_net_fops_create(&init_net, "unix", 0, &unix_seq_fops);
2133#endif
2134 unix_sysctl_register(); 2200 unix_sysctl_register();
2135out: 2201out:
2136 return rc; 2202 return rc;
@@ -2140,8 +2206,8 @@ static void __exit af_unix_exit(void)
2140{ 2206{
2141 sock_unregister(PF_UNIX); 2207 sock_unregister(PF_UNIX);
2142 unix_sysctl_unregister(); 2208 unix_sysctl_unregister();
2143 proc_net_remove(&init_net, "unix");
2144 proto_unregister(&unix_proto); 2209 proto_unregister(&unix_proto);
2210 unregister_pernet_subsys(&unix_net_ops);
2145} 2211}
2146 2212
2147module_init(af_unix_init); 2213module_init(af_unix_init);