From bfe2c8cb22c42d50fb6fe83d2e151ff32f7af3b5 Mon Sep 17 00:00:00 2001 From: kib Date: Sat, 29 Nov 2008 14:55:24 +0000 Subject: [PATCH] Fix iovec32 for linux32/amd64. Add a custom version of copyiniov() to deal with the 32-bit iovec pointers from userland (to be used later). Adjust prototypes for linux_readv() and linux_writev() to use new l_iovec32 definition and to match actual linux code. In particular, use ulong for fd (why ?). Submitted by: dchagin --- sys/amd64/linux32/linux.h | 10 +++++++ sys/amd64/linux32/linux32_machdep.c | 43 ++++++++++++++++++++++------- sys/amd64/linux32/syscalls.master | 8 +++--- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index 60598a0019b9..020ddd24d1f5 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -885,6 +885,16 @@ struct l_user_desc { (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \ LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD) +struct iovec; + +struct l_iovec32 { + uint32_t iov_base; + l_size_t iov_len; +}; + +int linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, + struct iovec **iovp, int error); + /* robust futexes */ struct linux_robust_list { l_uintptr_t next; diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index fcf01c89eb19..c8869e2e79e5 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -232,20 +232,15 @@ linux_execve(struct thread *td, struct linux_execve_args *args) return (error); } -struct iovec32 { - u_int32_t iov_base; - int iov_len; -}; - -CTASSERT(sizeof(struct iovec32) == 8); +CTASSERT(sizeof(struct l_iovec32) == 8); static int -linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) +linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop) { - struct iovec32 iov32; + struct l_iovec32 iov32; struct iovec *iov; struct uio *uio; - u_int iovlen; + uint32_t iovlen; int error, i; *uiop = NULL; @@ -255,7 +250,7 @@ linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK); iov = (struct iovec *)(uio + 1); for (i = 0; i < iovcnt; i++) { - error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); + error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32)); if (error) { free(uio, M_IOV); return (error); @@ -280,6 +275,34 @@ linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) return (0); } +int +linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp, + int error) +{ + struct l_iovec32 iov32; + struct iovec *iov; + uint32_t iovlen; + int i; + + *iovp = NULL; + if (iovcnt > UIO_MAXIOV) + return (error); + iovlen = iovcnt * sizeof(struct iovec); + iov = malloc(iovlen, M_IOV, M_WAITOK); + for (i = 0; i < iovcnt; i++) { + error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32)); + if (error) { + free(iov, M_IOV); + return (error); + } + iov[i].iov_base = PTRIN(iov32.iov_base); + iov[i].iov_len = iov32.iov_len; + } + *iovp = iov; + return(0); + +} + int linux_readv(struct thread *td, struct linux_readv_args *uap) { diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master index fe0485ea8b40..9aff0fc93171 100644 --- a/sys/amd64/linux32/syscalls.master +++ b/sys/amd64/linux32/syscalls.master @@ -252,10 +252,10 @@ 143 AUE_FLOCK NOPROTO { int flock(int fd, int how); } 144 AUE_MSYNC STD { int linux_msync(l_ulong addr, \ l_size_t len, l_int fl); } -145 AUE_READV STD { int linux_readv(int fd, struct iovec32 *iovp, \ - u_int iovcnt); } -146 AUE_WRITEV STD { int linux_writev(int fd, struct iovec32 *iovp, \ - u_int iovcnt); } +145 AUE_READV STD { int linux_readv(l_ulong fd, struct l_iovec32 *iovp, \ + l_ulong iovcnt); } +146 AUE_WRITEV STD { int linux_writev(l_ulong fd, struct l_iovec32 *iovp, \ + l_ulong iovcnt); } 147 AUE_GETSID STD { int linux_getsid(l_pid_t pid); } 148 AUE_NULL STD { int linux_fdatasync(l_uint fd); } 149 AUE_SYSCTL STD { int linux_sysctl( \