Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190929163028.9665-2-romain.perier@gmail.com>
Date: Sun, 29 Sep 2019 18:30:13 +0200
From: Romain Perier <romain.perier@...il.com>
To: kernel-hardening@...ts.openwall.com
Cc: Kees Cook <keescook@...omium.org>,
	Romain Perier <romain.perier@...il.com>
Subject: [PRE-REVIEW PATCH 01/16] tasklet: Prepare to change tasklet callback argument type

Nowadays, modern kernel subsystems that use callbacks pass the data
structure associated with a given callback as argument to the callback.
The tasklet subsystem remains the one to pass callback argument as an
arbitrary unsigned long argument. This has several problems:

- This keeps an extra field for storing the argument in each tasklet
data structure, it bloats the tasklet_struct structure with a redundant
.data field

- No type checking cannot be performed on this argument. Instead of
using container_of() like other callback subsystems, it forces callbacks
to do explicit type cast of the unsigned long argument into the required
object type.

- Buffer overflows can overwrite the .function and the .data field, so
an attacker can easily overwrite the function and its first argument
to whatever it wants.

This adds a new tasklet initialization API which will gradually replace
the existing one.

This work is greatly inspired from the timer_struct conversion series,
see commit e99e88a9d ("treewide: setup_timer() -> timer_setup()")

Signed-off-by: Romain Perier <romain.perier@...il.com>
---
 include/linux/interrupt.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 89fc59dab57d..f5332ae2dbeb 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -673,6 +673,18 @@ extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 extern void tasklet_init(struct tasklet_struct *t,
 			 void (*func)(unsigned long), unsigned long data);
 
+#define TASKLET_DATA_TYPE		unsigned long
+#define TASKLET_FUNC_TYPE		void (*)(TASKLET_DATA_TYPE)
+
+#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
+	container_of(callback_tasklet, typeof(*var), tasklet_fieldname)
+
+static inline void tasklet_setup(struct tasklet_struct *t,
+				 void (*callback)(struct tasklet_struct *))
+{
+	tasklet_init(t, (TASKLET_FUNC_TYPE)callback, (TASKLET_DATA_TYPE)t);
+}
+
 /*
  * Autoprobing for irqs:
  *
-- 
2.23.0

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.