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:
parent
ec217396c4
commit
a6886ef173
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user