ANDROID: timer: fix timer_setup with CFI
timer_setup casts the callback function to an incompatible type, which
trips CFI for all users of the API:
CFI failure (target: [<ffffff8da5b6bc88>] nf_ct_frag6_expire+0x0/0x4):
...
Call trace:
__cfi_check_fail+0x1c/0x24
...
call_timer_fn+0x304/0x308
Note that this only affects 4.14, the timer code was refactored in the
later upstream releases.
Bug: 130800382
Bug: 156058713
Change-Id: If7d706dcbe08ca0001d025606e5d3f3ca1559a7b
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
This commit is contained in:
committed by
Alistair Delva
parent
5bcde4a44d
commit
3045070cf5
@@ -21,6 +21,9 @@ struct timer_list {
|
||||
unsigned long data;
|
||||
u32 flags;
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
void (*__function)(struct timer_list *);
|
||||
#endif
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
struct lockdep_map lockdep_map;
|
||||
#endif
|
||||
@@ -172,6 +175,30 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
|
||||
#define TIMER_DATA_TYPE unsigned long
|
||||
#define TIMER_FUNC_TYPE void (*)(TIMER_DATA_TYPE)
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
/*
|
||||
* With CFI_CLANG, we cannot cast the callback function to TIMER_FUNC_TYPE
|
||||
* without tripping an indirect call check in call_timer_fn. Therefore, we
|
||||
* add a new field to struct timer_list and use __timer_callback to perform
|
||||
* the indirect call using the correct function pointer.
|
||||
*/
|
||||
static inline void __timer_callback(unsigned long data)
|
||||
{
|
||||
struct timer_list *timer = (struct timer_list *)data;
|
||||
|
||||
timer->__function(timer);
|
||||
}
|
||||
|
||||
static inline void timer_setup(struct timer_list *timer,
|
||||
void (*callback)(struct timer_list *),
|
||||
unsigned int flags)
|
||||
{
|
||||
timer->__function = callback;
|
||||
|
||||
__setup_timer(timer, __timer_callback,
|
||||
(TIMER_DATA_TYPE)timer, flags);
|
||||
}
|
||||
#else
|
||||
static inline void timer_setup(struct timer_list *timer,
|
||||
void (*callback)(struct timer_list *),
|
||||
unsigned int flags)
|
||||
@@ -179,6 +206,7 @@ static inline void timer_setup(struct timer_list *timer,
|
||||
__setup_timer(timer, (TIMER_FUNC_TYPE)callback,
|
||||
(TIMER_DATA_TYPE)timer, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define from_timer(var, callback_timer, timer_fieldname) \
|
||||
container_of(callback_timer, typeof(*var), timer_fieldname)
|
||||
|
||||
Reference in New Issue
Block a user