summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-01-30 07:20:36 +0000
committersobomax <sobomax@FreeBSD.org>2005-01-30 07:20:36 +0000
commit68d0bd21861da82ecf4f8a65da75bedd481808f7 (patch)
tree042e685eec02cb357f60671bc22dc8187b988d46
parentc1d75210e2c793e8e0b6cd0ce52bc8f9a4031869 (diff)
downloadFreeBSD-src-68d0bd21861da82ecf4f8a65da75bedd481808f7.zip
FreeBSD-src-68d0bd21861da82ecf4f8a65da75bedd481808f7.tar.gz
Extend kern_sendit() to take another enum uio_seg argument, which specifies
where the buffer to send lies and use it to eliminate yet another stackgap in linuxlator. MFC after: 2 weeks
-rw-r--r--sys/compat/linux/linux_socket.c44
-rw-r--r--sys/kern/uipc_syscalls.c7
-rw-r--r--sys/sys/syscallsubr.h2
3 files changed, 25 insertions, 28 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 1770edd..dd358ce 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -368,7 +368,8 @@ linux_sa_put(struct osockaddr *osa)
}
static int
-linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags)
+linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
+ enum uio_seg segflg)
{
struct mbuf *control;
struct sockaddr *to;
@@ -399,7 +400,8 @@ linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags)
} else
control = NULL;
- error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control);
+ error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control,
+ segflg);
bad:
if (to)
@@ -441,33 +443,25 @@ linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args)
/*
* linux_ip_copysize defines how many bytes we should copy
* from the beginning of the IP packet before we customize it for BSD.
- * It should include all the fields we modify (ip_len and ip_off)
- * and be as small as possible to minimize copying overhead.
+ * It should include all the fields we modify (ip_len and ip_off).
*/
#define linux_ip_copysize 8
struct ip *packet;
- caddr_t sg = stackgap_init();
struct msghdr msg;
- struct iovec aiov[2];
+ struct iovec aiov[1];
int error;
/* Check the packet isn't too small before we mess with it */
if (linux_args->len < linux_ip_copysize)
return (EINVAL);
- /*
- * Tweaking the user buffer in place would be bad manners.
- * We create a corrected IP header with just the needed length,
- * then use an iovec to glue it to the rest of the user packet
- * when calling sendit().
- */
- packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
+ packet = (struct ip *)malloc(linux_args->len, M_TEMP, M_WAITOK);
- /* Make a copy of the beginning of the packet to be sent */
+ /* Make kernel copy of the packet to be sent */
if ((error = copyin(PTRIN(linux_args->msg), packet,
- linux_ip_copysize)))
- return (error);
+ linux_args->len)))
+ goto goout;
/* Convert fields from Linux to BSD raw IP socket format */
packet->ip_len = linux_args->len;
@@ -477,15 +471,15 @@ linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args)
msg.msg_name = PTRIN(linux_args->to);
msg.msg_namelen = linux_args->tolen;
msg.msg_iov = aiov;
- msg.msg_iovlen = 2;
+ msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_flags = 0;
aiov[0].iov_base = (char *)packet;
- aiov[0].iov_len = linux_ip_copysize;
- aiov[1].iov_base = (char *)PTRIN(linux_args->msg) +
- linux_ip_copysize;
- aiov[1].iov_len = linux_args->len - linux_ip_copysize;
- error = linux_sendit(td, linux_args->s, &msg, linux_args->flags);
+ aiov[0].iov_len = linux_args->len;
+ error = linux_sendit(td, linux_args->s, &msg, linux_args->flags,
+ UIO_SYSSPACE);
+goout:
+ free(packet, M_TEMP);
return (error);
}
@@ -892,7 +886,8 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
msg.msg_flags = 0;
aiov.iov_base = PTRIN(linux_args.msg);
aiov.iov_len = linux_args.len;
- error = linux_sendit(td, linux_args.s, &msg, linux_args.flags);
+ error = linux_sendit(td, linux_args.s, &msg, linux_args.flags,
+ UIO_USERSPACE);
return (error);
}
@@ -968,7 +963,8 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
return (error);
msg.msg_iov = iov;
msg.msg_flags = 0;
- error = linux_sendit(td, linux_args.s, &msg, linux_args.flags);
+ error = linux_sendit(td, linux_args.s, &msg, linux_args.flags,
+ UIO_USERSPACE);
free(iov, M_IOV);
return (error);
}
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 8096564..8deefe5 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -690,7 +690,7 @@ sendit(td, s, mp, flags)
control = NULL;
}
- error = kern_sendit(td, s, mp, flags, control);
+ error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
bad:
if (to)
@@ -699,12 +699,13 @@ bad:
}
int
-kern_sendit(td, s, mp, flags, control)
+kern_sendit(td, s, mp, flags, control, segflg)
struct thread *td;
int s;
struct msghdr *mp;
int flags;
struct mbuf *control;
+ enum uio_seg segflg;
{
struct file *fp;
struct uio auio;
@@ -732,7 +733,7 @@ kern_sendit(td, s, mp, flags, control)
auio.uio_iov = mp->msg_iov;
auio.uio_iovcnt = mp->msg_iovlen;
- auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_segflg = segflg;
auio.uio_rw = UIO_WRITE;
auio.uio_td = td;
auio.uio_offset = 0; /* XXX */
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index b7bb0f1..57bed2c 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -90,7 +90,7 @@ int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);
int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_set *fd_ex, struct timeval *tvp);
int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
- struct mbuf *control);
+ struct mbuf *control, enum uio_seg segflg);
int kern_setitimer(struct thread *, u_int, struct itimerval *,
struct itimerval *);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
OpenPOWER on IntegriCloud