🇰🇷 한글 설명
Linux 커널의 네트워킹 스케줄러(qdisc) API에서 존재하지 않는 부모 클래스를 지정할 때 초기화 단계에서 null 포인터 참조로 인한 커널 패닉이 발생할 수 있는 취약점입니다. fq, hhf, choke 등 특정 qdisc가 qdisc_tree_reduce_backlog를 호출할 때 부모 클래스 존재 여부를 사전에 검증하지 않아 발생합니다.
💡 쉬운 설명
Linux 커널에서 네트워크 트래픽 관리 설정(qdisc)을 잘못 구성할 때 커널이 충돌할 수 있습니다. 관리자 권한이 필요하므로 로컬 공격만 가능합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
net/sched: Abort __tc_modify_qdisc if parent class does not exist
Lion's patch [1] revealed an ancient bug in the qdisc API.
Whenever a user creates/modifies a qdisc specifying as a parent another
qdisc, the qdisc API will, during grafting, detect that the user is
not trying to attach to a class and reject. However grafting is
performed after qdisc_create (and thus the qdiscs' init callback) is
executed. In qdiscs that eventually call qdisc_tree_reduce_backlog
during init or change (such as fq, hhf, choke, etc), an issue
arises. For example, executing the following commands:
sudo tc qdisc add dev lo root handle a: htb default 2
sudo tc qdisc add dev lo parent a: handle beef fq
Qdiscs such as fq, hhf, choke, etc unconditionally invoke
qdisc_tree_reduce_backlog() in their control path init() or change() which
then causes a failure to find the child class; however, that does not stop
the unconditional invocation of the assumed child qdisc's qlen_notify with
a null class. All these qdiscs make the assumption that class is non-null.
The solution is ensure that qdisc_leaf() which looks up the parent
class, and is invoked prior to qdisc_create(), should return failure on
not finding the class.
In this patch, we leverage qdisc_leaf to return ERR_PTRs whenever the
parentid doesn't correspond to a class, so that we can detect it
earlier on and abort before qdisc_create is called.
[1] https://lore.kernel.org/netdev/
[email protected]/
📍 영향받는 시스템
Linux kernel 5.x-6.x 버전 (정확한 버전 범위는 커널 빌드 설정에 따라 다름)
⚔️ 공격 벡터
로컬 권한 있는 사용자가 tc(traffic control) 명령으로 잘못된 qdisc 설정을 시도할 때 (예: sudo tc qdisc add dev lo parent a: handle beef fq)
🛡️ 대응 방법
최신 Linux kernel 패치 적용 또는 kernel을 5.15.160 이상, 6.1.104 이상, 6.6.46 이상, 6.7.14 이상, 6.8.1 이상으로 업그레이드
🔧 검증 코드
현재 커널 버전이 표시되고, 권장 버전 이상이면 안전하며 미만이면 패치 필요
uname -r | grep -E '^[456]\.([0-9]+)' && cat /proc/version | grep -oP 'Linux version \K[^ ]+'