libpayload: Fix potential NULL pointer dereference

Found-by: Klockwork
BUG=NONE
TEST=Boot to OS on GLK Sparky

Signed-off-by: Francois Toguo <francois.toguo.fotso@intel.com>
Change-Id: I9d4636f0429de829e746909492c2f543026a02ac
Reviewed-on: https://review.coreboot.org/c/coreboot/+/32083
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Lijian Zhao <lijian.zhao@intel.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Francois Toguo 2019-03-27 10:30:20 -07:00 committed by Patrick Georgi
parent e0c181d487
commit 651d8dd4f6
3 changed files with 44 additions and 2 deletions

View File

@ -634,6 +634,8 @@ static void *ehci_create_intr_queue(
/* create #reqcount transfer descriptors (qTDs) */ /* create #reqcount transfer descriptors (qTDs) */
intrq->head = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); intrq->head = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t));
if (!intrq->head)
fatal("Not enough DMA memory to create #reqcount TD.\n");
intr_qtd_t *cur_td = intrq->head; intr_qtd_t *cur_td = intrq->head;
for (i = 0; i < reqcount; ++i) { for (i = 0; i < reqcount; ++i) {
fill_intr_queue_td(intrq, cur_td, data); fill_intr_queue_td(intrq, cur_td, data);
@ -642,6 +644,8 @@ static void *ehci_create_intr_queue(
/* create one more qTD */ /* create one more qTD */
intr_qtd_t *const next_td = intr_qtd_t *const next_td =
(intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t));
if (!next_td)
fatal("Not enough DMA memory to create TD.\n");
cur_td->td.next_qtd = virt_to_phys(&next_td->td); cur_td->td.next_qtd = virt_to_phys(&next_td->td);
cur_td->next = next_td; cur_td->next = next_td;
cur_td = next_td; cur_td = next_td;
@ -651,6 +655,8 @@ static void *ehci_create_intr_queue(
/* create spare qTD */ /* create spare qTD */
intrq->spare = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); intrq->spare = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t));
if (!intrq->spare)
fatal("Not enough DMA memory to create spare qTD.\n");
intrq->spare->data = data; intrq->spare->data = data;
/* initialize QH */ /* initialize QH */
@ -824,13 +830,16 @@ ehci_init (unsigned long physical_bar)
* and doesn't violate the standard. * and doesn't violate the standard.
*/ */
EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)dma_memalign(64, sizeof(ehci_qh_t)); EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)dma_memalign(64, sizeof(ehci_qh_t));
if (!EHCI_INST(controller)->dummy_qh)
fatal("Not enough DMA memory for EHCI dummy TD.\n");
memset((void *)EHCI_INST(controller)->dummy_qh, 0, memset((void *)EHCI_INST(controller)->dummy_qh, 0,
sizeof(*EHCI_INST(controller)->dummy_qh)); sizeof(*EHCI_INST(controller)->dummy_qh));
EHCI_INST(controller)->dummy_qh->horiz_link_ptr = QH_TERMINATE; EHCI_INST(controller)->dummy_qh->horiz_link_ptr = QH_TERMINATE;
EHCI_INST(controller)->dummy_qh->td.next_qtd = QH_TERMINATE; EHCI_INST(controller)->dummy_qh->td.next_qtd = QH_TERMINATE;
EHCI_INST(controller)->dummy_qh->td.alt_next_qtd = QH_TERMINATE; EHCI_INST(controller)->dummy_qh->td.alt_next_qtd = QH_TERMINATE;
for (i = 0; i < 1024; ++i) for (i = 0; i < 1024; ++i)
periodic_list[i] = virt_to_phys(EHCI_INST(controller)->dummy_qh) periodic_list[i] =
virt_to_phys(EHCI_INST(controller)->dummy_qh)
| PS_TYPE_QH; | PS_TYPE_QH;
/* Make sure periodic schedule is disabled */ /* Make sure periodic schedule is disabled */

View File

