From patchwork Tue Sep 15 14:55:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364773 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brf2V0Bm4z9sTH for ; Wed, 16 Sep 2020 09:05:06 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727379AbgIOXE5 convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:04:57 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([185.58.86.151]:27881 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727277AbgIOOzX (ORCPT ); Tue, 15 Sep 2020 10:55:23 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-73-k-A8mJujN9e8Iji4iGTvBQ-1; Tue, 15 Sep 2020 15:55:09 +0100 X-MC-Unique: k-A8mJujN9e8Iji4iGTvBQ-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:09 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:09 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 1/9 next] mm:process_vm_access Call import_iovec() instead of rw_copy_check_uvector() Thread-Topic: [PATCH 1/9 next] mm:process_vm_access Call import_iovec() instead of rw_copy_check_uvector() Thread-Index: AdaLbkkTBW5in2pQRDCVHbW9ZQK6vQ== Date: Tue, 15 Sep 2020 14:55:08 +0000 Message-ID: Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This is the only direct call of rw_copy_check_uvector(). Removing it lets rw_copy_check_uvector() be inlined into import_iovec() and the horrid calling conventions fixed. Signed-off-by: David Laight --- mm/process_vm_access.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 29c052099aff..1cc3d6f66b31 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -264,7 +264,7 @@ static ssize_t process_vm_rw(pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; - struct iov_iter iter; + struct iov_iter iter_l, iter_r; ssize_t rc; int dir = vm_write ? WRITE : READ; @@ -272,23 +272,24 @@ static ssize_t process_vm_rw(pid_t pid, return -EINVAL; /* Check iovecs */ - rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter); + rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); if (rc < 0) return rc; - if (!iov_iter_count(&iter)) + if (!iov_iter_count(&iter_l)) goto free_iovecs; - rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, - iovstack_r, &iov_r); + rc = import_iovec(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, &iov_r, &iter_r); if (rc <= 0) goto free_iovecs; - rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, + flags, vm_write); free_iovecs: if (iov_r != iovstack_r) kfree(iov_r); - kfree(iov_l); + if (iov_l != iovstack_l) + kfree(iov_l); return rc; } @@ -322,30 +323,30 @@ compat_process_vm_rw(compat_pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; - struct iov_iter iter; + struct iov_iter iter_l, iter_r; ssize_t rc = -EFAULT; int dir = vm_write ? WRITE : READ; if (flags != 0) return -EINVAL; - rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter); + rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); if (rc < 0) return rc; - if (!iov_iter_count(&iter)) + if (!iov_iter_count(&iter_l)) goto free_iovecs; - rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, - UIO_FASTIOV, iovstack_r, - &iov_r); + rc = compat_import_iovec(0, rvec, riovcnt, UIO_FASTIOV, &iov_r, &iter_r); if (rc <= 0) goto free_iovecs; - rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, + flags, vm_write); free_iovecs: if (iov_r != iovstack_r) kfree(iov_r); - kfree(iov_l); + if (iov_l != iovstack_l) + kfree(iov_l); return rc; } From patchwork Tue Sep 15 14:55:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364454 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BrRBv6NQlz9sTt for ; Wed, 16 Sep 2020 00:56:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727373AbgIOO4U convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 10:56:20 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([207.82.80.151]:23630 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727345AbgIOOz0 (ORCPT ); Tue, 15 Sep 2020 10:55:26 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-288-mOzGhIWQMiei3nO_jMqMVw-1; Tue, 15 Sep 2020 15:55:14 +0100 X-MC-Unique: mOzGhIWQMiei3nO_jMqMVw-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:13 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:13 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 2/9 next] fs: Move rw_copy_check_uvector() into lib/iov_iter.c and make static. Thread-Topic: [PATCH 2/9 next] fs: Move rw_copy_check_uvector() into lib/iov_iter.c and make static. Thread-Index: AdaLbiWprMA2fZGETrKSDEjStPX0pA== Date: Tue, 15 Sep 2020 14:55:13 +0000 Message-ID: <9d35fdcc154749d8905d66b9419c4817@AcuMS.aculab.com> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This lets the compiler inline it into import_iovec() generating much better code. Signed-off-by: David Laight Reviewed-by: Christoph Hellwig --- fs/read_write.c | 179 ----------------------------------------- include/linux/compat.h | 6 -- include/linux/fs.h | 5 -- lib/iov_iter.c | 178 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 190 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 5db58b8c78d0..e5e891a88442 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -752,185 +752,6 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, return ret; } -/** - * rw_copy_check_uvector() - Copy an array of &struct iovec from userspace - * into the kernel and check that it is valid. - * - * @type: One of %CHECK_IOVEC_ONLY, %READ, or %WRITE. - * @uvector: Pointer to the userspace array. - * @nr_segs: Number of elements in userspace array. - * @fast_segs: Number of elements in @fast_pointer. - * @fast_pointer: Pointer to (usually small on-stack) kernel array. - * @ret_pointer: (output parameter) Pointer to a variable that will point to - * either @fast_pointer, a newly allocated kernel array, or NULL, - * depending on which array was used. - * - * This function copies an array of &struct iovec of @nr_segs from - * userspace into the kernel and checks that each element is valid (e.g. - * it does not point to a kernel address or cause overflow by being too - * large, etc.). - * - * As an optimization, the caller may provide a pointer to a small - * on-stack array in @fast_pointer, typically %UIO_FASTIOV elements long - * (the size of this array, or 0 if unused, should be given in @fast_segs). - * - * @ret_pointer will always point to the array that was used, so the - * caller must take care not to call kfree() on it e.g. in case the - * @fast_pointer array was used and it was allocated on the stack. - * - * Return: The total number of bytes covered by the iovec array on success - * or a negative error code on error. - */ -ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - unsigned long nr_segs, unsigned long fast_segs, - struct iovec *fast_pointer, - struct iovec **ret_pointer) -{ - unsigned long seg; - ssize_t ret; - struct iovec *iov = fast_pointer; - - /* - * SuS says "The readv() function *may* fail if the iovcnt argument - * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... - */ - if (nr_segs == 0) { - ret = 0; - goto out; - } - - /* - * First get the "struct iovec" from user memory and - * verify all the pointers - */ - if (nr_segs > UIO_MAXIOV) { - ret = -EINVAL; - goto out; - } - if (nr_segs > fast_segs) { - iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); - if (iov == NULL) { - ret = -ENOMEM; - goto out; - } - } - if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) { - ret = -EFAULT; - goto out; - } - - /* - * According to the Single Unix Specification we should return EINVAL - * if an element length is < 0 when cast to ssize_t or if the - * total length would overflow the ssize_t return value of the - * system call. - * - * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the - * overflow case. - */ - ret = 0; - for (seg = 0; seg < nr_segs; seg++) { - void __user *buf = iov[seg].iov_base; - ssize_t len = (ssize_t)iov[seg].iov_len; - - /* see if we we're about to use an invalid len or if - * it's about to overflow ssize_t */ - if (len < 0) { - ret = -EINVAL; - goto out; - } - if (type >= 0 - && unlikely(!access_ok(buf, len))) { - ret = -EFAULT; - goto out; - } - if (len > MAX_RW_COUNT - ret) { - len = MAX_RW_COUNT - ret; - iov[seg].iov_len = len; - } - ret += len; - } -out: - *ret_pointer = iov; - return ret; -} - -#ifdef CONFIG_COMPAT -ssize_t compat_rw_copy_check_uvector(int type, - const struct compat_iovec __user *uvector, unsigned long nr_segs, - unsigned long fast_segs, struct iovec *fast_pointer, - struct iovec **ret_pointer) -{ - compat_ssize_t tot_len; - struct iovec *iov = *ret_pointer = fast_pointer; - ssize_t ret = 0; - int seg; - - /* - * SuS says "The readv() function *may* fail if the iovcnt argument - * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... - */ - if (nr_segs == 0) - goto out; - - ret = -EINVAL; - if (nr_segs > UIO_MAXIOV) - goto out; - if (nr_segs > fast_segs) { - ret = -ENOMEM; - iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); - if (iov == NULL) - goto out; - } - *ret_pointer = iov; - - ret = -EFAULT; - if (!access_ok(uvector, nr_segs*sizeof(*uvector))) - goto out; - - /* - * Single unix specification: - * We should -EINVAL if an element length is not >= 0 and fitting an - * ssize_t. - * - * In Linux, the total length is limited to MAX_RW_COUNT, there is - * no overflow possibility. - */ - tot_len = 0; - ret = -EINVAL; - for (seg = 0; seg < nr_segs; seg++) { - compat_uptr_t buf; - compat_ssize_t len; - - if (__get_user(len, &uvector->iov_len) || - __get_user(buf, &uvector->iov_base)) { - ret = -EFAULT; - goto out; - } - if (len < 0) /* size_t not fitting in compat_ssize_t .. */ - goto out; - if (type >= 0 && - !access_ok(compat_ptr(buf), len)) { - ret = -EFAULT; - goto out; - } - if (len > MAX_RW_COUNT - tot_len) - len = MAX_RW_COUNT - tot_len; - tot_len += len; - iov->iov_base = compat_ptr(buf); - iov->iov_len = (compat_size_t) len; - uvector++; - iov++; - } - ret = tot_len; - -out: - return ret; -} -#endif - static ssize_t do_iter_read(struct file *file, struct iov_iter *iter, loff_t *pos, rwf_t flags) { diff --git a/include/linux/compat.h b/include/linux/compat.h index b354ce58966e..64bf699e8735 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -451,12 +451,6 @@ extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request, struct epoll_event; /* fortunately, this one is fixed-layout */ -extern ssize_t compat_rw_copy_check_uvector(int type, - const struct compat_iovec __user *uvector, - unsigned long nr_segs, - unsigned long fast_segs, struct iovec *fast_pointer, - struct iovec **ret_pointer); - extern void __user *compat_alloc_user_space(unsigned long len); int compat_restore_altstack(const compat_stack_t __user *uss); diff --git a/include/linux/fs.h b/include/linux/fs.h index 7519ae003a08..9571114f5036 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1887,11 +1887,6 @@ static inline int call_mmap(struct file *file, struct vm_area_struct *vma) return file->f_op->mmap(file, vma); } -ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - unsigned long nr_segs, unsigned long fast_segs, - struct iovec *fast_pointer, - struct iovec **ret_pointer); - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t vfs_readv(struct file *, const struct iovec __user *, diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 5e40786c8f12..59b71dc24e02 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1650,6 +1650,111 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) } EXPORT_SYMBOL(dup_iter); + +/** + * rw_copy_check_uvector() - Copy an array of &struct iovec from userspace + * into the kernel and check that it is valid. + * + * @type: One of %CHECK_IOVEC_ONLY, %READ, or %WRITE. + * @uvector: Pointer to the userspace array. + * @nr_segs: Number of elements in userspace array. + * @fast_segs: Number of elements in @fast_pointer. + * @fast_pointer: Pointer to (usually small on-stack) kernel array. + * @ret_pointer: (output parameter) Pointer to a variable that will point to + * either @fast_pointer, a newly allocated kernel array, or NULL, + * depending on which array was used. + * + * This function copies an array of &struct iovec of @nr_segs from + * userspace into the kernel and checks that each element is valid (e.g. + * it does not point to a kernel address or cause overflow by being too + * large, etc.). + * + * As an optimization, the caller may provide a pointer to a small + * on-stack array in @fast_pointer, typically %UIO_FASTIOV elements long + * (the size of this array, or 0 if unused, should be given in @fast_segs). + * + * @ret_pointer will always point to the array that was used, so the + * caller must take care not to call kfree() on it e.g. in case the + * @fast_pointer array was used and it was allocated on the stack. + * + * Return: The total number of bytes covered by the iovec array on success + * or a negative error code on error. + */ +static ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, + unsigned long nr_segs, unsigned long fast_segs, + struct iovec *fast_pointer, + struct iovec **ret_pointer) +{ + unsigned long seg; + ssize_t ret; + struct iovec *iov = fast_pointer; + + /* + * SuS says "The readv() function *may* fail if the iovcnt argument + * was less than or equal to 0, or greater than {IOV_MAX}. Linux has + * traditionally returned zero for zero segments, so... + */ + if (nr_segs == 0) { + ret = 0; + goto out; + } + + /* + * First get the "struct iovec" from user memory and + * verify all the pointers + */ + if (nr_segs > UIO_MAXIOV) { + ret = -EINVAL; + goto out; + } + if (nr_segs > fast_segs) { + iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); + if (iov == NULL) { + ret = -ENOMEM; + goto out; + } + } + if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) { + ret = -EFAULT; + goto out; + } + + /* + * According to the Single Unix Specification we should return EINVAL + * if an element length is < 0 when cast to ssize_t or if the + * total length would overflow the ssize_t return value of the + * system call. + * + * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the + * overflow case. + */ + ret = 0; + for (seg = 0; seg < nr_segs; seg++) { + void __user *buf = iov[seg].iov_base; + ssize_t len = (ssize_t)iov[seg].iov_len; + + /* see if we we're about to use an invalid len or if + * it's about to overflow ssize_t */ + if (len < 0) { + ret = -EINVAL; + goto out; + } + if (type >= 0 + && unlikely(!access_ok(buf, len))) { + ret = -EFAULT; + goto out; + } + if (len > MAX_RW_COUNT - ret) { + len = MAX_RW_COUNT - ret; + iov[seg].iov_len = len; + } + ret += len; + } +out: + *ret_pointer = iov; + return ret; +} + /** * import_iovec() - Copy an array of &struct iovec from userspace * into the kernel, check that it is valid, and initialize a new @@ -1695,6 +1800,79 @@ EXPORT_SYMBOL(import_iovec); #ifdef CONFIG_COMPAT #include +static ssize_t compat_rw_copy_check_uvector(int type, + const struct compat_iovec __user *uvector, unsigned long nr_segs, + unsigned long fast_segs, struct iovec *fast_pointer, + struct iovec **ret_pointer) +{ + compat_ssize_t tot_len; + struct iovec *iov = *ret_pointer = fast_pointer; + ssize_t ret = 0; + int seg; + + /* + * SuS says "The readv() function *may* fail if the iovcnt argument + * was less than or equal to 0, or greater than {IOV_MAX}. Linux has + * traditionally returned zero for zero segments, so... + */ + if (nr_segs == 0) + goto out; + + ret = -EINVAL; + if (nr_segs > UIO_MAXIOV) + goto out; + if (nr_segs > fast_segs) { + ret = -ENOMEM; + iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); + if (iov == NULL) + goto out; + } + *ret_pointer = iov; + + ret = -EFAULT; + if (!access_ok(uvector, nr_segs*sizeof(*uvector))) + goto out; + + /* + * Single unix specification: + * We should -EINVAL if an element length is not >= 0 and fitting an + * ssize_t. + * + * In Linux, the total length is limited to MAX_RW_COUNT, there is + * no overflow possibility. + */ + tot_len = 0; + ret = -EINVAL; + for (seg = 0; seg < nr_segs; seg++) { + compat_uptr_t buf; + compat_ssize_t len; + + if (__get_user(len, &uvector->iov_len) || + __get_user(buf, &uvector->iov_base)) { + ret = -EFAULT; + goto out; + } + if (len < 0) /* size_t not fitting in compat_ssize_t .. */ + goto out; + if (type >= 0 && + !access_ok(compat_ptr(buf), len)) { + ret = -EFAULT; + goto out; + } + if (len > MAX_RW_COUNT - tot_len) + len = MAX_RW_COUNT - tot_len; + tot_len += len; + iov->iov_base = compat_ptr(buf); + iov->iov_len = (compat_size_t) len; + uvector++; + iov++; + } + ret = tot_len; + +out: + return ret; +} + ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, From patchwork Tue Sep 15 14:55:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364772 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brf1c4GYcz9sTN for ; Wed, 16 Sep 2020 09:04:20 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727348AbgIOXER convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:04:17 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([185.58.86.151]:36299 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727343AbgIOOzZ (ORCPT ); Tue, 15 Sep 2020 10:55:25 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-249-wtWq1SXZOrCYpxXqKQvBlw-1; Tue, 15 Sep 2020 15:55:18 +0100 X-MC-Unique: wtWq1SXZOrCYpxXqKQvBlw-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:17 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:17 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 3/9 next] lib/iov_iter: Improved function for importing iovec[] from userpace. Thread-Topic: [PATCH 3/9 next] lib/iov_iter: Improved function for importing iovec[] from userpace. Thread-Index: AdaLbgrHxt5yVpCaR/OQiuIAS4DQuQ== Date: Tue, 15 Sep 2020 14:55:17 +0000 Message-ID: Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org import_iovec() has a 'pointer by reference' parameter to pass in the (on-stack) iov[] cache and return the address of a larger copy that the caller must free. This is non-intuitive, faffy to setup, and not that efficient. Instead just pass in the address of the cache and return the address to free (on success) or PTR_ERR() (on error). Additionally the size of the 'cache' is nominally variable but is often specified in a different source file to the actual cache passed. Use a structure for the 'cache' so that the compiler checks its size. To avoid having to change everything at once the 'struct iov_iter *' is passed to rw_copy_check_uvector() which is renamed iovec_import() and returns the malloced address on success. import_iovec() is then implemented using iovec_import(). The optimisation for zero length iov[] is removed (they'll now do a zero length copy_from_user() before returning success). The check for oversize iov[] is moved inside the check for iov[] larger than the supplied cache. The same changes have been made to the compat versions. Signed-off-by: David Laight --- include/linux/uio.h | 14 ++++ lib/iov_iter.c | 194 ++++++++++++++++++++------------------------ 2 files changed, 100 insertions(+), 108 deletions(-) diff --git a/include/linux/uio.h b/include/linux/uio.h index 3835a8a8e9ea..d26482d348f3 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -266,15 +266,29 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp, struct iov_iter *i); +struct iovec_cache { + struct iovec iov[UIO_FASTIOV]; +}; + ssize_t import_iovec(int type, const struct iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i); +struct iovec *iovec_import(int type, const struct iovec __user * uvector, + unsigned int nr_segs, struct iovec_cache *cache, + struct iov_iter *i); + #ifdef CONFIG_COMPAT struct compat_iovec; ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i); + +struct iovec *compat_iovec_import(int type, + const struct compat_iovec __user * uvector, + unsigned int nr_segs, struct iovec_cache *cache, + struct iov_iter *i); + #endif int import_single_range(int type, void __user *buf, size_t len, diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 59b71dc24e02..743bddfcbb05 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1650,69 +1650,50 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) } EXPORT_SYMBOL(dup_iter); - /** - * rw_copy_check_uvector() - Copy an array of &struct iovec from userspace - * into the kernel and check that it is valid. + * iovec_import() - Copy an array of &struct iovec from userspace + * into the kernel, check that it is valid, and initialize a new + * &struct iov_iter iterator to access it. * - * @type: One of %CHECK_IOVEC_ONLY, %READ, or %WRITE. + * @type: One of %CHECK_IOVEC_ONLY, %READ or %WRITE. * @uvector: Pointer to the userspace array. * @nr_segs: Number of elements in userspace array. - * @fast_segs: Number of elements in @fast_pointer. - * @fast_pointer: Pointer to (usually small on-stack) kernel array. - * @ret_pointer: (output parameter) Pointer to a variable that will point to - * either @fast_pointer, a newly allocated kernel array, or NULL, - * depending on which array was used. - * - * This function copies an array of &struct iovec of @nr_segs from - * userspace into the kernel and checks that each element is valid (e.g. - * it does not point to a kernel address or cause overflow by being too - * large, etc.). - * - * As an optimization, the caller may provide a pointer to a small - * on-stack array in @fast_pointer, typically %UIO_FASTIOV elements long - * (the size of this array, or 0 if unused, should be given in @fast_segs). - * - * @ret_pointer will always point to the array that was used, so the - * caller must take care not to call kfree() on it e.g. in case the - * @fast_pointer array was used and it was allocated on the stack. + * @fast_segs: Number of elements in @iov. + * @fast_pointer: Pointer to (usually small on-stack) kernel array. + * @i: Pointer to iterator that will be initialized on success. * - * Return: The total number of bytes covered by the iovec array on success - * or a negative error code on error. + * Return: Negative error code on error. + * Success address of iovec array array to free if there were + * more than fast_segs items, NULL otherwise. */ -static ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - unsigned long nr_segs, unsigned long fast_segs, - struct iovec *fast_pointer, - struct iovec **ret_pointer) +struct iovec *iovec_import(int type, const struct iovec __user * uvector, + unsigned int nr_segs, struct iovec_cache *cache, + struct iov_iter *i) { - unsigned long seg; - ssize_t ret; - struct iovec *iov = fast_pointer; + struct iovec *iov = cache->iov; + struct iovec *iov_kmalloc = NULL; + unsigned int seg; + size_t count; + int ret; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... + * traditionally returned zero for zero segments. + * No need to optimise... */ - if (nr_segs == 0) { - ret = 0; - goto out; - } /* * First get the "struct iovec" from user memory and * verify all the pointers */ - if (nr_segs > UIO_MAXIOV) { - ret = -EINVAL; - goto out; - } - if (nr_segs > fast_segs) { + if (!cache || nr_segs > ARRAY_SIZE(cache->iov)) { + if (nr_segs > UIO_MAXIOV) + return ERR_PTR(-EINVAL); iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); - if (iov == NULL) { - ret = -ENOMEM; - goto out; - } + if (iov == NULL) + return ERR_PTR(-ENOMEM); + iov_kmalloc = iov; } if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) { ret = -EFAULT; @@ -1728,7 +1709,7 @@ static ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvect * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the * overflow case. */ - ret = 0; + count = 0; for (seg = 0; seg < nr_segs; seg++) { void __user *buf = iov[seg].iov_base; ssize_t len = (ssize_t)iov[seg].iov_len; @@ -1744,16 +1725,21 @@ static ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvect ret = -EFAULT; goto out; } - if (len > MAX_RW_COUNT - ret) { - len = MAX_RW_COUNT - ret; + if (len > MAX_RW_COUNT - count) { + len = MAX_RW_COUNT - count; iov[seg].iov_len = len; } - ret += len; + count += len; } + + iov_iter_init(i, type, iov, nr_segs, count); + return iov_kmalloc; + out: - *ret_pointer = iov; - return ret; + kfree(iov_kmalloc); + return ERR_PTR(ret); } +EXPORT_SYMBOL(iovec_import); /** * import_iovec() - Copy an array of &struct iovec from userspace @@ -1781,57 +1767,47 @@ ssize_t import_iovec(int type, const struct iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i) { - ssize_t n; - struct iovec *p; - n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, - *iov, &p); - if (n < 0) { - if (p != *iov) - kfree(p); + struct iovec *iov_kmalloc; + + iov_kmalloc = iovec_import(type, uvector, nr_segs, + fast_segs >= UIO_FASTIOV ? (void *)*iov : NULL, i); + + if (IS_ERR(iov_kmalloc)) { *iov = NULL; - return n; + return PTR_ERR(iov_kmalloc); } - iov_iter_init(i, type, p, nr_segs, n); - *iov = p == *iov ? NULL : p; - return n; + + *iov = iov_kmalloc; + return i->count; } EXPORT_SYMBOL(import_iovec); #ifdef CONFIG_COMPAT #include -static ssize_t compat_rw_copy_check_uvector(int type, - const struct compat_iovec __user *uvector, unsigned long nr_segs, - unsigned long fast_segs, struct iovec *fast_pointer, - struct iovec **ret_pointer) +struct iovec *compat_iovec_import(int type, + const struct compat_iovec __user *uvector, unsigned int nr_segs, + struct iovec_cache *cache, struct iov_iter *i) { compat_ssize_t tot_len; - struct iovec *iov = *ret_pointer = fast_pointer; - ssize_t ret = 0; - int seg; - - /* - * SuS says "The readv() function *may* fail if the iovcnt argument - * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... - */ - if (nr_segs == 0) - goto out; - - ret = -EINVAL; - if (nr_segs > UIO_MAXIOV) - goto out; - if (nr_segs > fast_segs) { - ret = -ENOMEM; + struct iovec *iov = cache->iov; + struct iovec *iov_kmalloc = NULL; + int ret; + unsigned int seg; + + if (!cache || nr_segs > ARRAY_SIZE(cache->iov)) { + if (nr_segs > UIO_MAXIOV) + return ERR_PTR(-EINVAL); iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) - goto out; + return ERR_PTR(-ENOMEM); + iov_kmalloc = iov; } - *ret_pointer = iov; - ret = -EFAULT; - if (!access_ok(uvector, nr_segs*sizeof(*uvector))) + if (!access_ok(uvector, nr_segs*sizeof(*uvector))) { + ret = -EINVAL; goto out; + } /* * Single unix specification: @@ -1842,18 +1818,19 @@ static ssize_t compat_rw_copy_check_uvector(int type, * no overflow possibility. */ tot_len = 0; - ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { compat_uptr_t buf; compat_ssize_t len; - if (__get_user(len, &uvector->iov_len) || - __get_user(buf, &uvector->iov_base)) { + if (__get_user(len, &uvector[seg].iov_len) || + __get_user(buf, &uvector[seg].iov_base)) { ret = -EFAULT; goto out; } - if (len < 0) /* size_t not fitting in compat_ssize_t .. */ + if (len < 0) { /* size_t not fitting in compat_ssize_t .. */ + ret = -EINVAL; goto out; + } if (type >= 0 && !access_ok(compat_ptr(buf), len)) { ret = -EFAULT; @@ -1862,35 +1839,36 @@ static ssize_t compat_rw_copy_check_uvector(int type, if (len > MAX_RW_COUNT - tot_len) len = MAX_RW_COUNT - tot_len; tot_len += len; - iov->iov_base = compat_ptr(buf); - iov->iov_len = (compat_size_t) len; - uvector++; - iov++; + iov[seg].iov_base = compat_ptr(buf); + iov[seg].iov_len = len; } - ret = tot_len; + + iov_iter_init(i, type, iov, nr_segs, tot_len); + return iov_kmalloc; out: - return ret; + kfree(iov_kmalloc); + return ERR_PTR(ret); } +EXPORT_SYMBOL(compat_iovec_import); ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i) { - ssize_t n; - struct iovec *p; - n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, - *iov, &p); - if (n < 0) { - if (p != *iov) - kfree(p); + struct iovec *iov_kmalloc; + + iov_kmalloc = compat_iovec_import(type, uvector, nr_segs, + fast_segs >= UIO_FASTIOV ? (void *)*iov : NULL, i); + + if (IS_ERR(iov_kmalloc)) { *iov = NULL; - return n; + return PTR_ERR(iov_kmalloc); } - iov_iter_init(i, type, p, nr_segs, n); - *iov = p == *iov ? NULL : p; - return n; + + *iov = iov_kmalloc; + return i->count; } EXPORT_SYMBOL(compat_import_iovec); #endif From patchwork Tue Sep 15 14:55:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364770 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brf1L6FVQz9sTH for ; Wed, 16 Sep 2020 09:04:06 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727350AbgIOXEF convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:04:05 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([207.82.80.151]:22882 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727347AbgIOOzZ (ORCPT ); Tue, 15 Sep 2020 10:55:25 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-228-UwHUunUMNimNqcwZQRPI5A-1; Tue, 15 Sep 2020 15:55:21 +0100 X-MC-Unique: UwHUunUMNimNqcwZQRPI5A-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:20 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:20 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 4/9 next] fs/io_uring Don't use the return value from import_iovec(). Thread-Topic: [PATCH 4/9 next] fs/io_uring Don't use the return value from import_iovec(). Thread-Index: AdaLbe1b5RzSfSnfQoqJG9wxedvDFg== Date: Tue, 15 Sep 2020 14:55:20 +0000 Message-ID: <0dc67994b6b2478caa3d96a9e24d2bfb@AcuMS.aculab.com> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This is the only code that relies on import_iovec() returning iter.count on success. This allows a better interface to import_iovec(). Signed-off-by: David Laight Reviewed-by: Pavel Begunkov --- fs/io_uring.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 3790c7fe9fee..0df43882e4b3 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2824,7 +2824,7 @@ static ssize_t __io_import_iovec(int rw, struct io_kiocb *req, ret = import_single_range(rw, buf, sqe_len, *iovec, iter); *iovec = NULL; - return ret < 0 ? ret : sqe_len; + return ret; } if (req->flags & REQ_F_BUFFER_SELECT) { @@ -2853,7 +2853,7 @@ static ssize_t io_import_iovec(int rw, struct io_kiocb *req, if (!req->io) return __io_import_iovec(rw, req, iovec, iter, needs_lock); *iovec = NULL; - return iov_iter_count(&req->io->rw.iter); + return 0; } static inline loff_t *io_kiocb_ppos(struct kiocb *kiocb) @@ -3123,7 +3123,7 @@ static int io_read(struct io_kiocb *req, bool force_nonblock, if (ret < 0) return ret; iov_count = iov_iter_count(iter); - io_size = ret; + io_size = iov_count; req->result = io_size; ret = 0; @@ -3246,7 +3246,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock, if (ret < 0) return ret; iov_count = iov_iter_count(iter); - io_size = ret; + io_size = iov_count; req->result = io_size; /* Ensure we clear previously set non-block flag */ From patchwork Tue Sep 15 14:55:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364455 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BrRCf4cJdz9sTN for ; Wed, 16 Sep 2020 00:57:18 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726245AbgIOO4n convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 10:56:43 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([185.58.86.151]:29387 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727354AbgIOOz3 (ORCPT ); Tue, 15 Sep 2020 10:55:29 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-37-dfVtB9cCPvahLiPigLatfA-1; Tue, 15 Sep 2020 15:55:25 +0100 X-MC-Unique: dfVtB9cCPvahLiPigLatfA-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:24 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:24 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 5/9 next] scsi: Use iovec_import() instead of import_iovec(). Thread-Topic: [PATCH 5/9 next] scsi: Use iovec_import() instead of import_iovec(). Thread-Index: AdaLbdBrrJnvb+q4Sa6RtPibF1KBcw== Date: Tue, 15 Sep 2020 14:55:24 +0000 Message-ID: <27be46ece36c42d6a7dabf62c6ac7a98@AcuMS.aculab.com> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org iovec_import() has a safer calling convention than import_iovec(). Signed-off-by: David Laight --- block/scsi_ioctl.c | 14 ++++++++------ drivers/scsi/sg.c | 14 +++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ef722f04f88a..0343918a84d3 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -331,20 +331,22 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, ret = 0; if (hdr->iovec_count) { struct iov_iter i; - struct iovec *iov = NULL; + struct iovec *iov; #ifdef CONFIG_COMPAT if (in_compat_syscall()) - ret = compat_import_iovec(rq_data_dir(rq), + iov = compat_iovec_import(rq_data_dir(rq), hdr->dxferp, hdr->iovec_count, - 0, &iov, &i); + NULL, &i); else #endif - ret = import_iovec(rq_data_dir(rq), + iov = iovec_import(rq_data_dir(rq), hdr->dxferp, hdr->iovec_count, - 0, &iov, &i); - if (ret < 0) + NULL, &i); + if (IS_ERR(iov)) { + ret = PTR_ERR(iov); goto out_free_cdb; + } /* SG_IO howto says that the shorter of the two wins */ iov_iter_truncate(&i, hdr->dxfer_len); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 20472aaaf630..1dbc0a74add5 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1817,19 +1817,19 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) } if (iov_count) { - struct iovec *iov = NULL; + struct iovec *iov; struct iov_iter i; #ifdef CONFIG_COMPAT if (in_compat_syscall()) - res = compat_import_iovec(rw, hp->dxferp, iov_count, - 0, &iov, &i); + iov = compat_iovec_import(rw, hp->dxferp, iov_count, + NULL, &i); else #endif - res = import_iovec(rw, hp->dxferp, iov_count, - 0, &iov, &i); - if (res < 0) - return res; + iov = iovec_import(rw, hp->dxferp, iov_count, + NULL, &i); + if (IS_ERR(iov)) + return PTR_ERR(iov); iov_iter_truncate(&i, hp->dxfer_len); if (!iov_iter_count(&i)) { From patchwork Tue Sep 15 14:55:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364767 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brf0C6vdfz9sTH for ; Wed, 16 Sep 2020 09:03:07 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727322AbgIOXDD convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:03:03 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([207.82.80.151]:55849 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727154AbgIOOzu (ORCPT ); Tue, 15 Sep 2020 10:55:50 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-58-hE9Q3gdSNFe5XdWmGMGaOw-1; Tue, 15 Sep 2020 15:55:28 +0100 X-MC-Unique: hE9Q3gdSNFe5XdWmGMGaOw-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:27 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:27 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 6/9 next] security/keys: Use iovec_import() instead of import_iovec(). Thread-Topic: [PATCH 6/9 next] security/keys: Use iovec_import() instead of import_iovec(). Thread-Index: AdaLbbVb64qzHlH6QG+P0w/qtCnTtA== Date: Tue, 15 Sep 2020 14:55:27 +0000 Message-ID: <4cea8bac469142118b996f62294de6ef@AcuMS.aculab.com> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org iovec_import() has a safer calling convention than import_iovec(). Signed-off-by: David Laight --- security/keys/compat.c | 11 +++++------ security/keys/keyctl.c | 10 +++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/security/keys/compat.c b/security/keys/compat.c index 6ee9d8f6a4a5..c8b6cc77028b 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -26,18 +26,17 @@ static long compat_keyctl_instantiate_key_iov( unsigned ioc, key_serial_t ringid) { - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iovec_cache cache; struct iov_iter from; + struct iovec *iov; long ret; if (!_payload_iov) ioc = 0; - ret = compat_import_iovec(WRITE, _payload_iov, ioc, - ARRAY_SIZE(iovstack), &iov, - &from); - if (ret < 0) - return ret; + iov = compat_iovec_import(WRITE, _payload_iov, ioc, &cache, &from); + if (IS_ERR(iov)) + return PTR_ERR(iov); ret = keyctl_instantiate_key_common(id, &from, ringid); kfree(iov); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 9febd37a168f..9a90b89ef24b 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1276,17 +1276,17 @@ long keyctl_instantiate_key_iov(key_serial_t id, unsigned ioc, key_serial_t ringid) { - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iovec_cache cache; struct iov_iter from; + struct iovec *iov; long ret; if (!_payload_iov) ioc = 0; - ret = import_iovec(WRITE, _payload_iov, ioc, - ARRAY_SIZE(iovstack), &iov, &from); - if (ret < 0) - return ret; + iov = iovec_import(WRITE, _payload_iov, ioc, &cache, &from); + if (IS_ERR(iov)) + return PTR_ERR(iov); ret = keyctl_instantiate_key_common(id, &from, ringid); kfree(iov); return ret; From patchwork Tue Sep 15 14:55:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364764 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brdz71z5Qz9sTR for ; Wed, 16 Sep 2020 09:02:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727562AbgIOXCI convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:02:08 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([185.58.86.151]:48142 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727309AbgIOOzu (ORCPT ); Tue, 15 Sep 2020 10:55:50 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-5-ZlNQaq51PdSjWG-hec5MQA-1; Tue, 15 Sep 2020 15:55:31 +0100 X-MC-Unique: ZlNQaq51PdSjWG-hec5MQA-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:31 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:31 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 7/9 next] mm/process_vm_access: Use iovec_import() instead of import_iovec(). Thread-Topic: [PATCH 7/9 next] mm/process_vm_access: Use iovec_import() instead of import_iovec(). Thread-Index: AdaLbliE1LQuFgQoRvuMh1ueXN8hpw== Date: Tue, 15 Sep 2020 14:55:30 +0000 Message-ID: Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org iovec_import() has a safer calling convention than import_iovec(). Signed-off-by: David Laight --- mm/process_vm_access.c | 81 ++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 1cc3d6f66b31..048637944d47 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -260,10 +260,10 @@ static ssize_t process_vm_rw(pid_t pid, unsigned long riovcnt, unsigned long flags, int vm_write) { - struct iovec iovstack_l[UIO_FASTIOV]; - struct iovec iovstack_r[UIO_FASTIOV]; - struct iovec *iov_l = iovstack_l; - struct iovec *iov_r = iovstack_r; + struct iovec_cache cache_l; + struct iovec_cache cache_r; + struct iovec *iov_l; + struct iovec *iov_r; struct iov_iter iter_l, iter_r; ssize_t rc; int dir = vm_write ? WRITE : READ; @@ -272,24 +272,25 @@ static ssize_t process_vm_rw(pid_t pid, return -EINVAL; /* Check iovecs */ - rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); - if (rc < 0) - return rc; - if (!iov_iter_count(&iter_l)) - goto free_iovecs; - - rc = import_iovec(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, &iov_r, &iter_r); - if (rc <= 0) - goto free_iovecs; - - rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, - flags, vm_write); + iov_l = iovec_import(dir, lvec, liovcnt, &cache_l, &iter_l); + if (IS_ERR(iov_l)) + return PTR_ERR(iov_l); + if (!iov_iter_count(&iter_l)) { + rc = 0; + goto free_iovec_l; + } -free_iovecs: - if (iov_r != iovstack_r) + iov_r = iovec_import(CHECK_IOVEC_ONLY, rvec, riovcnt, &cache_r, &iter_r); + if (IS_ERR(iov_r)) { + rc = PTR_ERR(iov_r); + } else { + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, + iter_r.nr_segs, flags, vm_write); kfree(iov_r); - if (iov_l != iovstack_l) - kfree(iov_l); + } + +free_iovec_l: + kfree(iov_l); return rc; } @@ -319,10 +320,10 @@ compat_process_vm_rw(compat_pid_t pid, unsigned long riovcnt, unsigned long flags, int vm_write) { - struct iovec iovstack_l[UIO_FASTIOV]; - struct iovec iovstack_r[UIO_FASTIOV]; - struct iovec *iov_l = iovstack_l; - struct iovec *iov_r = iovstack_r; + struct iovec_cache cache_l; + struct iovec_cache cache_r; + struct iovec *iov_l; + struct iovec *iov_r; struct iov_iter iter_l, iter_r; ssize_t rc = -EFAULT; int dir = vm_write ? WRITE : READ; @@ -330,23 +331,25 @@ compat_process_vm_rw(compat_pid_t pid, if (flags != 0) return -EINVAL; - rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); - if (rc < 0) - return rc; - if (!iov_iter_count(&iter_l)) - goto free_iovecs; - rc = compat_import_iovec(0, rvec, riovcnt, UIO_FASTIOV, &iov_r, &iter_r); - if (rc <= 0) - goto free_iovecs; - - rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, - flags, vm_write); + iov_l = compat_iovec_import(dir, lvec, liovcnt, &cache_l, &iter_l); + if (IS_ERR(iov_l)) + return PTR_ERR(iov_l); + if (!iov_iter_count(&iter_l)) { + rc = 0; + goto free_iovec_l; + } -free_iovecs: - if (iov_r != iovstack_r) + iov_r = compat_iovec_import(0, rvec, riovcnt, &cache_r, &iter_r); + if (IS_ERR(iov_r)) { + rc = PTR_ERR(iov_r); + } else { + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, + iter_r.nr_segs, flags, vm_write); kfree(iov_r); - if (iov_l != iovstack_l) - kfree(iov_l); + } + +free_iovec_l: + kfree(iov_l); return rc; } From patchwork Tue Sep 15 14:55:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364766 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Brdzm0tDmz9sTR for ; Wed, 16 Sep 2020 09:02:44 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727448AbgIOXCC convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:02:02 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([207.82.80.151]:27049 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727363AbgIOOzv (ORCPT ); Tue, 15 Sep 2020 10:55:51 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-212-ouC9VtsePgW0zmxTBHC3SA-1; Tue, 15 Sep 2020 15:55:35 +0100 X-MC-Unique: ouC9VtsePgW0zmxTBHC3SA-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:34 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:34 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 8/9 next] fs: Use iovec_import() instead of import_iovec(). Thread-Topic: [PATCH 8/9 next] fs: Use iovec_import() instead of import_iovec(). Thread-Index: AdaLblh1gZNjsQwuQPyq7LxxRCu5GQ== Date: Tue, 15 Sep 2020 14:55:34 +0000 Message-ID: Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org iovec_import() has a safer calling convention than import_iovec(). Signed-off-by: David Laight --- fs/aio.c | 34 ++++++++++++------------ fs/read_write.c | 69 ++++++++++++++++++++++++++----------------------- fs/splice.c | 22 +++++++++------- 3 files changed, 65 insertions(+), 60 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index d5ec30385566..909c03143374 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1477,24 +1477,20 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb) return 0; } -static ssize_t aio_setup_rw(int rw, const struct iocb *iocb, - struct iovec **iovec, bool vectored, bool compat, +static struct iovec *aio_setup_rw(int rw, const struct iocb *iocb, + struct iovec_cache *cache, bool vectored, bool compat, struct iov_iter *iter) { void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf; size_t len = iocb->aio_nbytes; - if (!vectored) { - ssize_t ret = import_single_range(rw, buf, len, *iovec, iter); - *iovec = NULL; - return ret; - } + if (!vectored) + return ERR_PTR(import_single_range(rw, buf, len, cache->iov, iter)); #ifdef CONFIG_COMPAT if (compat) - return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec, - iter); + return compat_iovec_import(rw, buf, len, cache, iter); #endif - return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter); + return iovec_import(rw, buf, len, cache, iter); } static inline void aio_rw_done(struct kiocb *req, ssize_t ret) @@ -1520,8 +1516,9 @@ static inline void aio_rw_done(struct kiocb *req, ssize_t ret) static int aio_read(struct kiocb *req, const struct iocb *iocb, bool vectored, bool compat) { - struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iovec; struct file *file; int ret; @@ -1535,9 +1532,9 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb, if (unlikely(!file->f_op->read_iter)) return -EINVAL; - ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter); - if (ret < 0) - return ret; + iovec = aio_setup_rw(READ, iocb, &cache, vectored, compat, &iter); + if (IS_ERR(iovec)) + return PTR_ERR(iovec); ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); if (!ret) aio_rw_done(req, call_read_iter(file, req, &iter)); @@ -1548,8 +1545,9 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb, static int aio_write(struct kiocb *req, const struct iocb *iocb, bool vectored, bool compat) { - struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iovec; struct file *file; int ret; @@ -1563,9 +1561,9 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb, if (unlikely(!file->f_op->write_iter)) return -EINVAL; - ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter); - if (ret < 0) - return ret; + iovec = aio_setup_rw(WRITE, iocb, &cache, vectored, compat, &iter); + if (IS_ERR(iovec)) + return PTR_ERR(iovec); ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter)); if (!ret) { /* diff --git a/fs/read_write.c b/fs/read_write.c index e5e891a88442..6e3d4a646f3c 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -884,35 +884,38 @@ EXPORT_SYMBOL(vfs_iter_write); ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t ret; - ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); - if (ret >= 0) { - ret = do_iter_read(file, &iter, pos, flags); - kfree(iov); - } + iov = iovec_import(READ, vec, vlen, &cache, &iter); + if (IS_ERR(iov)) + return PTR_ERR(iov); + + ret = do_iter_read(file, &iter, pos, flags); + kfree(iov); return ret; } static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t ret; - ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); - if (ret >= 0) { - file_start_write(file); - ret = do_iter_write(file, &iter, pos, flags); - file_end_write(file); - kfree(iov); - } + iov = iovec_import(WRITE, vec, vlen, &cache, &iter); + if (IS_ERR(iov)) + return PTR_ERR(iov); + + file_start_write(file); + ret = do_iter_write(file, &iter, pos, flags); + file_end_write(file); + + kfree(iov); return ret; } @@ -1073,16 +1076,17 @@ static size_t compat_readv(struct file *file, const struct compat_iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t ret; - ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter); - if (ret >= 0) { - ret = do_iter_read(file, &iter, pos, flags); - kfree(iov); - } + iov = compat_iovec_import(READ, vec, vlen, &cache, &iter); + if (IS_ERR(iov)) + return PTR_ERR(iov); + + ret = do_iter_read(file, &iter, pos, flags); + kfree(iov); if (ret > 0) add_rchar(current, ret); inc_syscr(current); @@ -1181,18 +1185,19 @@ static size_t compat_writev(struct file *file, const struct compat_iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t ret; - ret = compat_import_iovec(WRITE, vec, vlen, UIO_FASTIOV, &iov, &iter); - if (ret >= 0) { - file_start_write(file); - ret = do_iter_write(file, &iter, pos, flags); - file_end_write(file); - kfree(iov); - } + iov = compat_iovec_import(WRITE, vec, vlen, &cache, &iter); + if (IS_ERR(iov)) + return PTR_ERR(iov); + + file_start_write(file); + ret = do_iter_write(file, &iter, pos, flags); + file_end_write(file); + kfree(iov); if (ret > 0) add_wchar(current, ret); inc_syscw(current); diff --git a/fs/splice.c b/fs/splice.c index d7c8a7c4db07..ec1a825525d0 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1349,9 +1349,9 @@ static long do_vmsplice(struct file *f, struct iov_iter *iter, unsigned int flag SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov, unsigned long, nr_segs, unsigned int, flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t error; struct fd f; int type; @@ -1361,9 +1361,10 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov, if (error) return error; - error = import_iovec(type, uiov, nr_segs, - ARRAY_SIZE(iovstack), &iov, &iter); - if (error >= 0) { + iov = iovec_import(type, uiov, nr_segs, &cache, &iter); + if (IS_ERR(iov)) { + error = PTR_ERR(iov); + } else { error = do_vmsplice(f.file, &iter, flags); kfree(iov); } @@ -1375,9 +1376,9 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov, COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32, unsigned int, nr_segs, unsigned int, flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec_cache cache; struct iov_iter iter; + struct iovec *iov; ssize_t error; struct fd f; int type; @@ -1387,9 +1388,10 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io if (error) return error; - error = compat_import_iovec(type, iov32, nr_segs, - ARRAY_SIZE(iovstack), &iov, &iter); - if (error >= 0) { + iov = compat_iovec_import(type, iov32, nr_segs, &cache, &iter); + if (IS_ERR(iov)) { + error = PTR_ERR(iov); + } else { error = do_vmsplice(f.file, &iter, flags); kfree(iov); } From patchwork Tue Sep 15 14:55:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Laight X-Patchwork-Id: 1364765 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ACULAB.COM Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BrdzD4Gd9z9sTH for ; Wed, 16 Sep 2020 09:02:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727555AbgIOXCF convert rfc822-to-8bit (ORCPT ); Tue, 15 Sep 2020 19:02:05 -0400 Received: from eu-smtp-delivery-151.mimecast.com ([185.58.86.151]:32866 "EHLO eu-smtp-delivery-151.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727368AbgIOOzv (ORCPT ); Tue, 15 Sep 2020 10:55:51 -0400 Received: from AcuMS.aculab.com (156.67.243.126 [156.67.243.126]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-225-gyJ64E1qMQiV4UPZ8HDYwQ-1; Tue, 15 Sep 2020 15:55:39 +0100 X-MC-Unique: gyJ64E1qMQiV4UPZ8HDYwQ-1 Received: from AcuMS.Aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) by AcuMS.aculab.com (fd9f:af1c:a25b:0:43c:695e:880f:8750) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 15 Sep 2020 15:55:38 +0100 Received: from AcuMS.Aculab.com ([fe80::43c:695e:880f:8750]) by AcuMS.aculab.com ([fe80::43c:695e:880f:8750%12]) with mapi id 15.00.1347.000; Tue, 15 Sep 2020 15:55:38 +0100 From: David Laight To: "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "io-uring@vger.kernel.org" , Jens Axboe , "David S. Miller" , Al Viro , linux-fsdevel Subject: [PATCH 9/9 net-next] net/socket: Use iovec_import() instead of import_iovec(). Thread-Topic: [PATCH 9/9 net-next] net/socket: Use iovec_import() instead of import_iovec(). Thread-Index: AdaLblhsBop7rm5NTB+HLmhgi+sj0w== Date: Tue, 15 Sep 2020 14:55:38 +0000 Message-ID: <73b88df9370e4e23b9e6f77557d22a66@AcuMS.aculab.com> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.202.205.107] MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=C51A453 smtp.mailfrom=david.laight@aculab.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: aculab.com Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org iovec_import() has a safer calling convention than import_iovec(). Also contains a small change to fs/io_uring.c Signed-off-by: David Laight --- fs/io_uring.c | 13 +++++++-- include/linux/socket.h | 15 +++++----- include/net/compat.h | 5 ++-- net/compat.c | 17 +++++------ net/socket.c | 66 ++++++++++++++++++------------------------ 5 files changed, 57 insertions(+), 59 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 0df43882e4b3..79707907e00d 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -4031,10 +4031,17 @@ static int io_setup_async_msg(struct io_kiocb *req, static int io_sendmsg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg) { - iomsg->iov = iomsg->fast_iov; + struct iovec *iov; + iomsg->msg.msg_name = &iomsg->addr; - return sendmsg_copy_msghdr(&iomsg->msg, req->sr_msg.umsg, - req->sr_msg.msg_flags, &iomsg->iov); + iov = sendmsg_copy_msghdr(&iomsg->msg, req->sr_msg.umsg, + req->sr_msg.msg_flags, + (void *)&iomsg->fast_iov); + if (IS_ERR(iov)) + return PTR_ERR(iov); + /* Save any buffer that must be freed after the request completes. */ + iomsg->iov = iov; + return 0; } static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) diff --git a/include/linux/socket.h b/include/linux/socket.h index e9cb30d8cbfb..58d82ac014e2 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -398,13 +398,14 @@ extern long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg, struct user_msghdr __user *umsg, struct sockaddr __user *uaddr, unsigned int flags); -extern int sendmsg_copy_msghdr(struct msghdr *msg, - struct user_msghdr __user *umsg, unsigned flags, - struct iovec **iov); -extern int recvmsg_copy_msghdr(struct msghdr *msg, - struct user_msghdr __user *umsg, unsigned flags, - struct sockaddr __user **uaddr, - struct iovec **iov); +struct iovec *sendmsg_copy_msghdr(struct msghdr *msg, + struct user_msghdr __user *umsg, + unsigned flags, struct iovec_cache *cache); +struct iovec *recvmsg_copy_msghdr(struct msghdr *msg, + struct user_msghdr __user *umsg, + unsigned flags, + struct sockaddr __user **uaddr, + struct iovec_cache *cache); extern int __copy_msghdr_from_user(struct msghdr *kmsg, struct user_msghdr __user *umsg, struct sockaddr __user **save_addr, diff --git a/include/net/compat.h b/include/net/compat.h index 745db0d605b6..61b8408e16b5 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -59,8 +59,9 @@ struct compat_rtentry { int __get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg, struct sockaddr __user **save_addr, compat_uptr_t *ptr, compat_size_t *len); -int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *, - struct sockaddr __user **, struct iovec **); +struct iovec *get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *, + struct sockaddr __user **, + struct iovec_cache *); int put_cmsg_compat(struct msghdr*, int, int, int, void *); int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, diff --git a/net/compat.c b/net/compat.c index 95ce707a30a3..3b37f6273891 100644 --- a/net/compat.c +++ b/net/compat.c @@ -85,22 +85,21 @@ int __get_compat_msghdr(struct msghdr *kmsg, return 0; } -int get_compat_msghdr(struct msghdr *kmsg, - struct compat_msghdr __user *umsg, - struct sockaddr __user **save_addr, - struct iovec **iov) +struct iovec *get_compat_msghdr(struct msghdr *kmsg, + struct compat_msghdr __user *umsg, + struct sockaddr __user **save_addr, + struct iovec_cache *cache) { compat_uptr_t ptr; compat_size_t len; - ssize_t err; + int err; err = __get_compat_msghdr(kmsg, umsg, save_addr, &ptr, &len); if (err) - return err; + return ERR_PTR(err); - err = compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr), - len, UIO_FASTIOV, iov, &kmsg->msg_iter); - return err < 0 ? err : 0; + return compat_iovec_import(save_addr ? READ : WRITE, compat_ptr(ptr), + len, cache, &kmsg->msg_iter); } /* Bleech... */ diff --git a/net/socket.c b/net/socket.c index 0c0144604f81..00feed199d53 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2275,10 +2275,10 @@ int __copy_msghdr_from_user(struct msghdr *kmsg, return 0; } -static int copy_msghdr_from_user(struct msghdr *kmsg, - struct user_msghdr __user *umsg, - struct sockaddr __user **save_addr, - struct iovec **iov) +static struct iovec *copy_msghdr_from_user(struct msghdr *kmsg, + struct user_msghdr __user *umsg, + struct sockaddr __user **save_addr, + struct iovec_cache *cache) { struct user_msghdr msg; ssize_t err; @@ -2286,12 +2286,11 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, err = __copy_msghdr_from_user(kmsg, umsg, save_addr, &msg.msg_iov, &msg.msg_iovlen); if (err) - return err; + return ERR_PTR(err); - err = import_iovec(save_addr ? READ : WRITE, + return iovec_import(save_addr ? READ : WRITE, msg.msg_iov, msg.msg_iovlen, - UIO_FASTIOV, iov, &kmsg->msg_iter); - return err < 0 ? err : 0; + cache, &kmsg->msg_iter); } static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, @@ -2369,24 +2368,18 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, return err; } -int sendmsg_copy_msghdr(struct msghdr *msg, +struct iovec *sendmsg_copy_msghdr(struct msghdr *msg, struct user_msghdr __user *umsg, unsigned flags, - struct iovec **iov) + struct iovec_cache *cache) { - int err; - if (flags & MSG_CMSG_COMPAT) { struct compat_msghdr __user *msg_compat; msg_compat = (struct compat_msghdr __user *) umsg; - err = get_compat_msghdr(msg, msg_compat, NULL, iov); - } else { - err = copy_msghdr_from_user(msg, umsg, NULL, iov); + return get_compat_msghdr(msg, msg_compat, NULL, cache); } - if (err < 0) - return err; - return 0; + return copy_msghdr_from_user(msg, umsg, NULL, cache); } static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, @@ -2395,14 +2388,15 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, unsigned int allowed_msghdr_flags) { struct sockaddr_storage address; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iovec_cache cache; + struct iovec *iov; ssize_t err; msg_sys->msg_name = &address; - err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov); - if (err < 0) - return err; + iov = sendmsg_copy_msghdr(msg_sys, msg, flags, &cache); + if (IS_ERR(iov)) + return PTR_ERR(iov); err = ____sys_sendmsg(sock, msg_sys, flags, used_address, allowed_msghdr_flags); @@ -2526,25 +2520,20 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, return __sys_sendmmsg(fd, mmsg, vlen, flags, true); } -int recvmsg_copy_msghdr(struct msghdr *msg, - struct user_msghdr __user *umsg, unsigned flags, - struct sockaddr __user **uaddr, - struct iovec **iov) +struct iovec *recvmsg_copy_msghdr(struct msghdr *msg, + struct user_msghdr __user *umsg, + unsigned flags, + struct sockaddr __user **uaddr, + struct iovec_cache *cache) { - ssize_t err; - if (MSG_CMSG_COMPAT & flags) { struct compat_msghdr __user *msg_compat; msg_compat = (struct compat_msghdr __user *) umsg; - err = get_compat_msghdr(msg, msg_compat, uaddr, iov); - } else { - err = copy_msghdr_from_user(msg, umsg, uaddr, iov); + return get_compat_msghdr(msg, msg_compat, uaddr, cache); } - if (err < 0) - return err; - return 0; + return copy_msghdr_from_user(msg, umsg, uaddr, cache); } static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys, @@ -2606,14 +2595,15 @@ static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys, static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, struct msghdr *msg_sys, unsigned int flags, int nosec) { - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iovec_cache cache; + struct iovec *iov; /* user mode address pointers */ struct sockaddr __user *uaddr; ssize_t err; - err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov); - if (err < 0) - return err; + iov = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &cache); + if (IS_ERR(iov)) + return PTR_ERR(iov); err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec); kfree(iov);