mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-15 14:56:13 +01:00
Do proper copyin of control message data in the Linux sendmsg syscall.
Instead of calling m_append with a user address, allocate an mbuf cluster and copy data into it using copyin. For the SCM_CREDS case, instead of zeroing a stack variable and appending that to the mbuf, zero part of the mbuf cluster directly. One mbuf cluster is also the size limit used by the FreeBSD sendmsg syscall (uipc_syscalls.c:sockargs()). PR: 217901 Reviewed by: kib MFC after: 3 days
This commit is contained in:
parent
90acd1d139
commit
e3b385fc95
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340631
@ -1085,7 +1085,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
l_uint flags)
|
||||
{
|
||||
struct cmsghdr *cmsg;
|
||||
struct cmsgcred cmcred;
|
||||
struct mbuf *control;
|
||||
struct msghdr msg;
|
||||
struct l_cmsghdr linux_cmsg;
|
||||
@ -1096,6 +1095,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
struct sockaddr *sa;
|
||||
sa_family_t sa_family;
|
||||
void *data;
|
||||
l_size_t len;
|
||||
int error;
|
||||
|
||||
error = copyin(msghdr, &linux_msg, sizeof(linux_msg));
|
||||
@ -1126,7 +1126,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
return (error);
|
||||
|
||||
control = NULL;
|
||||
cmsg = NULL;
|
||||
|
||||
if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
|
||||
error = kern_getsockname(td, s, &sa, &datalen);
|
||||
@ -1136,8 +1135,10 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
free(sa, M_SONAME);
|
||||
|
||||
error = ENOBUFS;
|
||||
cmsg = malloc(CMSG_HDRSZ, M_LINUX, M_WAITOK|M_ZERO);
|
||||
control = m_get(M_WAITOK, MT_CONTROL);
|
||||
MCLGET(control, M_WAITOK);
|
||||
data = mtod(control, void *);
|
||||
datalen = 0;
|
||||
|
||||
do {
|
||||
error = copyin(ptr_cmsg, &linux_cmsg,
|
||||
@ -1149,10 +1150,14 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr))
|
||||
goto bad;
|
||||
|
||||
if (datalen + CMSG_HDRSZ > MCLBYTES)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Now we support only SCM_RIGHTS and SCM_CRED,
|
||||
* so return EINVAL in any other cmsg_type
|
||||
*/
|
||||
cmsg = data;
|
||||
cmsg->cmsg_type =
|
||||
linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
|
||||
cmsg->cmsg_level =
|
||||
@ -1170,35 +1175,34 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
if (sa_family != AF_UNIX)
|
||||
continue;
|
||||
|
||||
data = LINUX_CMSG_DATA(ptr_cmsg);
|
||||
datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
|
||||
|
||||
switch (cmsg->cmsg_type)
|
||||
{
|
||||
case SCM_RIGHTS:
|
||||
break;
|
||||
|
||||
case SCM_CREDS:
|
||||
data = &cmcred;
|
||||
datalen = sizeof(cmcred);
|
||||
if (cmsg->cmsg_type == SCM_CREDS) {
|
||||
len = sizeof(struct cmsgcred);
|
||||
if (datalen + CMSG_SPACE(len) > MCLBYTES)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* The lower levels will fill in the structure
|
||||
*/
|
||||
bzero(data, datalen);
|
||||
break;
|
||||
memset(CMSG_DATA(data), 0, len);
|
||||
} else {
|
||||
len = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
|
||||
if (datalen + CMSG_SPACE(len) < datalen ||
|
||||
datalen + CMSG_SPACE(len) > MCLBYTES)
|
||||
goto bad;
|
||||
|
||||
error = copyin(LINUX_CMSG_DATA(ptr_cmsg),
|
||||
CMSG_DATA(data), len);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
cmsg->cmsg_len = CMSG_LEN(datalen);
|
||||
|
||||
error = ENOBUFS;
|
||||
if (!m_append(control, CMSG_HDRSZ, (c_caddr_t)cmsg))
|
||||
goto bad;
|
||||
if (!m_append(control, datalen, (c_caddr_t)data))
|
||||
goto bad;
|
||||
cmsg->cmsg_len = CMSG_LEN(len);
|
||||
data = (char *)data + CMSG_SPACE(len);
|
||||
datalen += CMSG_SPACE(len);
|
||||
} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
|
||||
|
||||
if (m_length(control, NULL) == 0) {
|
||||
control->m_len = datalen;
|
||||
if (datalen == 0) {
|
||||
m_freem(control);
|
||||
control = NULL;
|
||||
}
|
||||
@ -1212,8 +1216,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
bad:
|
||||
m_freem(control);
|
||||
free(iov, M_IOV);
|
||||
if (cmsg)
|
||||
free(cmsg, M_LINUX);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user