POSIX CPU Timers TOCTOU race (CVE-2025-38352)

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์ด ํŽ˜์ด์ง€๋Š” Linux/Android์˜ POSIX CPU timers์—์„œ ๋ฐœ์ƒํ•˜๋Š” TOCTOU race ์กฐ๊ฑด์„ ๋ฌธ์„œํ™”ํ•˜๋ฉฐ, ์ด๋Š” ํƒ€์ด๋จธ ์ƒํƒœ๋ฅผ ์†์ƒ์‹œํ‚ค๊ณ  kernel์„ crash์‹œํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠน์ • ์ƒํ™ฉ์—์„œ๋Š” privilege escalation์œผ๋กœ ์œ ๋„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Affected component: kernel/time/posix-cpu-timers.c
  • Primitive: task exit ์‹œ expiry vs deletion race
  • Config sensitive: CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n (IRQ-context expiry path)

Quick internals recap (relevant for exploitation)

  • ์„ธ ๊ฐ€์ง€ CPU ํด๋ก์ด cpu_clock_sample()์„ ํ†ตํ•ด ํƒ€์ด๋จธ ํšŒ๊ณ„๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค:
  • CPUCLOCK_PROF: utime + stime
  • CPUCLOCK_VIRT: utime only
  • CPUCLOCK_SCHED: task_sched_runtime()
  • Timer creation wires a timer to a task/pid and initializes the timerqueue nodes:
static int posix_cpu_timer_create(struct k_itimer *new_timer) {
struct pid *pid;
rcu_read_lock();
pid = pid_for_clock(new_timer->it_clock, false);
if (!pid) { rcu_read_unlock(); return -EINVAL; }
new_timer->kclock = &clock_posix_cpu;
timerqueue_init(&new_timer->it.cpu.node);
new_timer->it.cpu.pid = get_pid(pid);
rcu_read_unlock();
return 0;
}
  • Arming์€ per-base timerqueue์— ์‚ฝ์ž…๋˜๋ฉฐ next-expiry cache๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
static void arm_timer(struct k_itimer *timer, struct task_struct *p) {
struct posix_cputimer_base *base = timer_base(timer, p);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 newexp = cpu_timer_getexpires(ctmr);
if (!cpu_timer_enqueue(&base->tqhead, ctmr)) return;
if (newexp < base->nextevt) base->nextevt = newexp;
}
  • Fast path๋Š” ์บ์‹œ๋œ ๋งŒ๋ฃŒ ์ •๋ณด๊ฐ€ ํƒ€์ด๋จธ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐœ๋™ํ•  ๊ฐ€๋Šฅ์„ฑ์„ ์‹œ์‚ฌํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋น„์šฉ์ด ํฐ ์ฒ˜๋ฆฌ๋ฅผ ํ”ผํ•ฉ๋‹ˆ๋‹ค:
static inline bool fastpath_timer_check(struct task_struct *tsk) {
struct posix_cputimers *pct = &tsk->posix_cputimers;
if (!expiry_cache_is_inactive(pct)) {
u64 samples[CPUCLOCK_MAX];
task_sample_cputime(tsk, samples);
if (task_cputimers_expired(samples, pct))
return true;
}
return false;
}
  • Expiration์€ ๋งŒ๋ฃŒ๋œ ํƒ€์ด๋จธ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ , ์ด๋“ค์„ firing์œผ๋กœ ํ‘œ์‹œํ•œ ๋’ค ํ์—์„œ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค; ์‹ค์ œ ์ „๋‹ฌ์€ ์ง€์—ฐ๋ฉ๋‹ˆ๋‹ค:
