diff options
| author | Bart Van Assche <bvanassche@acm.org> | 2019-03-11 19:02:55 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2019-03-21 07:00:18 -0400 |
| commit | 82efcab3b9f3ef59e9713237c6e3c05c3a95c1ae (patch) | |
| tree | 3bbd3c0bb9bd14f7274279c711c2d9940a9bd098 /kernel/workqueue.c | |
| parent | 9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff) | |
workqueue: Only unregister a registered lockdep key
The recent change to prevent use after free and a memory leak introduced an
unconditional call to wq_unregister_lockdep() in the error handling
path. If the lockdep key had not been registered yet, then the lockdep core
emits a warning.
Only call wq_unregister_lockdep() if wq_register_lockdep() has been
called first.
Fixes: 009bb421b6ce ("workqueue, lockdep: Fix an alloc_workqueue() error path")
Reported-by: syzbot+be0c198232f86389c3dd@syzkaller.appspotmail.com
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Qian Cai <cai@lca.pw>
Link: https://lkml.kernel.org/r/20190311230255.176081-1-bvanassche@acm.org
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4026d1871407..ddee541ea97a 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -4266,7 +4266,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt, | |||
| 4266 | INIT_LIST_HEAD(&wq->list); | 4266 | INIT_LIST_HEAD(&wq->list); |
| 4267 | 4267 | ||
| 4268 | if (alloc_and_link_pwqs(wq) < 0) | 4268 | if (alloc_and_link_pwqs(wq) < 0) |
| 4269 | goto err_free_wq; | 4269 | goto err_unreg_lockdep; |
| 4270 | 4270 | ||
| 4271 | if (wq_online && init_rescuer(wq) < 0) | 4271 | if (wq_online && init_rescuer(wq) < 0) |
| 4272 | goto err_destroy; | 4272 | goto err_destroy; |
| @@ -4292,9 +4292,10 @@ struct workqueue_struct *alloc_workqueue(const char *fmt, | |||
| 4292 | 4292 | ||
| 4293 | return wq; | 4293 | return wq; |
| 4294 | 4294 | ||
| 4295 | err_free_wq: | 4295 | err_unreg_lockdep: |
| 4296 | wq_unregister_lockdep(wq); | 4296 | wq_unregister_lockdep(wq); |
| 4297 | wq_free_lockdep(wq); | 4297 | wq_free_lockdep(wq); |
| 4298 | err_free_wq: | ||
| 4298 | free_workqueue_attrs(wq->unbound_attrs); | 4299 | free_workqueue_attrs(wq->unbound_attrs); |
| 4299 | kfree(wq); | 4300 | kfree(wq); |
| 4300 | return NULL; | 4301 | return NULL; |
