发布时间: 2024年9月3日
修改时间: 2024年9月14日
In the Linux kernel, the following vulnerability has been resolved:bpf: Fail bpf_timer_cancel when callback is being cancelledGiven a schedule:timer1 cb timer2 cbbpf_timer_cancel(timer2); bpf_timer_cancel(timer1);Both bpf_timer_cancel calls would wait for the other callback to finishexecuting, introducing a lockup.Add an atomic_t count named cancelling in bpf_hrtimer. This keepstrack of all in-flight cancellation requests for a given BPF timer.Whenever cancelling a BPF timer, we must check if we have outstandingcancellation requests, and if so, we must fail the operation with anerror (-EDEADLK) since cancellation is synchronous and waits for thecallback to finish executing. This implies that we can enter a deadlocksituation involving two or more timer callbacks executing in paralleland attempting to cancel one another.Note that we avoid incrementing the cancelling counter for the targettimer (the one being cancelled) if bpf_timer_cancel is not invoked froma callback, to avoid spurious errors. The whole point of detectingcur->cancelling and returning -EDEADLK is to not enter a busy wait loop(which may or may not lead to a lockup). This does not apply in case thecaller is in a non-callback context, the other side can continue tocancel as it sees fit without running into errors.Background on prior attempts:Earlier versions of this patch used a bool cancelling bit and used thefollowing pattern under timer->lock to publish cancellation status.lock(t->lock);t->cancelling = true;mb();if (cur->cancelling) return -EDEADLK;unlock(t->lock);hrtimer_cancel(t->timer);t->cancelling = false;The store outside the critical section could overwrite a parallelrequests t->cancelling assignment to true, to ensure the parallelyexecuting callback observes its cancellation status.It would be necessary to clear this cancelling bit once hrtimer_cancelis done, but lack of serialization introduced races. Another option wasexplored where bpf_timer_start would clear the bit when (re)starting thetimer under timer->lock. This would ensure serialized access to thecancelling bit, but may allow it to be cleared before in-flighthrtimer_cancel has finished executing, such that lockups can occuragain.Thus, we choose an atomic counter to keep track of all outstandingcancellation requests and use it to prevent lockups in case callbacksattempt to cancel each other while executing in parallel.
NVD | openEuler | |
---|---|---|
CVSS评分 | 5.5 | 5.5 |
Attack Vector | Local | Local |
Attack Complexity | Low | Low |
Privileges Required | Low | Low |
User Interaction | None | None |
Scope | Unchanged | Unchanged |
Confidentiality | None | None |
Integrity | None | None |
Availability | High | High |
公告名 | 概要 | 发布时间 |
---|---|---|
KylinSec-SA-2024-3594 | In the Linux kernel, the following vulnerability has been resolved:bpf: Fail bpf_timer_cancel when callback is being cancelledGiven a schedule:timer1 cb timer2 cbbpf_timer_cancel(timer2); bpf_timer_cancel(timer1);Both bpf_timer_cancel calls would wait for the other callback to finishexecuting, introducing a lockup.Add an atomic_t count named cancelling in bpf_hrtimer. This keepstrack of all in-flight cancellation requests for a given BPF timer.Whenever cancelling a BPF timer, we must check if we have outstandingcancellation requests, and if so, we must fail the operation with anerror (-EDEADLK) since cancellation is synchronous and waits for thecallback to finish executing. This implies that we can enter a deadlocksituation involving two or more timer callbacks executing in paralleland attempting to cancel one another.Note that we avoid incrementing the cancelling counter for the targettimer (the one being cancelled) if bpf_timer_cancel is not invoked froma callback, to avoid spurious errors. The whole point of detectingcur->cancelling and returning -EDEADLK is to not enter a busy wait loop(which may or may not lead to a lockup). This does not apply in case thecaller is in a non-callback context, the other side can continue tocancel as it sees fit without running into errors.Background on prior attempts:Earlier versions of this patch used a bool cancelling bit and used thefollowing pattern under timer->lock to publish cancellation status.lock(t->lock);t->cancelling = true;mb();if (cur->cancelling) return -EDEADLK;unlock(t->lock);hrtimer_cancel(t->timer);t->cancelling = false;The store outside the critical section could overwrite a parallelrequests t->cancelling assignment to true, to ensure the parallelyexecuting callback observes its cancellation status.It would be necessary to clear this cancelling bit once hrtimer_cancelis done, but lack of serialization introduced races. Another option wasexplored where bpf_timer_start would clear the bit when (re)starting thetimer under timer->lock. This would ensure serialized access to thecancelling bit, but may allow it to be cleared before in-flighthrtimer_cancel has finished executing, such that lockups can occuragain.Thus, we choose an atomic counter to keep track of all outstandingcancellation requests and use it to prevent lockups in case callbacksattempt to cancel each other while executing in parallel. | 2024年9月3日 |
产品 | 包 | 状态 |
---|---|---|
KY3.4-5A | kernel | Unaffected |
KY3.5.2 | kernel | Unaffected |
V6 | kernel | Fixed |