diff options
author | Jeff Moyer <jmoyer@redhat.com> | 2010-05-26 17:44:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 12:12:53 -0400 |
commit | 9d85cba718efeef9ca00ce3f7f34f5880737aa9b (patch) | |
tree | d445d35d915b65dac171e58f83c75feb15d625fd /include | |
parent | b83733639a494d5f42fa00a2506563fbd2d3015d (diff) |
aio: fix the compat vectored operations
The aio compat code was not converting the struct iovecs from 32bit to
64bit pointers, causing either EINVAL to be returned from io_getevents, or
EFAULT as the result of the I/O. This patch passes a compat flag to
io_submit to signal that pointer conversion is necessary for a given iocb
array.
A variant of this was tested by Michael Tokarev. I have also updated the
libaio test harness to exercise this code path with good success.
Further, I grabbed a copy of ltp and ran the
testcases/kernel/syscall/readv and writev tests there (compiled with -m32
on my 64bit system). All seems happy, but extra eyes on this would be
welcome.
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: fix CONFIG_COMPAT=n build]
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Reported-by: Michael Tokarev <mjt@tls.msk.ru>
Cc: Zach Brown <zach.brown@oracle.com>
Cc: <stable@kernel.org> [2.6.35.1]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/aio.h | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/include/linux/aio.h b/include/linux/aio.h index 811dbb369379..7a8db4155281 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h | |||
@@ -212,6 +212,8 @@ extern void kick_iocb(struct kiocb *iocb); | |||
212 | extern int aio_complete(struct kiocb *iocb, long res, long res2); | 212 | extern int aio_complete(struct kiocb *iocb, long res, long res2); |
213 | struct mm_struct; | 213 | struct mm_struct; |
214 | extern void exit_aio(struct mm_struct *mm); | 214 | extern void exit_aio(struct mm_struct *mm); |
215 | extern long do_io_submit(aio_context_t ctx_id, long nr, | ||
216 | struct iocb __user *__user *iocbpp, bool compat); | ||
215 | #else | 217 | #else |
216 | static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; } | 218 | static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; } |
217 | static inline int aio_put_req(struct kiocb *iocb) { return 0; } | 219 | static inline int aio_put_req(struct kiocb *iocb) { return 0; } |
@@ -219,6 +221,9 @@ static inline void kick_iocb(struct kiocb *iocb) { } | |||
219 | static inline int aio_complete(struct kiocb *iocb, long res, long res2) { return 0; } | 221 | static inline int aio_complete(struct kiocb *iocb, long res, long res2) { return 0; } |
220 | struct mm_struct; | 222 | struct mm_struct; |
221 | static inline void exit_aio(struct mm_struct *mm) { } | 223 | static inline void exit_aio(struct mm_struct *mm) { } |
224 | static inline long do_io_submit(aio_context_t ctx_id, long nr, | ||
225 | struct iocb __user * __user *iocbpp, | ||
226 | bool compat) { return 0; } | ||
222 | #endif /* CONFIG_AIO */ | 227 | #endif /* CONFIG_AIO */ |
223 | 228 | ||
224 | static inline struct kiocb *list_kiocb(struct list_head *h) | 229 | static inline struct kiocb *list_kiocb(struct list_head *h) |