Skip to content

Commit

Permalink
OS-4983 lxbrand nginx proxy mangles content
Browse files Browse the repository at this point in the history
OS-4829 lxbrand convert readv/writev to IKE
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
  • Loading branch information
pfmooney committed Nov 30, 2015
1 parent 6ee6839 commit 5ed3437
Show file tree
Hide file tree
Showing 6 changed files with 528 additions and 154 deletions.
122 changes: 0 additions & 122 deletions usr/src/lib/brand/lx/lx_brand/common/iovec.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,128 +160,6 @@ lx_pwrite64(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4,
}
#endif

/*
* Implementation of Linux readv() and writev() system calls.
*
* The Linux system calls differ from the Solaris system calls in a few key
* areas:
*
* - On Solaris, the maximum number of I/O vectors that can be passed to readv()
* or writev() is IOV_MAX (16). Linux has a much larger restriction (1024).
*
* - Passing 0 as a vector count is an error on Solaris, but on Linux results
* in a return value of 0. Even though the man page says the opposite.
*
* - If the Nth vector results in an error, Solaris will return an error code
* for the entire operation. Linux only returns an error if there has been
* no data transferred yet. Otherwise, it returns the number of bytes
* transferred up until that point.
*
* In order to accomodate these differences, we implement these functions as a
* series of ordinary read() or write() calls.
*/

#define LX_IOV_MAX 1024 /* Also called MAX_IOVEC */

static int
lx_iovec_copy_and_check(const struct iovec *iovp, struct iovec *iov, int count)
{
#if defined(_ILP32)
int i;
ssize_t cnt = 0;
#endif

if (uucopy(iovp, (void *)iov, count * sizeof (struct iovec)) != 0)
return (-errno);

#if defined(_ILP32)
for (i = 0; i < count; i++) {
cnt += iov[i].iov_len;
if (iov[i].iov_len < 0 || cnt < 0)
return (-EINVAL);
}
#endif

return (0);
}

long
lx_readv(uintptr_t p1, uintptr_t p2, uintptr_t p3)
{
int fd = (int)p1;
const struct iovec *iovp = (const struct iovec *)p2;
int count = (int)p3;
struct iovec *iov;
ssize_t total = 0, ret;
int i;

if (count == 0)
return (0);

if (count < 0 || count > LX_IOV_MAX)
return (-EINVAL);

if (lx_is_directory(fd))
return (-EISDIR);

iov = SAFE_ALLOCA(count * sizeof (struct iovec));
if (iov == NULL)
return (-ENOMEM);
if ((ret = lx_iovec_copy_and_check(iovp, iov, count)) != 0)
return (ret);

for (i = 0; i < count; i++) {
ret = read(fd, iov[i].iov_base, iov[i].iov_len);

if (ret < 0) {
if (total > 0)
return (total);
return (-errno);
}

total += ret;
}

return (total);
}

long
lx_writev(uintptr_t p1, uintptr_t p2, uintptr_t p3)
{
int fd = (int)p1;
const struct iovec *iovp = (const struct iovec *)p2;
int count = (int)p3;
struct iovec *iov;
ssize_t total = 0, ret;
int i;

if (count == 0)
return (0);

if (count < 0 || count > LX_IOV_MAX)
return (-EINVAL);

iov = SAFE_ALLOCA(count * sizeof (struct iovec));
if (iov == NULL)
return (-ENOMEM);
if ((ret = lx_iovec_copy_and_check(iovp, iov, count)) != 0)
return (ret);

for (i = 0; i < count; i++) {
ret = write(fd, iov[i].iov_base, iov[i].iov_len);

if (ret < 0) {
if (total > 0)
return (total);
return (-errno);
}

total += ret;
}

return (total);
}

long
lx_preadv(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
{
Expand Down
8 changes: 4 additions & 4 deletions usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,8 +959,8 @@ static lx_syscall_handler_t lx_handlers[] = {
NULL, /* 16: ioctl */
lx_pread, /* 17: pread64 */
lx_pwrite, /* 18: pwrite64 */
lx_readv, /* 19: readv */
lx_writev, /* 20: writev */
NULL, /* 19: readv */
NULL, /* 20: writev */
lx_access, /* 21: access */
NULL, /* 22: pipe */
lx_select, /* 23: select */
Expand Down Expand Up @@ -1416,8 +1416,8 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_select, /* 142: select */
lx_flock, /* 143: flock */
lx_msync, /* 144: msync */
lx_readv, /* 145: readv */
lx_writev, /* 146: writev */
NULL, /* 145: readv */
NULL, /* 146: writev */
lx_getsid, /* 147: getsid */
lx_fdatasync, /* 148: fdatasync */
lx_sysctl, /* 149: sysctl */
Expand Down
2 changes: 0 additions & 2 deletions usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ extern long lx_vhangup(void);
extern long lx_fadvise64(uintptr_t, off64_t, uintptr_t, uintptr_t);
extern long lx_fadvise64_64(uintptr_t, off64_t, off64_t, uintptr_t);

extern long lx_readv(uintptr_t, uintptr_t, uintptr_t);
extern long lx_writev(uintptr_t, uintptr_t, uintptr_t);
extern long lx_pread(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_pwrite(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_preadv(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
Expand Down
8 changes: 4 additions & 4 deletions usr/src/uts/common/brand/lx/os/lx_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,8 @@ lx_sysent_t lx_sysent32[] = {
{"select", NULL, 0, 5}, /* 142 */
{"flock", NULL, 0, 2}, /* 143 */
{"msync", NULL, 0, 3}, /* 144 */
{"readv", NULL, 0, 3}, /* 145 */
{"writev", NULL, 0, 3}, /* 146 */
{"readv", lx_readv, 0, 3}, /* 145 */
{"writev", lx_writev, 0, 3}, /* 146 */
{"getsid", NULL, 0, 1}, /* 147 */
{"fdatasync", NULL, 0, 1}, /* 148 */
{"sysctl", NULL, 0, 1}, /* 149 */
Expand Down Expand Up @@ -1006,8 +1006,8 @@ lx_sysent_t lx_sysent64[] = {
{"ioctl", lx_ioctl, 0, 3}, /* 16 */
{"pread64", NULL, 0, 4}, /* 17 */
{"pwrite64", NULL, 0, 4}, /* 18 */
{"readv", NULL, 0, 3}, /* 19 */
{"writev", NULL, 0, 3}, /* 20 */
{"readv", lx_readv, 0, 3}, /* 19 */
{"writev", lx_writev, 0, 3}, /* 20 */
{"access", NULL, 0, 2}, /* 21 */
{"pipe", lx_pipe, 0, 1}, /* 22 */
{"select", NULL, 0, 5}, /* 23 */
Expand Down
2 changes: 2 additions & 0 deletions usr/src/uts/common/brand/lx/sys/lx_syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ extern long lx_prctl();
extern long lx_prlimit64();
extern long lx_ptrace();
extern long lx_read();
extern long lx_readv();
extern long lx_recv();
extern long lx_recvmsg();
extern long lx_recvfrom();
Expand Down Expand Up @@ -125,6 +126,7 @@ extern long lx_wait4();
extern long lx_waitid();
extern long lx_waitpid();
extern long lx_write();
extern long lx_writev();
extern long lx_xattr();

#if defined(_LP64)
Expand Down

0 comments on commit 5ed3437

Please sign in to comment.