Skip to content

Commit ac34ebb

Browse files
Christopher Yeohtorvalds
Christopher Yeoh
authored andcommitted
aio/vfs: cleanup of rw_copy_check_uvector() and compat_rw_copy_check_uvector()
A cleanup of rw_copy_check_uvector and compat_rw_copy_check_uvector after changes made to support CMA in an earlier patch. Rather than having an additional check_access parameter to these functions, the first paramater type is overloaded to allow the caller to specify CHECK_IOVEC_ONLY which means check that the contents of the iovec are valid, but do not check the memory that they point to. This is used by process_vm_readv/writev where we need to validate that a iovec passed to the syscall is valid but do not want to check the memory that it points to at this point because it refers to an address space in another process. Signed-off-by: Chris Yeoh <yeohc@au1.ibm.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent ee62c6b commit ac34ebb

File tree

8 files changed

+29
-23
lines changed

8 files changed

+29
-23
lines changed

fs/aio.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1446,13 +1446,13 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
14461446
ret = compat_rw_copy_check_uvector(type,
14471447
(struct compat_iovec __user *)kiocb->ki_buf,
14481448
kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
1449-
&kiocb->ki_iovec, 1);
1449+
&kiocb->ki_iovec);
14501450
else
14511451
#endif
14521452
ret = rw_copy_check_uvector(type,
14531453
(struct iovec __user *)kiocb->ki_buf,
14541454
kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
1455-
&kiocb->ki_iovec, 1);
1455+
&kiocb->ki_iovec);
14561456
if (ret < 0)
14571457
goto out;
14581458

fs/compat.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ compat_sys_io_getevents(aio_context_t ctx_id,
532532
ssize_t compat_rw_copy_check_uvector(int type,
533533
const struct compat_iovec __user *uvector, unsigned long nr_segs,
534534
unsigned long fast_segs, struct iovec *fast_pointer,
535-
struct iovec **ret_pointer, int check_access)
535+
struct iovec **ret_pointer)
536536
{
537537
compat_ssize_t tot_len;
538538
struct iovec *iov = *ret_pointer = fast_pointer;
@@ -579,7 +579,7 @@ ssize_t compat_rw_copy_check_uvector(int type,
579579
}
580580
if (len < 0) /* size_t not fitting in compat_ssize_t .. */
581581
goto out;
582-
if (check_access &&
582+
if (type >= 0 &&
583583
!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
584584
ret = -EFAULT;
585585
goto out;
@@ -1094,7 +1094,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
10941094
goto out;
10951095

10961096
tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
1097-
UIO_FASTIOV, iovstack, &iov, 1);
1097+
UIO_FASTIOV, iovstack, &iov);
10981098
if (tot_len == 0) {
10991099
ret = 0;
11001100
goto out;

fs/read_write.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,7 @@ ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
633633
ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
634634
unsigned long nr_segs, unsigned long fast_segs,
635635
struct iovec *fast_pointer,
636-
struct iovec **ret_pointer,
637-
int check_access)
636+
struct iovec **ret_pointer)
638637
{
639638
unsigned long seg;
640639
ssize_t ret;
@@ -690,7 +689,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
690689
ret = -EINVAL;
691690
goto out;
692691
}
693-
if (check_access
692+
if (type >= 0
694693
&& unlikely(!access_ok(vrfy_dir(type), buf, len))) {
695694
ret = -EFAULT;
696695
goto out;
@@ -723,7 +722,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
723722
}
724723

725724
ret = rw_copy_check_uvector(type, uvector, nr_segs,
726-
ARRAY_SIZE(iovstack), iovstack, &iov, 1);
725+
ARRAY_SIZE(iovstack), iovstack, &iov);
727726
if (ret <= 0)
728727
goto out;
729728

include/linux/compat.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,7 @@ extern ssize_t compat_rw_copy_check_uvector(int type,
577577
const struct compat_iovec __user *uvector,
578578
unsigned long nr_segs,
579579
unsigned long fast_segs, struct iovec *fast_pointer,
580-
struct iovec **ret_pointer,
581-
int check_access);
580+
struct iovec **ret_pointer);
582581

583582
extern void __user *compat_alloc_user_space(unsigned long len);
584583

include/linux/fs.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ struct inodes_stat_t {
173173
#define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA)
174174
#define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
175175

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+
176185
#define SEL_IN 1
177186
#define SEL_OUT 2
178187
#define SEL_EX 4
@@ -1690,8 +1699,7 @@ struct seq_file;
16901699
ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
16911700
unsigned long nr_segs, unsigned long fast_segs,
16921701
struct iovec *fast_pointer,
1693-
struct iovec **ret_pointer,
1694-
int check_access);
1702+
struct iovec **ret_pointer);
16951703

16961704
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
16971705
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);

mm/process_vm_access.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,15 @@ static ssize_t process_vm_rw(pid_t pid,
371371
/* Check iovecs */
372372
if (vm_write)
373373
rc = rw_copy_check_uvector(WRITE, lvec, liovcnt, UIO_FASTIOV,
374-
iovstack_l, &iov_l, 1);
374+
iovstack_l, &iov_l);
375375
else
376376
rc = rw_copy_check_uvector(READ, lvec, liovcnt, UIO_FASTIOV,
377-
iovstack_l, &iov_l, 1);
377+
iovstack_l, &iov_l);
378378
if (rc <= 0)
379379
goto free_iovecs;
380380

381-
rc = rw_copy_check_uvector(READ, rvec, riovcnt, UIO_FASTIOV,
382-
iovstack_r, &iov_r, 0);
381+
rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV,
382+
iovstack_r, &iov_r);
383383
if (rc <= 0)
384384
goto free_iovecs;
385385

@@ -438,16 +438,16 @@ compat_process_vm_rw(compat_pid_t pid,
438438
if (vm_write)
439439
rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt,
440440
UIO_FASTIOV, iovstack_l,
441-
&iov_l, 1);
441+
&iov_l);
442442
else
443443
rc = compat_rw_copy_check_uvector(READ, lvec, liovcnt,
444444
UIO_FASTIOV, iovstack_l,
445-
&iov_l, 1);
445+
&iov_l);
446446
if (rc <= 0)
447447
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,
449449
UIO_FASTIOV, iovstack_r,
450-
&iov_r, 0);
450+
&iov_r);
451451
if (rc <= 0)
452452
goto free_iovecs;
453453

security/keys/compat.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ long compat_keyctl_instantiate_key_iov(
3838

3939
ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
4040
ARRAY_SIZE(iovstack),
41-
iovstack, &iov, 1);
41+
iovstack, &iov);
4242
if (ret < 0)
4343
return ret;
4444
if (ret == 0)

security/keys/keyctl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ long keyctl_instantiate_key_iov(key_serial_t id,
11101110
goto no_payload;
11111111

11121112
ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
1113-
ARRAY_SIZE(iovstack), iovstack, &iov, 1);
1113+
ARRAY_SIZE(iovstack), iovstack, &iov);
11141114
if (ret < 0)
11151115
return ret;
11161116
if (ret == 0)

0 commit comments

Comments
 (0)