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:
Dmitry Chagin 2015-05-24 16:26:55 +00:00
parent 437c43c1cb
commit 9599b0ec3a

View File

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