From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "Gopal, Puunithaaraj" Date: Sat, 12 Jan 2019 00:05:13 +0800 Subject: [PATCH] intel-ipu4: ici: Move empty list check into spinlock to avoid list get out of sync. Under race condition, the list content can be modified to become empty. This will cause invalid object access. Change-Id: Ica5351c7f1b3e34fec7d2cbe8789062a2f42ff7d Tracked-On: OAM-72430 Tracked-On: OOLI2-2387 Signed-off-by: Gopal, Puunithaaraj --- .../media/pci/intel/ici/ici-isys-frame-buf.c | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/media/pci/intel/ici/ici-isys-frame-buf.c b/drivers/media/pci/intel/ici/ici-isys-frame-buf.c index 5d3c87612a7d..ff497f8fdd5e 100644 --- a/drivers/media/pci/intel/ici/ici-isys-frame-buf.c +++ b/drivers/media/pci/intel/ici/ici-isys-frame-buf.c @@ -698,10 +698,12 @@ void ici_isys_frame_buf_ready(struct ici_isys_pipeline static void unmap_buf(struct ici_frame_buf_wrapper *buf) { int i; - + dev_dbg(&buf->buf_list->strm_dev->dev, "buf: %p\n", buf); for (i = 0; i < buf->frame_info.num_planes; i++) { struct ici_kframe_plane *kframe_plane = &buf->kframe_info.planes[i]; + dev_dbg(&buf->buf_list->strm_dev->dev, "kframe_plane: %p\n", + kframe_plane); switch (kframe_plane->mem_type) { case ICI_MEM_USERPTR: ici_put_userpages(kframe_plane->dev, @@ -747,36 +749,52 @@ void ici_isys_frame_buf_stream_cancel(struct struct ici_frame_buf_wrapper *buf; unsigned long flags = 0; - while (!list_empty(&buf_list->getbuf_list)) { + while (1) { spin_lock_irqsave(&buf_list->lock, flags); + if (list_empty(&buf_list->getbuf_list)) { + spin_unlock_irqrestore(&buf_list->lock, flags); + break; + } buf = list_entry(buf_list->getbuf_list.next, struct ici_frame_buf_wrapper, node); list_del(&buf->node); spin_unlock_irqrestore(&buf_list->lock, flags); + dev_dbg(&buf_list->strm_dev->dev, "buf: %p\n", buf); if (as->strm_dev.virt_dev_id < 0) unmap_buf(buf); else unmap_buf_virt(buf); } - while (!list_empty(&buf_list->putbuf_list)) { + while (1) { spin_lock_irqsave(&buf_list->lock, flags); + if (list_empty(&buf_list->putbuf_list)) { + spin_unlock_irqrestore(&buf_list->lock, flags); + break; + } buf = list_entry(buf_list->putbuf_list.next, struct ici_frame_buf_wrapper, node); list_del(&buf->node); spin_unlock_irqrestore(&buf_list->lock, flags); + dev_dbg(&buf_list->strm_dev->dev, "buf: %p\n", buf); if (as->strm_dev.virt_dev_id < 0) unmap_buf(buf); else unmap_buf_virt(buf); } - while (!list_empty(&buf_list->interlacebuf_list)) { + while (1) { spin_lock_irqsave(&buf_list->short_packet_queue_lock, flags); + if (list_empty(&buf_list->interlacebuf_list)) { + spin_unlock_irqrestore + (&buf_list->short_packet_queue_lock, flags); + break; + } buf = list_entry(buf_list->interlacebuf_list.next, struct ici_frame_buf_wrapper, node); list_del(&buf->node); spin_unlock_irqrestore(&buf_list->short_packet_queue_lock, flags); + dev_dbg(&buf_list->strm_dev->dev, "buf: %p\n", buf); unmap_buf(buf); } } -- https://clearlinux.org