Date: Wed, 4 Oct 2017 13:13:38 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r324278 - in head/sys/compat/linuxkpi/common: include/linux src Message-ID: <201710041313.v94DDcNC045759@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Wed Oct 4 13:13:38 2017 New Revision: 324278 URL: https://svnweb.freebsd.org/changeset/base/324278 Log: Make sure the timer belonging to the delayed work in the LinuxKPI gets drained before invoking the work function. Else the timer mutex may still be in use which can lead to use-after-free situations, because the work function might free the work structure before returning. MFC after: 1 week Sponsored by: Mellanox Technologies Modified: head/sys/compat/linuxkpi/common/include/linux/workqueue.h head/sys/compat/linuxkpi/common/src/linux_work.c Modified: head/sys/compat/linuxkpi/common/include/linux/workqueue.h ============================================================================== --- head/sys/compat/linuxkpi/common/include/linux/workqueue.h Wed Oct 4 12:58:30 2017 (r324277) +++ head/sys/compat/linuxkpi/common/include/linux/workqueue.h Wed Oct 4 13:13:38 2017 (r324278) @@ -215,6 +215,7 @@ extern struct workqueue_struct *system_power_efficient extern void linux_init_delayed_work(struct delayed_work *, work_func_t); extern void linux_work_fn(void *, int); +extern void linux_delayed_work_fn(void *, int); extern struct workqueue_struct *linux_create_workqueue_common(const char *, int); extern void linux_destroy_workqueue(struct workqueue_struct *); extern bool linux_queue_work_on(int cpu, struct workqueue_struct *, struct work_struct *); Modified: head/sys/compat/linuxkpi/common/src/linux_work.c ============================================================================== --- head/sys/compat/linuxkpi/common/src/linux_work.c Wed Oct 4 12:58:30 2017 (r324277) +++ head/sys/compat/linuxkpi/common/src/linux_work.c Wed Oct 4 13:13:38 2017 (r324278) @@ -260,6 +260,23 @@ done: WQ_EXEC_UNLOCK(wq); } +void +linux_delayed_work_fn(void *context, int pending) +{ + struct delayed_work *dwork = context; + + /* + * Make sure the timer belonging to the delayed work gets + * drained before invoking the work function. Else the timer + * mutex may still be in use which can lead to use-after-free + * situations, because the work function might free the work + * structure before returning. + */ + callout_drain(&dwork->timer.callout); + + linux_work_fn(&dwork->work, pending); +} + static void linux_delayed_work_timer_fn(void *arg) { @@ -550,7 +567,8 @@ void linux_init_delayed_work(struct delayed_work *dwork, work_func_t func) { memset(dwork, 0, sizeof(*dwork)); - INIT_WORK(&dwork->work, func); + dwork->work.func = func; + TASK_INIT(&dwork->work.work_task, 0, linux_delayed_work_fn, dwork); mtx_init(&dwork->timer.mtx, spin_lock_name("lkpi-dwork"), NULL, MTX_DEF | MTX_NOWITNESS); callout_init_mtx(&dwork->timer.callout, &dwork->timer.mtx, 0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710041313.v94DDcNC045759>