From 20c4c9e77ea6a57f3c0409efabb615e549832d5a Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Tue, 21 Aug 2007 19:07:10 +0000 Subject: [PATCH] Don't trust the user, and enforce the iovec limit. Also check for negative positions smaller -1 (as -1 means using current address). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22031 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/posix/limits.h | 2 +- src/system/kernel/fs/fd.c | 40 +++++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/headers/posix/limits.h b/headers/posix/limits.h index 509fbe69c5..fd44b23fdf 100644 --- a/headers/posix/limits.h +++ b/headers/posix/limits.h @@ -27,7 +27,7 @@ #define ARG_MAX (32768) #define ATEXIT_MAX (32) /* XXXdbg */ #define CHILD_MAX (1024) -#define IOV_MAX (256) /* really there is no limit */ +#define IOV_MAX (1024) #define FILESIZEBITS (64) #define LINK_MAX (1) #define LOGIN_NAME_MAX (32) /* XXXdbg */ diff --git a/src/system/kernel/fs/fd.c b/src/system/kernel/fs/fd.c index 458e3f005b..2b5ca628c9 100644 --- a/src/system/kernel/fs/fd.c +++ b/src/system/kernel/fs/fd.c @@ -481,6 +481,9 @@ _user_read(int fd, off_t pos, void *buffer, size_t length) if (!IS_USER_ADDRESS(buffer)) return B_BAD_ADDRESS; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(false), fd); if (!descriptor) return B_FILE_ERROR; @@ -523,6 +526,13 @@ _user_readv(int fd, off_t pos, const iovec *userVecs, size_t count) if (!IS_USER_ADDRESS(userVecs)) return B_BAD_ADDRESS; + if (pos < -1) + return B_BAD_VALUE; + + /* prevent integer overflow exploit in malloc() */ + if (count > IOV_MAX) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(false), fd); if (!descriptor) return B_FILE_ERROR; @@ -554,7 +564,7 @@ _user_readv(int fd, off_t pos, const iovec *userVecs, size_t count) break; } - if ((uint32)bytesRead + length > SSIZE_MAX) + if ((uint64)bytesRead + length > SSIZE_MAX) bytesRead = SSIZE_MAX; else bytesRead += (ssize_t)length; @@ -584,6 +594,9 @@ _user_write(int fd, off_t pos, const void *buffer, size_t length) if (IS_KERNEL_ADDRESS(buffer)) return B_BAD_ADDRESS; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(false), fd); if (!descriptor) return B_FILE_ERROR; @@ -626,6 +639,13 @@ _user_writev(int fd, off_t pos, const iovec *userVecs, size_t count) if (!IS_USER_ADDRESS(userVecs)) return B_BAD_ADDRESS; + if (pos < -1) + return B_BAD_VALUE; + + /* prevent integer overflow exploit in malloc() */ + if (count > IOV_MAX) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(false), fd); if (!descriptor) return B_FILE_ERROR; @@ -657,7 +677,7 @@ _user_writev(int fd, off_t pos, const iovec *userVecs, size_t count) break; } - if ((uint32)bytesWritten + length > SSIZE_MAX) + if ((uint64)bytesWritten + length > SSIZE_MAX) bytesWritten = SSIZE_MAX; else bytesWritten += (ssize_t)length; @@ -795,6 +815,9 @@ _kern_read(int fd, off_t pos, void *buffer, size_t length) struct file_descriptor *descriptor; ssize_t bytesRead; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(true), fd); if (!descriptor) return B_FILE_ERROR; @@ -832,6 +855,9 @@ _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count) status_t status; uint32 i; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(true), fd); if (!descriptor) return B_FILE_ERROR; @@ -852,7 +878,7 @@ _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count) break; } - if ((uint32)bytesRead + length > SSIZE_MAX) + if ((uint64)bytesRead + length > SSIZE_MAX) bytesRead = SSIZE_MAX; else bytesRead += (ssize_t)length; @@ -874,6 +900,9 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t length) struct file_descriptor *descriptor; ssize_t bytesWritten; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(true), fd); if (descriptor == NULL) return B_FILE_ERROR; @@ -911,6 +940,9 @@ _kern_writev(int fd, off_t pos, const iovec *vecs, size_t count) status_t status; uint32 i; + if (pos < -1) + return B_BAD_VALUE; + descriptor = get_fd(get_current_io_context(true), fd); if (!descriptor) return B_FILE_ERROR; @@ -931,7 +963,7 @@ _kern_writev(int fd, off_t pos, const iovec *vecs, size_t count) break; } - if ((uint32)bytesWritten + length > SSIZE_MAX) + if ((uint64)bytesWritten + length > SSIZE_MAX) bytesWritten = SSIZE_MAX; else bytesWritten += (ssize_t)length;