return early if work is cancelled before being scheduled
authorjsg <jsg@openbsd.org>
Mon, 17 May 2021 00:17:26 +0000 (00:17 +0000)
committerjsg <jsg@openbsd.org>
Mon, 17 May 2021 00:17:26 +0000 (00:17 +0000)
cheloha@ noticed that task_del(9) was being called with a NULL taskq
from inteldrm(4), which was not noticed as the function returns early
from testing a flag in the task.  This situation occurs when work is
cancelled before it is scheduled.

ok kettenis@ cheloha@

sys/dev/pci/drm/include/linux/workqueue.h

index 703d2f0..a0c7134 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: workqueue.h,v 1.4 2021/02/14 03:42:55 jsg Exp $       */
+/*     $OpenBSD: workqueue.h,v 1.5 2021/05/17 00:17:26 jsg Exp $       */
 /*
  * Copyright (c) 2015 Mark Kettenis
  *
@@ -95,7 +95,8 @@ queue_work(struct workqueue_struct *wq, struct work_struct *work)
 static inline void
 cancel_work_sync(struct work_struct *work)
 {
-       task_del(work->tq, &work->task);
+       if (work->tq != NULL)
+               task_del(work->tq, &work->task);
 }
 
 #define work_pending(work)     task_pending(&(work)->task)
@@ -169,6 +170,8 @@ mod_delayed_work(struct workqueue_struct *wq,
 static inline bool
 cancel_delayed_work(struct delayed_work *dwork)
 {
+       if (dwork->tq == NULL)
+               return false;
        if (timeout_del(&dwork->to))
                return true;
        return task_del(dwork->tq, &dwork->work.task);
@@ -177,6 +180,8 @@ cancel_delayed_work(struct delayed_work *dwork)
 static inline bool
 cancel_delayed_work_sync(struct delayed_work *dwork)
 {
+       if (dwork->tq == NULL)
+               return false;
        if (timeout_del(&dwork->to))
                return true;
        return task_del(dwork->tq, &dwork->work.task);