diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 134 |
1 files changed, 86 insertions, 48 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a4631477cedf..49d5093eb055 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -451,7 +451,7 @@ static void unix_write_space(struct sock *sk) | |||
451 | rcu_read_lock(); | 451 | rcu_read_lock(); |
452 | if (unix_writable(sk)) { | 452 | if (unix_writable(sk)) { |
453 | wq = rcu_dereference(sk->sk_wq); | 453 | wq = rcu_dereference(sk->sk_wq); |
454 | if (wq_has_sleeper(wq)) | 454 | if (skwq_has_sleeper(wq)) |
455 | wake_up_interruptible_sync_poll(&wq->wait, | 455 | wake_up_interruptible_sync_poll(&wq->wait, |
456 | POLLOUT | POLLWRNORM | POLLWRBAND); | 456 | POLLOUT | POLLWRNORM | POLLWRBAND); |
457 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 457 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
@@ -953,32 +953,20 @@ fail: | |||
953 | return NULL; | 953 | return NULL; |
954 | } | 954 | } |
955 | 955 | ||
956 | static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) | 956 | static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, |
957 | struct path *res) | ||
957 | { | 958 | { |
958 | struct dentry *dentry; | 959 | int err; |
959 | struct path path; | ||
960 | int err = 0; | ||
961 | /* | ||
962 | * Get the parent directory, calculate the hash for last | ||
963 | * component. | ||
964 | */ | ||
965 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
966 | err = PTR_ERR(dentry); | ||
967 | if (IS_ERR(dentry)) | ||
968 | return err; | ||
969 | 960 | ||
970 | /* | 961 | err = security_path_mknod(path, dentry, mode, 0); |
971 | * All right, let's create it. | ||
972 | */ | ||
973 | err = security_path_mknod(&path, dentry, mode, 0); | ||
974 | if (!err) { | 962 | if (!err) { |
975 | err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); | 963 | err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); |
976 | if (!err) { | 964 | if (!err) { |
977 | res->mnt = mntget(path.mnt); | 965 | res->mnt = mntget(path->mnt); |
978 | res->dentry = dget(dentry); | 966 | res->dentry = dget(dentry); |
979 | } | 967 | } |
980 | } | 968 | } |
981 | done_path_create(&path, dentry); | 969 | |
982 | return err; | 970 | return err; |
983 | } | 971 | } |
984 | 972 | ||
@@ -989,10 +977,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
989 | struct unix_sock *u = unix_sk(sk); | 977 | struct unix_sock *u = unix_sk(sk); |
990 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; | 978 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
991 | char *sun_path = sunaddr->sun_path; | 979 | char *sun_path = sunaddr->sun_path; |
992 | int err; | 980 | int err, name_err; |
993 | unsigned int hash; | 981 | unsigned int hash; |
994 | struct unix_address *addr; | 982 | struct unix_address *addr; |
995 | struct hlist_head *list; | 983 | struct hlist_head *list; |
984 | struct path path; | ||
985 | struct dentry *dentry; | ||
996 | 986 | ||
997 | err = -EINVAL; | 987 | err = -EINVAL; |
998 | if (sunaddr->sun_family != AF_UNIX) | 988 | if (sunaddr->sun_family != AF_UNIX) |
@@ -1008,14 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1008 | goto out; | 998 | goto out; |
1009 | addr_len = err; | 999 | addr_len = err; |
1010 | 1000 | ||
1001 | name_err = 0; | ||
1002 | dentry = NULL; | ||
1003 | if (sun_path[0]) { | ||
1004 | /* Get the parent directory, calculate the hash for last | ||
1005 | * component. | ||
1006 | */ | ||
1007 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
1008 | |||
1009 | if (IS_ERR(dentry)) { | ||
1010 | /* delay report until after 'already bound' check */ | ||
1011 | name_err = PTR_ERR(dentry); | ||
1012 | dentry = NULL; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1011 | err = mutex_lock_interruptible(&u->readlock); | 1016 | err = mutex_lock_interruptible(&u->readlock); |
1012 | if (err) | 1017 | if (err) |
1013 | goto out; | 1018 | goto out_path; |
1014 | 1019 | ||
1015 | err = -EINVAL; | 1020 | err = -EINVAL; |
1016 | if (u->addr) | 1021 | if (u->addr) |
1017 | goto out_up; | 1022 | goto out_up; |
1018 | 1023 | ||
1024 | if (name_err) { | ||
1025 | err = name_err == -EEXIST ? -EADDRINUSE : name_err; | ||
1026 | goto out_up; | ||
1027 | } | ||
1028 | |||
1019 | err = -ENOMEM; | 1029 | err = -ENOMEM; |
1020 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); | 1030 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); |
1021 | if (!addr) | 1031 | if (!addr) |
@@ -1026,11 +1036,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1026 | addr->hash = hash ^ sk->sk_type; | 1036 | addr->hash = hash ^ sk->sk_type; |
1027 | atomic_set(&addr->refcnt, 1); | 1037 | atomic_set(&addr->refcnt, 1); |
1028 | 1038 | ||
1029 | if (sun_path[0]) { | 1039 | if (dentry) { |
1030 | struct path path; | 1040 | struct path u_path; |
1031 | umode_t mode = S_IFSOCK | | 1041 | umode_t mode = S_IFSOCK | |
1032 | (SOCK_INODE(sock)->i_mode & ~current_umask()); | 1042 | (SOCK_INODE(sock)->i_mode & ~current_umask()); |
1033 | err = unix_mknod(sun_path, mode, &path); | 1043 | err = unix_mknod(dentry, &path, mode, &u_path); |
1034 | if (err) { | 1044 | if (err) { |
1035 | if (err == -EEXIST) | 1045 | if (err == -EEXIST) |
1036 | err = -EADDRINUSE; | 1046 | err = -EADDRINUSE; |
@@ -1038,9 +1048,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1038 | goto out_up; | 1048 | goto out_up; |
1039 | } | 1049 | } |
1040 | addr->hash = UNIX_HASH_SIZE; | 1050 | addr->hash = UNIX_HASH_SIZE; |
1041 | hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1); | 1051 | hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
1042 | spin_lock(&unix_table_lock); | 1052 | spin_lock(&unix_table_lock); |
1043 | u->path = path; | 1053 | u->path = u_path; |
1044 | list = &unix_socket_table[hash]; | 1054 | list = &unix_socket_table[hash]; |
1045 | } else { | 1055 | } else { |
1046 | spin_lock(&unix_table_lock); | 1056 | spin_lock(&unix_table_lock); |
@@ -1063,6 +1073,10 @@ out_unlock: | |||
1063 | spin_unlock(&unix_table_lock); | 1073 | spin_unlock(&unix_table_lock); |
1064 | out_up: | 1074 | out_up: |
1065 | mutex_unlock(&u->readlock); | 1075 | mutex_unlock(&u->readlock); |
1076 | out_path: | ||
1077 | if (dentry) | ||
1078 | done_path_create(&path, dentry); | ||
1079 | |||
1066 | out: | 1080 | out: |
1067 | return err; | 1081 | return err; |
1068 | } | 1082 | } |
@@ -1499,6 +1513,21 @@ static void unix_destruct_scm(struct sk_buff *skb) | |||
1499 | sock_wfree(skb); | 1513 | sock_wfree(skb); |
1500 | } | 1514 | } |
1501 | 1515 | ||
1516 | /* | ||
1517 | * The "user->unix_inflight" variable is protected by the garbage | ||
1518 | * collection lock, and we just read it locklessly here. If you go | ||
1519 | * over the limit, there might be a tiny race in actually noticing | ||
1520 | * it across threads. Tough. | ||
1521 | */ | ||
1522 | static inline bool too_many_unix_fds(struct task_struct *p) | ||
1523 | { | ||
1524 | struct user_struct *user = current_user(); | ||
1525 | |||
1526 | if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) | ||
1527 | return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); | ||
1528 | return false; | ||
1529 | } | ||
1530 | |||
1502 | #define MAX_RECURSION_LEVEL 4 | 1531 | #define MAX_RECURSION_LEVEL 4 |
1503 | 1532 | ||
1504 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1533 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) |
@@ -1507,6 +1536,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1507 | unsigned char max_level = 0; | 1536 | unsigned char max_level = 0; |
1508 | int unix_sock_count = 0; | 1537 | int unix_sock_count = 0; |
1509 | 1538 | ||
1539 | if (too_many_unix_fds(current)) | ||
1540 | return -ETOOMANYREFS; | ||
1541 | |||
1510 | for (i = scm->fp->count - 1; i >= 0; i--) { | 1542 | for (i = scm->fp->count - 1; i >= 0; i--) { |
1511 | struct sock *sk = unix_get_socket(scm->fp->fp[i]); | 1543 | struct sock *sk = unix_get_socket(scm->fp->fp[i]); |
1512 | 1544 | ||
@@ -1528,10 +1560,8 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1528 | if (!UNIXCB(skb).fp) | 1560 | if (!UNIXCB(skb).fp) |
1529 | return -ENOMEM; | 1561 | return -ENOMEM; |
1530 | 1562 | ||
1531 | if (unix_sock_count) { | 1563 | for (i = scm->fp->count - 1; i >= 0; i--) |
1532 | for (i = scm->fp->count - 1; i >= 0; i--) | 1564 | unix_inflight(scm->fp->fp[i]); |
1533 | unix_inflight(scm->fp->fp[i]); | ||
1534 | } | ||
1535 | return max_level; | 1565 | return max_level; |
1536 | } | 1566 | } |
1537 | 1567 | ||
@@ -2078,8 +2108,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2078 | struct scm_cookie scm; | 2108 | struct scm_cookie scm; |
2079 | struct sock *sk = sock->sk; | 2109 | struct sock *sk = sock->sk; |
2080 | struct unix_sock *u = unix_sk(sk); | 2110 | struct unix_sock *u = unix_sk(sk); |
2081 | int noblock = flags & MSG_DONTWAIT; | 2111 | struct sk_buff *skb, *last; |
2082 | struct sk_buff *skb; | 2112 | long timeo; |
2083 | int err; | 2113 | int err; |
2084 | int peeked, skip; | 2114 | int peeked, skip; |
2085 | 2115 | ||
@@ -2087,30 +2117,38 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2087 | if (flags&MSG_OOB) | 2117 | if (flags&MSG_OOB) |
2088 | goto out; | 2118 | goto out; |
2089 | 2119 | ||
2090 | err = mutex_lock_interruptible(&u->readlock); | 2120 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
2091 | if (unlikely(err)) { | ||
2092 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN | ||
2093 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
2094 | */ | ||
2095 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
2096 | goto out; | ||
2097 | } | ||
2098 | 2121 | ||
2099 | skip = sk_peek_offset(sk, flags); | 2122 | do { |
2123 | mutex_lock(&u->readlock); | ||
2100 | 2124 | ||
2101 | skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); | 2125 | skip = sk_peek_offset(sk, flags); |
2102 | if (!skb) { | 2126 | skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err, |
2127 | &last); | ||
2128 | if (skb) | ||
2129 | break; | ||
2130 | |||
2131 | mutex_unlock(&u->readlock); | ||
2132 | |||
2133 | if (err != -EAGAIN) | ||
2134 | break; | ||
2135 | } while (timeo && | ||
2136 | !__skb_wait_for_more_packets(sk, &err, &timeo, last)); | ||
2137 | |||
2138 | if (!skb) { /* implies readlock unlocked */ | ||
2103 | unix_state_lock(sk); | 2139 | unix_state_lock(sk); |
2104 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ | 2140 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ |
2105 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && | 2141 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && |
2106 | (sk->sk_shutdown & RCV_SHUTDOWN)) | 2142 | (sk->sk_shutdown & RCV_SHUTDOWN)) |
2107 | err = 0; | 2143 | err = 0; |
2108 | unix_state_unlock(sk); | 2144 | unix_state_unlock(sk); |
2109 | goto out_unlock; | 2145 | goto out; |
2110 | } | 2146 | } |
2111 | 2147 | ||
2112 | wake_up_interruptible_sync_poll(&u->peer_wait, | 2148 | if (wq_has_sleeper(&u->peer_wait)) |
2113 | POLLOUT | POLLWRNORM | POLLWRBAND); | 2149 | wake_up_interruptible_sync_poll(&u->peer_wait, |
2150 | POLLOUT | POLLWRNORM | | ||
2151 | POLLWRBAND); | ||
2114 | 2152 | ||
2115 | if (msg->msg_name) | 2153 | if (msg->msg_name) |
2116 | unix_copy_addr(msg, skb->sk); | 2154 | unix_copy_addr(msg, skb->sk); |
@@ -2162,7 +2200,6 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2162 | 2200 | ||
2163 | out_free: | 2201 | out_free: |
2164 | skb_free_datagram(sk, skb); | 2202 | skb_free_datagram(sk, skb); |
2165 | out_unlock: | ||
2166 | mutex_unlock(&u->readlock); | 2203 | mutex_unlock(&u->readlock); |
2167 | out: | 2204 | out: |
2168 | return err; | 2205 | return err; |
@@ -2302,6 +2339,7 @@ again: | |||
2302 | 2339 | ||
2303 | if (signal_pending(current)) { | 2340 | if (signal_pending(current)) { |
2304 | err = sock_intr_errno(timeo); | 2341 | err = sock_intr_errno(timeo); |
2342 | scm_destroy(&scm); | ||
2305 | goto out; | 2343 | goto out; |
2306 | } | 2344 | } |
2307 | 2345 | ||