bnxt(4): Fix ioctls when user addresses are inaccessable.

Check copyin's error code (differ adding copyout checks at this time).

Don't directly access user memory in the switch statement.

Since bnxt_ioctl_data isn't all that big, use a stack allocation.

Reviewed by:	jhb
MFC after:	3 days
Sponsored by:	DARPA
Differential Revision:	https://reviews.freebsd.org/D23933
This commit is contained in:
Brooks Davis 2020-03-04 17:55:57 +00:00
parent cc1efc23c8
commit ac09be5297

View File

@ -1650,25 +1650,26 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
{
struct bnxt_softc *softc = iflib_get_softc(ctx);
struct ifreq *ifr = (struct ifreq *)data;
struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer;
struct bnxt_ioctl_header *ioh =
(struct bnxt_ioctl_header *)(ifbuf->buffer);
struct bnxt_ioctl_header *ioh;
size_t iol;
int rc = ENOTSUP;
struct bnxt_ioctl_data *iod = NULL;
struct bnxt_ioctl_data iod_storage, *iod = &iod_storage;
switch (command) {
case SIOCGPRIVATE_0:
if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0)
goto exit;
iod = malloc(ifbuf->length, M_DEVBUF, M_NOWAIT | M_ZERO);
if (!iod) {
rc = ENOMEM;
goto exit;
}
copyin(ioh, iod, ifbuf->length);
ioh = ifr_buffer_get_buffer(ifr);
iol = ifr_buffer_get_length(ifr);
if (iol > sizeof(iod_storage))
return (EINVAL);
switch (ioh->type) {
if ((rc = copyin(ioh, iod, iol)) != 0)
goto exit;
switch (iod->hdr.type) {
case BNXT_HWRM_NVM_FIND_DIR_ENTRY:
{
struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find =
@ -1686,7 +1687,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1726,7 +1727,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
remain -= csize;
}
if (iod->hdr.rc == 0)
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
iflib_dma_free(&dma_data);
rc = 0;
@ -1746,7 +1747,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1766,7 +1767,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1788,7 +1789,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1807,7 +1808,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1827,7 +1828,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1854,7 +1855,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
copyout(dma_data.idi_vaddr, get->data,
get->entry_length * get->entries);
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
iflib_dma_free(&dma_data);
@ -1875,7 +1876,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1897,7 +1898,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1916,7 +1917,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1937,7 +1938,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1958,7 +1959,7 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
else {
iod->hdr.rc = 0;
copyout(iod, ioh, ifbuf->length);
copyout(iod, ioh, iol);
}
rc = 0;
@ -1969,8 +1970,6 @@ bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
}
exit:
if (iod)
free(iod, M_DEVBUF);
return rc;
}