#define MAX_COLLECTED 20
static u64 collect_timerqueue(struct timerqueue_head *head,
struct list_head *firing, u64 now) {
struct timerqueue_node *next; int i = 0;
while ((next = timerqueue_getnext(head))) {
struct cpu_timer *ctmr = container_of(next, struct cpu_timer, node);
u64 expires = cpu_timer_getexpires(ctmr);
if (++i == MAX_COLLECTED || now < expires) return expires;
ctmr->firing = 1;                           // critical state
rcu_assign_pointer(ctmr->handling, current);
cpu_timer_dequeue(ctmr);
list_add_tail(&ctmr->elist, firing);
}
return U64_MAX;
}

๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ ๋ชจ๋“œ ๋‘ ๊ฐ€์ง€

  • CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y: ๋งŒ๋ฃŒ๋Š” ๋Œ€์ƒ ํƒœ์Šคํฌ์˜ task_work๋ฅผ ํ†ตํ•ด ์—ฐ๊ธฐ๋จ
  • CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n: ๋งŒ๋ฃŒ๋Š” IRQ ์ปจํ…์ŠคํŠธ์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌ๋จ
POSIX CPU timer ์‹คํ–‰ ๊ฒฝ๋กœ๋“ค ```c void run_posix_cpu_timers(void) { struct task_struct *tsk = current; __run_posix_cpu_timers(tsk); } #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK static inline void __run_posix_cpu_timers(struct task_struct *tsk) { if (WARN_ON_ONCE(tsk->posix_cputimers_work.scheduled)) return; tsk->posix_cputimers_work.scheduled = true; task_work_add(tsk, &tsk->posix_cputimers_work.work, TWA_RESUME); } #else static inline void __run_posix_cpu_timers(struct task_struct *tsk) { lockdep_posixtimer_enter(); handle_posix_cpu_timers(tsk); // IRQ-context path lockdep_posixtimer_exit(); } #endif ```

IRQ-context ๊ฒฝ๋กœ์—์„œ๋Š” firing list๊ฐ€ sighand ์™ธ๋ถ€์—์„œ ์ฒ˜๋ฆฌ๋œ๋‹ค

IRQ-context ์ฒ˜๋ฆฌ ๊ฒฝ๋กœ ```c static void handle_posix_cpu_timers(struct task_struct *tsk) { struct k_itimer *timer, *next; unsigned long flags, start; LIST_HEAD(firing); if (!lock_task_sighand(tsk, &flags)) return; // may fail on exit do { start = READ_ONCE(jiffies); barrier(); check_thread_timers(tsk, &firing); check_process_timers(tsk, &firing); } while (!posix_cpu_timers_enable_work(tsk, start)); unlock_task_sighand(tsk, &flags); // race window opens here list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) { int cpu_firing; spin_lock(&timer->it_lock); list_del_init(&timer->it.cpu.elist); cpu_firing = timer->it.cpu.firing; // read then reset timer->it.cpu.firing = 0; if (likely(cpu_firing >= 0)) cpu_timer_fire(timer); rcu_assign_pointer(timer->it.cpu.handling, NULL); spin_unlock(&timer->it_lock); } } ```

Root cause: IRQ ์‹œ์ ์˜ ๋งŒ๋ฃŒ์™€ ํƒœ์Šคํฌ ์ข…๋ฃŒ ์ค‘ ๋™์‹œ ์‚ญ์ œ ์‚ฌ์ด์˜ TOCTOU Preconditions

  • CONFIG_POSIX_CPU_TIMERS_TASK_WORK is disabled (IRQ ๊ฒฝ๋กœ ์‚ฌ์šฉ ์ค‘)
  • ๋Œ€์ƒ ํƒœ์Šคํฌ๊ฐ€ ์ข…๋ฃŒ ์ค‘์ด์ง€๋งŒ ์™„์ „ํžˆ ํšŒ์ˆ˜๋˜์ง€ ์•Š์Œ
  • ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์ผํ•œ ํƒ€์ด๋จธ์— ๋Œ€ํ•ด posix_cpu_timer_del()์„(๋ฅผ) ๋™์‹œ์— ํ˜ธ์ถœํ•จ

