[PATCH v1 2/6] x86/resctrl: Add hook for releasing task_struct references

From: Peter Newman
Date: Mon Mar 25 2024 - 14:24:46 EST


In order for the task_struct to hold references to rdtgroups, it must be
possible to release these references before a concurrent deletion causes
them to be freed.

It is not possible for resctrl code to do this with
for_each_process_thread() because the task can still switch in after it
has been removed from the tasklist, at which point the task_struct could
be referring to freed memory.

Signed-off-by: Peter Newman <peternewman@xxxxxxxxxx>
---
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 10 ++++++++++
include/linux/resctrl.h | 6 ++++++
kernel/exit.c | 3 +++
3 files changed, 19 insertions(+)

diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 5d599d99f94b..9b1969e4235a 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -2931,6 +2931,16 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
read_unlock(&tasklist_lock);
}

+/**
+ * exit_resctrl() - called at thread destruction to release resources
+ *
+ * This hook is called just before the task is removed from the global tasklist
+ * and still reachable via for_each_process_thread().
+ */
+void exit_resctrl(struct task_struct *tsk)
+{
+}
+
static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
{
struct rdtgroup *sentry, *stmp;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 62d607939a73..b2af1fbc7aa1 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -325,4 +325,10 @@ static inline void resctrl_sched_in(struct task_struct *tsk)
#endif
}

+#ifdef CONFIG_X86_CPU_RESCTRL
+void exit_resctrl(struct task_struct *tsk);
+#else
+static inline void exit_resctrl(struct task_struct *tsk) {}
+#endif
+
#endif /* _RESCTRL_H */
diff --git a/kernel/exit.c b/kernel/exit.c
index 41a12630cbbc..ccdc90ff6d71 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -70,6 +70,7 @@
#include <linux/sysfs.h>
#include <linux/user_events.h>
#include <linux/uaccess.h>
+#include <linux/resctrl.h>

#include <uapi/linux/wait.h>

@@ -862,6 +863,8 @@ void __noreturn do_exit(long code)
tsk->exit_code = code;
taskstats_exit(tsk, group_dead);

+ exit_resctrl(tsk);
+
exit_mm();

if (group_dead)
--
2.44.0.396.g6e790dbe36-goog