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
This commit is contained in:
Maxim Sobolev 2005-01-30 07:20:36 +00:00
parent ec217396c4
commit a6886ef173
3 changed files with 25 additions and 28 deletions

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 *);