diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-04-08 18:18:48 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-04-17 12:52:26 -0400 |
commit | f50298556436ef0f32257b8ea19b112f9028b0a5 (patch) | |
tree | 32c3e7022475150ad1cbfb87f9d29c23f446ee05 /fs/compat.c | |
parent | 2b8910264a7fec4599b620e5206eb877a207f40a (diff) |
move compat_rw_copy_check_uvector() over to fs/read_write.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 76 |
1 files changed, 0 insertions, 76 deletions
diff --git a/fs/compat.c b/fs/compat.c index 3e94559c452e..ca2f3ca5dacd 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -54,82 +54,6 @@ | |||
54 | #include <asm/ioctls.h> | 54 | #include <asm/ioctls.h> |
55 | #include "internal.h" | 55 | #include "internal.h" |
56 | 56 | ||
57 | /* A write operation does a read from user space and vice versa */ | ||
58 | #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) | ||
59 | |||
60 | ssize_t compat_rw_copy_check_uvector(int type, | ||
61 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | ||
62 | unsigned long fast_segs, struct iovec *fast_pointer, | ||
63 | struct iovec **ret_pointer) | ||
64 | { | ||
65 | compat_ssize_t tot_len; | ||
66 | struct iovec *iov = *ret_pointer = fast_pointer; | ||
67 | ssize_t ret = 0; | ||
68 | int seg; | ||
69 | |||
70 | /* | ||
71 | * SuS says "The readv() function *may* fail if the iovcnt argument | ||
72 | * was less than or equal to 0, or greater than {IOV_MAX}. Linux has | ||
73 | * traditionally returned zero for zero segments, so... | ||
74 | */ | ||
75 | if (nr_segs == 0) | ||
76 | goto out; | ||
77 | |||
78 | ret = -EINVAL; | ||
79 | if (nr_segs > UIO_MAXIOV) | ||
80 | goto out; | ||
81 | if (nr_segs > fast_segs) { | ||
82 | ret = -ENOMEM; | ||
83 | iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); | ||
84 | if (iov == NULL) | ||
85 | goto out; | ||
86 | } | ||
87 | *ret_pointer = iov; | ||
88 | |||
89 | ret = -EFAULT; | ||
90 | if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) | ||
91 | goto out; | ||
92 | |||
93 | /* | ||
94 | * Single unix specification: | ||
95 | * We should -EINVAL if an element length is not >= 0 and fitting an | ||
96 | * ssize_t. | ||
97 | * | ||
98 | * In Linux, the total length is limited to MAX_RW_COUNT, there is | ||
99 | * no overflow possibility. | ||
100 | */ | ||
101 | tot_len = 0; | ||
102 | ret = -EINVAL; | ||
103 | for (seg = 0; seg < nr_segs; seg++) { | ||
104 | compat_uptr_t buf; | ||
105 | compat_ssize_t len; | ||
106 | |||
107 | if (__get_user(len, &uvector->iov_len) || | ||
108 | __get_user(buf, &uvector->iov_base)) { | ||
109 | ret = -EFAULT; | ||
110 | goto out; | ||
111 | } | ||
112 | if (len < 0) /* size_t not fitting in compat_ssize_t .. */ | ||
113 | goto out; | ||
114 | if (type >= 0 && | ||
115 | !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { | ||
116 | ret = -EFAULT; | ||
117 | goto out; | ||
118 | } | ||
119 | if (len > MAX_RW_COUNT - tot_len) | ||
120 | len = MAX_RW_COUNT - tot_len; | ||
121 | tot_len += len; | ||
122 | iov->iov_base = compat_ptr(buf); | ||
123 | iov->iov_len = (compat_size_t) len; | ||
124 | uvector++; | ||
125 | iov++; | ||
126 | } | ||
127 | ret = tot_len; | ||
128 | |||
129 | out: | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | struct compat_ncp_mount_data { | 57 | struct compat_ncp_mount_data { |
134 | compat_int_t version; | 58 | compat_int_t version; |
135 | compat_uint_t ncp_fd; | 59 | compat_uint_t ncp_fd; |