* miscfuncs.cc (check_iovec_for_read): Don't check buffer when zero length
iov_len. (check_iovec_for_write): Ditto. * fhandler.h (fhandler_base::readv): New method. (fhandler_base::writev): Ditto. * fhandler.cc (fhandler_base::readv): New method. (fhandler_base::writev): Ditto. * syscalls.cc (_read): Delegate to readv(2). (_write): Ditto, mutatis mutandi. (readv): Rewrite, based on the old _read code, to use the new fhandler_base::readv method. Improve access mode handling and ensure all calls reach the final strace statement. (writev): Ditto, mutatis mutandi. * include/sys/uio.h (struct iovec): Change field types to match SUSv3. * winsup.h (check_iovec_for_read): New function. (check_iovec_for_write): Ditto. * miscfuncs.cc (check_iovec_for_read): Ditto. (check_iovec_for_write): Ditto.
This commit is contained in:
@ -11,6 +11,9 @@ details. */
|
||||
#include "winsup.h"
|
||||
#include "cygerrno.h"
|
||||
#include <sys/errno.h>
|
||||
#include <sys/uio.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <winbase.h>
|
||||
#include <winnls.h>
|
||||
|
||||
@ -179,6 +182,76 @@ __check_invalid_read_ptr_errno (const void *s, unsigned sz)
|
||||
return set_errno (EFAULT);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
check_iovec_for_read (const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
if (iovcnt <= 0 || iovcnt > IOV_MAX)
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (__check_invalid_read_ptr_errno (iov, iovcnt * sizeof (*iov)))
|
||||
return -1;
|
||||
|
||||
size_t tot = 0;
|
||||
|
||||
while (iovcnt != 0)
|
||||
{
|
||||
if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iov->iov_len
|
||||
&& __check_null_invalid_struct_errno (iov->iov_base, iov->iov_len))
|
||||
return -1;
|
||||
|
||||
iov += 1;
|
||||
iovcnt -= 1;
|
||||
}
|
||||
|
||||
assert (tot <= SSIZE_MAX);
|
||||
|
||||
return (ssize_t) tot;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
check_iovec_for_write (const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
if (iovcnt <= 0 || iovcnt > IOV_MAX)
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (__check_invalid_read_ptr_errno (iov, iovcnt * sizeof (*iov)))
|
||||
return -1;
|
||||
|
||||
size_t tot = 0;
|
||||
|
||||
while (iovcnt != 0)
|
||||
{
|
||||
if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iov->iov_len
|
||||
&& __check_invalid_read_ptr_errno (iov->iov_base, iov->iov_len))
|
||||
return -1;
|
||||
|
||||
iov += 1;
|
||||
iovcnt -= 1;
|
||||
}
|
||||
|
||||
assert (tot <= SSIZE_MAX);
|
||||
|
||||
return (ssize_t) tot;
|
||||
}
|
||||
|
||||
UINT
|
||||
get_cp ()
|
||||
{
|
||||
|
Reference in New Issue
Block a user