Sequence

  1. update_process_times()๊ฐ€ IRQ ์ปจํ…์ŠคํŠธ์—์„œ ์ข…๋ฃŒ ์ค‘์ธ ํƒœ์Šคํฌ์— ๋Œ€ํ•ด run_posix_cpu_timers()๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  2. collect_timerqueue()๋Š” ctmr->firing = 1๋กœ ์„ค์ •ํ•˜๊ณ  ํƒ€์ด๋จธ๋ฅผ ์ž„์‹œ firing ๋ฆฌ์ŠคํŠธ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.
  3. handle_posix_cpu_timers()๋Š” unlock_task_sighand()๋ฅผ ํ†ตํ•ด sighand๋ฅผ ํ•ด์ œํ•˜์—ฌ ๋ฝ ๋ฐ–์—์„œ ํƒ€์ด๋จธ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  4. unlock ์งํ›„, ์ข…๋ฃŒ ์ค‘์ธ ํƒœ์Šคํฌ๊ฐ€ ํšŒ์ˆ˜๋  ์ˆ˜ ์žˆ๊ณ ; ํ˜•์ œ ์Šค๋ ˆ๋“œ๊ฐ€ posix_cpu_timer_del()๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  5. ์ด ์ฐฝ์—์„œ posix_cpu_timer_del()๋Š” cpu_timer_task_rcu()/lock_task_sighand()๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ํš๋“ํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋”ฐ๋ผ์„œ timer->it.cpu.firing์„ ๊ฒ€์‚ฌํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ์ธ-ํ”Œ๋ผ์ดํŠธ ๊ฐ€๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ญ์ œ๋Š” firing์ด ์•„๋‹Œ ๊ฒƒ์ฒ˜๋Ÿผ ์ง„ํ–‰๋˜์–ด ๋งŒ๋ฃŒ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ์ƒํƒœ๋ฅผ ์†์ƒ์‹œํ‚ค๋ฉฐ, ์ถฉ๋Œ/UB๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

Why TASK_WORK mode is safe by design

  • CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y์ธ ๊ฒฝ์šฐ, ๋งŒ๋ฃŒ๋Š” task_work๋กœ ์—ฐ๊ธฐ๋ฉ๋‹ˆ๋‹ค; exit_task_work๋Š” exit_notify ์ด์ „์— ์‹คํ–‰๋˜๋ฏ€๋กœ IRQ ์‹œ์ ์˜ ํšŒ์ˆ˜์™€์˜ ๊ฒน์นจ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๊ทธ ๊ฒฝ์šฐ์—๋„, ํƒœ์Šคํฌ๊ฐ€ ์ด๋ฏธ ์ข…๋ฃŒ ์ค‘์ด๋ฉด task_work_add()๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค; exit_state์— ๋”ฐ๋ฅธ ์ œ์–ด๋กœ ๋‘ ๋ชจ๋“œ๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

Fix (Android common kernel) and rationale

  • ํ˜„์žฌ ํƒœ์Šคํฌ๊ฐ€ ์ข…๋ฃŒ ์ค‘์ด๋ฉด ์กฐ๊ธฐ ๋ฆฌํ„ด์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ชจ๋“  ์ฒ˜๋ฆฌ๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค:
// kernel/time/posix-cpu-timers.c (Android common kernel commit 157f357d50b5038e5eaad0b2b438f923ac40afeb)
if (tsk->exit_state)
return;
  • ์ด๋Š” ์ข…๋ฃŒ ์ค‘์ธ ํƒœ์Šคํฌ์— ๋Œ€ํ•ด handle_posix_cpu_timers()์— ์ง„์ž…ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜์—ฌ, posix_cpu_timer_del()๊ฐ€ it.cpu.firing์„ ๋†“์น˜๊ณ  ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ์™€ ๊ฒฝ์Ÿํ•˜๋Š” ์œˆ๋„์šฐ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

Impact

  • ๋™์‹œ ๋งŒ๋ฃŒ/์‚ญ์ œ ์ค‘ ํƒ€์ด๋จธ ๊ตฌ์กฐ์ฒด์˜ ์ปค๋„ ๋ฉ”๋ชจ๋ฆฌ ์†์ƒ์€ ์ฆ‰์‹œ ํฌ๋ž˜์‹œ(DoS)๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž„์˜์˜ ์ปค๋„ ์ƒํƒœ ์กฐ์ž‘ ๊ธฐํšŒ ๋•Œ๋ฌธ์— ๊ถŒํ•œ ์ƒ์Šน์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

Triggering the bug (safe, reproducible conditions) Build/config

  • CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n์ด ์„ค์ •๋˜์–ด ์žˆ๊ณ  exit_state gating fix๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์€ ์ปค๋„์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

Runtime strategy

  • ์ข…๋ฃŒ ์ง์ „์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜์—ฌ CPU ํƒ€์ด๋จธ๋ฅผ ๋ถ€์ฐฉํ•˜์„ธ์š” (์Šค๋ ˆ๋“œ๋ณ„ ๋˜๋Š” ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์‹œ๊ณ„):
  • ์Šค๋ ˆ๋“œ๋ณ„์˜ ๊ฒฝ์šฐ: timer_create(CLOCK_THREAD_CPUTIME_ID, โ€ฆ)
  • ํ”„๋กœ์„ธ์Šค ์ „์ฒด์˜ ๊ฒฝ์šฐ: timer_create(CLOCK_PROCESS_CPUTIME_ID, โ€ฆ)
  • ๋งค์šฐ ์งง์€ ์ดˆ๊ธฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„๊ณผ ์ž‘์€ ๊ฐ„๊ฒฉ์œผ๋กœ ์„ค์ •ํ•˜์—ฌ IRQ ๊ฒฝ๋กœ ์ง„์ž…์„ ์ตœ๋Œ€ํ™”ํ•˜์„ธ์š”:
static timer_t t;
static void setup_cpu_timer(void) {
struct sigevent sev = {0};
sev.sigev_notify = SIGEV_SIGNAL;    // delivery type not critical for the race
sev.sigev_signo = SIGUSR1;
if (timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &t)) perror("timer_create");
struct itimerspec its = {0};
its.it_value.tv_nsec = 1;           // fire ASAP
its.it_interval.tv_nsec = 1;        // re-fire
if (timer_settime(t, 0, &its, NULL)) perror("timer_settime");
}
  • ํ˜•์ œ ์Šค๋ ˆ๋“œ์—์„œ ๋Œ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๋™์•ˆ ๋™์ผํ•œ ํƒ€์ด๋จธ๋ฅผ ๋™์‹œ์— ์‚ญ์ œ:
void *deleter(void *arg) {
for (;;) (void)timer_delete(t);     // hammer delete in a loop
}
  • ๋ ˆ์ด์Šค ์ฆํญ ์š”์ธ: ๋†’์€ ์Šค์ผ€์ค„๋Ÿฌ ํ‹ฑ ์†๋„, CPU ๋ถ€ํ•˜, ๋ฐ˜๋ณต์ ์ธ ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ/์žฌ์ƒ์„ฑ ์‚ฌ์ดํด. ํฌ๋ž˜์‹œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ posix_cpu_timer_del()๊ฐ€ unlock_task_sighand() ์งํ›„ task ์กฐํšŒ/์ž ๊ธˆ์— ์‹คํŒจํ•˜์—ฌ firing์„ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํƒ์ง€ ๋ฐ ์™„ํ™”

  • ์™„ํ™”: exit_state guard๋ฅผ ์ ์šฉํ•˜์„ธ์š”; ๊ฐ€๋Šฅํ•˜๋ฉด CONFIG_POSIX_CPU_TIMERS_TASK_WORK ํ™œ์„ฑํ™”๋ฅผ ์šฐ์„  ๊ณ ๋ คํ•˜์„ธ์š”.
  • ๊ด€์ฐฐ์„ฑ: unlock_task_sighand()/posix_cpu_timer_del() ์ฃผ๋ณ€์— tracepoints/WARN_ONCE๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”; it.cpu.firing==1์ด cpu_timer_task_rcu()/lock_task_sighand() ์‹คํŒจ์™€ ํ•จ๊ป˜ ๊ด€์ธก๋˜๋ฉด ๊ฒฝ๋ณด๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์„ธ์š”; task ์ข…๋ฃŒ ์ฃผ๋ณ€์˜ timerqueue ๋ถˆ์ผ์น˜๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์„ธ์š”.

