aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c87
-rw-r--r--net/unix/garbage.c17
2 files changed, 76 insertions, 28 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2358f2690ec5..928691c43408 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -85,7 +85,7 @@
85#include <linux/module.h> 85#include <linux/module.h>
86#include <linux/kernel.h> 86#include <linux/kernel.h>
87#include <linux/signal.h> 87#include <linux/signal.h>
88#include <linux/sched.h> 88#include <linux/sched/signal.h>
89#include <linux/errno.h> 89#include <linux/errno.h>
90#include <linux/string.h> 90#include <linux/string.h>
91#include <linux/stat.h> 91#include <linux/stat.h>
@@ -100,7 +100,7 @@
100#include <linux/in.h> 100#include <linux/in.h>
101#include <linux/fs.h> 101#include <linux/fs.h>
102#include <linux/slab.h> 102#include <linux/slab.h>
103#include <asm/uaccess.h> 103#include <linux/uaccess.h>
104#include <linux/skbuff.h> 104#include <linux/skbuff.h>
105#include <linux/netdevice.h> 105#include <linux/netdevice.h>
106#include <net/net_namespace.h> 106#include <net/net_namespace.h>
@@ -117,6 +117,7 @@
117#include <net/checksum.h> 117#include <net/checksum.h>
118#include <linux/security.h> 118#include <linux/security.h>
119#include <linux/freezer.h> 119#include <linux/freezer.h>
120#include <linux/file.h>
120 121
121struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; 122struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
122EXPORT_SYMBOL_GPL(unix_socket_table); 123EXPORT_SYMBOL_GPL(unix_socket_table);
@@ -315,7 +316,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
315 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { 316 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
316 struct dentry *dentry = unix_sk(s)->path.dentry; 317 struct dentry *dentry = unix_sk(s)->path.dentry;
317 318
318 if (dentry && d_real_inode(dentry) == i) { 319 if (dentry && d_backing_inode(dentry) == i) {
319 sock_hold(s); 320 sock_hold(s);
320 goto found; 321 goto found;
321 } 322 }
@@ -635,7 +636,7 @@ static int unix_bind(struct socket *, struct sockaddr *, int);
635static int unix_stream_connect(struct socket *, struct sockaddr *, 636static int unix_stream_connect(struct socket *, struct sockaddr *,
636 int addr_len, int flags); 637 int addr_len, int flags);
637static int unix_socketpair(struct socket *, struct socket *); 638static int unix_socketpair(struct socket *, struct socket *);
638static int unix_accept(struct socket *, struct socket *, int); 639static int unix_accept(struct socket *, struct socket *, int, bool);
639static int unix_getname(struct socket *, struct sockaddr *, int *, int); 640static int unix_getname(struct socket *, struct sockaddr *, int *, int);
640static unsigned int unix_poll(struct file *, struct socket *, poll_table *); 641static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
641static unsigned int unix_dgram_poll(struct file *, struct socket *, 642static unsigned int unix_dgram_poll(struct file *, struct socket *,
@@ -913,7 +914,7 @@ static struct sock *unix_find_other(struct net *net,
913 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); 914 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
914 if (err) 915 if (err)
915 goto fail; 916 goto fail;
916 inode = d_real_inode(path.dentry); 917 inode = d_backing_inode(path.dentry);
917 err = inode_permission(inode, MAY_WRITE); 918 err = inode_permission(inode, MAY_WRITE);
918 if (err) 919 if (err)
919 goto put_fail; 920 goto put_fail;
@@ -995,6 +996,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
995 unsigned int hash; 996 unsigned int hash;
996 struct unix_address *addr; 997 struct unix_address *addr;
997 struct hlist_head *list; 998 struct hlist_head *list;
999 struct path path = { NULL, NULL };
998 1000
999 err = -EINVAL; 1001 err = -EINVAL;
1000 if (sunaddr->sun_family != AF_UNIX) 1002 if (sunaddr->sun_family != AF_UNIX)
@@ -1010,9 +1012,20 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
1010 goto out; 1012 goto out;
1011 addr_len = err; 1013 addr_len = err;
1012 1014
1015 if (sun_path[0]) {
1016 umode_t mode = S_IFSOCK |
1017 (SOCK_INODE(sock)->i_mode & ~current_umask());
1018 err = unix_mknod(sun_path, mode, &path);
1019 if (err) {
1020 if (err == -EEXIST)
1021 err = -EADDRINUSE;
1022 goto out;
1023 }
1024 }
1025
1013 err = mutex_lock_interruptible(&u->bindlock); 1026 err = mutex_lock_interruptible(&u->bindlock);
1014 if (err) 1027 if (err)
1015 goto out; 1028 goto out_put;
1016 1029
1017 err = -EINVAL; 1030 err = -EINVAL;
1018 if (u->addr) 1031 if (u->addr)
@@ -1029,18 +1042,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
1029 atomic_set(&addr->refcnt, 1); 1042 atomic_set(&addr->refcnt, 1);
1030 1043
1031 if (sun_path[0]) { 1044 if (sun_path[0]) {
1032 struct path path;
1033 umode_t mode = S_IFSOCK |
1034 (SOCK_INODE(sock)->i_mode & ~current_umask());
1035 err = unix_mknod(sun_path, mode, &path);
1036 if (err) {
1037 if (err == -EEXIST)
1038 err = -EADDRINUSE;
1039 unix_release_addr(addr);
1040 goto out_up;
1041 }
1042 addr->hash = UNIX_HASH_SIZE; 1045 addr->hash = UNIX_HASH_SIZE;
1043 hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); 1046 hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
1044 spin_lock(&unix_table_lock); 1047 spin_lock(&unix_table_lock);
1045 u->path = path; 1048 u->path = path;
1046 list = &unix_socket_table[hash]; 1049 list = &unix_socket_table[hash];
@@ -1065,6 +1068,9 @@ out_unlock:
1065 spin_unlock(&unix_table_lock); 1068 spin_unlock(&unix_table_lock);
1066out_up: 1069out_up:
1067 mutex_unlock(&u->bindlock); 1070 mutex_unlock(&u->bindlock);
1071out_put:
1072 if (err)
1073 path_put(&path);
1068out: 1074out:
1069 return err; 1075 return err;
1070} 1076}
@@ -1396,7 +1402,8 @@ static void unix_sock_inherit_flags(const struct socket *old,
1396 set_bit(SOCK_PASSSEC, &new->flags); 1402 set_bit(SOCK_PASSSEC, &new->flags);
1397} 1403}
1398 1404
1399static int unix_accept(struct socket *sock, struct socket *newsock, int flags) 1405static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
1406 bool kern)
1400{ 1407{
1401 struct sock *sk = sock->sk; 1408 struct sock *sk = sock->sk;
1402 struct sock *tsk; 1409 struct sock *tsk;
@@ -2113,8 +2120,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2113 mutex_lock(&u->iolock); 2120 mutex_lock(&u->iolock);
2114 2121
2115 skip = sk_peek_offset(sk, flags); 2122 skip = sk_peek_offset(sk, flags);
2116 skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err, 2123 skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip,
2117 &last); 2124 &err, &last);
2118 if (skb) 2125 if (skb)
2119 break; 2126 break;
2120 2127
@@ -2587,6 +2594,43 @@ long unix_outq_len(struct sock *sk)
2587} 2594}
2588EXPORT_SYMBOL_GPL(unix_outq_len); 2595EXPORT_SYMBOL_GPL(unix_outq_len);
2589 2596
2597static int unix_open_file(struct sock *sk)
2598{
2599 struct path path;
2600 struct file *f;
2601 int fd;
2602
2603 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
2604 return -EPERM;
2605
2606 unix_state_lock(sk);
2607 path = unix_sk(sk)->path;
2608 if (!path.dentry) {
2609 unix_state_unlock(sk);
2610 return -ENOENT;
2611 }
2612
2613 path_get(&path);
2614 unix_state_unlock(sk);
2615
2616 fd = get_unused_fd_flags(O_CLOEXEC);
2617 if (fd < 0)
2618 goto out;
2619
2620 f = dentry_open(&path, O_PATH, current_cred());
2621 if (IS_ERR(f)) {
2622 put_unused_fd(fd);
2623 fd = PTR_ERR(f);
2624 goto out;
2625 }
2626
2627 fd_install(fd, f);
2628out:
2629 path_put(&path);
2630
2631 return fd;
2632}
2633
2590static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 2634static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2591{ 2635{
2592 struct sock *sk = sock->sk; 2636 struct sock *sk = sock->sk;
@@ -2605,6 +2649,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2605 else 2649 else
2606 err = put_user(amount, (int __user *)arg); 2650 err = put_user(amount, (int __user *)arg);
2607 break; 2651 break;
2652 case SIOCUNIXFILE:
2653 err = unix_open_file(sk);
2654 break;
2608 default: 2655 default:
2609 err = -ENOIOCTLCMD; 2656 err = -ENOIOCTLCMD;
2610 break; 2657 break;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 6a0d48525fcf..c36757e72844 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -146,6 +146,7 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
146 if (s) { 146 if (s) {
147 struct unix_sock *u = unix_sk(s); 147 struct unix_sock *u = unix_sk(s);
148 148
149 BUG_ON(!atomic_long_read(&u->inflight));
149 BUG_ON(list_empty(&u->link)); 150 BUG_ON(list_empty(&u->link));
150 151
151 if (atomic_long_dec_and_test(&u->inflight)) 152 if (atomic_long_dec_and_test(&u->inflight))
@@ -341,6 +342,14 @@ void unix_gc(void)
341 } 342 }
342 list_del(&cursor); 343 list_del(&cursor);
343 344
345 /* Now gc_candidates contains only garbage. Restore original
346 * inflight counters for these as well, and remove the skbuffs
347 * which are creating the cycle(s).
348 */
349 skb_queue_head_init(&hitlist);
350 list_for_each_entry(u, &gc_candidates, link)
351 scan_children(&u->sk, inc_inflight, &hitlist);
352
344 /* not_cycle_list contains those sockets which do not make up a 353 /* not_cycle_list contains those sockets which do not make up a
345 * cycle. Restore these to the inflight list. 354 * cycle. Restore these to the inflight list.
346 */ 355 */
@@ -350,14 +359,6 @@ void unix_gc(void)
350 list_move_tail(&u->link, &gc_inflight_list); 359 list_move_tail(&u->link, &gc_inflight_list);
351 } 360 }
352 361
353 /* Now gc_candidates contains only garbage. Restore original
354 * inflight counters for these as well, and remove the skbuffs
355 * which are creating the cycle(s).
356 */
357 skb_queue_head_init(&hitlist);
358 list_for_each_entry(u, &gc_candidates, link)
359 scan_children(&u->sk, inc_inflight, &hitlist);
360
361 spin_unlock(&unix_gc_lock); 362 spin_unlock(&unix_gc_lock);
362 363
363 /* Here we are. Hitlist is filled. Die. */ 364 /* Here we are. Hitlist is filled. Die. */