
Linux कर्नेल रेस कंडीशन्स को KCOV ट्रेस का उपयोग करके एक्सप्लोर करने के लिए टूलकिट: समवर्ती निष्पादन और मेमोरी एक्सेस के लिए GUI और टर्मिनल व्यूअर, साथ ही स्वचालित A-B-A ऑर्डरिंग परीक्षण।
यह लिनक्स कर्नेल रेस कंडीशन्स की खोज और सामान्य कर्नेल डिबगिंग के लिए टूलिंग है।
घोषणा ब्लॉग पोस्ट भी देखें https://projectzero.google/2026/09/maccconc-race-condition.html।
वर्तमान में तीन टूल हैं:
यह आधिकारिक रूप से समर्थित Google उत्पाद नहीं है। यह प्रोजेक्ट Google Open Source Software Vulnerability Rewards Program के लिए पात्र नहीं है।
सबसे पहले, LLVM का एक संस्करण प्राप्त करें जिसमें कमिट dc5c6d008f48 शामिल हो; अर्थात् या तो HEAD से बिल्ड, रिलीज़ ब्रांच से नहीं, या संस्करण >=23 पर बिल्ड। ऐसे बिल्ड, उदाहरण के लिए, https://apt.llvm.org/ पर उपलब्ध हैं। यदि आप googler हैं, तो http://go/maccconc-kernel-build-notes देखें।
आवश्यक पैच के साथ एक कर्नेल ट्री प्राप्त करें https://github.com/thejh/linux से, ब्रांच kcov-tracing-full।
कर्नेल को कॉन्फ़िगर और बिल्ड करते समय, make वेरिएबल्स
CC / LLVM / LLVM_PREFIX को https://docs.kernel.org/kbuild/llvm.html पर
प्रलेखित अनुसार सेट करें ताकि सही LLVM
टूलचेन का उपयोग सुनिश्चित हो।
निष्पादित बेसिक ब्लॉक्स (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 से बिल्ड करें।
यदि आप आवश्यक कर्नेल कॉन्फ़िग फ़्लैग सक्षम करते हैं और लिनक्स डिस्ट्रीब्यूशन वाली डिस्क इमेज, या कुछ ऐसा ही उपयोग करते हैं, तो आप बिल्ड किए गए कर्नेल को सामान्य 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 के समान।
टेस्टकेस demo-inode-attr-change के साथ उदाहरण उपयोग, ऑर्डरिंग बाधाओं के साथ चलाने के लिए जो दर्शाती हैं कि fstat() द्वारा UID और GID का पढ़ना fchown() के संबंध में परमाणु नहीं है:
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