diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 12:25:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 12:25:20 -0500 |
commit | 19e7b5f99474107e8d0b4b3e4652fa19ddb87efc (patch) | |
tree | 49f15b76c07b4c90d6fbd17b49d69017c81a4b58 /net/sctp/socket.c | |
parent | 26064ea409b4d4acb05903a36f3fe2fdccb3d8aa (diff) | |
parent | ce4c253573ad184603e0fa77876ba155b0cde46d (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.c | 59 |
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 | ||
1065 | out: | 1048 | out: |
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 | } |