aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c80
1 files changed, 63 insertions, 17 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2358f2690ec5..e2d18b9f910f 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -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 }
@@ -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}
@@ -2113,8 +2119,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2113 mutex_lock(&u->iolock); 2119 mutex_lock(&u->iolock);
2114 2120
2115 skip = sk_peek_offset(sk, flags); 2121 skip = sk_peek_offset(sk, flags);
2116 skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err, 2122 skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip,
2117 &last); 2123 &err, &last);
2118 if (skb) 2124 if (skb)
2119 break; 2125 break;
2120 2126
@@ -2587,6 +2593,43 @@ long unix_outq_len(struct sock *sk)
2587} 2593}
2588EXPORT_SYMBOL_GPL(unix_outq_len); 2594EXPORT_SYMBOL_GPL(unix_outq_len);
2589 2595
2596static int unix_open_file(struct sock *sk)
2597{
2598 struct path path;
2599 struct file *f;
2600 int fd;
2601
2602 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
2603 return -EPERM;
2604
2605 unix_state_lock(sk);
2606 path = unix_sk(sk)->path;
2607 if (!path.dentry) {
2608 unix_state_unlock(sk);
2609 return -ENOENT;
2610 }
2611
2612 path_get(&path);
2613 unix_state_unlock(sk);
2614
2615 fd = get_unused_fd_flags(O_CLOEXEC);
2616 if (fd < 0)
2617 goto out;
2618
2619 f = dentry_open(&path, O_PATH, current_cred());
2620 if (IS_ERR(f)) {
2621 put_unused_fd(fd);
2622 fd = PTR_ERR(f);
2623 goto out;
2624 }
2625
2626 fd_install(fd, f);
2627out:
2628 path_put(&path);
2629
2630 return fd;
2631}
2632
2590static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 2633static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2591{ 2634{
2592 struct sock *sk = sock->sk; 2635 struct sock *sk = sock->sk;
@@ -2605,6 +2648,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2605 else 2648 else
2606 err = put_user(amount, (int __user *)arg); 2649 err = put_user(amount, (int __user *)arg);
2607 break; 2650 break;
2651 case SIOCUNIXFILE:
2652 err = unix_open_file(sk);
2653 break;
2608 default: 2654 default:
2609 err = -ENOIOCTLCMD; 2655 err = -ENOIOCTLCMD;
2610 break; 2656 break;