summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2002-09-19 08:36:47 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-09-19 08:36:47 -0700
commitd4872de38e4c74dd5c56facbd986da46ca551b65 (patch)
tree9eed86e6eb11d9fe885e91d528666cec306e656b /include
parentbd90a275f400dc3b46dd72cec221f1db13bffc0f (diff)
[PATCH] readv/writev bounds checking fixes
- writev currently returns -EFAULT if _any_ of the segments has an invalid address. We should only return -EFAULT if the first segment has a bad address. If some of the first segments have valid addresses we need to write them and return a partial result. - The current code only checks if the sum-of-lengths is negative. If individual segments have a negative length but the result is positive we miss that. So rework the code to detect this, and to be immune to odd wrapping situations. As a bonus, we save one pass across the iovec. - ditto for readv. The check for "does any segment have a negative length" has already been performed in do_readv_writev(), but it's basically free here, and we need to do it for generic_file_read/write anyway. This all means that the iov_length() function is unsafe because of wrap/overflow isues. It should only be used after the generic_file_read/write or do_readv_writev() checking has been performed. Its callers have been reviewed and they are OK. The code now passes LTP testing and has been QA'd by Janet's team.
Diffstat (limited to 'include')
-rw-r--r--include/linux/uio.h6
1 files changed, 5 insertions, 1 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h
index ec098c8e6793..85b2f0ec9d3f 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -35,7 +35,11 @@ struct iovec
#endif
/*
- * Total number of bytes covered by an iovec
+ * Total number of bytes covered by an iovec.
+ *
+ * NOTE that it is not safe to use this function until all the iovec's
+ * segment lengths have been validated. Because the individual lengths can
+ * overflow a size_t when added together.
*/
static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
{