diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/tipc/socket.c | 38 |
1 files changed, 15 insertions, 23 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 125dcb0737b2..d45a294f47e9 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -289,7 +289,7 @@ static int release(struct socket *sock) | |||
| 289 | if (buf == NULL) | 289 | if (buf == NULL) |
| 290 | break; | 290 | break; |
| 291 | atomic_dec(&tipc_queue_size); | 291 | atomic_dec(&tipc_queue_size); |
| 292 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) | 292 | if (TIPC_SKB_CB(buf)->handle != 0) |
| 293 | buf_discard(buf); | 293 | buf_discard(buf); |
| 294 | else { | 294 | else { |
| 295 | if ((sock->state == SS_CONNECTING) || | 295 | if ((sock->state == SS_CONNECTING) || |
| @@ -917,9 +917,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
| 917 | 917 | ||
| 918 | /* Catch invalid receive requests */ | 918 | /* Catch invalid receive requests */ |
| 919 | 919 | ||
| 920 | if (m->msg_iovlen != 1) | ||
| 921 | return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ | ||
| 922 | |||
| 923 | if (unlikely(!buf_len)) | 920 | if (unlikely(!buf_len)) |
| 924 | return -EINVAL; | 921 | return -EINVAL; |
| 925 | 922 | ||
| @@ -991,11 +988,10 @@ restart: | |||
| 991 | sz = buf_len; | 988 | sz = buf_len; |
| 992 | m->msg_flags |= MSG_TRUNC; | 989 | m->msg_flags |= MSG_TRUNC; |
| 993 | } | 990 | } |
| 994 | if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), | 991 | res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg), |
| 995 | sz))) { | 992 | m->msg_iov, sz); |
| 996 | res = -EFAULT; | 993 | if (res) |
| 997 | goto exit; | 994 | goto exit; |
| 998 | } | ||
| 999 | res = sz; | 995 | res = sz; |
| 1000 | } else { | 996 | } else { |
| 1001 | if ((sock->state == SS_READY) || | 997 | if ((sock->state == SS_READY) || |
| @@ -1041,16 +1037,11 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1041 | unsigned int sz; | 1037 | unsigned int sz; |
| 1042 | int sz_to_copy, target, needed; | 1038 | int sz_to_copy, target, needed; |
| 1043 | int sz_copied = 0; | 1039 | int sz_copied = 0; |
| 1044 | char __user *crs = m->msg_iov->iov_base; | ||
| 1045 | unsigned char *buf_crs; | ||
| 1046 | u32 err; | 1040 | u32 err; |
| 1047 | int res = 0; | 1041 | int res = 0; |
| 1048 | 1042 | ||
| 1049 | /* Catch invalid receive attempts */ | 1043 | /* Catch invalid receive attempts */ |
| 1050 | 1044 | ||
| 1051 | if (m->msg_iovlen != 1) | ||
| 1052 | return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ | ||
| 1053 | |||
| 1054 | if (unlikely(!buf_len)) | 1045 | if (unlikely(!buf_len)) |
| 1055 | return -EINVAL; | 1046 | return -EINVAL; |
| 1056 | 1047 | ||
| @@ -1112,24 +1103,25 @@ restart: | |||
| 1112 | /* Capture message data (if valid) & compute return value (always) */ | 1103 | /* Capture message data (if valid) & compute return value (always) */ |
| 1113 | 1104 | ||
| 1114 | if (!err) { | 1105 | if (!err) { |
| 1115 | buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); | 1106 | u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle); |
| 1116 | sz = (unsigned char *)msg + msg_size(msg) - buf_crs; | ||
| 1117 | 1107 | ||
| 1108 | sz -= offset; | ||
| 1118 | needed = (buf_len - sz_copied); | 1109 | needed = (buf_len - sz_copied); |
| 1119 | sz_to_copy = (sz <= needed) ? sz : needed; | 1110 | sz_to_copy = (sz <= needed) ? sz : needed; |
| 1120 | if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { | 1111 | |
| 1121 | res = -EFAULT; | 1112 | res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset, |
| 1113 | m->msg_iov, sz_to_copy); | ||
| 1114 | if (res) | ||
| 1122 | goto exit; | 1115 | goto exit; |
| 1123 | } | 1116 | |
| 1124 | sz_copied += sz_to_copy; | 1117 | sz_copied += sz_to_copy; |
| 1125 | 1118 | ||
| 1126 | if (sz_to_copy < sz) { | 1119 | if (sz_to_copy < sz) { |
| 1127 | if (!(flags & MSG_PEEK)) | 1120 | if (!(flags & MSG_PEEK)) |
| 1128 | TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; | 1121 | TIPC_SKB_CB(buf)->handle = |
| 1122 | (void *)(unsigned long)(offset + sz_to_copy); | ||
| 1129 | goto exit; | 1123 | goto exit; |
| 1130 | } | 1124 | } |
| 1131 | |||
| 1132 | crs += sz_to_copy; | ||
| 1133 | } else { | 1125 | } else { |
| 1134 | if (sz_copied != 0) | 1126 | if (sz_copied != 0) |
| 1135 | goto exit; /* can't add error msg to valid data */ | 1127 | goto exit; /* can't add error msg to valid data */ |
| @@ -1256,7 +1248,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1256 | 1248 | ||
| 1257 | /* Enqueue message (finally!) */ | 1249 | /* Enqueue message (finally!) */ |
| 1258 | 1250 | ||
| 1259 | TIPC_SKB_CB(buf)->handle = msg_data(msg); | 1251 | TIPC_SKB_CB(buf)->handle = 0; |
| 1260 | atomic_inc(&tipc_queue_size); | 1252 | atomic_inc(&tipc_queue_size); |
| 1261 | __skb_queue_tail(&sk->sk_receive_queue, buf); | 1253 | __skb_queue_tail(&sk->sk_receive_queue, buf); |
| 1262 | 1254 | ||
| @@ -1608,7 +1600,7 @@ restart: | |||
| 1608 | buf = __skb_dequeue(&sk->sk_receive_queue); | 1600 | buf = __skb_dequeue(&sk->sk_receive_queue); |
| 1609 | if (buf) { | 1601 | if (buf) { |
| 1610 | atomic_dec(&tipc_queue_size); | 1602 | atomic_dec(&tipc_queue_size); |
| 1611 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { | 1603 | if (TIPC_SKB_CB(buf)->handle != 0) { |
| 1612 | buf_discard(buf); | 1604 | buf_discard(buf); |
| 1613 | goto restart; | 1605 | goto restart; |
| 1614 | } | 1606 | } |
