git: 407b687dfef6 - stable/13 - Make sure all tasklets are drained before unloading the LinuxKPI. Else use-after-free may happen.

Hans Petter Selasky hselasky at FreeBSD.org
Wed Jun 2 12:24:48 UTC 2021


The branch stable/13 has been updated by hselasky:

URL: https://cgit.FreeBSD.org/src/commit/?id=407b687dfef6bf20623726a71127b63f4fb20615

commit 407b687dfef6bf20623726a71127b63f4fb20615
Author:     Hans Petter Selasky <hselasky at FreeBSD.org>
AuthorDate: 2021-05-21 06:52:59 +0000
Commit:     Hans Petter Selasky <hselasky at FreeBSD.org>
CommitDate: 2021-06-02 11:23:19 +0000

    Make sure all tasklets are drained before unloading the LinuxKPI.
    Else use-after-free may happen.
    
    This change also partially cherry picks support for the
    taskqgroup_drain_all() function.
    
    Sponsored by:   Mellanox Technologies // NVIDIA Networking
    
    (cherry picked from commit 209d4919c5270fe9e3c1d809cf91355d222dc2f3)
---
 sys/compat/linuxkpi/common/src/linux_tasklet.c |  2 ++
 sys/kern/subr_gtaskqueue.c                     | 13 +++++++++++++
 sys/sys/gtaskqueue.h                           |  1 +
 3 files changed, 16 insertions(+)

diff --git a/sys/compat/linuxkpi/common/src/linux_tasklet.c b/sys/compat/linuxkpi/common/src/linux_tasklet.c
index 9a4c01737466..26e7bb75cf19 100644
--- a/sys/compat/linuxkpi/common/src/linux_tasklet.c
+++ b/sys/compat/linuxkpi/common/src/linux_tasklet.c
@@ -128,6 +128,8 @@ tasklet_subsystem_uninit(void *arg __unused)
 	struct tasklet_worker *tw;
 	int i;
 
+	taskqgroup_drain_all(qgroup_softirq);
+
 	CPU_FOREACH(i) {
 		if (CPU_ABSENT(i))
 			continue;
diff --git a/sys/kern/subr_gtaskqueue.c b/sys/kern/subr_gtaskqueue.c
index 3eac29631244..c4db60890eee 100644
--- a/sys/kern/subr_gtaskqueue.c
+++ b/sys/kern/subr_gtaskqueue.c
@@ -817,3 +817,16 @@ void
 taskqgroup_destroy(struct taskqgroup *qgroup)
 {
 }
+
+void
+taskqgroup_drain_all(struct taskqgroup *tqg)
+{
+	struct gtaskqueue *q;
+
+	for (int i = 0; i < mp_ncpus; i++) {
+		q = tqg->tqg_queue[i].tgc_taskq;
+		if (q == NULL)
+			continue;
+		gtaskqueue_drain_all(q);
+	}
+}
diff --git a/sys/sys/gtaskqueue.h b/sys/sys/gtaskqueue.h
index aa352902c65b..f662aa39f00e 100644
--- a/sys/sys/gtaskqueue.h
+++ b/sys/sys/gtaskqueue.h
@@ -80,6 +80,7 @@ void	taskqgroup_detach(struct taskqgroup *qgroup, struct grouptask *gtask);
 struct taskqgroup *taskqgroup_create(const char *name, int cnt, int stride);
 void	taskqgroup_destroy(struct taskqgroup *qgroup);
 void	taskqgroup_bind(struct taskqgroup *qgroup);
+void	taskqgroup_drain_all(struct taskqgroup *qgroup);
 
 #define	GTASK_INIT(gtask, flags, priority, func, context) do {	\
 	(gtask)->ta_flags = flags;				\


More information about the dev-commits-src-all mailing list