
KCOV 트레이스를 사용하여 Linux 커널 경쟁 조건을 탐구하기 위한 툴킷: 동시 실행 및 메모리 접근을 위한 GUI 및 터미널 뷰어, 그리고 자동 A-B-A 순서 테스트를 제공합니다.
이것은 Linux 커널 경쟁 조건(race condition)을 탐구하고 일반적인 커널 디버깅을 위한 도구입니다.
발표 블로그 글 https://projectzero.google/2026/09/maccconc-race-condition.html도 참고하세요.
현재 세 가지 도구가 있습니다:
이것은 공식적으로 지원되는 Google 제품이 아닙니다. 이 프로젝트는 Google Open Source Software Vulnerability Rewards Program의 대상이 아닙니다.
먼저, 커밋 dc5c6d008f48을 포함하는 LLVM 버전을 구하세요. 즉, 릴리스 브랜치가 아닌 HEAD에서 빌드하거나 버전 >=23의 빌드여야 합니다. 이러한 빌드는 예를 들어 https://apt.llvm.org/ 에서 사용할 수 있습니다. googler라면 http://go/maccconc-kernel-build-notes 를 참고하세요.
필요한 패치가 포함된 커널 트리를 https://github.com/thejh/linux 의 kcov-tracing-full 브랜치에서 구하세요.
커널을 구성하고 빌드할 때, 올바른 LLVM 툴체인이 사용되도록
https://docs.kernel.org/kbuild/llvm.html에 문서화된 대로 make 변수
CC / LLVM / LLVM_PREFIX를 설정하세요.
실행된 기본 블록(GUI용)에 대한 더 명확한 정보를 얻고 테일 콜 최적화로 인한
혼란스러운 호출 스택을 피하려면 이 환경 변수를 설정하세요:
export KCFLAGS="-fno-optimize-sibling-calls -mllvm -sanitizer-coverage-prune-blocks=false"
평소처럼 커널을 구성하세요. 기존 구성에서 시작하지 않는 경우
make [...] kvm_guest.config에서 시작하는 것이 유용할 수 있습니다.
다음 커널 구성 플래그가 설정되어 있는지 확인하세요(예를 들어 ncurses 구성 UI
make [...] nconfig를 통해 또는 .config 하단에 붙여넣어서):
# for core functionality
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_KASAN=y
CONFIG_KASAN_OUTLINE=y
CONFIG_KCOV=y
CONFIG_KCOV_EXT_RECORDS=y
CONFIG_KCOV_MEMORY=y
CONFIG_KALLSYMS_ALL=y
# to give the GUI information about source lines and inlining
CONFIG_DEBUG_INFO_DWARF5=y
# for communicating with the GUI
CONFIG_VSOCKETS=y
CONFIG_VIRTIO_VSOCKETS=y
CONFIG_VIRTIO_PCI=y
# for maximizing the potential for race conditions
CONFIG_PREEMPT=y
# for making virtual addresses at runtime the same as in vmlinux
CONFIG_RANDOMIZE_BASE=n
# needed for several samples
CONFIG_TMPFS=y
RCU와 관련된 경쟁 조건을 테스트하려면 다음을 활성화할 수도 있지만, 이는 큰 속도 저하를 초래하며 현재 GUI를 사용하는 경우에만 제대로 작동합니다.
CONFIG_RCU_EXPERT=y
CONFIG_RCU_STRICT_GRACE_PERIOD=y
테스트하려는 커널 기능은 모듈이 아닌 커널에 컴파일되어 있는지 확인하세요.
사용자 공간 도구는 호스트 머신에서 빌드하는 것이 권장됩니다. 특히 GUI는 게스트가 아닌 호스트에서 실행되도록 설계되었습니다.
git과 빌드 의존성을 설치하세요. Debian의 경우:
sudo apt install git build-essential pkg-config libcapstone-dev libdw-dev libglfw3-dev
이 저장소를 복제한 후, 다음으로 서브모듈을 다운로드하세요:
git submodule update --init --recursive
make로 빌드하세요.
필요한 커널 구성 플래그를 활성화하고 Linux 배포판이 있는 디스크 이미지 등을 사용하면 일반 QEMU VM에서 빌드된 커널을 부팅할 수 있습니다. 하지만 권장되는 방법은 대신 다음과 같이 kvmtool을 설치하는 것입니다:
git clone https://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git
cd kvmtool
make
make install
그런 다음 다음과 같이 빌드된 커널을 부팅할 수 있습니다($HOME/bin이 $PATH에 있다고 가정):
lkvm run --kernel [path to kernel tree]/arch/x86/boot/bzImage --vsock 5 --console virtio
이렇게 하면 호스트 파일시스템의 읽기 전용 뷰가 /host에 마운트된 환경에서 셸을 얻을 수 있으며, 최소한의 rootfs는 대부분 /bin, /lib, /usr 등을 이 호스트 파일시스템으로의 심볼릭 링크로 구성됩니다. /와 /host 모두 9p 파일시스템입니다.
각 부팅 후 게스트에서 debugfs와 tmpfs를 수동으로 마운트하세요:
sh-5.3# mount -t debugfs none /sys/kernel/debug
sh-5.3# mount -t tmpfs none /tmp
sh-5.3#
테스트 케이스는 네 개의 함수를 정의하는 C 코드입니다:
void test_setup(void) { [...] }
void test_thread1(void) { [...] }
void test_thread2(void) { [...] }
void test_end(void) { [...] }
테스트 케이스가 실행될 때마다 test_setup()이 먼저 실행되고, 그런 다음 test_thread1()과 test_thread2()가 병렬로 실행되며, 마지막으로 test_end()가 실행됩니다.
테스트 케이스는 다음과 같이 공유 라이브러리로 빌드해야 합니다:
$ cc -shared -o [name].so [name].c -fPIC
testcase/ 폴더의 샘플 테스트 케이스는 다음과 같이 make로도 빌드할 수 있습니다:
$ make testcase/demo-dup-vs-close.so
cc -shared -o testcase/demo-dup-vs-close.so testcase/demo-dup-vs-close.c -Wall
kcov-autorace 도구는 A-B-A 실행 순서를 자동으로 탐구할 수 있습니다.
A-B-A 순서는 스레드 A가 어느 지점까지 실행되고, 그런 다음 스레드 B가 완전히
실행되고, 그런 다음 스레드 A가 실행을 마치는 순서입니다.
호스트에서 테스트 케이스를 빌드한 후, kcov-autorace 헬퍼를 사용하여
게스트에서 실행할 수 있습니다. 예를 들어:
sh-5.3# cd /host/{path to checkout on the host}
sh-5.3# ./kcov-autorace testcase/demo-dup-vs-close.so
loading kallsyms
RCU state (excluded): base=ffffffff82770100 len=500
loading testcase
initializing kcov
collecting A-B coverage
dup(5) = 6 (success)
testing candidates
dup(5) = -1 (Bad file descriptor)
dup(5) = -1 (Bad file descriptor)
dup(5) = -1 (Bad file descriptor)
dup(5) = 5 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
dup(5) = 6 (success)
stats: injection-failed:0 wait-timeout:7 reordered:4
sh-5.3#
이는 close(5)와 dup(5)의 A-B-A 순서가 존재하여 dup(5)가 5를 반환하게 만든다는 것을 보여줍니다.
kcov-autorace와 다른 도구들은 하드코딩된 스핀 대기 타임아웃
SPIN_LIMIT을 사용한다는 점에 유의하세요.
kcov-terminal 도구는 수동으로 지정된 순서 제약 조건으로 테스트케이스를
실행하는 데 사용할 수 있습니다. 이는 전체 순서를 지정하지 않고, 대신
"A가 B보다 먼저 발생해야 한다"는 규칙의 집합입니다.
이 도구는 kcov-autorace와 유사하게 게스트에서 사용됩니다.
fstat()에 의한 UID와 GID 읽기가 fchown()에 대해 원자적이지 않음을 보여주는
순서 제약 조건으로 실행하기 위한 테스트케이스 demo-inode-attr-change의
사용 예:
sh-5.3# ./kcov-terminal testcase/demo-inode-attr-change.so
uid=0 gid=0
===== filtered to interference set, no RCU core =====
LEGEND:
type: R=read W=write M=modify(read+write) F=free A=atomic