🇰🇷 한글 설명
Linux 커널의 powerpc perf 모듈에서 해제된 메모리 관리 구조체(current->mm)에 접근할 때 NULL 포인터 역참조로 인한 커널 패닉이 발생합니다. BPF 프로파일링 프로그램 실행 시 트리거될 수 있습니다.
💡 쉬운 설명
Linux 시스템의 성능 분석 도구가 이미 제거된 메모리 영역에 접근하려다 시스템이 충돌합니다. BPF 프로파일링 도구를 실행할 때 발생합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
powerpc, perf: Check that current->mm is alive before getting user callchain
It may happen that mm is already released, which leads to kernel panic.
This adds the NULL check for current->mm, similarly to
commit 20afc60f892d ("x86, perf: Check that current->mm is alive before getting user callchain").
I was getting this panic when running a profiling BPF program
(profile.py from bcc-tools):
[26215.051935] Kernel attempted to read user page (588) - exploit attempt? (uid: 0)
[26215.051950] BUG: Kernel NULL pointer dereference on read at 0x00000588
[26215.051952] Faulting instruction address: 0xc00000000020fac0
[26215.051957] Oops: Kernel access of bad area, sig: 11 [#1]
[...]
[26215.052049] Call Trace:
[26215.052050] [c000000061da6d30] [c00000000020fc10] perf_callchain_user_64+0x2d0/0x490 (unreliable)
[26215.052054] [c000000061da6dc0] [c00000000020f92c] perf_callchain_user+0x1c/0x30
[26215.052057] [c000000061da6de0] [c0000000005ab2a0] get_perf_callchain+0x100/0x360
[26215.052063] [c000000061da6e70] [c000000000573bc8] bpf_get_stackid+0x88/0xf0
[26215.052067] [c000000061da6ea0] [c008000000042258] bpf_prog_16d4ab9ab662f669_do_perf_event+0xf8/0x274
[...]
In addition, move storing the top-level stack entry to generic
perf_callchain_user to make sure the top-evel entry is always captured,
even if current->mm is NULL.
[Maddy: fixed message to avoid checkpatch format style error]
📍 영향받는 시스템
Linux kernel powerpc 아키텍처 (모든 버전, 수정 전)
⚔️ 공격 벡터
로컬 사용자가 BPF 프로파일링 프로그램(예: bcc-tools profile.py) 실행
🛡️ 대응 방법
Linux 커널을 최신 버전으로 업그레이드하거나 현재->mm NULL 체크 패치 적용
🔧 검증 코드
커널 버전과 perf_callchain_user 함수의 NULL 체크 존재 여부 확인. NULL 체크가 있으면 패치 적용됨.
cat /proc/version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' && grep -r 'if (current->mm)' /boot/config-* 2>/dev/null