Rewrite linux_recvfrom. To avoid double conversion of sockaddr use
kern_recvit() directly. And check fromlen parameter before sockaddr copyin and conversion. Differential Revision: https://reviews.freebsd.org/D1082
This commit is contained in:
parent
437c43c1cb
commit
9599b0ec3a
@ -428,7 +428,6 @@ linux_to_bsd_sockaddr(struct sockaddr *arg, int len)
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
linux_sa_put(struct osockaddr *osa)
|
||||
{
|
||||
@ -1027,41 +1026,50 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
|
||||
int
|
||||
linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
|
||||
{
|
||||
struct recvfrom_args /* {
|
||||
int s;
|
||||
caddr_t buf;
|
||||
size_t len;
|
||||
int flags;
|
||||
struct sockaddr * __restrict from;
|
||||
socklen_t * __restrict fromlenaddr;
|
||||
} */ bsd_args;
|
||||
size_t len;
|
||||
struct msghdr msg;
|
||||
struct iovec aiov;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(PTRIN(args->fromlen), &len, sizeof(size_t))))
|
||||
if (PTRIN(args->fromlen) != NULL) {
|
||||
error = copyin(PTRIN(args->fromlen), &msg.msg_namelen,
|
||||
sizeof(msg.msg_namelen));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = linux_to_bsd_sockaddr((struct sockaddr *)PTRIN(args->from),
|
||||
msg.msg_namelen);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
} else
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
msg.msg_name = (struct sockaddr * __restrict)PTRIN(args->from);
|
||||
msg.msg_iov = &aiov;
|
||||
msg.msg_iovlen = 1;
|
||||
aiov.iov_base = PTRIN(args->buf);
|
||||
aiov.iov_len = args->len;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_flags = linux_to_bsd_msg_flags(args->flags);
|
||||
|
||||
error = kern_recvit(td, args->s, &msg, UIO_USERSPACE, NULL);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
bsd_args.s = args->s;
|
||||
bsd_args.buf = PTRIN(args->buf);
|
||||
bsd_args.len = args->len;
|
||||
bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
|
||||
/* XXX: */
|
||||
bsd_args.from = (struct sockaddr * __restrict)PTRIN(args->from);
|
||||
bsd_args.fromlenaddr = PTRIN(args->fromlen);/* XXX */
|
||||
|
||||
linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len);
|
||||
error = sys_recvfrom(td, &bsd_args);
|
||||
bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
if (args->from) {
|
||||
if (PTRIN(args->from) != NULL) {
|
||||
error = bsd_to_linux_sockaddr((struct sockaddr *)
|
||||
PTRIN(args->from));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = linux_sa_put((struct osockaddr *)
|
||||
PTRIN(args->from));
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
|
||||
if (PTRIN(args->fromlen) != NULL)
|
||||
error = copyout(&msg.msg_namelen, PTRIN(args->fromlen),
|
||||
sizeof(msg.msg_namelen));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user