mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	iov_iter: transparently handle compat iovecs in import_iovec
Use in compat_syscall to import either native or the compat iovecs, and remove the now superflous compat_import_iovec. This removes the need for special compat logic in most callers, and the remaining ones can still be simplified by using __import_iovec with a bool compat parameter. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									bfdc59701d
								
							
						
					
					
						commit
						89cd35c58b
					
				
					 11 changed files with 26 additions and 65 deletions
				
			
		| 
						 | 
				
			
			@ -333,16 +333,8 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 | 
			
		|||
		struct iov_iter i;
 | 
			
		||||
		struct iovec *iov = NULL;
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
		ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
 | 
			
		||||
				   hdr->iovec_count, 0, &iov, &i);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto out_free_cdb;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1820,14 +1820,7 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
 | 
			
		|||
		struct iovec *iov = NULL;
 | 
			
		||||
		struct iov_iter 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);
 | 
			
		||||
		res = import_iovec(rw, hp->dxferp, iov_count, 0, &iov, &i);
 | 
			
		||||
		if (res < 0)
 | 
			
		||||
			return res;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								fs/aio.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								fs/aio.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1489,12 +1489,8 @@ static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
 | 
			
		|||
		*iovec = NULL;
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
	return __import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter, compat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2846,13 +2846,8 @@ static ssize_t __io_import_iovec(int rw, struct io_kiocb *req,
 | 
			
		|||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
	return __import_iovec(rw, buf, sqe_len, UIO_FASTIOV, iovec, iter,
 | 
			
		||||
			      req->ctx->compat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t io_import_iovec(int rw, struct io_kiocb *req,
 | 
			
		||||
| 
						 | 
				
			
			@ -4166,8 +4161,9 @@ 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);
 | 
			
		||||
		ret = __import_iovec(READ, uiov, iov_len, UIO_FASTIOV,
 | 
			
		||||
				     &iomsg->iov, &iomsg->msg.msg_iter,
 | 
			
		||||
				     false);
 | 
			
		||||
		if (ret > 0)
 | 
			
		||||
			ret = 0;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -4207,9 +4203,9 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
 | 
			
		|||
		sr->len = iomsg->iov[0].iov_len;
 | 
			
		||||
		iomsg->iov = NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = compat_import_iovec(READ, uiov, len, UIO_FASTIOV,
 | 
			
		||||
						&iomsg->iov,
 | 
			
		||||
						&iomsg->msg.msg_iter);
 | 
			
		||||
		ret = __import_iovec(READ, (struct iovec __user *)uiov, len,
 | 
			
		||||
				   UIO_FASTIOV, &iomsg->iov,
 | 
			
		||||
				   &iomsg->msg.msg_iter, true);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1078,7 +1078,8 @@ static size_t compat_readv(struct file *file,
 | 
			
		|||
	struct iov_iter iter;
 | 
			
		||||
	ssize_t ret;
 | 
			
		||||
 | 
			
		||||
	ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter);
 | 
			
		||||
	ret = import_iovec(READ, (const struct iovec __user *)vec, vlen,
 | 
			
		||||
			   UIO_FASTIOV, &iov, &iter);
 | 
			
		||||
	if (ret >= 0) {
 | 
			
		||||
		ret = do_iter_read(file, &iter, pos, flags);
 | 
			
		||||
		kfree(iov);
 | 
			
		||||
| 
						 | 
				
			
			@ -1186,7 +1187,8 @@ static size_t compat_writev(struct file *file,
 | 
			
		|||
	struct iov_iter iter;
 | 
			
		||||
	ssize_t ret;
 | 
			
		||||
 | 
			
		||||
	ret = compat_import_iovec(WRITE, vec, vlen, UIO_FASTIOV, &iov, &iter);
 | 
			
		||||
	ret = import_iovec(WRITE, (const struct iovec __user *)vec, vlen,
 | 
			
		||||
			   UIO_FASTIOV, &iov, &iter);
 | 
			
		||||
	if (ret >= 0) {
 | 
			
		||||
		file_start_write(file);
 | 
			
		||||
		ret = do_iter_write(file, &iter, pos, flags);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1387,7 +1387,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
 | 
			
		|||
	if (error)
 | 
			
		||||
		return error;
 | 
			
		||||
 | 
			
		||||
	error = compat_import_iovec(type, iov32, nr_segs,
 | 
			
		||||
	error = import_iovec(type, (struct iovec __user *)iov32, nr_segs,
 | 
			
		||||
			     ARRAY_SIZE(iovstack), &iov, &iter);
 | 
			
		||||
	if (error >= 0) {
 | 
			
		||||
		error = do_vmsplice(f.file, &iter, flags);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -275,14 +275,6 @@ 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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1806,21 +1806,11 @@ 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, false);
 | 
			
		||||
	return __import_iovec(type, uvec, nr_segs, fast_segs, iovp, i,
 | 
			
		||||
			      in_compat_syscall());
 | 
			
		||||
}
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -326,7 +326,8 @@ 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);
 | 
			
		||||
	rc = import_iovec(dir, (const struct iovec __user *)lvec, liovcnt,
 | 
			
		||||
			  UIO_FASTIOV, &iov_l, &iter);
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		return rc;
 | 
			
		||||
	if (!iov_iter_count(&iter))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,8 +98,8 @@ int get_compat_msghdr(struct msghdr *kmsg,
 | 
			
		|||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr),
 | 
			
		||||
				   len, UIO_FASTIOV, iov, &kmsg->msg_iter);
 | 
			
		||||
	err = import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr), len,
 | 
			
		||||
			   UIO_FASTIOV, iov, &kmsg->msg_iter);
 | 
			
		||||
	return err < 0 ? err : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,9 +33,8 @@ static long compat_keyctl_instantiate_key_iov(
 | 
			
		|||
	if (!_payload_iov)
 | 
			
		||||
		ioc = 0;
 | 
			
		||||
 | 
			
		||||
	ret = compat_import_iovec(WRITE, _payload_iov, ioc,
 | 
			
		||||
				  ARRAY_SIZE(iovstack), &iov,
 | 
			
		||||
				  &from);
 | 
			
		||||
	ret = import_iovec(WRITE, (const struct iovec __user *)_payload_iov,
 | 
			
		||||
			   ioc, ARRAY_SIZE(iovstack), &iov, &from);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue