timer_list / hrtimer function-pointer hijack¶
Heap'te bulunan bir
struct timer_list(veyastruct hrtimer) object'ininfunctionpointer'ını corrupt et; böylece timer ateşlendiğinde kernel, argüman olarak timer object'inin kendisiyle attacker'ın seçtiği bir adresi çağırır.
Mechanism¶
Note
struct timer_list klasik low-resolution timer'dır. Süresi dolduğunda kernel, function
pointer'ını tek argüman olarak timer pointer'ının kendisini geçirerek çağırır (modern
signature void (*function)(struct timer_list *)). Dolayısıyla function'ı corrupt etmek,
kernel'in arg0 olarak (attacker'ın etkileyebileceği) timer object'i ile attacker'ın seçtiği
bir adresi çağırmasını sağlar — bir mov rsp, [rdi+x] stack pivot veya tek seferlik bir call
gadget için ideal. High-resolution muadili struct hrtimer'dır; callback'i
enum hrtimer_restart (*function)(struct hrtimer *)'dir ve HRTIMER_NORESTART ya da
HRTIMER_RESTART döndürmelidir. Her iki callback de softirq/interrupt context'inden çalışır
(timer_list için __run_timers / run_timer_softirq; hrtimer için hrtimer softirq'i),
dolayısıyla hijack edilen control flow herhangi bir task context'i dışında yürütülür.
Walkthrough¶
Struct (include/linux/timer_types.h'tan birebir):
struct timer_list {
struct hlist_node entry; /* +0x00, 16 bytes */
unsigned long expires; /* +0x10 */
void (*function)(struct timer_list *); /* +0x18 */
u32 flags; /* +0x20 */
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
- Bir write primitive (UAF, overflow veya arbitrary write) kullanarak
+0x18offset'indekifunction'ı hedef adresle overwrite et.+0x10'dakiexpires, ne zaman ateşleneceğini kontrol eder — callback'i talep üzerine tetikleyecek şekilde arm et. - Timer ateşlendiğinde kernel,
rditimer object'ine işaret eder halde kontrolü aktararaktimer->function(timer)'a eşdeğer işlemi gerçekleştirir. hrtimeriçin, embeddedfunctionfield'ını (normal işleyiştetimerfd_tmrprocgibi bir.textpointer'ı) overwrite et ve aynı etki için süresinin dolmasını bekle; callback,enum hrtimer_restartdönüş konvansiyonuna uymalıdır.
Warning
Callback softirq/IRQ context'inde çalışır — "herhangi bir task ile ilişkili değildir" — bu
nedenle bir ROP chain tipik olarak doğrudan return etmek yerine msleep() ve bir
fork()/"telefork" hilesiyle biter; böylece privileged bir userspace task geri kazanılır.
Mitigation¶
- CFI (
CONFIG_CFI_CLANG/ kCFI), indirect-call hedefinin type signature'ını doğrular ve arbitrary bir adrese yapılan call-through'u bloklar. timer_list/hrtimerbirçok heap object'inin içine embed edildiği için, CFI'nin özellikle hedeflediği generic bir write-what-where → control-flow primitive'idir.