diff options
-rw-r--r-- | net/sctp/socket.c | 59 |
1 files changed, 11 insertions, 48 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3204a9b29407..c2cccc9902d6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -970,13 +970,6 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw) | |||
970 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() | 970 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
971 | * from userspace. | 971 | * from userspace. |
972 | * | 972 | * |
973 | * We don't use copy_from_user() for optimization: we first do the | ||
974 | * sanity checks (buffer size -fast- and access check-healthy | ||
975 | * pointer); if all of those succeed, then we can alloc the memory | ||
976 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
977 | * the copying without checking the user space area | ||
978 | * (__copy_from_user()). | ||
979 | * | ||
980 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | 973 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does |
981 | * it. | 974 | * it. |
982 | * | 975 | * |
@@ -1006,25 +999,15 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1006 | if (unlikely(addrs_size <= 0)) | 999 | if (unlikely(addrs_size <= 0)) |
1007 | return -EINVAL; | 1000 | return -EINVAL; |
1008 | 1001 | ||
1009 | /* Check the user passed a healthy pointer. */ | 1002 | kaddrs = vmemdup_user(addrs, addrs_size); |
1010 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | 1003 | if (unlikely(IS_ERR(kaddrs))) |
1011 | return -EFAULT; | 1004 | return PTR_ERR(kaddrs); |
1012 | |||
1013 | /* Alloc space for the address array in kernel memory. */ | ||
1014 | kaddrs = kmalloc(addrs_size, GFP_USER | __GFP_NOWARN); | ||
1015 | if (unlikely(!kaddrs)) | ||
1016 | return -ENOMEM; | ||
1017 | |||
1018 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
1019 | kfree(kaddrs); | ||
1020 | return -EFAULT; | ||
1021 | } | ||
1022 | 1005 | ||
1023 | /* Walk through the addrs buffer and count the number of addresses. */ | 1006 | /* Walk through the addrs buffer and count the number of addresses. */ |
1024 | addr_buf = kaddrs; | 1007 | addr_buf = kaddrs; |
1025 | while (walk_size < addrs_size) { | 1008 | while (walk_size < addrs_size) { |
1026 | if (walk_size + sizeof(sa_family_t) > addrs_size) { | 1009 | if (walk_size + sizeof(sa_family_t) > addrs_size) { |
1027 | kfree(kaddrs); | 1010 | kvfree(kaddrs); |
1028 | return -EINVAL; | 1011 | return -EINVAL; |
1029 | } | 1012 | } |
1030 | 1013 | ||
@@ -1035,7 +1018,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1035 | * causes the address buffer to overflow return EINVAL. | 1018 | * causes the address buffer to overflow return EINVAL. |
1036 | */ | 1019 | */ |
1037 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | 1020 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { |
1038 | kfree(kaddrs); | 1021 | kvfree(kaddrs); |
1039 | return -EINVAL; | 1022 | return -EINVAL; |
1040 | } | 1023 | } |
1041 | addrcnt++; | 1024 | addrcnt++; |
@@ -1065,7 +1048,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1065 | } | 1048 | } |
1066 | 1049 | ||
1067 | out: | 1050 | out: |
1068 | kfree(kaddrs); | 1051 | kvfree(kaddrs); |
1069 | 1052 | ||
1070 | return err; | 1053 | return err; |
1071 | } | 1054 | } |
@@ -1323,13 +1306,6 @@ out_free: | |||
1323 | * land and invoking either sctp_connectx(). This is used for tunneling | 1306 | * land and invoking either sctp_connectx(). This is used for tunneling |
1324 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | 1307 | * the sctp_connectx() request through sctp_setsockopt() from userspace. |
1325 | * | 1308 | * |
1326 | * We don't use copy_from_user() for optimization: we first do the | ||
1327 | * sanity checks (buffer size -fast- and access check-healthy | ||
1328 | * pointer); if all of those succeed, then we can alloc the memory | ||
1329 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
1330 | * the copying without checking the user space area | ||
1331 | * (__copy_from_user()). | ||
1332 | * | ||
1333 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | 1309 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does |
1334 | * it. | 1310 | * it. |
1335 | * | 1311 | * |
@@ -1345,7 +1321,6 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1345 | sctp_assoc_t *assoc_id) | 1321 | sctp_assoc_t *assoc_id) |
1346 | { | 1322 | { |
1347 | struct sockaddr *kaddrs; | 1323 | struct sockaddr *kaddrs; |
1348 | gfp_t gfp = GFP_KERNEL; | ||
1349 | int err = 0; | 1324 | int err = 0; |
1350 | 1325 | ||
1351 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", | 1326 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", |
@@ -1354,24 +1329,12 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1354 | if (unlikely(addrs_size <= 0)) | 1329 | if (unlikely(addrs_size <= 0)) |
1355 | return -EINVAL; | 1330 | return -EINVAL; |
1356 | 1331 | ||
1357 | /* Check the user passed a healthy pointer. */ | 1332 | kaddrs = vmemdup_user(addrs, addrs_size); |
1358 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | 1333 | if (unlikely(IS_ERR(kaddrs))) |
1359 | return -EFAULT; | 1334 | return PTR_ERR(kaddrs); |
1360 | |||
1361 | /* Alloc space for the address array in kernel memory. */ | ||
1362 | if (sk->sk_socket->file) | ||
1363 | gfp = GFP_USER | __GFP_NOWARN; | ||
1364 | kaddrs = kmalloc(addrs_size, gfp); | ||
1365 | if (unlikely(!kaddrs)) | ||
1366 | return -ENOMEM; | ||
1367 | |||
1368 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
1369 | err = -EFAULT; | ||
1370 | } else { | ||
1371 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); | ||
1372 | } | ||
1373 | 1335 | ||
1374 | kfree(kaddrs); | 1336 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1337 | kvfree(kaddrs); | ||
1375 | 1338 | ||
1376 | return err; | 1339 | return err; |
1377 | } | 1340 | } |