Skip to contentSkip to conversation

timer: Add function-change canary

RFC PATCH In review Kees Cook 1 participant 2 messages Aug 8, 2017 High-resolution timers, timer wheel, clockevents

lore
Share & tools
lore

Kees Cook

author
#0 lore raw

RFC PATCH 1/1 timer: Add function-change canary

This introduces canaries to struct timer_list in an effort to protect the function callback pointer from getting rewritten during stack or heap overflow attacks. The struct timer_list has become a recent target for security flaw exploitation because it includes the "data" argument in the structure, along with the function callback. This provides attackers with a ROP-like primitive for performing limited kernel function calls without needing all the prerequisites to stage a ROP attack.

Recent examples of exploits using struct timer_list attacks:

http://www.openwall.com/lists/oss-security/2016/12/06/1
(https://www.exploit-db.com/exploits/40871/)

https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html
(https://www.exploit-db.com/exploits/41458/)

Timers normally have their callback functions initialized either via the setup_timer_*() macros or manually before calls to add_timer(). The per-timer canary gets set in either case, and then checked at timer expiration time before calling the function.

---
 include/linux/timer.h |  6 ++++--
 kernel/time/timer.c   | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 3 deletions(-)
include/linux/timer.h +4 -2
index e6789b8757d5..9aac0da9d2ec 100644
@@ -16,6 +16,7 @@ struct timer_list {
 	 */
 	struct hlist_node	entry;
 	unsigned long		expires;
+	unsigned long		canary;
 	void			(*function)(unsigned long);
 	unsigned long		data;
 	u32			flags;
@@ -91,6 +92,7 @@ struct timer_list {
 
 void init_timer_key(struct timer_list *timer, unsigned int flags,
 		    const char *name, struct lock_class_key *key);
+void init_timer_func(struct timer_list *timer, void (*func)(unsigned long));
 
 #ifdef CONFIG_DEBUG_OBJECTS_TIMERS
 extern void init_timer_on_stack_key(struct timer_list *timer,
@@ -140,14 +142,14 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
 #define __setup_timer(_timer, _fn, _data, _flags)			\
 	do {								\
 		__init_timer((_timer), (_flags));			\
-		(_timer)->function = (_fn);				\
+		init_timer_func((_timer), (_fn));			\
 		(_timer)->data = (_data);				\
 	} while (0)
 
 #define __setup_timer_on_stack(_timer, _fn, _data, _flags)		\
 	do {								\
 		__init_timer_on_stack((_timer), (_flags));		\
-		(_timer)->function = (_fn);				\
+		init_timer_func((_timer), (_fn));			\
 		(_timer)->data = (_data);				\
 	} while (0)
 
kernel/time/timer.c +44 -1

87 lines not on this page · raw message

Signature · 6 lines
2.7.4


-- 
Kees Cook
Pixel Security
author
#1 lore raw
Quoted 13 lines · Kees Cook

This introduces canaries to struct timer_list in an effort to protect the function callback pointer from getting rewritten during stack or heap overflow attacks. The struct timer_list has become a recent target for security flaw exploitation because it includes the "data" argument in the structure, along with the function callback. This provides attackers with a ROP-like primitive for performing limited kernel function calls without needing all the prerequisites to stage a ROP attack.

Recent examples of exploits using struct timer_list attacks:

http://www.openwall.com/lists/oss-security/2016/12/06/1
(https://www.exploit-db.com/exploits/40871/)

Quoted 7 lines

https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html
(https://www.exploit-db.com/exploits/41458/)

Timers normally have their callback functions initialized either via the setup_timer_*() macros or manually before calls to add_timer(). The per-timer canary gets set in either case, and then checked at timer expiration time before calling the function.

Har har, I missed DEFINE_TIMER() which is rather widely used. :P

I'll send a v2, though the canary may end up being a bit weaker to deal with static initializers.

-Kees

Signature · 2 lines
Kees Cook
Pixel Security