๊ฐ์‚ฌ ํ•ต์‹ฌ ์ง€์  (๊ฒ€ํ† ์ž์šฉ)

  • update_process_times() โ†’ run_posix_cpu_timers() (IRQ)
  • __run_posix_cpu_timers() ์„ ํƒ (TASK_WORK vs IRQ ๊ฒฝ๋กœ)
  • collect_timerqueue(): ctmr->firing๋ฅผ ์„ค์ •ํ•˜๊ณ  ๋…ธ๋“œ๋“ค์„ ์ด๋™
  • handle_posix_cpu_timers(): firing ๋ฃจํ”„ ์ „์— sighand๋ฅผ ํ•ด์ œ
  • posix_cpu_timer_del(): it.cpu.firing์— ์˜์กดํ•ด ์ง„ํ–‰ ์ค‘ ๋งŒ๋ฃŒ๋ฅผ ๊ฐ์ง€ํ•จ; exit/reap ๋™์•ˆ task ์กฐํšŒ/์ž ๊ธˆ์ด ์‹คํŒจํ•˜๋ฉด ์ด ๊ฒ€์‚ฌ๊ฐ€ ๊ฑด๋„ˆ๋›ฐ์–ด์ง

์ต์Šคํ”Œ๋กœ์ž‡ ์—ฐ๊ตฌ ์ฐธ๊ณ 

  • ๊ณต๊ฐœ๋œ ๋™์ž‘์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” kernel crash primitive์ž…๋‹ˆ๋‹ค; ์ด๋ฅผ privilege escalation์œผ๋กœ ์ „ํ™˜ํ•˜๋ ค๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณธ ์š”์•ฝ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ์ถ”๊ฐ€์ ์ธ ์ œ์–ด ๊ฐ€๋Šฅํ•œ ์˜ค๋ฒ„๋žฉ(๊ฐ์ฒด ์ˆ˜๋ช… ๋˜๋Š” write-what-where ์˜ํ–ฅ)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  PoC๋Š” ์‹œ์Šคํ…œ์„ ๋ถˆ์•ˆ์ •ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋‹ˆ emulators/VMs์—์„œ๋งŒ ์‹คํ–‰ํ•˜์„ธ์š”.

