aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2022-05-28 20:29:12 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2022-05-28 20:29:12 +0000
commit3a99aac66f8d12386e8382aaf29d2e82e6b5353b (patch)
tree336fde2be583e20e51f737682937ad48be611f40
parent77d678b7a4075a056be621b46be50377f08bfc9e (diff)
downloadsrc-3a99aac66f8d12386e8382aaf29d2e82e6b5353b.tar.gz
src-3a99aac66f8d12386e8382aaf29d2e82e6b5353b.zip
linux(4): Check the socket before any others sanity checks
Strictly speaking, this check is performed by the kern_recvit(), but in the Linux emulation layer before calling the kernel we do other sanity checks and conversions from Linux types to the native types. This changes an order of the error returning that is critical for some buggy Linux applications. For recvmmsg() syscall this fixes a panic in case when the user-supplied vlen value is 0, then error is not initialized and garbage passed to the bsd_to_linux_errno(). MFC after: 2 weeks
-rw-r--r--sys/compat/linux/linux_socket.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index b5ec32835981..8aa425bc14c0 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -1731,7 +1731,14 @@ int
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
{
struct msghdr bsd_msg;
+ struct file *fp;
+ int error;
+ error = getsock_cap(td, args->s, &cap_recv_rights,
+ &fp, NULL, NULL);
+ if (error != 0)
+ return (error);
+ fdrop(fp, td);
return (linux_recvmsg_common(td, args->s, PTRIN(args->msg),
args->flags, &bsd_msg));
}
@@ -1742,9 +1749,14 @@ linux_recvmmsg_common(struct thread *td, l_int s, struct l_mmsghdr *msg,
{
struct msghdr bsd_msg;
struct timespec ts;
+ struct file *fp;
l_uint retval;
int error, datagrams;
+ error = getsock_cap(td, s, &cap_recv_rights,
+ &fp, NULL, NULL);
+ if (error != 0)
+ return (error);
datagrams = 0;
while (datagrams < vlen) {
error = linux_recvmsg_common(td, s, &msg->msg_hdr,
@@ -1780,6 +1792,7 @@ linux_recvmmsg_common(struct thread *td, l_int s, struct l_mmsghdr *msg,
}
if (error == 0)
td->td_retval[0] = datagrams;
+ fdrop(fp, td);
return (error);
}