@ -212,6 +212,8 @@ ohci_init (unsigned long physical_bar)
udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */ udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */
OHCI_INST (controller)->opreg->HcFmInterval = interval; OHCI_INST (controller)->opreg->HcFmInterval = interval;
OHCI_INST (controller)->hcca = dma_memalign(256, 256); OHCI_INST (controller)->hcca = dma_memalign(256, 256);
if (!OHCI_INST(controller)->hcca)
fatal("Not enough DMA memory for OHCI HCCA.\n");
memset((void*)OHCI_INST (controller)->hcca, 0, 256); memset((void*)OHCI_INST (controller)->hcca, 0, 256);
if (dma_initialized()) { if (dma_initialized()) {
@ -223,6 +225,8 @@ ohci_init (unsigned long physical_bar)
/* Initialize interrupt table. */ /* Initialize interrupt table. */
u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable; u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable;
ed_t *const periodic_ed = dma_memalign(sizeof(ed_t), sizeof(ed_t)); ed_t *const periodic_ed = dma_memalign(sizeof(ed_t), sizeof(ed_t));
if (!periodic_ed)
fatal("Not enough DMA memory for OHCI interrupt table.\n");
memset((void *)periodic_ed, 0, sizeof(*periodic_ed)); memset((void *)periodic_ed, 0, sizeof(*periodic_ed));
for (i = 0; i < 32; ++i) for (i = 0; i < 32; ++i)
intr_table[i] = virt_to_phys(periodic_ed); intr_table[i] = virt_to_phys(periodic_ed);
@ -378,6 +382,8 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, int dalen,
/* First TD. */ /* First TD. */
td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!first_td)
fatal("Not enough DMA memory for OHCI first TD in buffer.\n");
memset((void *)first_td, 0, sizeof(*first_td)); memset((void *)first_td, 0, sizeof(*first_td));
cur = first_td; cur = first_td;
@ -392,6 +398,8 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, int dalen,
while (pages > 0) { while (pages > 0) {
/* One more TD. */ /* One more TD. */
td_t *const next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); td_t *const next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!next)
fatal("Not enough DMA memory for OHCI new page.\n");
memset((void *)next, 0, sizeof(*next)); memset((void *)next, 0, sizeof(*next));
/* Linked to the previous. */ /* Linked to the previous. */
cur->next_td = virt_to_phys(next); cur->next_td = virt_to_phys(next);
@ -426,6 +434,8 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, int dalen,
/* One more TD. */ /* One more TD. */
td_t *const next_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); td_t *const next_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!next_td)
fatal("Not enough DMA memory for OHCI additional TD.\n");
memset((void *)next_td, 0, sizeof(*next_td)); memset((void *)next_td, 0, sizeof(*next_td));
/* Linked to the previous. */ /* Linked to the previous. */
cur->next_td = virt_to_phys(next_td); cur->next_td = virt_to_phys(next_td);
@ -441,12 +451,16 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, int dalen,
/* Final dummy TD. */ /* Final dummy TD. */
td_t *const final_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); td_t *const final_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!final_td)
fatal("Not enough DMA memory for OHCI dummy TD!\n");
memset((void *)final_td, 0, sizeof(*final_td)); memset((void *)final_td, 0, sizeof(*final_td));
/* Linked to the previous. */ /* Linked to the previous. */
cur->next_td = virt_to_phys(final_td); cur->next_td = virt_to_phys(final_td);
/* Data structures */ /* Data structures */
ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t)); ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t));
if (!head)
fatal("Not enough DMA memory for OHCI data structures.\n");
memset((void*)head, 0, sizeof(*head)); memset((void*)head, 0, sizeof(*head));
head->config = (dev->address << ED_FUNC_SHIFT) | head->config = (dev->address << ED_FUNC_SHIFT) |
(0 << ED_EP_SHIFT) | (0 << ED_EP_SHIFT) |
@ -519,6 +533,8 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *src, int finalize)
/* First TD. */ /* First TD. */
td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!first_td)
fatal("Not enough DMA memory for OHCI bulk transfer.\n");
memset((void *)first_td, 0, sizeof(*first_td)); memset((void *)first_td, 0, sizeof(*first_td));
cur = next = first_td; cur = next = first_td;
@ -557,6 +573,8 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *src, int finalize)
} }
/* One more TD. */ /* One more TD. */
next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t));
if (!next)
fatal("Not enough DMA mem for TD bulk transfer.\n");
memset((void *)next, 0, sizeof(*next)); memset((void *)next, 0, sizeof(*next));
/* Linked to the previous. */ /* Linked to the previous. */
cur->next_td = virt_to_phys(next); cur->next_td = virt_to_phys(next);
@ -569,6 +587,8 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *src, int finalize)
/* Data structures */ /* Data structures */
ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t)); ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t));
if (!head)
fatal("Not enough DMA memory for OHCI bulk transfer's head.\n");
memset((void*)head, 0, sizeof(*head)); memset((void*)head, 0, sizeof(*head));
head->config = (ep->dev->address << ED_FUNC_SHIFT) | head->config = (ep->dev->address << ED_FUNC_SHIFT) |
((ep->endpoint & 0xf) << ED_EP_SHIFT) | ((ep->endpoint & 0xf) << ED_EP_SHIFT) |
@ -665,6 +685,11 @@ ohci_create_intr_queue(endpoint_t *const ep, const int reqsize,
intr_queue_t *const intrq = intr_queue_t *const intrq =
(intr_queue_t *)dma_memalign(sizeof(intrq->ed), sizeof(*intrq)); (intr_queue_t *)dma_memalign(sizeof(intrq->ed), sizeof(*intrq));
if (!intrq) {
usb_debug("Not enough DMA memory for intr queue.\n");
free(intrq);
return NULL;
}
memset(intrq, 0, sizeof(*intrq)); memset(intrq, 0, sizeof(*intrq));
intrq->data = (u8 *)dma_malloc(reqcount * reqsize); intrq->data = (u8 *)dma_malloc(reqcount * reqsize);
intrq->reqsize = reqsize; intrq->reqsize = reqsize;
@ -674,6 +699,8 @@ ohci_create_intr_queue(endpoint_t *const ep, const int reqsize,
u8 *cur_data = intrq->data; u8 *cur_data = intrq->data;
for (i = 0; i < reqcount; ++i) { for (i = 0; i < reqcount; ++i) {
intrq_td_t *const td = dma_memalign(sizeof(td->td), sizeof(*td)); intrq_td_t *const td = dma_memalign(sizeof(td->td), sizeof(*td));
if (!td)
fatal("Not enough DMA mem to transfer descriptor.\n");
++intrq->remaining_tds; ++intrq->remaining_tds;
ohci_fill_intrq_td(td, intrq, cur_data); ohci_fill_intrq_td(td, intrq, cur_data);
cur_data += reqsize; cur_data += reqsize;
@ -686,6 +713,8 @@ ohci_create_intr_queue(endpoint_t *const ep, const int reqsize,
/* Create last, dummy TD. */ /* Create last, dummy TD. */
intrq_td_t *dummy_td = dma_memalign(sizeof(dummy_td->td), sizeof(*dummy_td)); intrq_td_t *dummy_td = dma_memalign(sizeof(dummy_td->td), sizeof(*dummy_td));
if (!dummy_td)
fatal("Not enough memory to add dummy TD.\n");
memset(dummy_td, 0, sizeof(*dummy_td)); memset(dummy_td, 0, sizeof(*dummy_td));
dummy_td->intrq = intrq; dummy_td->intrq = intrq;
if (last_td) if (last_td)

View File

@ -317,6 +317,8 @@ uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen
unsigned short req = ((unsigned short *) devreq)[0]; unsigned short req = ((unsigned short *) devreq)[0];
int i; int i;
td_t *tds = memalign (16, sizeof (td_t) * count); td_t *tds = memalign (16, sizeof (td_t) * count);
if (!tds)
fatal("Not enough memory for uhci control.\n");
memset (tds, 0, sizeof (td_t) * count); memset (tds, 0, sizeof (td_t) * count);
count--; /* to compensate for 0-indexed array */ count--; /* to compensate for 0-indexed array */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
@ -386,6 +388,8 @@ create_schedule (int numpackets)
if (numpackets == 0) if (numpackets == 0)
return 0; return 0;
td_t *tds = memalign (16, sizeof (td_t) * numpackets); td_t *tds = memalign (16, sizeof (td_t) * numpackets);
if (!tds)
fatal("Not enough memory for packets scheduling.\n");
memset (tds, 0, sizeof (td_t) * numpackets); memset (tds, 0, sizeof (td_t) * numpackets);
int i; int i;
for (i = 0; i < numpackets; i++) { for (i = 0; i < numpackets; i++) {