Chronomaly exploit strategy (priv-esc without fixed text offsets)

  • Tested target & configs: x86_64 v5.10.157 under QEMU (4 cores, 3 GB RAM). Critical options: CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n, CONFIG_PREEMPT=y, CONFIG_SLAB_MERGE_DEFAULT=n, DEBUG_LIST=n, BUG_ON_DATA_CORRUPTION=n, LIST_HARDENED=n.
  • Race steering with CPU timers: ๋ ˆ์ด์‹ฑ ์Šค๋ ˆ๋“œ(race_func())๊ฐ€ CPU๋ฅผ ์†Œ๋ชจํ•˜๋Š” ๋™์•ˆ CPU timers๊ฐ€ ๋ฐœ๋™ํ•จ; free_func()๋Š” ํƒ€์ด๋จธ๊ฐ€ ๋ฐœ๋™ํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด SIGUSR1์„ ํด๋งํ•ฉ๋‹ˆ๋‹ค. ์‹ ํ˜ธ๊ฐ€ ๊ฐ„ํ—์ ์œผ๋กœ๋งŒ ๋„์ฐฉํ•˜๋„๋ก CPU_USAGE_THRESHOLD๋ฅผ ์กฐ์ •ํ•˜์„ธ์š”(๊ฐ„ํ—์ ์œผ๋กœ โ€œParent raced too late/too earlyโ€ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•จ). ํƒ€์ด๋จธ๊ฐ€ ํ•ญ์ƒ ๋ฐœ๋™ํ•˜๋ฉด threshold๋ฅผ ๋‚ฎ์ถ”๊ณ , ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ ์ „์— ์ ˆ๋Œ€ ๋ฐœ๋™ํ•˜์ง€ ์•Š์œผ๋ฉด ๋†’์ด์„ธ์š”.
  • Dual-process alignment into send_sigqueue(): ๋ถ€๋ชจ/์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” send_sigqueue() ๋‚ด๋ถ€์˜ ๋‘ ๋ฒˆ์งธ ๋ ˆ์ด์Šค ์ฐฝ์„ ๋…ธ๋ฆฝ๋‹ˆ๋‹ค. ๋ถ€๋ชจ๋Š” ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์ „์— PARENT_SETTIME_DELAY_US ๋งˆ์ดํฌ๋กœ์ดˆ๋งŒํผ sleepํ•ฉ๋‹ˆ๋‹ค; ๋Œ€๋ถ€๋ถ„ โ€œParent raced too lateโ€œ๊ฐ€ ๋ณด์ด๋ฉด ๊ฐ’์„ ์ค„์ด๊ณ , ๋Œ€๋ถ€๋ถ„ โ€œParent raced too earlyโ€œ๊ฐ€ ๋ณด์ด๋ฉด ๊ฐ’์„ ๋Š˜๋ฆฌ์„ธ์š”. ๋‘˜ ๋‹ค ๋ณด์ด๋ฉด ์ฐฝ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค; ํŠœ๋‹์ด ์™„๋ฃŒ๋˜๋ฉด ์•ฝ 1๋ถ„ ๋‚ด์— ์„ฑ๊ณต์ด ๊ธฐ๋Œ€๋ฉ๋‹ˆ๋‹ค.
  • Cross-cache UAF replacement: ์ต์Šคํ”Œ๋กœ์ž‡์€ struct sigqueue๋ฅผ ํ•ด์ œํ•œ ๋’ค ํ• ๋‹น๊ธฐ ์ƒํƒœ๋ฅผ ์ •๋ฆฌ(sigqueue_crosscache_preallocs())ํ•˜์—ฌ dangling uaf_sigqueue์™€ ๊ต์ฒด๋  realloc_sigqueue๊ฐ€ pipe buffer ๋ฐ์ดํ„ฐ ํŽ˜์ด์ง€์— ๊ฐ™์ด ๋ฐฐ์น˜๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค(ํฌ๋กœ์Šค-์บ์‹œ ์žฌํ• ๋‹น). ์‹ ๋ขฐ์„ฑ์€ ์ด์ „์— ์ ์€ ์ˆ˜์˜ sigqueue ํ• ๋‹น์ด ์žˆ๋Š” ์กฐ์šฉํ•œ ์ปค๋„์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค; ์ด๋ฏธ per-CPU/per-node ๋ถ€๋ถ„ ์Šฌ๋žฉ ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜๋Š” ๋ฐ”์œ ์‹œ์Šคํ…œ์—์„œ๋Š” ๊ต์ฒด๊ฐ€ ์‹คํŒจํ•˜๊ณ  ์ฒด์ธ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๋Š” ์‹œ๋„๋Ÿฌ์šด ์ปค๋„์— ๋Œ€ํ•œ ์ตœ์ ํ™”๋ฅผ ์ผ๋ถ€๋Ÿฌ ์ƒ๋žตํ–ˆ์Šต๋‹ˆ๋‹ค.

See also

Ksmbd Streams Xattr Oob Write Cve 2025 37947

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