Fix another user address dereference in linux_sendmsg syscall.
This was hidden behind the LINUX_CMSG_NXTHDR macro which dereferences its second argument. Stop using the macro as well as LINUX_CMSG_FIRSTHDR. Use the size field of the kernel copy of the control message header to obtain the next control message. PR: 217901 MFC after: 2 days X-MFC-With: r340631
This commit is contained in:
parent
0a05369d45
commit
7df0e7beb7
@ -1096,6 +1096,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
sa_family_t sa_family;
|
||||
void *data;
|
||||
l_size_t len;
|
||||
l_size_t clen;
|
||||
int error;
|
||||
|
||||
error = copyin(msghdr, &linux_msg, sizeof(linux_msg));
|
||||
@ -1127,7 +1128,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
|
||||
control = NULL;
|
||||
|
||||
if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
|
||||
if (linux_msg.msg_controllen >= sizeof(struct l_cmsghdr)) {
|
||||
error = kern_getsockname(td, s, &sa, &datalen);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
@ -1140,6 +1141,8 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
data = mtod(control, void *);
|
||||
datalen = 0;
|
||||
|
||||
ptr_cmsg = PTRIN(linux_msg.msg_control);
|
||||
clen = linux_msg.msg_controllen;
|
||||
do {
|
||||
error = copyin(ptr_cmsg, &linux_cmsg,
|
||||
sizeof(struct l_cmsghdr));
|
||||
@ -1147,7 +1150,8 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
goto bad;
|
||||
|
||||
error = EINVAL;
|
||||
if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr))
|
||||
if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr) ||
|
||||
linux_cmsg.cmsg_len > clen)
|
||||
goto bad;
|
||||
|
||||
if (datalen + CMSG_HDRSZ > MCLBYTES)
|
||||
@ -1199,7 +1203,14 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
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 (clen <= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len))
|
||||
break;
|
||||
|
||||
clen -= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len);
|
||||
ptr_cmsg = (struct l_cmsghdr *)((char *)ptr_cmsg +
|
||||
LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len));
|
||||
} while(clen >= sizeof(struct l_cmsghdr));
|
||||
|
||||
control->m_len = datalen;
|
||||
if (datalen == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user