diff options
-rw-r--r-- | fs/aio.c | 4 | ||||
-rw-r--r-- | fs/compat.c | 6 | ||||
-rw-r--r-- | fs/read_write.c | 7 | ||||
-rw-r--r-- | include/linux/compat.h | 3 | ||||
-rw-r--r-- | include/linux/fs.h | 12 | ||||
-rw-r--r-- | mm/process_vm_access.c | 16 | ||||
-rw-r--r-- | security/keys/compat.c | 2 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 |
8 files changed, 29 insertions, 23 deletions
@@ -1446,13 +1446,13 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat) | |||
1446 | ret = compat_rw_copy_check_uvector(type, | 1446 | ret = compat_rw_copy_check_uvector(type, |
1447 | (struct compat_iovec __user *)kiocb->ki_buf, | 1447 | (struct compat_iovec __user *)kiocb->ki_buf, |
1448 | kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec, | 1448 | kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec, |
1449 | &kiocb->ki_iovec, 1); | 1449 | &kiocb->ki_iovec); |
1450 | else | 1450 | else |
1451 | #endif | 1451 | #endif |
1452 | ret = rw_copy_check_uvector(type, | 1452 | ret = rw_copy_check_uvector(type, |
1453 | (struct iovec __user *)kiocb->ki_buf, | 1453 | (struct iovec __user *)kiocb->ki_buf, |
1454 | kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec, | 1454 | kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec, |
1455 | &kiocb->ki_iovec, 1); | 1455 | &kiocb->ki_iovec); |
1456 | if (ret < 0) | 1456 | if (ret < 0) |
1457 | goto out; | 1457 | goto out; |
1458 | 1458 | ||
diff --git a/fs/compat.c b/fs/compat.c index 0781e619a62a..6556a9ce8a28 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -532,7 +532,7 @@ out: | |||
532 | ssize_t compat_rw_copy_check_uvector(int type, | 532 | ssize_t compat_rw_copy_check_uvector(int type, |
533 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | 533 | const struct compat_iovec __user *uvector, unsigned long nr_segs, |
534 | unsigned long fast_segs, struct iovec *fast_pointer, | 534 | unsigned long fast_segs, struct iovec *fast_pointer, |
535 | struct iovec **ret_pointer, int check_access) | 535 | struct iovec **ret_pointer) |
536 | { | 536 | { |
537 | compat_ssize_t tot_len; | 537 | compat_ssize_t tot_len; |
538 | struct iovec *iov = *ret_pointer = fast_pointer; | 538 | struct iovec *iov = *ret_pointer = fast_pointer; |
@@ -579,7 +579,7 @@ ssize_t compat_rw_copy_check_uvector(int type, | |||
579 | } | 579 | } |
580 | if (len < 0) /* size_t not fitting in compat_ssize_t .. */ | 580 | if (len < 0) /* size_t not fitting in compat_ssize_t .. */ |
581 | goto out; | 581 | goto out; |
582 | if (check_access && | 582 | if (type >= 0 && |
583 | !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { | 583 | !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { |
584 | ret = -EFAULT; | 584 | ret = -EFAULT; |
585 | goto out; | 585 | goto out; |
@@ -1094,7 +1094,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1094 | goto out; | 1094 | goto out; |
1095 | 1095 | ||
1096 | tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs, | 1096 | tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs, |
1097 | UIO_FASTIOV, iovstack, &iov, 1); | 1097 | UIO_FASTIOV, iovstack, &iov); |
1098 | if (tot_len == 0) { | 1098 | if (tot_len == 0) { |
1099 | ret = 0; | 1099 | ret = 0; |
1100 | goto out; | 1100 | goto out; |
diff --git a/fs/read_write.c b/fs/read_write.c index ffc99d22e0a3..c20614f86c01 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -633,8 +633,7 @@ ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, | |||
633 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, | 633 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, |
634 | unsigned long nr_segs, unsigned long fast_segs, | 634 | unsigned long nr_segs, unsigned long fast_segs, |
635 | struct iovec *fast_pointer, | 635 | struct iovec *fast_pointer, |
636 | struct iovec **ret_pointer, | 636 | struct iovec **ret_pointer) |
637 | int check_access) | ||
638 | { | 637 | { |
639 | unsigned long seg; | 638 | unsigned long seg; |
640 | ssize_t ret; | 639 | ssize_t ret; |
@@ -690,7 +689,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, | |||
690 | ret = -EINVAL; | 689 | ret = -EINVAL; |
691 | goto out; | 690 | goto out; |
692 | } | 691 | } |
693 | if (check_access | 692 | if (type >= 0 |
694 | && unlikely(!access_ok(vrfy_dir(type), buf, len))) { | 693 | && unlikely(!access_ok(vrfy_dir(type), buf, len))) { |
695 | ret = -EFAULT; | 694 | ret = -EFAULT; |
696 | goto out; | 695 | goto out; |
@@ -723,7 +722,7 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
723 | } | 722 | } |
724 | 723 | ||
725 | ret = rw_copy_check_uvector(type, uvector, nr_segs, | 724 | ret = rw_copy_check_uvector(type, uvector, nr_segs, |
726 | ARRAY_SIZE(iovstack), iovstack, &iov, 1); | 725 | ARRAY_SIZE(iovstack), iovstack, &iov); |
727 | if (ret <= 0) | 726 | if (ret <= 0) |
728 | goto out; | 727 | goto out; |
729 | 728 | ||
diff --git a/include/linux/compat.h b/include/linux/compat.h index 5d46217f84ad..4e890394ef99 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -577,8 +577,7 @@ extern ssize_t compat_rw_copy_check_uvector(int type, | |||
577 | const struct compat_iovec __user *uvector, | 577 | const struct compat_iovec __user *uvector, |
578 | unsigned long nr_segs, | 578 | unsigned long nr_segs, |
579 | unsigned long fast_segs, struct iovec *fast_pointer, | 579 | unsigned long fast_segs, struct iovec *fast_pointer, |
580 | struct iovec **ret_pointer, | 580 | struct iovec **ret_pointer); |
581 | int check_access); | ||
582 | 581 | ||
583 | extern void __user *compat_alloc_user_space(unsigned long len); | 582 | extern void __user *compat_alloc_user_space(unsigned long len); |
584 | 583 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 038076b27ea4..cf2c5611b19b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -173,6 +173,15 @@ struct inodes_stat_t { | |||
173 | #define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA) | 173 | #define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA) |
174 | #define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) | 174 | #define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) |
175 | 175 | ||
176 | |||
177 | /* | ||
178 | * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector | ||
179 | * that indicates that they should check the contents of the iovec are | ||
180 | * valid, but not check the memory that the iovec elements | ||
181 | * points too. | ||
182 | */ | ||
183 | #define CHECK_IOVEC_ONLY -1 | ||
184 | |||
176 | #define SEL_IN 1 | 185 | #define SEL_IN 1 |
177 | #define SEL_OUT 2 | 186 | #define SEL_OUT 2 |
178 | #define SEL_EX 4 | 187 | #define SEL_EX 4 |
@@ -1690,8 +1699,7 @@ struct seq_file; | |||
1690 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, | 1699 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, |
1691 | unsigned long nr_segs, unsigned long fast_segs, | 1700 | unsigned long nr_segs, unsigned long fast_segs, |
1692 | struct iovec *fast_pointer, | 1701 | struct iovec *fast_pointer, |
1693 | struct iovec **ret_pointer, | 1702 | struct iovec **ret_pointer); |
1694 | int check_access); | ||
1695 | 1703 | ||
1696 | extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); | 1704 | extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); |
1697 | extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); | 1705 | extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); |
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index c20ff48994c2..926b46649749 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c | |||
@@ -371,15 +371,15 @@ static ssize_t process_vm_rw(pid_t pid, | |||
371 | /* Check iovecs */ | 371 | /* Check iovecs */ |
372 | if (vm_write) | 372 | if (vm_write) |
373 | rc = rw_copy_check_uvector(WRITE, lvec, liovcnt, UIO_FASTIOV, | 373 | rc = rw_copy_check_uvector(WRITE, lvec, liovcnt, UIO_FASTIOV, |
374 | iovstack_l, &iov_l, 1); | 374 | iovstack_l, &iov_l); |
375 | else | 375 | else |
376 | rc = rw_copy_check_uvector(READ, lvec, liovcnt, UIO_FASTIOV, | 376 | rc = rw_copy_check_uvector(READ, lvec, liovcnt, UIO_FASTIOV, |
377 | iovstack_l, &iov_l, 1); | 377 | iovstack_l, &iov_l); |
378 | if (rc <= 0) | 378 | if (rc <= 0) |
379 | goto free_iovecs; | 379 | goto free_iovecs; |
380 | 380 | ||
381 | rc = rw_copy_check_uvector(READ, rvec, riovcnt, UIO_FASTIOV, | 381 | rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, |
382 | iovstack_r, &iov_r, 0); | 382 | iovstack_r, &iov_r); |
383 | if (rc <= 0) | 383 | if (rc <= 0) |
384 | goto free_iovecs; | 384 | goto free_iovecs; |
385 | 385 | ||
@@ -438,16 +438,16 @@ compat_process_vm_rw(compat_pid_t pid, | |||
438 | if (vm_write) | 438 | if (vm_write) |
439 | rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt, | 439 | rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt, |
440 | UIO_FASTIOV, iovstack_l, | 440 | UIO_FASTIOV, iovstack_l, |
441 | &iov_l, 1); | 441 | &iov_l); |
442 | else | 442 | else |
443 | rc = compat_rw_copy_check_uvector(READ, lvec, liovcnt, | 443 | rc = compat_rw_copy_check_uvector(READ, lvec, liovcnt, |
444 | UIO_FASTIOV, iovstack_l, | 444 | UIO_FASTIOV, iovstack_l, |
445 | &iov_l, 1); | 445 | &iov_l); |
446 | if (rc <= 0) | 446 | if (rc <= 0) |
447 | goto free_iovecs; | 447 | goto free_iovecs; |
448 | rc = compat_rw_copy_check_uvector(READ, rvec, riovcnt, | 448 | rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, |
449 | UIO_FASTIOV, iovstack_r, | 449 | UIO_FASTIOV, iovstack_r, |
450 | &iov_r, 0); | 450 | &iov_r); |
451 | if (rc <= 0) | 451 | if (rc <= 0) |
452 | goto free_iovecs; | 452 | goto free_iovecs; |
453 | 453 | ||
diff --git a/security/keys/compat.c b/security/keys/compat.c index fab4f8dda6c6..c92d42b021aa 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -38,7 +38,7 @@ long compat_keyctl_instantiate_key_iov( | |||
38 | 38 | ||
39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
40 | ARRAY_SIZE(iovstack), | 40 | ARRAY_SIZE(iovstack), |
41 | iovstack, &iov, 1); | 41 | iovstack, &iov); |
42 | if (ret < 0) | 42 | if (ret < 0) |
43 | return ret; | 43 | return ret; |
44 | if (ret == 0) | 44 | if (ret == 0) |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 18f29de88fda..21907ea35b15 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1110,7 +1110,7 @@ long keyctl_instantiate_key_iov(key_serial_t id, | |||
1110 | goto no_payload; | 1110 | goto no_payload; |
1111 | 1111 | ||
1112 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 1112 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
1113 | ARRAY_SIZE(iovstack), iovstack, &iov, 1); | 1113 | ARRAY_SIZE(iovstack), iovstack, &iov); |
1114 | if (ret < 0) | 1114 | if (ret < 0) |
1115 | return ret; | 1115 | return ret; |
1116 | if (ret == 0) | 1116 | if (ret == 0) |