Commit dd254f5a authored by Al Viro's avatar Al Viro

fold checks into iterate_and_advance()

they are open-coded in all users except iov_iter_advance(), and there
they wouldn't be a bad idea either - as it is, iov_iter_advance(i, 0)
ends up dereferencing potentially past the end of iovec array.  It
doesn't do anything with the value it reads, and very unlikely to
trigger an oops on dereference, but it is not impossible.
Reported-by: default avatarJiri Slaby <jslaby@suse.cz>
Reported-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 7367ab91
...@@ -99,6 +99,9 @@ ...@@ -99,6 +99,9 @@
} }
#define iterate_and_advance(i, n, v, I, B, K) { \ #define iterate_and_advance(i, n, v, I, B, K) { \
if (unlikely(i->count < n)) \
n = i->count; \
if (n) { \
size_t skip = i->iov_offset; \ size_t skip = i->iov_offset; \
if (unlikely(i->type & ITER_BVEC)) { \ if (unlikely(i->type & ITER_BVEC)) { \
const struct bio_vec *bvec; \ const struct bio_vec *bvec; \
...@@ -133,6 +136,7 @@ ...@@ -133,6 +136,7 @@
} \ } \
i->count -= n; \ i->count -= n; \
i->iov_offset = skip; \ i->iov_offset = skip; \
} \
} }
static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes,
...@@ -386,12 +390,6 @@ static void memzero_page(struct page *page, size_t offset, size_t len) ...@@ -386,12 +390,6 @@ static void memzero_page(struct page *page, size_t offset, size_t len)
size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
{ {
const char *from = addr; const char *from = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len,
v.iov_len), v.iov_len),
...@@ -407,12 +405,6 @@ EXPORT_SYMBOL(copy_to_iter); ...@@ -407,12 +405,6 @@ EXPORT_SYMBOL(copy_to_iter);
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
{ {
char *to = addr; char *to = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base,
v.iov_len), v.iov_len),
...@@ -428,12 +420,6 @@ EXPORT_SYMBOL(copy_from_iter); ...@@ -428,12 +420,6 @@ EXPORT_SYMBOL(copy_from_iter);
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
{ {
char *to = addr; char *to = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_from_user_nocache((to += v.iov_len) - v.iov_len, __copy_from_user_nocache((to += v.iov_len) - v.iov_len,
v.iov_base, v.iov_len), v.iov_base, v.iov_len),
...@@ -474,12 +460,6 @@ EXPORT_SYMBOL(copy_page_from_iter); ...@@ -474,12 +460,6 @@ EXPORT_SYMBOL(copy_page_from_iter);
size_t iov_iter_zero(size_t bytes, struct iov_iter *i) size_t iov_iter_zero(size_t bytes, struct iov_iter *i)
{ {
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__clear_user(v.iov_base, v.iov_len), __clear_user(v.iov_base, v.iov_len),
memzero_page(v.bv_page, v.bv_offset, v.bv_len), memzero_page(v.bv_page, v.bv_offset, v.bv_len),
...@@ -666,12 +646,6 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, ...@@ -666,12 +646,6 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
char *to = addr; char *to = addr;
__wsum sum, next; __wsum sum, next;
size_t off = 0; size_t off = 0;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
sum = *csum; sum = *csum;
iterate_and_advance(i, bytes, v, ({ iterate_and_advance(i, bytes, v, ({
int err = 0; int err = 0;
...@@ -710,12 +684,6 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, ...@@ -710,12 +684,6 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
const char *from = addr; const char *from = addr;
__wsum sum, next; __wsum sum, next;
size_t off = 0; size_t off = 0;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
sum = *csum; sum = *csum;
iterate_and_advance(i, bytes, v, ({ iterate_and_advance(i, bytes, v, ({
int err = 0; int err = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment