diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9e91d6e5df63..981aaf8b6ace 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/crypto.h> | 64 | #include <linux/crypto.h> |
65 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
66 | #include <linux/file.h> | 66 | #include <linux/file.h> |
67 | #include <linux/compat.h> | ||
67 | 68 | ||
68 | #include <net/ip.h> | 69 | #include <net/ip.h> |
69 | #include <net/icmp.h> | 70 | #include <net/icmp.h> |
@@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk, | |||
1368 | /* | 1369 | /* |
1369 | * New (hopefully final) interface for the API. | 1370 | * New (hopefully final) interface for the API. |
1370 | * We use the sctp_getaddrs_old structure so that use-space library | 1371 | * We use the sctp_getaddrs_old structure so that use-space library |
1371 | * can avoid any unnecessary allocations. The only defferent part | 1372 | * can avoid any unnecessary allocations. The only different part |
1372 | * is that we store the actual length of the address buffer into the | 1373 | * is that we store the actual length of the address buffer into the |
1373 | * addrs_num structure member. That way we can re-use the existing | 1374 | * addrs_num structure member. That way we can re-use the existing |
1374 | * code. | 1375 | * code. |
1375 | */ | 1376 | */ |
1377 | #ifdef CONFIG_COMPAT | ||
1378 | struct compat_sctp_getaddrs_old { | ||
1379 | sctp_assoc_t assoc_id; | ||
1380 | s32 addr_num; | ||
1381 | compat_uptr_t addrs; /* struct sockaddr * */ | ||
1382 | }; | ||
1383 | #endif | ||
1384 | |||
1376 | static int sctp_getsockopt_connectx3(struct sock *sk, int len, | 1385 | static int sctp_getsockopt_connectx3(struct sock *sk, int len, |
1377 | char __user *optval, | 1386 | char __user *optval, |
1378 | int __user *optlen) | 1387 | int __user *optlen) |
@@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len, | |||
1381 | sctp_assoc_t assoc_id = 0; | 1390 | sctp_assoc_t assoc_id = 0; |
1382 | int err = 0; | 1391 | int err = 0; |
1383 | 1392 | ||
1384 | if (len < sizeof(param)) | 1393 | #ifdef CONFIG_COMPAT |
1385 | return -EINVAL; | 1394 | if (is_compat_task()) { |
1395 | struct compat_sctp_getaddrs_old param32; | ||
1386 | 1396 | ||
1387 | if (copy_from_user(¶m, optval, sizeof(param))) | 1397 | if (len < sizeof(param32)) |
1388 | return -EFAULT; | 1398 | return -EINVAL; |
1399 | if (copy_from_user(¶m32, optval, sizeof(param32))) | ||
1400 | return -EFAULT; | ||
1389 | 1401 | ||
1390 | err = __sctp_setsockopt_connectx(sk, | 1402 | param.assoc_id = param32.assoc_id; |
1391 | (struct sockaddr __user *)param.addrs, | 1403 | param.addr_num = param32.addr_num; |
1392 | param.addr_num, &assoc_id); | 1404 | param.addrs = compat_ptr(param32.addrs); |
1405 | } else | ||
1406 | #endif | ||
1407 | { | ||
1408 | if (len < sizeof(param)) | ||
1409 | return -EINVAL; | ||
1410 | if (copy_from_user(¶m, optval, sizeof(param))) | ||
1411 | return -EFAULT; | ||
1412 | } | ||
1393 | 1413 | ||
1414 | err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *) | ||
1415 | param.addrs, param.addr_num, | ||
1416 | &assoc_id); | ||
1394 | if (err == 0 || err == -EINPROGRESS) { | 1417 | if (err == 0 || err == -EINPROGRESS) { |
1395 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) | 1418 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) |
1396 | return -EFAULT; | 1419 | return -EFAULT; |
@@ -2092,12 +2115,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
2092 | sctp_skb_pull(skb, copied); | 2115 | sctp_skb_pull(skb, copied); |
2093 | skb_queue_head(&sk->sk_receive_queue, skb); | 2116 | skb_queue_head(&sk->sk_receive_queue, skb); |
2094 | 2117 | ||
2095 | /* When only partial message is copied to the user, increase | ||
2096 | * rwnd by that amount. If all the data in the skb is read, | ||
2097 | * rwnd is updated when the event is freed. | ||
2098 | */ | ||
2099 | if (!sctp_ulpevent_is_notification(event)) | ||
2100 | sctp_assoc_rwnd_increase(event->asoc, copied); | ||
2101 | goto out; | 2118 | goto out; |
2102 | } else if ((event->msg_flags & MSG_NOTIFICATION) || | 2119 | } else if ((event->msg_flags & MSG_NOTIFICATION) || |
2103 | (event->msg_flags & MSG_EOR)) | 2120 | (event->msg_flags & MSG_EOR)) |