From 836219141ff7a77e7fab0bd749edd746fd36fef2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 23 Oct 2020 10:20:56 +0200 Subject: [PATCH] Revert "iov_iter: transparently handle compat iovecs in import_iovec" This reverts commit 89cd35c58bc2e36bfdc23dde67a429b08cf4ae03. Bug: 171539436 Signed-off-by: Greg Kroah-Hartman Change-Id: I44ac1575af118ddbc3ee22a70f81cba282f5372a --- block/scsi_ioctl.c | 12 ++++++++++-- drivers/scsi/sg.c | 9 ++++++++- fs/aio.c | 8 ++++++-- fs/io_uring.c | 20 ++++++++++++-------- fs/read_write.c | 6 ++---- fs/splice.c | 2 +- include/linux/uio.h | 8 ++++++++ lib/iov_iter.c | 14 ++++++++++++-- mm/process_vm_access.c | 3 +-- net/compat.c | 4 ++-- security/keys/compat.c | 5 +++-- 11 files changed, 65 insertions(+), 26 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 97e0b162a0d9..72108404718f 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -333,8 +333,16 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, struct iov_iter i; struct iovec *iov = NULL; - ret = import_iovec(rq_data_dir(rq), hdr->dxferp, - hdr->iovec_count, 0, &iov, &i); +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + ret = compat_import_iovec(rq_data_dir(rq), + hdr->dxferp, hdr->iovec_count, + 0, &iov, &i); + else +#endif + ret = import_iovec(rq_data_dir(rq), + hdr->dxferp, hdr->iovec_count, + 0, &iov, &i); if (ret < 0) goto out_free_cdb; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index bfa8d77322d7..20472aaaf630 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1820,7 +1820,14 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) struct iovec *iov = NULL; struct iov_iter i; - res = import_iovec(rw, hp->dxferp, iov_count, 0, &iov, &i); +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + res = compat_import_iovec(rw, hp->dxferp, iov_count, + 0, &iov, &i); + else +#endif + res = import_iovec(rw, hp->dxferp, iov_count, + 0, &iov, &i); if (res < 0) return res; diff --git a/fs/aio.c b/fs/aio.c index c45c20d87538..d5ec30385566 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1489,8 +1489,12 @@ static ssize_t aio_setup_rw(int rw, const struct iocb *iocb, *iovec = NULL; return ret; } - - return __import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter, compat); +#ifdef CONFIG_COMPAT + if (compat) + return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec, + iter); +#endif + return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter); } static inline void aio_rw_done(struct kiocb *req, ssize_t ret) diff --git a/fs/io_uring.c b/fs/io_uring.c index f58b3d6bba8a..aae0ef2ec34d 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2852,8 +2852,13 @@ static ssize_t __io_import_iovec(int rw, struct io_kiocb *req, return ret; } - return __import_iovec(rw, buf, sqe_len, UIO_FASTIOV, iovec, iter, - req->ctx->compat); +#ifdef CONFIG_COMPAT + if (req->ctx->compat) + return compat_import_iovec(rw, buf, sqe_len, UIO_FASTIOV, + iovec, iter); +#endif + + return import_iovec(rw, buf, sqe_len, UIO_FASTIOV, iovec, iter); } static ssize_t io_import_iovec(int rw, struct io_kiocb *req, @@ -4195,9 +4200,8 @@ static int __io_recvmsg_copy_hdr(struct io_kiocb *req, sr->len); iomsg->iov = NULL; } else { - ret = __import_iovec(READ, uiov, iov_len, UIO_FASTIOV, - &iomsg->iov, &iomsg->msg.msg_iter, - false); + ret = import_iovec(READ, uiov, iov_len, UIO_FASTIOV, + &iomsg->iov, &iomsg->msg.msg_iter); if (ret > 0) ret = 0; } @@ -4237,9 +4241,9 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req, sr->len = iomsg->iov[0].iov_len; iomsg->iov = NULL; } else { - ret = __import_iovec(READ, (struct iovec __user *)uiov, len, - UIO_FASTIOV, &iomsg->iov, - &iomsg->msg.msg_iter, true); + ret = compat_import_iovec(READ, uiov, len, UIO_FASTIOV, + &iomsg->iov, + &iomsg->msg.msg_iter); if (ret < 0) return ret; } diff --git a/fs/read_write.c b/fs/read_write.c index 709dc129b052..bb4be0861b23 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1086,8 +1086,7 @@ static size_t compat_readv(struct file *file, struct iov_iter iter; ssize_t ret; - ret = import_iovec(READ, (const struct iovec __user *)vec, vlen, - UIO_FASTIOV, &iov, &iter); + ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter); if (ret >= 0) { ret = do_iter_read(file, &iter, pos, flags); kfree(iov); @@ -1195,8 +1194,7 @@ static size_t compat_writev(struct file *file, struct iov_iter iter; ssize_t ret; - ret = import_iovec(WRITE, (const struct iovec __user *)vec, vlen, - UIO_FASTIOV, &iov, &iter); + 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); diff --git a/fs/splice.c b/fs/splice.c index e1a77ef1886a..ce75aec52274 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1407,7 +1407,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io if (error) return error; - error = import_iovec(type, (struct iovec __user *)iov32, nr_segs, + error = compat_import_iovec(type, iov32, nr_segs, ARRAY_SIZE(iovstack), &iov, &iter); if (error >= 0) { error = do_vmsplice(f.file, &iter, flags); diff --git a/include/linux/uio.h b/include/linux/uio.h index 72d88566694e..bc7e3b3eec98 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -275,6 +275,14 @@ ssize_t import_iovec(int type, const struct iovec __user *uvec, ssize_t __import_iovec(int type, const struct iovec __user *uvec, unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, struct iov_iter *i, bool compat); + +#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); +#endif + int import_single_range(int type, void __user *buf, size_t len, struct iovec *iov, struct iov_iter *i); diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 14cae2584db4..1b92d6c865e9 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1801,11 +1801,21 @@ ssize_t import_iovec(int type, const struct iovec __user *uvec, unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, struct iov_iter *i) { - return __import_iovec(type, uvec, nr_segs, fast_segs, iovp, i, - in_compat_syscall()); + return __import_iovec(type, uvec, nr_segs, fast_segs, iovp, i, false); } EXPORT_SYMBOL(import_iovec); +#ifdef CONFIG_COMPAT +ssize_t compat_import_iovec(int type, const struct compat_iovec __user *uvec, + unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, + struct iov_iter *i) +{ + return __import_iovec(type, (const struct iovec __user *)uvec, nr_segs, + fast_segs, iovp, i, true); +} +EXPORT_SYMBOL(compat_import_iovec); +#endif + int import_single_range(int rw, void __user *buf, size_t len, struct iovec *iov, struct iov_iter *i) { diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 3f2156aab442..5e728c20c2be 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -326,8 +326,7 @@ compat_process_vm_rw(compat_pid_t pid, if (flags != 0) return -EINVAL; - rc = import_iovec(dir, (const struct iovec __user *)lvec, liovcnt, - UIO_FASTIOV, &iov_l, &iter); + rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter); if (rc < 0) return rc; if (!iov_iter_count(&iter)) diff --git a/net/compat.c b/net/compat.c index ddd15af3a283..95ce707a30a3 100644 --- a/net/compat.c +++ b/net/compat.c @@ -98,8 +98,8 @@ int get_compat_msghdr(struct msghdr *kmsg, if (err) return err; - err = import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr), len, - UIO_FASTIOV, iov, &kmsg->msg_iter); + err = compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr), + len, UIO_FASTIOV, iov, &kmsg->msg_iter); return err < 0 ? err : 0; } diff --git a/security/keys/compat.c b/security/keys/compat.c index 7ae531db031c..6ee9d8f6a4a5 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -33,8 +33,9 @@ static long compat_keyctl_instantiate_key_iov( if (!_payload_iov) ioc = 0; - ret = import_iovec(WRITE, (const struct iovec __user *)_payload_iov, - ioc, ARRAY_SIZE(iovstack), &iov, &from); + ret = compat_import_iovec(WRITE, _payload_iov, ioc, + ARRAY_SIZE(iovstack), &iov, + &from); if (ret < 0) return ret;