summaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 12:25:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 12:25:20 -0500
commit19e7b5f99474107e8d0b4b3e4652fa19ddb87efc (patch)
tree49f15b76c07b4c90d6fbd17b49d69017c81a4b58 /net/sctp/socket.c
parent26064ea409b4d4acb05903a36f3fe2fdccb3d8aa (diff)
parentce4c253573ad184603e0fa77876ba155b0cde46d (diff)
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: "All kinds of misc stuff, without any unifying topic, from various people. Neil's d_anon patch, several bugfixes, introduction of kvmalloc analogue of kmemdup_user(), extending bitfield.h to deal with fixed-endians, assorted cleanups all over the place..." * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (28 commits) alpha: osf_sys.c: use timespec64 where appropriate alpha: osf_sys.c: fix put_tv32 regression jffs2: Fix use-after-free bug in jffs2_iget()'s error handling path dcache: delete unused d_hash_mask dcache: subtract d_hash_shift from 32 in advance fs/buffer.c: fold init_buffer() into init_page_buffers() fs: fold __inode_permission() into inode_permission() fs: add RWF_APPEND sctp: use vmemdup_user() rather than badly open-coding memdup_user() snd_ctl_elem_init_enum_names(): switch to vmemdup_user() replace_user_tlv(): switch to vmemdup_user() new primitive: vmemdup_user() memdup_user(): switch to GFP_USER eventfd: fold eventfd_ctx_get() into eventfd_ctx_fileget() eventfd: fold eventfd_ctx_read() into eventfd_read() eventfd: convert to use anon_inode_getfd() nfs4file: get rid of pointless include of btrfs.h uvc_v4l2: clean copyin/copyout up vme_user: don't use __copy_..._user() usx2y: don't bother with memdup_user() for 16-byte structure ...
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c59
1 files changed, 11 insertions, 48 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 37382317fba4..737e551fbf67 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -968,13 +968,6 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
968 * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() 968 * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
969 * from userspace. 969 * from userspace.
970 * 970 *
971 * We don't use copy_from_user() for optimization: we first do the
972 * sanity checks (buffer size -fast- and access check-healthy
973 * pointer); if all of those succeed, then we can alloc the memory
974 * (expensive operation) needed to copy the data to kernel. Then we do
975 * the copying without checking the user space area
976 * (__copy_from_user()).
977 *
978 * On exit there is no need to do sockfd_put(), sys_setsockopt() does 971 * On exit there is no need to do sockfd_put(), sys_setsockopt() does
979 * it. 972 * it.
980 * 973 *
@@ -1004,25 +997,15 @@ static int sctp_setsockopt_bindx(struct sock *sk,
1004 if (unlikely(addrs_size <= 0)) 997 if (unlikely(addrs_size <= 0))
1005 return -EINVAL; 998 return -EINVAL;
1006 999
1007 /* Check the user passed a healthy pointer. */ 1000 kaddrs = vmemdup_user(addrs, addrs_size);
1008 if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) 1001 if (unlikely(IS_ERR(kaddrs)))
1009 return -EFAULT; 1002 return PTR_ERR(kaddrs);
1010
1011 /* Alloc space for the address array in kernel memory. */
1012 kaddrs = kmalloc(addrs_size, GFP_USER | __GFP_NOWARN);
1013 if (unlikely(!kaddrs))
1014 return -ENOMEM;
1015
1016 if (__copy_from_user(kaddrs, addrs, addrs_size)) {
1017 kfree(kaddrs);
1018 return -EFAULT;
1019 }
1020 1003
1021 /* Walk through the addrs buffer and count the number of addresses. */ 1004 /* Walk through the addrs buffer and count the number of addresses. */
1022 addr_buf = kaddrs; 1005 addr_buf = kaddrs;
1023 while (walk_size < addrs_size) { 1006 while (walk_size < addrs_size) {
1024 if (walk_size + sizeof(sa_family_t) > addrs_size) { 1007 if (walk_size + sizeof(sa_family_t) > addrs_size) {
1025 kfree(kaddrs); 1008 kvfree(kaddrs);
1026 return -EINVAL; 1009 return -EINVAL;
1027 } 1010 }
1028 1011
@@ -1033,7 +1016,7 @@ static int sctp_setsockopt_bindx(struct sock *sk,
1033 * causes the address buffer to overflow return EINVAL. 1016 * causes the address buffer to overflow return EINVAL.
1034 */ 1017 */
1035 if (!af || (walk_size + af->sockaddr_len) > addrs_size) { 1018 if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
1036 kfree(kaddrs); 1019 kvfree(kaddrs);
1037 return -EINVAL; 1020 return -EINVAL;
1038 } 1021 }
1039 addrcnt++; 1022 addrcnt++;
@@ -1063,7 +1046,7 @@ static int sctp_setsockopt_bindx(struct sock *sk,
1063 } 1046 }
1064 1047
1065out: 1048out:
1066 kfree(kaddrs); 1049 kvfree(kaddrs);
1067 1050
1068 return err; 1051 return err;
1069} 1052}
@@ -1321,13 +1304,6 @@ out_free:
1321 * land and invoking either sctp_connectx(). This is used for tunneling 1304 * land and invoking either sctp_connectx(). This is used for tunneling
1322 * the sctp_connectx() request through sctp_setsockopt() from userspace. 1305 * the sctp_connectx() request through sctp_setsockopt() from userspace.
1323 * 1306 *
1324 * We don't use copy_from_user() for optimization: we first do the
1325 * sanity checks (buffer size -fast- and access check-healthy
1326 * pointer); if all of those succeed, then we can alloc the memory
1327 * (expensive operation) needed to copy the data to kernel. Then we do
1328 * the copying without checking the user space area
1329 * (__copy_from_user()).
1330 *
1331 * On exit there is no need to do sockfd_put(), sys_setsockopt() does 1307 * On exit there is no need to do sockfd_put(), sys_setsockopt() does
1332 * it. 1308 * it.
1333 * 1309 *
@@ -1343,7 +1319,6 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
1343 sctp_assoc_t *assoc_id) 1319 sctp_assoc_t *assoc_id)
1344{ 1320{
1345 struct sockaddr *kaddrs; 1321 struct sockaddr *kaddrs;
1346 gfp_t gfp = GFP_KERNEL;
1347 int err = 0; 1322 int err = 0;
1348 1323
1349 pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", 1324 pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n",
@@ -1352,24 +1327,12 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
1352 if (unlikely(addrs_size <= 0)) 1327 if (unlikely(addrs_size <= 0))
1353 return -EINVAL; 1328 return -EINVAL;
1354 1329
1355 /* Check the user passed a healthy pointer. */ 1330 kaddrs = vmemdup_user(addrs, addrs_size);
1356 if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) 1331 if (unlikely(IS_ERR(kaddrs)))
1357 return -EFAULT; 1332 return PTR_ERR(kaddrs);
1358
1359 /* Alloc space for the address array in kernel memory. */
1360 if (sk->sk_socket->file)
1361 gfp = GFP_USER | __GFP_NOWARN;
1362 kaddrs = kmalloc(addrs_size, gfp);
1363 if (unlikely(!kaddrs))
1364 return -ENOMEM;
1365
1366 if (__copy_from_user(kaddrs, addrs, addrs_size)) {
1367 err = -EFAULT;
1368 } else {
1369 err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
1370 }
1371 1333
1372 kfree(kaddrs); 1334 err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
1335 kvfree(kaddrs);
1373 1336
1374 return err; 1337 return err;
1375} 1338}