{"owner":"google","repo":"security-research","hasSkills":true,"totalSkillsCount":4,"totalTokensCount":13993,"categories":["root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["kvmctf/rules.md","v8ctf/rules.md","analysis/kernel/dashboard/tools/README.md","kernelctf/rules.md"],"skills":{"kvmctf/rules.md":"# kvmCTF Overview\n\nkvmCTF is a part of the\n[Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules)\nand is focused on eliminating VM-reachable Kernel-based Virtual Machine (KVM)\nvulnerabilities in upstream mainline kernel. We invite security researchers to\ndemonstrate their bug hunting and exploitation techniques on an LTS kernel version.\nEventually we might add experimental mitigations to KVM that we would like to see\nif and how researchers can bypass them.\n\nWe are additionally asking researchers to publish their submissions, helping the\ncommunity to learn from each other’s techniques.\n\n# Competition Rules\n\n## Target: Linux LTS KVM\n\nThe host runs v6.1.74 and runs on an Intel(R) Xeon(R) Gold 5222 CPU @ 3.80GHz.\nParticipants will have the option to select whether they want the host to run\nwith `CONFIG_KASAN` disabled or enabled. The complete setup of the host can be\ndownloaded\n[here](https://storage.googleapis.com/kvmctf/latest.tar.gz) in a\ngzip format and contains the following:\n* The kernel patch we applied on the kernel tree.\n* The kernel configuration files.\n* The gcc and binutils versions used to compile the kernel.\n* The virsh version used to run the VM.\n* The produced `vmlinux` images.\n* The produced `bzImage` binaries.\n* The produced `ko` module binaries.\n* The `qemu-kvm` command used to run the guest.\n\nParticipants will be connected to a Debian 12.5 (bookworm) guest that runs on a\n`v6.1.0-21` kernel compiled with the default Debian config.\n\nThe goal is to perform a successful guest-to-host attack. Currently we do not\nreward QEMU, host-to-KVM or CPU/DRAM/HW-based vulnerabilities.\n\nNote: Although our testing environment runs an LTS kernel, vulnerabilities must\nbe reproducible in the upstream Linux mainline master branch to be eligible.\nVulnerabilities that only exist in downstream backports or older LTS trees are\nout of scope.\n\n## Rewards\n| Tier                   | Reward   |\n|------------------------| -------- |\n| Full VM escape         | $250,000 |\n| Arbitrary memory write | $100,000 |\n| Arbitrary memory read  | $50,000  |\n| Relative memory write  | $50,000  |\n| Denial of Service      | $20,000  |\n| Relative memory read   | $10,000  |\n\n\nNote that the above rewards do not stack. For instance, if you submit a full VM\nescape exploit that takes advantage of an arbitrary memory read you will be\nrewarded with $250,000, not $250,000 + $50,000.\n\n## Flags\nYour submission should contain proof that your exploit succeeded in one of the\nabove tiers. This is achieved by providing each tier's corresponding flag (a\n64-bit number). Note that providing the flag does **not** automatically\nguarantee the corresponding reward, your exploit must take advantage of a\nvulnerability of that tier. For instance, if you use an arbitrary memory read\nvulnerability to read the arbitrary memory write flag, you will **not** be\ncompensated with the arbitrary memory write reward.\n### RCE flag\nTo obtain this flag your exploit should read the contents of the\n`/root/rce_flag` file in the host file system.\n### Arbitrary memory accesses\nFor the arbitrary memory write tier your exploit should overwrite the contents\nof the write flag address (its default value is `0xdeadbeef41424344` so your\nexploit should modify any or all of its bits), whereas for the arbitrary memory\nread tier your exploit should read the contents of the read flag address. The\ntarget addresses (both virtual and physical) can be found in the\n`/root/addresses` file in the guest file system. For the arbitrary memory write\ntier, your exploit should first overwrite the contents of the write flag address\nand then call hypercall `#100` which will return the corresponding flag in\n`RAX`. For the arbitrary memory read tier, the flag is the contents of the read\nflag address.\n### Relative memory accesses\nThe relative memory read and relative memory write are available only if the\nhost runs with `CONFIG_KASAN` enabled. The mapping between the KASAN violations\nand the reward tiers is the following:\n\n| Operation     | KASAN violation         | Reward Tier           |\n| ------------  | ----------------------- | ------------------    |\n| Memory Write  | use-after-free          | Relative memory write |\n| Memory Write  | out-of-bounds           | Relative memory write |\n| Memory Write  | slab-out-of-bounds      | Relative memory write |\n| Memory Write  | global-out-of-bounds    | Relative memory write |\n| Memory Write  | stack-out-of-bounds     | Relative memory write |\n| Memory Write  | alloca-out-of-bounds    | Relative memory write |\n| Memory Write  | vmalloc-out-of-bounds   | Relative memory write |\n| Memory Write  | user-memory-access      | Relative memory write |\n| Memory Write  | wild-memory-access      | Relative memory write |\n| *             | double-free             | Relative memory write |\n| *             | invalid-free            | Relative memory write |\n| Memory Read   | use-after-free          | Relative memory read  |\n| Memory Read   | out-of-bounds           | Relative memory read  |\n| Memory Read   | slab-out-of-bounds      | Relative memory read  |\n| Memory Read   | global-out-of-bounds    | Relative memory read  |\n| Memory Read   | stack-out-of-bounds     | Relative memory read  |\n| Memory Read   | alloca-out-of-bounds    | Relative memory read  |\n| Memory Read   | vmalloc-out-of-bounds   | Relative memory read  |\n| Memory Read   | user-memory-access      | Relative memory read  |\n| Memory Read   | wild-memory-access      | Relative memory read  |\n| *             | null-ptr-deref          | Denial of Service     |\n\nFor the relative memory write tier, your exploit should first perform the\noperation that produces the KASAN violation and then call hypercall `#101` which\nwill return the flag in `RAX`.\nSimilarly, for the relative memory read tier, your exploit should first perform\nthe operation to produce the KASAN violation and then call hypercall `#102`\nwhich will return the flag in `RAX`.\n\n### Denial of Service\nThe Denial of Service tier rewards exploits that induce a `null-ptr-deref` KASAN\nviolation, or that make the host panic or otherwise\ncrash. In the former case, your exploit should first perform the operation to\nproduce the KASAN violation and then call hypercall `#103` which will return the\nflag in `RAX`.\nIn the latter case, you do not need to provide a flag: after executing your\nexploit and crashing the host just specify in the submission form that you are\nsubmitting a Denial of Service exploit.\n\n## Process\nTo try your exploit on our server you will have to reserve a time slot. You can\ndo it using the command:\n\n``socat FILE:`tty`,raw,echo=0 ssl:kvmctf.ctfcompetition.com:1337,cafile=server_cert.pem``\n\n`server_cert.pem`:\n```\n-----BEGIN CERTIFICATE-----\nMIIBXTCCAQ+gAwIBAgIUcU+vah86fZls1/1gfDBEotuQTi4wBQYDK2VwMCQxIjAg\nBgNVBAMMGWt2bWN0Zi5jdGZjb21wZXRpdGlvbi5jb20wHhcNMjQwMzI2MTc1MjUw\nWhcNMzQwMzI0MTc1MjUwWjAkMSIwIAYDVQQDDBlrdm1jdGYuY3RmY29tcGV0aXRp\nb24uY29tMCowBQYDK2VwAyEAWiQBWTd51Qej7hPho7MtkLu6gtOJhyGM8lVr4dlf\nr6OjUzBRMB0GA1UdDgQWBBSGgjr7/oy7f72v7fjy+Boe7dmTaTAfBgNVHSMEGDAW\ngBSGgjr7/oy7f72v7fjy+Boe7dmTaTAPBgNVHRMBAf8EBTADAQH/MAUGAytlcANB\nAKwz9VdZ1e81DObSMEmeAm5mBc+Hsu50etwjDQGAPMoag+qcPddvlmlxcmuKY4QO\nOzLhYAILFWvYJrT5uTF0FwU=\n-----END CERTIFICATE-----\n```\n\nand follow the prompts. Note that the reservations are done using the UTC time\nso please convert your desired time to UTC before reserving. You will need to\nprovide an email address and whether you want a KASAN-enabled host, and you will\nbe given a key (both in your terminal and in an email verification). To connect\nto the server during your reserved time slot you can use the same command as\nabove. You will be asked to provide the email address you used to reserve the\ntime slot and the key you received. After verification, you will be redirected\nto the server.\n\n## Additional eligibility rules\nOnly the first submission for a vulnerability is eligible for a reward.\nIf a patch commit fixes multiple vulnerabilities, we assume the root cause is the same\nand we consider further submissions as duplicates.\nIf the same vulnerability is fixed in multiple patch commits, then we\nstill consider it as the same vulnerability, thus making further submissions\nduplicates.\n\n# Submission process\nNote: Minor details of the submission process may change from time to time,\nplease make sure you check this page again for updates when you make a new\nsubmission.\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n* There is no patch commit in the mainline tree, and\n* The vulnerability is not disclosed in any form (e.g. there is no Syzkaller\n  report about the bug)\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although\n      the bug was disclosed by Syzkaller more than 30 days ago, there is no fix\n      and you convince the maintainers to fix the bug)\n\nThe submission process contains two stages. The purpose of the two-stage system\nis to make sure the vulnerability details are not shared with us before the\npatch is released but to still provide a way for 0-day vulnerability finders\nto prove that they found the vulnerability by submitting the flag to us\nin the first stage.\n\n### First stage\n\n1. Exploit the bug and capture the flag from the target environment (the flag is\n   a proof of successful exploitation).\n2. Compress the exploit and its source code as a .tar.gz filei, calculate its\n   SHA256 checksum.\n   * Save this exact file, you will need to send us this later.\n   * Try to keep this file to the minimum necessary, leave out large files like\n     e.g. vmlinux, bzImage as they can be downloaded separately if needed.\n3. Go to\n   [https://bughunters.google.com/report/vrp](https://bughunters.google.com/report/vrp)\n4. Sign in (this helps us identify you and send you a reward)\n5. In the \"Report Description\" field put a summary of the report – please\n   mention \"kvmCTF\", the time slot and the reward tier (e.g. `kvmCTF\n   2025_01_01_00_00: Relative Memory Write`)\n6. Enter `Linux Kernel` into the affected product / website field, select the\n   `My product is not listed in the product list` checkbox.\n7. Enter `kernel.org` into the URL field.\n8. Enter the following information in the `Please describe the technical details\n   of the vulnerability` field:\n   * The first line should be \"kvmCTF\"\n   * The second line should be \"Reward Tier: \" followed by the targeted reward\n     tier.\n   * The third line should be \"Email: \" followed by the email used to reserve\n     the time slot.\n   * The fourth line should be \"Time slot: \" followed by the reserved time slot\n     (e.g. 2025/01/01 00:00).\n   * The fifth line should be the \"Flag: \" followed by the flag you obtained.\n     If your exploit is a \"Denial of Service\" and crashed the host, please fill\n     this line with \"Flag: Host Crash\".\n9. Enter the hash computed at step 2 in the `Please briefly explain who can\n   exploit the vulnerability, and what they gain when doing so` field.\n11. Select `Privilege Escalation` as the Vulnerability Type.\n12. Select `No, this vulnerability is private`.\n13. Select `Yes` on `Do you plan to disclose this bug publicly?`\n14. Set the date (at most 14 days after the date of filling this report) that\n    you plan to report the vulnerability.\n15. You can optionally donate twice the reward to charity if you select\n      \"Donate to charity and double my reward.\"\n16. Submit your report.\n17. We will review your submission and contact you when to proceed with the rest\n    of the steps.\n\n### Second stage\n1. Report the vulnerability to security@kernel.org within 7 days of receiving\n   the notice.\n   * Note: A submission will be considered ineligible if it turns out that this\n     requirement was not respected.\n2. Make sure that you are credited in the Reported-By tag of the patch that\n   fixes the bug.\n   * Use the same email address in the Reported-By tag as you use in the\n     bughunters website or the one you used to reserve the time slot.\n   * If there is no Reported-By tag on a patch commit, then a 0-day submission\n     is eligible only if this is the first 0-day submission for that patch\n     commit (based on the submission time of the bughunters report).\n   * If it is unclear who reported the bug, then we reserve the right to\n     invalidate the submission, change the reward or make a custom decision at\n     our discretion. \n3. Wait for the patch to land in a release candidate on the mainline tree (and\n    tagged in Git).\n4. Contact us within 7 days and provide the following details:\n    * The patch commit, CVE (optionally, if it is already known) and the exact\n    target(s) (e.g. `LTS 6.1.74`).\n    * Describe the vulnerability in detail (see the Documentation requirements\n    section)\n    * Reuse the contents of your `vulnerability.md` if it already exists (see\n    the \"Exploit PR file structure\" section).\n5. Wait for Linux to publish a CVE or publish the vulnerability details\n   yourself on [oss-sec](https://seclists.org/oss-sec/).\n6. After the vulnerability is disclosed via a CVE or oss-sec, wait 30 days\n    (recommendation, see notes below) and send us your exploit with the\n    description of the exploitation technique via a PR to [the security-research\n    repo](https://github.com/google/security-research/) (see required structure\n    below).\n7. Make sure that the PR is merged (this is a requirement to get a reward).\n\nA submission will not be eligible as a 0-day submission if the vulnerability\ndetails were reported somewhere (e.g. Pwn2Own) other than\n[security@kernel.org](mailto:security@kernel.org).\n\n## Note about making the exploit public\nYou have to publish your exploit within 90 days of disclosing the vulnerability\nto be eligible for a reward.\n\nWe recommend publishing the exploit 30 days after\nthe vulnerability was disclosed. This gives the industry time to apply patches.\nRead our stance on the topic in [Google’s disclosure\npolicy](http://about.google/appsecurity).\n\nWe only process submissions after the exploit is public (and we can only issue\nrewards when the submission was processed), but not sooner than 30 days after\nthe vulnerability disclosure.\n\nIf you publish sooner than 30 days, you won’t get the reward faster. If you want\nto delay the publication (disclose later than 30 days but within the 90 days\nwindow), you could do that, but you would get the money later (we want to\nencourage you to publish the exploit details sooner than later).\n\n## Exploit PR file structure\nThe submission should be put into the `pocs/linux/kvmctf/<cve>/` folder within\nthe [security-research](https://github.com/google/security-research/) repo,\nwhere:\n* cve is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\nFor example: `pocs/linux/kvmctf/CVE-2023-1872/`.\n\nThe structure of this submission folder should be:\n* `original.tar.gz`\n  * Required, contains the original exploit. Its hash must match the one\n    submitted initially via the submission (this hash cannot be modified later).\n* `docs/vulnerability.md`\n  * Required, description of the vulnerability.\n* `docs/exploit.md`\n  * Required, description of how the exploits work.\n* `exploit/6.1.x/`\n  * `exploit.c`\n    * Required, source code of the exploit.\n  * `exploit`\n    * Required, compiled exploit which stole the flag.\n  * `Makefile`\n    * Required, includes target (`exploit`) to compile exploit.c into exploit\n      and target (`run`) to run the exploit on the live instance (which steals\n      the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries\nfor the exploit). The exploit can be split into multiple files, although we\nprefer if it is kept as a single `.c` file.\n# Documentation requirements\n## Vulnerability\nIf possible please include the following information in the vulnerability\ndetails:\n* Commit which introduced the vulnerability\n* Commit which fixed the vulnerability\n* Affected kernel versions\n* Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n## Exploit\nMake sure that the exploit is properly commented and the accompanying exploit.md\nincludes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the\nfollowing activities, include them as a separate step:\n* Triggering a vulnerability.\n* Converting one attack primitive into another.\n* Spraying or grooming the heap.\n* Leaking host information.\n* Overwriting host memory.\n* Getting RIP control.\n* Executing interesting post-RIP approaches.\n* Doing a major step towards a successful exploitation which is not listed\n  above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role\n(e.g. vulnerable object, victim object), and their respective caches (e.g.\n`kmalloc-1k`) and the used field members of the object (e.g. getting RIP control\nvia `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n* Non-trivial constant values should be explained, for example:\n  * Flag and enumeration values\n  * Field offsets\n  * Function addresses\n  * ROP gadget offsets\n* ROP chain items should be explained.\n  * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to\n    e.g. `call_usermodehelper_exec`.\n* Fake structures should be explained; i.e. which structure is created and what\n  fields are set.\n  * E.g. `data[0x8] = base + 0x123456;` -> data variable contains a fake `struct\n    file`, the field at 0x8 offset is a `f_inode` pointer which is set to ...\n* Usage of multi-threading (or forking)\n  * Why is it needed?\n  * If a race condition is exploited, then what code paths are raced.\n  * Communication and synchronization between two the threads (e.g. what data\n    was sent between the threads, and when the threads are waiting on each\n    other).\n* Separation between code parts which are needed to trigger the vulnerability\n  and parts which are part of the exploitation process (spraying, heap grooming,\n  cross-cache, converting one primitive to another).\n* Any action (e.g. MSR update, hypercall) where a side-effect of the action is\n  used for the exploit and not the main functionality, for example:\n  * Hypercall used for spraying a specific structure, not for its main purpose.\n  * Change of some MSR value with a non-trivial effect.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the\ntime during your testing).\n# Additional information\n## Program change notifications and communication\nWe announce program changes through\n[#kvmctf-announcements](https://discord.gg/gBrsEgvAUk) Discord channel. This\ndocument is updated to reflect the current set of kvmCTF rules.\n\nIf you have any question regarding kvmCTF, feel free to ask on the\n[#kvmctf](https://discord.gg/c8drZpwYBn) Discord channel.\n","v8ctf/rules.md":"# v8CTF Rules\n\nThe v8CTF is a part of the [Google VRP](https://g.co/vrp) in which we reward successful exploitation attempts against a V8 version running on our infrastructure.\nThis program is orthogonal to the [Chrome VRP](https://g.co/chrome/vrp), if you find a bug and exploit it, you can submit the bug to the Chrome VRP and use the exploit for the v8CTF.\n\n## Rules\n\nThe following rules apply to the eligibility of exploits starting with M156:\n* Your exploit needs to exfiltrate the flag from our v8CTF infrastructure.\n* Every bug used in the submission (e.g. V8 memory corruption, V8 sandbox) must have been found by you as the first reporter.\n* Exploits need to be reasonably fast and stable. We accept submissions with an average runtime of less than 1 minute and at least 80% success rate.\n* Valid submissions get a reward of $20,000.\n\n## Submission Process\n\n1. Make sure to report the bugs first to the [Chrome VRP](https://g.co/chrome/vrp).\n1. Exploit the bug and capture the flag from our v8CTF environment.\n    1. The flag format is v8CTF{$unix_timestamp:$signature}.\n1. Create a .tar.gz archive of your exploit and calculate its sha256, e.g. with `sha256sum exploit.tar.gz`.\n    1. Provide an archive that can be verified using our reproduction setup (see [kctf/challenge-templates/repro-chrome/README.md](kctf/challenge-templates/repro-chrome/README.md))\n    1. Please double check that the exploit doesn’t have any external dependencies.\n1. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLScoWE5-XoF85dXMjWKTIrJGTEfCybFaktsYZMCZ86iFPrW8Ew/viewform?usp=header_link) with the flag and the exploit sha256 sum. You need to use the same email address you reported the bugs from.\n1. A bug in the Google Issue Tracker will be filed on your behalf. Attach the exploit matching the sha256 sum and a short write up to the bug.\n1. Give us a few days to validate your submission.\n\n## Setup\n\nYou can find a description of our v8CTF infrastructure in the [README](https://github.com/google/security-research/blob/master/v8ctf/README.md).\n\n## Communication\n\nWe have two discord channels set up on the [Capture The Flag](https://discord.gg/hqcSdTk6vm) server:\n\n* #v8ctf-announcements: will be used for announcements such as changes to the rules and the start time for n-day submissions.\n* #v8ctf: is open to all. If you have any questions, please ask here.\n\nAnd you can find data about existing submissions in [this sheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vTWvO0tFNl8fJbOmTV1nwGJi4fAy5pDg-6DsHARRubj8I6c7_11RQ36Jv735zj9EQggz6AWjAOaebJh/pubhtml).\n","analysis/kernel/dashboard/tools/README.md":"# Kernel Call-Graph & Privilege Analysis CLI Tools (`tools/`)\n\nThis directory contains three command-line analysis tools (`find_paths.py`, `inspect_calls.py`, `check_privilege.py`) backed by shared domain libraries under `tools/lib/` (`callgraph.py`, `metadata.py`, `privilege.py`) that query the unified Dashboard SQLite database (`kernel_dashboard-<version>.db`) and optional Syzkaller coverage database to answer core vulnerability triage and attack-surface questions:\n\n1. **`find_paths.py`** — *\"Which syscalls or non-syscall entry points can reach this line or function, and what is the call chain?\"*\n2. **`inspect_calls.py`** — *\"Who calls this function (directly, asynchronously, or via `ops_targets` function pointers), and what does it call?\"*\n3. **`check_privilege.py`** — *\"Is this line or function reachable from an unprivileged user, or is every path gated by `capable()` / `ns_capable()` / Kconfig / runtime tunables?\"*\n\n```text\n                                                      ┌──► find_paths.py       (Syscall/entry-to-target shortest call chains + coverage)\n                                                      │\nkernel_dashboard-<ver>.db ──► tools/lib/{callgraph,        ┼──► inspect_calls.py    (1-hop & multi-hop caller/callee neighborhood + ops dispatch)\n                                    metadata,         │\n                                    privilege}.py     └──► check_privilege.py  (Dijkstra capability-gate & 2D entry precondition verdict)\n```\n\n---\n\n## 1. Architecture, Shared Libraries & Required SQLite Tables\n\n### Shared Library Modules (`tools/lib/`)\n- **`tools/lib/callgraph.py`**: Database connection & index management (`open_databases`, `ensure_indexes`, `table_exists`, `clean_file_path`), function and span lookup (`get_enclosing_function`, `get_function_by_name`, `load_functions_for_files`), reverse call-graph traversal across direct calls, `ops_targets` function pointers, and `async_edges` callbacks (`get_callers`, `iter_pruned_callers`), syscall and non-syscall entry discovery (`is_syscall_root`, `load_entry_roots`, `is_entry_root`, `load_target_reachable_set`, `get_reachable_syscalls`, `get_reachable_entries`, `select_eval_roots`), and tree banner helpers (`format_root_label`, `format_target_banner`).\n- **`tools/lib/metadata.py`**: Kconfig `#ifdef`/`#else`/Makefile precondition extraction and symbol metadata lookup (`get_line_configs`, `get_kconfig_metadata`), Syzkaller dynamic coverage correlation (`get_syzkaller_coverage`, `is_line_covered_by_syzkaller`), target and call-path step builders (`build_target_info`, `make_path_step`, `make_caller_step`), and shared CLI argument parsing (`add_common_cli_args`, `handle_common_cli_setup`, `extract_reachability_cli_kwargs`).\n- **`tools/lib/privilege.py`**: Dynamic `CAP_*` constant resolution (`load_capability_map`, `format_capability`, `deduplicate_gates`, `add_call_span`), polymorphic `conditions` table parsing across direct call gates, `__guarded_span__:<ns_scope>` line-span guards, `__genl_ops_gate__:<ns_scope>` Generic Netlink flags, `sysctl`, and `module_param` tunables (`load_condition_gates`, `get_call_site_gates`, `load_runtime_tunables`), the 2D entry-precondition model (`get_entry_precondition`), and capability verdict classification (`classify_gates`).\n\n### CLI Tools Summary\n\n| Tool | Core Question Answered | SQLite Tables Used | Output Formats |\n| :--- | :--- | :--- | :--- |\n| **`find_paths.py`** | Finds shortest call paths from `__do_sys_*` syscalls and non-syscall `entry_node` roots to a target `(file, line)` or `function`, traversing direct calls (`edges`), indirect struct function-pointer calls (`ops_targets`), and asynchronous registrations (`async_edges`). | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `tree` (default), `list`, `json`, `mermaid` |\n| **`inspect_calls.py`** | Inspects 1-hop or multi-hop callers (`--callers`), callees (`--callees`), or both (`--both`), resolving indirect ops table dispatches (e.g., `inode_operations->link`, `file_operations->unlocked_ioctl`) and annotating call-site capability gates. | `function_locations`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations` (+ optional Syzkaller DB) | `summary` (default), `tree`, `list`, `json` |\n| **`check_privilege.py`** | Crosses static call paths with control-flow-dominating capability checks (`conditions` + `macroinvocation_locations`), Kconfig guards, runtime tunables, and 2D non-syscall entry floors using a weighted Dijkstra search (`COST_UNGATED=1`, `COST_NS_CAPABLE=10,000`, `COST_CAPABLE=1,000,000`) to find the least-privileged path to a target. | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `summary` (default), `tree`, `paths`, `json` |\n\n> **Automatic Index Creation**: On first run, `callgraph.ensure_indexes()` automatically verifies and creates lightweight traversal indexes (`idx_fl_file_lines`, `idx_fl_name`, `idx_sn_fn`, `idx_sn_sys`, `idx_loc_msg`, `idx_loc_uri_line`, `idx_edges_target`, `idx_edges_source`, `idx_ops_target`, `idx_ops_exprcall`, plus conditional indexes on `configs`, `kconfig_symbols`, `async_edges`, and `entry_node`) if they do not already exist. You can also pre-build them explicitly with `--ensure-indexes`.\n\n---\n\n## 2. Tool 1: Syscall Reachability Path Finder (`find_paths.py`)\n\n### Key Features\n- **Target Resolution**: Accepts either `--file <path> --line <num>` (resolving the enclosing kernel function automatically) or `--function <name>`.\n- **Hybrid Call-Graph Traversal**: Combines direct call edges (`locations` / `edges` from `all-calls.ql`) with indirect ops-table dispatch edges (`ops_targets` from `ops_edges.ql`).\n- **Syzkaller Coverage Correlation**: When `--syzkaller-db` is provided, annotates each step along the call path with dynamic coverage indicators and optional Syzkaller reproduction programs (`--show-repro`).\n\n### CLI Usage & Examples\n```bash\n# Find the shortest syscall path to a specific source line:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --file mm/shmem.c --line 1500\n\n# Find paths to a function across all reachable syscalls (up to 10 syscalls):\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10\n\n# Pin reachability search to a specific syscall and output a Mermaid diagram:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function unix_stream_connect \\\n  --syscall connect \\\n  --format mermaid\n```\n\n---\n\n## 3. Tool 2: Call-Graph Neighborhood Inspector (`inspect_calls.py`)\n\n### Key Features\n- **Bidirectional Inspection**:\n  - `--callers`: Discovers direct callers and indirect callers invoking the function via `ops_targets` struct fields (e.g., `vfs_link` $\\rightarrow$ `inode_operations.link` $\\rightarrow$ `shmem_link`).\n  - `--callees`: Discovers direct calls made by the function and indirect `ExprCall` sites within the function, listing candidate target implementations.\n  - `--both` (default): Displays full 360-degree caller and callee context.\n- **Multi-Hop Expansion**: Use `--depth <N>` to expand caller/callee trees up to `N` hops.\n- **Inline Capability Gate Annotations**: Automatically highlights whether any caller or outgoing call site is guarded by `capable()` / `ns_capable()`.\n\n### CLI Usage & Examples\n```bash\n# Inspect both callers and callees of a function (1-hop summary):\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link\n\n# Inspect 2 hops of callers for a specific file and line in JSON format:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1250 \\\n  --callers --depth 2 --format json\n\n# Show all indirect dispatch candidates without truncation:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function vfs_ioctl \\\n  --callees --all\n```\n\n---\n\n## 4. Tool 3: Capability & Unprivileged Reachability Analyzer (`check_privilege.py`)\n\n### Key Features\n- **Least-Privileged Path Discovery**: Uses Dijkstra's algorithm over the reverse call graph with edge weights penalizing capability checks (`COST_UNGATED = 1`, `COST_NS_CAPABLE = 10,000`, `COST_CAPABLE = 1,000,000`). If *any* unprivileged path exists alongside gated paths, `check_privilege.py` surfaces the ungated route first.\n- **Symbolic `CAP_*` Resolution**: Correlates `conditions` check locations with `macroinvocation_locations` to resolve integer capability constants (`21`, `12`, etc.) into human-readable names (`CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, etc.).\n- **Intra-Procedural Target Line Checks**: When given `--file` and `--line` inside a function body, checks both inter-procedural gates on callers and intra-procedural `IfStmt` capability checks dominating the target line within the enclosing function.\n- **Four Clear Security Verdicts**:\n  - `REACHABLE WITH NO PRIVILEGE (UNGATED)`\n  - `REACHABLE BEHIND USER NAMESPACE CAPABILITY` (`ns_capable(...)`)\n  - `REACHABLE, BUT ONLY BEHIND <CAP_NAME>` (`capable(CAP_SYS_ADMIN)`, etc.)\n  - `UNREACHABLE`\n\n### `conditions` Table Schema & Polymorphic `call` Column Contract\nThe `conditions` table (`condition_type`, `condition_loc`, `if_stmt_loc`, `condition_arg`, `call`, `call_loc`) generated by `queries/condition-graph-direct.ql` uses a polymorphic `call` / `call_loc` encoding to represent three distinct kinds of gate records without schema changes:\n1. **Direct Call-Site Gate Rows**: `call` is the CodeQL call string (e.g., `\"call to foo\"` or `\"call to expression\"`), and `call_loc` is the source location of the guarded `Call` expression.\n2. **Guarded Line-Span Rows (`__guarded_span__:<ns_scope>`)**: `call` starts with `\"__guarded_span__:\"` followed by the classified user-namespace scope (`init_user_ns`, `net_ns`, `s_user_ns`, `mnt_ns`, `f_cred`, or `user_ns`), and `call_loc` encodes the controlled line interval `[minLine, maxLine]` as `\"file://<path>:<minLine>:1:<maxLine>:1\"`. Consumers (`load_condition_gates` in `tools/lib/privilege.py`) use this span to gate any direct call, indirect `ops_targets` dispatch, or `--line` target falling within `[minLine, maxLine]`.\n3. **Generic Netlink Declarative Gate Rows (`__genl_ops_gate__:<ns_scope>`)**: `call` starts with `\"__genl_ops_gate__:\"` followed by `init_user_ns` (`GENL_ADMIN_PERM`) or `net_ns` (`GENL_UNS_ADMIN_PERM`), and `call_loc` encodes the gated Netlink handler function's body span `[startLine, endLine]`. Consumers attach these gates directly to the registered handler function.\n\n> **Caveat on Single-Interval `[minLine, maxLine]` Span Approximation**: Controlled spans for `IfStmt` capability guards are represented as a single contiguous line interval `[minLine, maxLine]` (bounded for early-abort `if (!capable(...)) return/goto` guards by `min(labelLine) - 1`, the next `switch` case label, or the enclosing block end). If an aborting branch has multiple `goto` targets, `min(labelLine)` is a conservative lower bound; conversely, unusual intra-procedural control flow (such as backward jumps or intervening unconditional paths inside the same block) is approximated by line containment rather than full basic-block post-dominance.\n\n### CLI Usage & Examples\n```bash\n# Check whether a specific kernel line is reachable without privileges:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1420\n\n# Evaluate privilege requirements across all reachable syscalls:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10 \\\n  --format tree\n\n# Print compact arrow-separated call chains with gate annotations:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link \\\n  --format paths\n```\n\n---\n\n## 5. Running Unit Tests & Linting (`tools/tests/`)\n\nThe `tools/tests/` directory contains unit and synthetic-database integration tests for both the shared libraries (`test_lib.py`) and all three CLI tools (`test_find_paths.py`, `test_inspect_calls.py`, `test_check_privilege.py`), sharing schema fixtures from `tools/tests/fixtures.py`:\n\n```bash\n# Run the full unit test suite:\npytest tools/tests -v\n\n# Format and run pylint (80-column Google style, zero lint suppressions):\npyformat -i -s 4 tools/*.py tools/lib/*.py tools/tests/*.py\npylint --max-line-length=80 tools/*.py tools/lib/*.py tools/tests/*.py\n```\n\n---\n\n## 6. Known Limitations & Design Tradeoffs\n\n- **Out-of-Line Capability Wrapper Depth (`queries/condition_graph.qll`)**: `DirectCapabilityCheck` resolves up to 2 hops of out-of-line helper wrappers (`f -> g -> capable`). Deeper capability chains (3+ hops) where intermediate helpers perform side effects before returning a boolean are intentionally not treated as pure capability predicates.\n- **Conjunctive vs. Disjunctive Guarded Spans (`__guarded_span__`)**: When a single `if` condition combines multiple capability checks (`if (!capable(A) && !capable(B)) return -EPERM` vs. `if (!capable(A) || !capable(B)) return -EPERM`), both capability checks share the same guarded line span `[minLine, maxLine]`. Consumers union the gates covering a call site rather than solving full boolean SAT over compound branch conditions.\n- **Build-Configuration Scope (`kernel_dashboard-<ver>.db`)**: The CodeQL database reflects a single compiled kernel configuration and architecture (`x86_64`). Code inside `#ifdef CONFIG_X` blocks disabled in that build is not compiled into the AST and will not appear in `function_locations`, `edges`, or `conditions` (though raw `#ifdef` ranges remain visible in `configs`).\n- **User-Namespace Scope (`ns_capable`) is Necessary, Not Sufficient**: When a path is gated by `ns_capable(ns->user_ns, CAP_*)` (`REACHABLE BEHIND USER NAMESPACE CAPABILITY`), unprivileged user-namespace reachability requires *both* the `ns_capable` check and that the object/subsystem can be instantiated inside a non-`init_net` / non-`init_user_ns` namespace. If an earlier caller or ops table binds the path to `init_net` or `init_user_ns`, global privilege is still required.\n- **BPF Verifier Program-Type Allowlists (`bpf_entry`)**: Reachability from a `bpf_entry` root assumes `BPF_PROG_LOAD` succeeds (`CAP_BPF` or `kernel.unprivileged_bpf_disabled=0`), but individual BPF helpers and kfuncs are further restricted by per-program-type verifier allowlists (`get_func_proto` / `btf_kfunc_id_set`).\n- **Bridge Traversal Depth Cap (`--max-bridge-depth`)**: Backward root collection (`get_reachable_syscalls`, `get_reachable_entries`) caps indirect/async bridge hops at `--max-bridge-depth` (default `6`) and direct hops at `20`. If traversal hits this cap with unexplored callers remaining and no root is found, `check_privilege.py` reports `UNREACHABLE (DEPTH-LIMITED)` (`target_info[\"depth_truncated\"] = True`).\n- **Async Context Bucketing (`queries/async_edges.qll`)**: `perf_event.overflow_handler` (PMI/NMI), `kprobe`/`kretprobe` handlers (trap context), and `ftrace_ops.func` (arbitrary function-entry context) are grouped under `mechanism = \"irq\"` (`context = \"hardirq\"`) for backward call-graph bridging.\n\n","kernelctf/rules.md":"# kernelCTF rules\n\n> [!WARNING]\n> These rules apply from 2026-09-04, you can find [the previous version of the rules on Github](https://github.com/google/security-research/blob/88ec1d535b0d147eec404751f0457e7162450aed/kernelctf/rules.md).\n\nkernelCTF is a part of the [Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules) and is focused on making exploiting Linux kernel vulnerabilities harder by inviting security researchers to demonstrate their exploitation techniques on 0-day vulnerabilities.\n\nWe are asking researchers to publish their submissions, helping the community to learn from each other's techniques.\n\n# Reward structure and targets\n\n## Target: Hardened (`hardened-v1-7.x`)\n\nThe target is Linux 7.2-rc5 (x86_64) based on the [COS kernel config](https://cos.googlesource.com/third_party/kernel/+/refs/heads/cos-6.12/arch/x86/configs/lakitu_defconfig) with additional hardenings and a reduced attack surface.\n\n### Configuration changes\n\n* **Mitigation features enabled:**\n  * `kCFI` + `IBT`\n  * `SLAB_VIRTUAL=y`\n  * `KMALLOC_PARTITION_TYPED=y`\n  * `SLAB_MERGE_DEFAULT=n`\n\n* **Disabled subsystems (reduced attack surface):**\n  * `CONFIG_IO_URING=n`\n  * `CONFIG_USER_NS=n`\n  * `CONFIG_TLS=n`\n  * `CONFIG_CRYPTO_USER_API_AEAD=n`\n  * `CONFIG_BPF_UNPRIV_DEFAULT_OFF=y`\n  * `CONFIG_AF_UNIX_OOB=n`\n\n### Requirements\n\n* **Stability:** Submissions must achieve at least 70% stability based on 20 exploit runs. The exploit needs to run within 5 minutes, otherwise it will be counted as a failed run when we measure stability.\n* **Vulnerability works on LTS 6.12:** The underlying vulnerability must be triggerable on the latest LTS 6.12. When executed with the `--vuln-trigger` flag on LTS 6.12, the exploit must crash the system (a full LPE chain is not required on LTS).\n\n### Reward\n\n* **$71,337**\n\nWe have retired separate target tiers and bonus categories in favor of a single static reward per eligible exploit.\n\n### Target updates\n\nOnly one submission is eligible per kernel version. The 7.2 version will generally remain fixed due to the `SLAB_VIRTUAL` porting requirement. However, we will update the LTS version (used for vulnerability freshness testing) when we release new slots, upgrading the LTS kernel version every 2-4 weeks on average.\n\n## Submission evaluation system\n\nOn weeks when a slot is released, the submission window will open on Monday at 12:00 UTC and close on Friday at 12:00 UTC, at which point the winning submission will be selected.\n\nSubmissions are evaluated on both speed and reliability over **20 exploit runs**. The server extracts the pre-compiled `exploit` binary from your `.tar.gz` archive and executes it (without recompilation), awarding a final score based on the following formula:\n\n$$\\text{Score} = 2 \\times (\\text{Stability \\%}) + \\max(100 - \\text{AVG}(\\text{time\\_in\\_sec}), 0)$$\n\n* **Maximum Possible Score:** 300 pts (100% stability, 0-second runtime).\n* **Minimum Passing Score:** 140 pts (70% stability, $\\ge 100$-second runtime).\n* **Winning Criterion:** The submission with the highest overall score wins the reward. If there is a tie, the submission with the earlier flag capture time (the timestamp recorded in the flag) wins. If there is still a tie, the earlier form submission time will be used.\n* **Submission Limits:** Only one submission per researcher is eligible per slot. Researchers may evaluate on the server up to 10 times per slot based on their email address (you can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6)), but only their latest submission before the Friday 12:00 UTC deadline will be used. Please do not use different email addresses to bypass this requirement as payment providers will flag this and it will block the reward payment.\n\n### Connecting to the evaluation system\n\nYou can interact with the evaluation server using `client/cli.py` (from the `server/` directory):\n\n```bash\n# Evaluate exploit against remote server (default target)\npython3 client/cli.py exploit_binary --action evaluate --researcher-token <token>\n```\n\nYou can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6).\n\nIf you do not want to run a full evaluation and only want to test a part of the exploit, you can use:\n* `--action lpe-test`: Test local privilege escalation and flag retrieval on the hardened target.\n* `--action vuln-test`: Test triggering the vulnerability (kernel crash) on the LTS target.\n\nFor a raw interactive connection to the service menu, you can use `client/connect.sh`:\n\n```bash\n./client/connect.sh\n```\n\nFor the full guide and options (such as local testing), see the [`server/README.md` (\"Using `client/cli.py`\" section)](server/README.md#using-clientclipy).\n\nYou can use a maximum of two connections per IPv4 address and the connection will be closed after 60 minutes. Evaluation runs are limited to 10 attempts per researcher per open slot based on your email address.\n\nThe source code running on the server is available [on our Github](https://github.com/google/security-research/tree/master/kernelctf/server).\n\n## Additional eligibility rules\n\n### Vulnerability dupes\n\nOnly the first submission for a vulnerability is eligible for a reward.\n\nThis means: if a vulnerability is exploited on the target by Researcher A, it can no longer be exploited on the target (even if the LTS kernel version is updated).\n\nIf a patch commit fixes multiple vulnerabilities (e.g. by backporting a new version of a component to the stable tree), we assume the root cause is the same and we consider further submissions as duplicates.\n\nIf the same vulnerability is fixed in multiple patch commits (e.g. in commit A in the mainline tree and separately in commit B in the stable tree), then we still consider it as the same vulnerability, thus making further submissions duplicates.\n\nIf you are unsure about eligibility, contact us on the [#kernelctf Discord channel](https://discord.gg/ECS5VnJZys) before making the submission.\n\n# Submission process\n\n_Note: Minor details of the submission process may change from time to time, please make sure you check this page again for updates when you make a new submission._\n\nBefore you start the submission process, please make sure that the submission window is currently open (Monday 12:00 UTC to Friday 12:00 UTC on slot release weeks) and that you are submitting for the active target version by checking the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) or the evaluation server.\n\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n\n  * There is no patch commit in the mainline tree, and\n\n  * The vulnerability is not disclosed in any form (e.g. there is no Syzkaller report about the bug)\n\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although the bug was disclosed by Syzkaller more than 30 days ago, there is no fix and you convince the maintainers to fix the bug)\n\nA submission will not be eligible if the vulnerability details were reported somewhere (e.g. Pwn2Own) other than [security@kernel.org](mailto:security@kernel.org).\n\nThe submission process has two stages to make sure the vulnerability details are not shared with us before the patch is released:\n\n## Stage 1: Initial submission (before patch release)\n\n  0. Compress the compiled `exploit` binary, its source code, and all the build files as a `.tar.gz` file.\n\n     * Save this exact file, you will need to send us this later.\n\n     * Note: The evaluation system will extract the `exploit` binary from the archive and run it without recompilation.\n\n     * Try to keep this file to the minimum necessary, leave out large files like e.g. `vmlinux`, `bzImage` as they can be downloaded separately if needed.\n\n  1. Upload the compressed file to the evaluation system, which will provide a flag upon successful exploitation.\n\n  2. Submit the flag on [this form](https://forms.gle/cjA9M1ZNUSc6adGE6) with the additional details requested.\n\n     * Save the link as you’ll have to edit this form later.\n\n  3. Check the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) after submitting the form and confirm that your submission was added and your score is correct.\n\n  4. Wait until Friday at 12:00 UTC and verify that your submission won the current slot. If there are multiple submissions for the same slot, another submission with a higher score may take the slot (in case of a tie, the earlier flag capture time, and then the earlier form submission time wins). If your submission does not win, you must wait for a new, empty slot to be released (start from Step 1).\n\n  5. Report the vulnerability to security@kernel.org within 7 days of winning the slot.\n\n     * Note: A submission will be considered ineligible if it turns out that this requirement was not respected.\n\n  6. If you are not the author of the patch that fixes the bug, make sure that you are credited in the `Reported-By` tag of the patch that fixes the bug.\n\n     * Do not include the `Reported-By` tag if you both discovered the flaw and authored the patch.\n\n     * Use the same email address in the `Reported-By` tag as you use for the form submission or in the \"Email address used in Reported-By tag\" field of the form.\n\n     * If there is no `Reported-By` tag on a patch commit, then a 0-day submission is eligible only if this is the first 0-day submission for that patch commit (based on the first stage submission date).\n\n     * If it is unclear who reported the bug, then the reward can be split (multiple reporters), reduced, or invalidated at our discretion.\n\n  7. Wait for the patch to land in a release candidate on the mainline tree (and be tagged in Git) or be committed to a stable tree, whichever happens first.\n\n     * Make sure that the patch correctly fixes the vulnerability you reported. If it does not, report the issue to the kernel and wait for the correct patch commit, otherwise your submission will be ineligible.\n\n## Stage 2: After patch release\n\n  1. Modify the form within 7 days by following the previously saved link and fill out the extra vulnerability details.\n\n     * If the 7-day deadline is missed, then the submission may be considered ineligible for reward at our discretion.\n\n  2. Send us your exploit within 90 days with the description of the exploitation technique via a PR to [the security-research repo](https://github.com/google/security-research/) (see required structure below). This is a mandatory step for us to start verification of the vulnerability.\n\n  3. Once the PR's GitHub Actions (GHA) checks pass and we confirm the submission exploits the claimed vulnerability, you receive the first half of the reward. After a manual review and the PR is merged, the second half is issued.\n\n### Google Bughunter's website registration and reward payments\n\nSubmitting reports via [bughunters.google.com](https://bughunters.google.com/) prior to PR submission is **no longer required**; an issue will automatically be created on the portal for winning entries.\n\nHowever, to collect your payout reward:\n  1. You must register once on [bughunters.google.com](https://bughunters.google.com/) so we can send you the reward.\n  2. We highly recommend changing your payment provider to BugCrowd for a better payment process. You can [read here](https://bughunters.google.com/blog/6483936851394560/announcing-bugcrowd-as-a-new-bughunters-google-com-payment-option) how.\n  3. If you'd like to split your reward with another researcher, please [read our FAQ regarding the process](https://bughunters.google.com/about/frequently-asked-questions#q-is-it-possible-to-split-the-reward-for-a-report-with-other-researchers-for-example-if-we-collaborated-on-the-report-).\n\n## Note about making the exploit public\n\nYou have to publish your exploit within 90 days of submitting the patch commit via the Google Form to be eligible for a reward.\n\nWe only process submissions after the exploit becomes public. We can only issue the first half of the reward once the PR passes the automated checks and the initial review confirms that the submission exploits the claimed vulnerability. Following an in-depth review and successful quality checks, the PR will be merged, and the second half of the reward will be issued.\n\nIf you want to delay the publication (within the 90 days window), you could do that, but you would get the money later (we want to encourage you to publish the exploit details sooner than later).\n\nThe above is about the exploit itself, not the vulnerability. We automatically share some limited vulnerability details of the submissions on our [public submission spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml?gid=2095368189), as a CVE, once you submit the extra vulnerability details via the form in Stage 2.\n\n## Exploit PR file structure\n\nThe submission should be put into the `pocs/linux/kernelctf/<cve>_<targets>/` folder within the [security-research repo](https://github.com/google/security-research/), where:\n\n  * `cve` is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\n\n  * `<targets>` is the list of targets separated by underscore (`_`)\n\n    * Valid target names: `hardened-v1-7.x`\n\n  * If there is a conflicting submission directory name, then append `_2` (or `_3`, etc.) after the directory name.\n\nFor example: `pocs/linux/kernelctf/CVE-2023-1872_hardened-v1-7.x/`.\n\nThe structure of this submission folder should be:\n\n  * `original.tar.gz`\n\n    * Required; contains the original exploit (compiled binary and source code used to build it). Its hash must match the one calculated by the evaluation system and encoded within the flag you submitted in the form.\n\n  * `metadata.json`\n\n    * Required, structured metadata information following [this JSON schema (version 3)](metadata.schema.v3.json).\n\n  * `docs/vulnerability.md`\n\n    * Required, description of the vulnerability.\n\n  * `docs/exploit.md`\n\n    * Required, description of how the exploits work. If exploits are too different, then it can also be put next to exploits.\n\n  * `exploit/hardened-v1-7.x/`<br>\n\n    * `exploit.c`\n       * Required, source code of the exploit.\n\n    * `exploit`\n       * Required, compiled exploit which stole the flag.\n\n    * `Makefile`\n       * Required, includes target (`exploit`) to compile `exploit.c` into `exploit` and target (`run`) to run the exploit on the live instance (which steals the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries for the exploit). The exploit can be split into multiple files, although we prefer if it is kept as a single `.c` file.\n\n## Documentation requirements\n\n### Vulnerability\n\nIf possible please include the following information in the vulnerability details:\n\n  * Requirements to trigger the vulnerability:\n    * [Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html)\n    * Kernel configuration\n\n  * Commit which introduced the vulnerability\n\n  * Commit which fixed the vulnerability\n\n  * Affected kernel versions\n\n  * Affected component, subsystem\n\n  * Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n\n  * Which syscalls or syscall parameters are needed to be blocked to prevent triggering the vulnerability? (If there is any easy way to block it.)\n\n### Exploit\n\nEnsure that exploit code follows [kernelCTF code style guide](https://google.github.io/security-research/kernelctf/style_guide).\n\nMake sure that the exploit is properly commented and the accompanying `exploit.md` includes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the following activities, include them as a separate step:\n\n  * Triggering a vulnerability.\n\n  * Converting one attack primitive into another.\n\n  * Spraying or grooming the heap.\n\n  * Executing cross-cache attack.\n\n  * Leaking information (e.g. heap pointer, kASLR base address).\n\n  * Overwriting kernel memory.\n\n  * Getting RIP control.\n\n  * Executing interesting post-RIP approaches.\n\n  * Doing a major step towards a successful exploitation which is not listed above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role (e.g. vulnerable object, victim object), and their respective caches (e.g. `kmalloc-1k`) and the used field members of the object (e.g. getting RIP control via `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n\n  * Non-trivial constant values should be explained, for example:\n    * Flag and enumeration values\n    * Field offsets\n    * Function addresses\n    * ROP gadget offsets\n\n  * ROP chain items should be explained.\n    * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to e.g. `call_usermodehelper_exec`.\n\n  * Fake structures should be explained; i.e. which structure is created and what fields are set.\n    * E.g. `data[0x8] = base + 0x123456`; -> data variable contains a fake `struct file`, the field at 0x8 offset is a `f_inode` pointer which is set to `...`\n\n  * Usage of multi-threading (or forking)\n    * Why is it needed?\n    * If a race condition is exploited, then what code paths are raced.\n    * Communication and synchronization between the two threads (e.g. what data was sent between the threads, and when the threads are waiting on each other).\n\n  * Environmental requirements\n    * If specific climit or cpu affinity settings are required, then explain why they are needed.\n    * Which limit the exploit runs into using the default settings.\n\n  * Namespaces usage and why are they required.\n\n  * Separation between code parts which are needed to trigger the vulnerability and parts which are part of the exploitation process (spraying, heap grooming, cross-cache, converting one primitive to another).\n\n  * Any action (e.g. syscall) where a side-effect of the action is used for the exploit and not the main functionality, for example:\n    * Syscall used for spraying a specific structure, not for its main purpose.\n    * Some calls (e.g. `sleep`) used for a specific side-effect which is not trivial see.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the time during your testing).\n\nYour exploit must support the `--vuln-trigger` argument, which triggers the underlying vulnerability to crash the system (ideally under KASAN) on other versions without requiring a full LPE chain. To stay within [vuln-verify workflow](https://github.com/google/security-research/blob/master/.github/workflows/kernelctf-vuln-verify.yaml) time limits, this mode should skip non-essential steps such as KASLR prefetching.\n\n# Additional information\n\n## Program change notifications and communication\n\nWe announce program changes through [#kernelctf-announcements](https://discord.gg/yXue2RwDEA) Discord channel. All major changes are going to be announced 2 weeks in advance before they take an effect. This document will be updated to reflect current set of kernelCTF rules.\n\n## Questions about program\n\nIf you have any questions regarding kernelCTF, check [the FAQ page](faq.md) and feel free to ask on the [#kernelctf](https://discord.gg/ECS5VnJZys) Discord channel.\n\n## Non-kernel vulnerabilities\n\nIf you are submitting a non-kernel vulnerability affecting our kCTF VRP cluster, please submit the vulnerability to our [kCTF VRP](https://google.github.io/kctf/vrp.html).\n\n## Legal points\n\nkernelCTF is part of Google VRP, so its rules including but not limited to [these Legal points](https://bughunters.google.com/about/rules/google-friends/google-and-alphabet-vulnerability-reward-program-vrp-rules#legal-points) apply.\n\nYou should understand that we can cancel the program at any time and the decision as to whether or not to pay a reward and how much has to be entirely at our discretion.\n"},"files":{"kvmctf/rules.md":"# kvmCTF Overview\n\nkvmCTF is a part of the\n[Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules)\nand is focused on eliminating VM-reachable Kernel-based Virtual Machine (KVM)\nvulnerabilities in upstream mainline kernel. We invite security researchers to\ndemonstrate their bug hunting and exploitation techniques on an LTS kernel version.\nEventually we might add experimental mitigations to KVM that we would like to see\nif and how researchers can bypass them.\n\nWe are additionally asking researchers to publish their submissions, helping the\ncommunity to learn from each other’s techniques.\n\n# Competition Rules\n\n## Target: Linux LTS KVM\n\nThe host runs v6.1.74 and runs on an Intel(R) Xeon(R) Gold 5222 CPU @ 3.80GHz.\nParticipants will have the option to select whether they want the host to run\nwith `CONFIG_KASAN` disabled or enabled. The complete setup of the host can be\ndownloaded\n[here](https://storage.googleapis.com/kvmctf/latest.tar.gz) in a\ngzip format and contains the following:\n* The kernel patch we applied on the kernel tree.\n* The kernel configuration files.\n* The gcc and binutils versions used to compile the kernel.\n* The virsh version used to run the VM.\n* The produced `vmlinux` images.\n* The produced `bzImage` binaries.\n* The produced `ko` module binaries.\n* The `qemu-kvm` command used to run the guest.\n\nParticipants will be connected to a Debian 12.5 (bookworm) guest that runs on a\n`v6.1.0-21` kernel compiled with the default Debian config.\n\nThe goal is to perform a successful guest-to-host attack. Currently we do not\nreward QEMU, host-to-KVM or CPU/DRAM/HW-based vulnerabilities.\n\nNote: Although our testing environment runs an LTS kernel, vulnerabilities must\nbe reproducible in the upstream Linux mainline master branch to be eligible.\nVulnerabilities that only exist in downstream backports or older LTS trees are\nout of scope.\n\n## Rewards\n| Tier                   | Reward   |\n|------------------------| -------- |\n| Full VM escape         | $250,000 |\n| Arbitrary memory write | $100,000 |\n| Arbitrary memory read  | $50,000  |\n| Relative memory write  | $50,000  |\n| Denial of Service      | $20,000  |\n| Relative memory read   | $10,000  |\n\n\nNote that the above rewards do not stack. For instance, if you submit a full VM\nescape exploit that takes advantage of an arbitrary memory read you will be\nrewarded with $250,000, not $250,000 + $50,000.\n\n## Flags\nYour submission should contain proof that your exploit succeeded in one of the\nabove tiers. This is achieved by providing each tier's corresponding flag (a\n64-bit number). Note that providing the flag does **not** automatically\nguarantee the corresponding reward, your exploit must take advantage of a\nvulnerability of that tier. For instance, if you use an arbitrary memory read\nvulnerability to read the arbitrary memory write flag, you will **not** be\ncompensated with the arbitrary memory write reward.\n### RCE flag\nTo obtain this flag your exploit should read the contents of the\n`/root/rce_flag` file in the host file system.\n### Arbitrary memory accesses\nFor the arbitrary memory write tier your exploit should overwrite the contents\nof the write flag address (its default value is `0xdeadbeef41424344` so your\nexploit should modify any or all of its bits), whereas for the arbitrary memory\nread tier your exploit should read the contents of the read flag address. The\ntarget addresses (both virtual and physical) can be found in the\n`/root/addresses` file in the guest file system. For the arbitrary memory write\ntier, your exploit should first overwrite the contents of the write flag address\nand then call hypercall `#100` which will return the corresponding flag in\n`RAX`. For the arbitrary memory read tier, the flag is the contents of the read\nflag address.\n### Relative memory accesses\nThe relative memory read and relative memory write are available only if the\nhost runs with `CONFIG_KASAN` enabled. The mapping between the KASAN violations\nand the reward tiers is the following:\n\n| Operation     | KASAN violation         | Reward Tier           |\n| ------------  | ----------------------- | ------------------    |\n| Memory Write  | use-after-free          | Relative memory write |\n| Memory Write  | out-of-bounds           | Relative memory write |\n| Memory Write  | slab-out-of-bounds      | Relative memory write |\n| Memory Write  | global-out-of-bounds    | Relative memory write |\n| Memory Write  | stack-out-of-bounds     | Relative memory write |\n| Memory Write  | alloca-out-of-bounds    | Relative memory write |\n| Memory Write  | vmalloc-out-of-bounds   | Relative memory write |\n| Memory Write  | user-memory-access      | Relative memory write |\n| Memory Write  | wild-memory-access      | Relative memory write |\n| *             | double-free             | Relative memory write |\n| *             | invalid-free            | Relative memory write |\n| Memory Read   | use-after-free          | Relative memory read  |\n| Memory Read   | out-of-bounds           | Relative memory read  |\n| Memory Read   | slab-out-of-bounds      | Relative memory read  |\n| Memory Read   | global-out-of-bounds    | Relative memory read  |\n| Memory Read   | stack-out-of-bounds     | Relative memory read  |\n| Memory Read   | alloca-out-of-bounds    | Relative memory read  |\n| Memory Read   | vmalloc-out-of-bounds   | Relative memory read  |\n| Memory Read   | user-memory-access      | Relative memory read  |\n| Memory Read   | wild-memory-access      | Relative memory read  |\n| *             | null-ptr-deref          | Denial of Service     |\n\nFor the relative memory write tier, your exploit should first perform the\noperation that produces the KASAN violation and then call hypercall `#101` which\nwill return the flag in `RAX`.\nSimilarly, for the relative memory read tier, your exploit should first perform\nthe operation to produce the KASAN violation and then call hypercall `#102`\nwhich will return the flag in `RAX`.\n\n### Denial of Service\nThe Denial of Service tier rewards exploits that induce a `null-ptr-deref` KASAN\nviolation, or that make the host panic or otherwise\ncrash. In the former case, your exploit should first perform the operation to\nproduce the KASAN violation and then call hypercall `#103` which will return the\nflag in `RAX`.\nIn the latter case, you do not need to provide a flag: after executing your\nexploit and crashing the host just specify in the submission form that you are\nsubmitting a Denial of Service exploit.\n\n## Process\nTo try your exploit on our server you will have to reserve a time slot. You can\ndo it using the command:\n\n``socat FILE:`tty`,raw,echo=0 ssl:kvmctf.ctfcompetition.com:1337,cafile=server_cert.pem``\n\n`server_cert.pem`:\n```\n-----BEGIN CERTIFICATE-----\nMIIBXTCCAQ+gAwIBAgIUcU+vah86fZls1/1gfDBEotuQTi4wBQYDK2VwMCQxIjAg\nBgNVBAMMGWt2bWN0Zi5jdGZjb21wZXRpdGlvbi5jb20wHhcNMjQwMzI2MTc1MjUw\nWhcNMzQwMzI0MTc1MjUwWjAkMSIwIAYDVQQDDBlrdm1jdGYuY3RmY29tcGV0aXRp\nb24uY29tMCowBQYDK2VwAyEAWiQBWTd51Qej7hPho7MtkLu6gtOJhyGM8lVr4dlf\nr6OjUzBRMB0GA1UdDgQWBBSGgjr7/oy7f72v7fjy+Boe7dmTaTAfBgNVHSMEGDAW\ngBSGgjr7/oy7f72v7fjy+Boe7dmTaTAPBgNVHRMBAf8EBTADAQH/MAUGAytlcANB\nAKwz9VdZ1e81DObSMEmeAm5mBc+Hsu50etwjDQGAPMoag+qcPddvlmlxcmuKY4QO\nOzLhYAILFWvYJrT5uTF0FwU=\n-----END CERTIFICATE-----\n```\n\nand follow the prompts. Note that the reservations are done using the UTC time\nso please convert your desired time to UTC before reserving. You will need to\nprovide an email address and whether you want a KASAN-enabled host, and you will\nbe given a key (both in your terminal and in an email verification). To connect\nto the server during your reserved time slot you can use the same command as\nabove. You will be asked to provide the email address you used to reserve the\ntime slot and the key you received. After verification, you will be redirected\nto the server.\n\n## Additional eligibility rules\nOnly the first submission for a vulnerability is eligible for a reward.\nIf a patch commit fixes multiple vulnerabilities, we assume the root cause is the same\nand we consider further submissions as duplicates.\nIf the same vulnerability is fixed in multiple patch commits, then we\nstill consider it as the same vulnerability, thus making further submissions\nduplicates.\n\n# Submission process\nNote: Minor details of the submission process may change from time to time,\nplease make sure you check this page again for updates when you make a new\nsubmission.\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n* There is no patch commit in the mainline tree, and\n* The vulnerability is not disclosed in any form (e.g. there is no Syzkaller\n  report about the bug)\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although\n      the bug was disclosed by Syzkaller more than 30 days ago, there is no fix\n      and you convince the maintainers to fix the bug)\n\nThe submission process contains two stages. The purpose of the two-stage system\nis to make sure the vulnerability details are not shared with us before the\npatch is released but to still provide a way for 0-day vulnerability finders\nto prove that they found the vulnerability by submitting the flag to us\nin the first stage.\n\n### First stage\n\n1. Exploit the bug and capture the flag from the target environment (the flag is\n   a proof of successful exploitation).\n2. Compress the exploit and its source code as a .tar.gz filei, calculate its\n   SHA256 checksum.\n   * Save this exact file, you will need to send us this later.\n   * Try to keep this file to the minimum necessary, leave out large files like\n     e.g. vmlinux, bzImage as they can be downloaded separately if needed.\n3. Go to\n   [https://bughunters.google.com/report/vrp](https://bughunters.google.com/report/vrp)\n4. Sign in (this helps us identify you and send you a reward)\n5. In the \"Report Description\" field put a summary of the report – please\n   mention \"kvmCTF\", the time slot and the reward tier (e.g. `kvmCTF\n   2025_01_01_00_00: Relative Memory Write`)\n6. Enter `Linux Kernel` into the affected product / website field, select the\n   `My product is not listed in the product list` checkbox.\n7. Enter `kernel.org` into the URL field.\n8. Enter the following information in the `Please describe the technical details\n   of the vulnerability` field:\n   * The first line should be \"kvmCTF\"\n   * The second line should be \"Reward Tier: \" followed by the targeted reward\n     tier.\n   * The third line should be \"Email: \" followed by the email used to reserve\n     the time slot.\n   * The fourth line should be \"Time slot: \" followed by the reserved time slot\n     (e.g. 2025/01/01 00:00).\n   * The fifth line should be the \"Flag: \" followed by the flag you obtained.\n     If your exploit is a \"Denial of Service\" and crashed the host, please fill\n     this line with \"Flag: Host Crash\".\n9. Enter the hash computed at step 2 in the `Please briefly explain who can\n   exploit the vulnerability, and what they gain when doing so` field.\n11. Select `Privilege Escalation` as the Vulnerability Type.\n12. Select `No, this vulnerability is private`.\n13. Select `Yes` on `Do you plan to disclose this bug publicly?`\n14. Set the date (at most 14 days after the date of filling this report) that\n    you plan to report the vulnerability.\n15. You can optionally donate twice the reward to charity if you select\n      \"Donate to charity and double my reward.\"\n16. Submit your report.\n17. We will review your submission and contact you when to proceed with the rest\n    of the steps.\n\n### Second stage\n1. Report the vulnerability to security@kernel.org within 7 days of receiving\n   the notice.\n   * Note: A submission will be considered ineligible if it turns out that this\n     requirement was not respected.\n2. Make sure that you are credited in the Reported-By tag of the patch that\n   fixes the bug.\n   * Use the same email address in the Reported-By tag as you use in the\n     bughunters website or the one you used to reserve the time slot.\n   * If there is no Reported-By tag on a patch commit, then a 0-day submission\n     is eligible only if this is the first 0-day submission for that patch\n     commit (based on the submission time of the bughunters report).\n   * If it is unclear who reported the bug, then we reserve the right to\n     invalidate the submission, change the reward or make a custom decision at\n     our discretion. \n3. Wait for the patch to land in a release candidate on the mainline tree (and\n    tagged in Git).\n4. Contact us within 7 days and provide the following details:\n    * The patch commit, CVE (optionally, if it is already known) and the exact\n    target(s) (e.g. `LTS 6.1.74`).\n    * Describe the vulnerability in detail (see the Documentation requirements\n    section)\n    * Reuse the contents of your `vulnerability.md` if it already exists (see\n    the \"Exploit PR file structure\" section).\n5. Wait for Linux to publish a CVE or publish the vulnerability details\n   yourself on [oss-sec](https://seclists.org/oss-sec/).\n6. After the vulnerability is disclosed via a CVE or oss-sec, wait 30 days\n    (recommendation, see notes below) and send us your exploit with the\n    description of the exploitation technique via a PR to [the security-research\n    repo](https://github.com/google/security-research/) (see required structure\n    below).\n7. Make sure that the PR is merged (this is a requirement to get a reward).\n\nA submission will not be eligible as a 0-day submission if the vulnerability\ndetails were reported somewhere (e.g. Pwn2Own) other than\n[security@kernel.org](mailto:security@kernel.org).\n\n## Note about making the exploit public\nYou have to publish your exploit within 90 days of disclosing the vulnerability\nto be eligible for a reward.\n\nWe recommend publishing the exploit 30 days after\nthe vulnerability was disclosed. This gives the industry time to apply patches.\nRead our stance on the topic in [Google’s disclosure\npolicy](http://about.google/appsecurity).\n\nWe only process submissions after the exploit is public (and we can only issue\nrewards when the submission was processed), but not sooner than 30 days after\nthe vulnerability disclosure.\n\nIf you publish sooner than 30 days, you won’t get the reward faster. If you want\nto delay the publication (disclose later than 30 days but within the 90 days\nwindow), you could do that, but you would get the money later (we want to\nencourage you to publish the exploit details sooner than later).\n\n## Exploit PR file structure\nThe submission should be put into the `pocs/linux/kvmctf/<cve>/` folder within\nthe [security-research](https://github.com/google/security-research/) repo,\nwhere:\n* cve is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\nFor example: `pocs/linux/kvmctf/CVE-2023-1872/`.\n\nThe structure of this submission folder should be:\n* `original.tar.gz`\n  * Required, contains the original exploit. Its hash must match the one\n    submitted initially via the submission (this hash cannot be modified later).\n* `docs/vulnerability.md`\n  * Required, description of the vulnerability.\n* `docs/exploit.md`\n  * Required, description of how the exploits work.\n* `exploit/6.1.x/`\n  * `exploit.c`\n    * Required, source code of the exploit.\n  * `exploit`\n    * Required, compiled exploit which stole the flag.\n  * `Makefile`\n    * Required, includes target (`exploit`) to compile exploit.c into exploit\n      and target (`run`) to run the exploit on the live instance (which steals\n      the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries\nfor the exploit). The exploit can be split into multiple files, although we\nprefer if it is kept as a single `.c` file.\n# Documentation requirements\n## Vulnerability\nIf possible please include the following information in the vulnerability\ndetails:\n* Commit which introduced the vulnerability\n* Commit which fixed the vulnerability\n* Affected kernel versions\n* Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n## Exploit\nMake sure that the exploit is properly commented and the accompanying exploit.md\nincludes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the\nfollowing activities, include them as a separate step:\n* Triggering a vulnerability.\n* Converting one attack primitive into another.\n* Spraying or grooming the heap.\n* Leaking host information.\n* Overwriting host memory.\n* Getting RIP control.\n* Executing interesting post-RIP approaches.\n* Doing a major step towards a successful exploitation which is not listed\n  above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role\n(e.g. vulnerable object, victim object), and their respective caches (e.g.\n`kmalloc-1k`) and the used field members of the object (e.g. getting RIP control\nvia `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n* Non-trivial constant values should be explained, for example:\n  * Flag and enumeration values\n  * Field offsets\n  * Function addresses\n  * ROP gadget offsets\n* ROP chain items should be explained.\n  * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to\n    e.g. `call_usermodehelper_exec`.\n* Fake structures should be explained; i.e. which structure is created and what\n  fields are set.\n  * E.g. `data[0x8] = base + 0x123456;` -> data variable contains a fake `struct\n    file`, the field at 0x8 offset is a `f_inode` pointer which is set to ...\n* Usage of multi-threading (or forking)\n  * Why is it needed?\n  * If a race condition is exploited, then what code paths are raced.\n  * Communication and synchronization between two the threads (e.g. what data\n    was sent between the threads, and when the threads are waiting on each\n    other).\n* Separation between code parts which are needed to trigger the vulnerability\n  and parts which are part of the exploitation process (spraying, heap grooming,\n  cross-cache, converting one primitive to another).\n* Any action (e.g. MSR update, hypercall) where a side-effect of the action is\n  used for the exploit and not the main functionality, for example:\n  * Hypercall used for spraying a specific structure, not for its main purpose.\n  * Change of some MSR value with a non-trivial effect.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the\ntime during your testing).\n# Additional information\n## Program change notifications and communication\nWe announce program changes through\n[#kvmctf-announcements](https://discord.gg/gBrsEgvAUk) Discord channel. This\ndocument is updated to reflect the current set of kvmCTF rules.\n\nIf you have any question regarding kvmCTF, feel free to ask on the\n[#kvmctf](https://discord.gg/c8drZpwYBn) Discord channel.\n","v8ctf/rules.md":"# v8CTF Rules\n\nThe v8CTF is a part of the [Google VRP](https://g.co/vrp) in which we reward successful exploitation attempts against a V8 version running on our infrastructure.\nThis program is orthogonal to the [Chrome VRP](https://g.co/chrome/vrp), if you find a bug and exploit it, you can submit the bug to the Chrome VRP and use the exploit for the v8CTF.\n\n## Rules\n\nThe following rules apply to the eligibility of exploits starting with M156:\n* Your exploit needs to exfiltrate the flag from our v8CTF infrastructure.\n* Every bug used in the submission (e.g. V8 memory corruption, V8 sandbox) must have been found by you as the first reporter.\n* Exploits need to be reasonably fast and stable. We accept submissions with an average runtime of less than 1 minute and at least 80% success rate.\n* Valid submissions get a reward of $20,000.\n\n## Submission Process\n\n1. Make sure to report the bugs first to the [Chrome VRP](https://g.co/chrome/vrp).\n1. Exploit the bug and capture the flag from our v8CTF environment.\n    1. The flag format is v8CTF{$unix_timestamp:$signature}.\n1. Create a .tar.gz archive of your exploit and calculate its sha256, e.g. with `sha256sum exploit.tar.gz`.\n    1. Provide an archive that can be verified using our reproduction setup (see [kctf/challenge-templates/repro-chrome/README.md](kctf/challenge-templates/repro-chrome/README.md))\n    1. Please double check that the exploit doesn’t have any external dependencies.\n1. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLScoWE5-XoF85dXMjWKTIrJGTEfCybFaktsYZMCZ86iFPrW8Ew/viewform?usp=header_link) with the flag and the exploit sha256 sum. You need to use the same email address you reported the bugs from.\n1. A bug in the Google Issue Tracker will be filed on your behalf. Attach the exploit matching the sha256 sum and a short write up to the bug.\n1. Give us a few days to validate your submission.\n\n## Setup\n\nYou can find a description of our v8CTF infrastructure in the [README](https://github.com/google/security-research/blob/master/v8ctf/README.md).\n\n## Communication\n\nWe have two discord channels set up on the [Capture The Flag](https://discord.gg/hqcSdTk6vm) server:\n\n* #v8ctf-announcements: will be used for announcements such as changes to the rules and the start time for n-day submissions.\n* #v8ctf: is open to all. If you have any questions, please ask here.\n\nAnd you can find data about existing submissions in [this sheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vTWvO0tFNl8fJbOmTV1nwGJi4fAy5pDg-6DsHARRubj8I6c7_11RQ36Jv735zj9EQggz6AWjAOaebJh/pubhtml).\n","analysis/kernel/dashboard/tools/README.md":"# Kernel Call-Graph & Privilege Analysis CLI Tools (`tools/`)\n\nThis directory contains three command-line analysis tools (`find_paths.py`, `inspect_calls.py`, `check_privilege.py`) backed by shared domain libraries under `tools/lib/` (`callgraph.py`, `metadata.py`, `privilege.py`) that query the unified Dashboard SQLite database (`kernel_dashboard-<version>.db`) and optional Syzkaller coverage database to answer core vulnerability triage and attack-surface questions:\n\n1. **`find_paths.py`** — *\"Which syscalls or non-syscall entry points can reach this line or function, and what is the call chain?\"*\n2. **`inspect_calls.py`** — *\"Who calls this function (directly, asynchronously, or via `ops_targets` function pointers), and what does it call?\"*\n3. **`check_privilege.py`** — *\"Is this line or function reachable from an unprivileged user, or is every path gated by `capable()` / `ns_capable()` / Kconfig / runtime tunables?\"*\n\n```text\n                                                      ┌──► find_paths.py       (Syscall/entry-to-target shortest call chains + coverage)\n                                                      │\nkernel_dashboard-<ver>.db ──► tools/lib/{callgraph,        ┼──► inspect_calls.py    (1-hop & multi-hop caller/callee neighborhood + ops dispatch)\n                                    metadata,         │\n                                    privilege}.py     └──► check_privilege.py  (Dijkstra capability-gate & 2D entry precondition verdict)\n```\n\n---\n\n## 1. Architecture, Shared Libraries & Required SQLite Tables\n\n### Shared Library Modules (`tools/lib/`)\n- **`tools/lib/callgraph.py`**: Database connection & index management (`open_databases`, `ensure_indexes`, `table_exists`, `clean_file_path`), function and span lookup (`get_enclosing_function`, `get_function_by_name`, `load_functions_for_files`), reverse call-graph traversal across direct calls, `ops_targets` function pointers, and `async_edges` callbacks (`get_callers`, `iter_pruned_callers`), syscall and non-syscall entry discovery (`is_syscall_root`, `load_entry_roots`, `is_entry_root`, `load_target_reachable_set`, `get_reachable_syscalls`, `get_reachable_entries`, `select_eval_roots`), and tree banner helpers (`format_root_label`, `format_target_banner`).\n- **`tools/lib/metadata.py`**: Kconfig `#ifdef`/`#else`/Makefile precondition extraction and symbol metadata lookup (`get_line_configs`, `get_kconfig_metadata`), Syzkaller dynamic coverage correlation (`get_syzkaller_coverage`, `is_line_covered_by_syzkaller`), target and call-path step builders (`build_target_info`, `make_path_step`, `make_caller_step`), and shared CLI argument parsing (`add_common_cli_args`, `handle_common_cli_setup`, `extract_reachability_cli_kwargs`).\n- **`tools/lib/privilege.py`**: Dynamic `CAP_*` constant resolution (`load_capability_map`, `format_capability`, `deduplicate_gates`, `add_call_span`), polymorphic `conditions` table parsing across direct call gates, `__guarded_span__:<ns_scope>` line-span guards, `__genl_ops_gate__:<ns_scope>` Generic Netlink flags, `sysctl`, and `module_param` tunables (`load_condition_gates`, `get_call_site_gates`, `load_runtime_tunables`), the 2D entry-precondition model (`get_entry_precondition`), and capability verdict classification (`classify_gates`).\n\n### CLI Tools Summary\n\n| Tool | Core Question Answered | SQLite Tables Used | Output Formats |\n| :--- | :--- | :--- | :--- |\n| **`find_paths.py`** | Finds shortest call paths from `__do_sys_*` syscalls and non-syscall `entry_node` roots to a target `(file, line)` or `function`, traversing direct calls (`edges`), indirect struct function-pointer calls (`ops_targets`), and asynchronous registrations (`async_edges`). | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `tree` (default), `list`, `json`, `mermaid` |\n| **`inspect_calls.py`** | Inspects 1-hop or multi-hop callers (`--callers`), callees (`--callees`), or both (`--both`), resolving indirect ops table dispatches (e.g., `inode_operations->link`, `file_operations->unlocked_ioctl`) and annotating call-site capability gates. | `function_locations`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations` (+ optional Syzkaller DB) | `summary` (default), `tree`, `list`, `json` |\n| **`check_privilege.py`** | Crosses static call paths with control-flow-dominating capability checks (`conditions` + `macroinvocation_locations`), Kconfig guards, runtime tunables, and 2D non-syscall entry floors using a weighted Dijkstra search (`COST_UNGATED=1`, `COST_NS_CAPABLE=10,000`, `COST_CAPABLE=1,000,000`) to find the least-privileged path to a target. | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `summary` (default), `tree`, `paths`, `json` |\n\n> **Automatic Index Creation**: On first run, `callgraph.ensure_indexes()` automatically verifies and creates lightweight traversal indexes (`idx_fl_file_lines`, `idx_fl_name`, `idx_sn_fn`, `idx_sn_sys`, `idx_loc_msg`, `idx_loc_uri_line`, `idx_edges_target`, `idx_edges_source`, `idx_ops_target`, `idx_ops_exprcall`, plus conditional indexes on `configs`, `kconfig_symbols`, `async_edges`, and `entry_node`) if they do not already exist. You can also pre-build them explicitly with `--ensure-indexes`.\n\n---\n\n## 2. Tool 1: Syscall Reachability Path Finder (`find_paths.py`)\n\n### Key Features\n- **Target Resolution**: Accepts either `--file <path> --line <num>` (resolving the enclosing kernel function automatically) or `--function <name>`.\n- **Hybrid Call-Graph Traversal**: Combines direct call edges (`locations` / `edges` from `all-calls.ql`) with indirect ops-table dispatch edges (`ops_targets` from `ops_edges.ql`).\n- **Syzkaller Coverage Correlation**: When `--syzkaller-db` is provided, annotates each step along the call path with dynamic coverage indicators and optional Syzkaller reproduction programs (`--show-repro`).\n\n### CLI Usage & Examples\n```bash\n# Find the shortest syscall path to a specific source line:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --file mm/shmem.c --line 1500\n\n# Find paths to a function across all reachable syscalls (up to 10 syscalls):\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10\n\n# Pin reachability search to a specific syscall and output a Mermaid diagram:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function unix_stream_connect \\\n  --syscall connect \\\n  --format mermaid\n```\n\n---\n\n## 3. Tool 2: Call-Graph Neighborhood Inspector (`inspect_calls.py`)\n\n### Key Features\n- **Bidirectional Inspection**:\n  - `--callers`: Discovers direct callers and indirect callers invoking the function via `ops_targets` struct fields (e.g., `vfs_link` $\\rightarrow$ `inode_operations.link` $\\rightarrow$ `shmem_link`).\n  - `--callees`: Discovers direct calls made by the function and indirect `ExprCall` sites within the function, listing candidate target implementations.\n  - `--both` (default): Displays full 360-degree caller and callee context.\n- **Multi-Hop Expansion**: Use `--depth <N>` to expand caller/callee trees up to `N` hops.\n- **Inline Capability Gate Annotations**: Automatically highlights whether any caller or outgoing call site is guarded by `capable()` / `ns_capable()`.\n\n### CLI Usage & Examples\n```bash\n# Inspect both callers and callees of a function (1-hop summary):\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link\n\n# Inspect 2 hops of callers for a specific file and line in JSON format:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1250 \\\n  --callers --depth 2 --format json\n\n# Show all indirect dispatch candidates without truncation:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function vfs_ioctl \\\n  --callees --all\n```\n\n---\n\n## 4. Tool 3: Capability & Unprivileged Reachability Analyzer (`check_privilege.py`)\n\n### Key Features\n- **Least-Privileged Path Discovery**: Uses Dijkstra's algorithm over the reverse call graph with edge weights penalizing capability checks (`COST_UNGATED = 1`, `COST_NS_CAPABLE = 10,000`, `COST_CAPABLE = 1,000,000`). If *any* unprivileged path exists alongside gated paths, `check_privilege.py` surfaces the ungated route first.\n- **Symbolic `CAP_*` Resolution**: Correlates `conditions` check locations with `macroinvocation_locations` to resolve integer capability constants (`21`, `12`, etc.) into human-readable names (`CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, etc.).\n- **Intra-Procedural Target Line Checks**: When given `--file` and `--line` inside a function body, checks both inter-procedural gates on callers and intra-procedural `IfStmt` capability checks dominating the target line within the enclosing function.\n- **Four Clear Security Verdicts**:\n  - `REACHABLE WITH NO PRIVILEGE (UNGATED)`\n  - `REACHABLE BEHIND USER NAMESPACE CAPABILITY` (`ns_capable(...)`)\n  - `REACHABLE, BUT ONLY BEHIND <CAP_NAME>` (`capable(CAP_SYS_ADMIN)`, etc.)\n  - `UNREACHABLE`\n\n### `conditions` Table Schema & Polymorphic `call` Column Contract\nThe `conditions` table (`condition_type`, `condition_loc`, `if_stmt_loc`, `condition_arg`, `call`, `call_loc`) generated by `queries/condition-graph-direct.ql` uses a polymorphic `call` / `call_loc` encoding to represent three distinct kinds of gate records without schema changes:\n1. **Direct Call-Site Gate Rows**: `call` is the CodeQL call string (e.g., `\"call to foo\"` or `\"call to expression\"`), and `call_loc` is the source location of the guarded `Call` expression.\n2. **Guarded Line-Span Rows (`__guarded_span__:<ns_scope>`)**: `call` starts with `\"__guarded_span__:\"` followed by the classified user-namespace scope (`init_user_ns`, `net_ns`, `s_user_ns`, `mnt_ns`, `f_cred`, or `user_ns`), and `call_loc` encodes the controlled line interval `[minLine, maxLine]` as `\"file://<path>:<minLine>:1:<maxLine>:1\"`. Consumers (`load_condition_gates` in `tools/lib/privilege.py`) use this span to gate any direct call, indirect `ops_targets` dispatch, or `--line` target falling within `[minLine, maxLine]`.\n3. **Generic Netlink Declarative Gate Rows (`__genl_ops_gate__:<ns_scope>`)**: `call` starts with `\"__genl_ops_gate__:\"` followed by `init_user_ns` (`GENL_ADMIN_PERM`) or `net_ns` (`GENL_UNS_ADMIN_PERM`), and `call_loc` encodes the gated Netlink handler function's body span `[startLine, endLine]`. Consumers attach these gates directly to the registered handler function.\n\n> **Caveat on Single-Interval `[minLine, maxLine]` Span Approximation**: Controlled spans for `IfStmt` capability guards are represented as a single contiguous line interval `[minLine, maxLine]` (bounded for early-abort `if (!capable(...)) return/goto` guards by `min(labelLine) - 1`, the next `switch` case label, or the enclosing block end). If an aborting branch has multiple `goto` targets, `min(labelLine)` is a conservative lower bound; conversely, unusual intra-procedural control flow (such as backward jumps or intervening unconditional paths inside the same block) is approximated by line containment rather than full basic-block post-dominance.\n\n### CLI Usage & Examples\n```bash\n# Check whether a specific kernel line is reachable without privileges:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1420\n\n# Evaluate privilege requirements across all reachable syscalls:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10 \\\n  --format tree\n\n# Print compact arrow-separated call chains with gate annotations:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link \\\n  --format paths\n```\n\n---\n\n## 5. Running Unit Tests & Linting (`tools/tests/`)\n\nThe `tools/tests/` directory contains unit and synthetic-database integration tests for both the shared libraries (`test_lib.py`) and all three CLI tools (`test_find_paths.py`, `test_inspect_calls.py`, `test_check_privilege.py`), sharing schema fixtures from `tools/tests/fixtures.py`:\n\n```bash\n# Run the full unit test suite:\npytest tools/tests -v\n\n# Format and run pylint (80-column Google style, zero lint suppressions):\npyformat -i -s 4 tools/*.py tools/lib/*.py tools/tests/*.py\npylint --max-line-length=80 tools/*.py tools/lib/*.py tools/tests/*.py\n```\n\n---\n\n## 6. Known Limitations & Design Tradeoffs\n\n- **Out-of-Line Capability Wrapper Depth (`queries/condition_graph.qll`)**: `DirectCapabilityCheck` resolves up to 2 hops of out-of-line helper wrappers (`f -> g -> capable`). Deeper capability chains (3+ hops) where intermediate helpers perform side effects before returning a boolean are intentionally not treated as pure capability predicates.\n- **Conjunctive vs. Disjunctive Guarded Spans (`__guarded_span__`)**: When a single `if` condition combines multiple capability checks (`if (!capable(A) && !capable(B)) return -EPERM` vs. `if (!capable(A) || !capable(B)) return -EPERM`), both capability checks share the same guarded line span `[minLine, maxLine]`. Consumers union the gates covering a call site rather than solving full boolean SAT over compound branch conditions.\n- **Build-Configuration Scope (`kernel_dashboard-<ver>.db`)**: The CodeQL database reflects a single compiled kernel configuration and architecture (`x86_64`). Code inside `#ifdef CONFIG_X` blocks disabled in that build is not compiled into the AST and will not appear in `function_locations`, `edges`, or `conditions` (though raw `#ifdef` ranges remain visible in `configs`).\n- **User-Namespace Scope (`ns_capable`) is Necessary, Not Sufficient**: When a path is gated by `ns_capable(ns->user_ns, CAP_*)` (`REACHABLE BEHIND USER NAMESPACE CAPABILITY`), unprivileged user-namespace reachability requires *both* the `ns_capable` check and that the object/subsystem can be instantiated inside a non-`init_net` / non-`init_user_ns` namespace. If an earlier caller or ops table binds the path to `init_net` or `init_user_ns`, global privilege is still required.\n- **BPF Verifier Program-Type Allowlists (`bpf_entry`)**: Reachability from a `bpf_entry` root assumes `BPF_PROG_LOAD` succeeds (`CAP_BPF` or `kernel.unprivileged_bpf_disabled=0`), but individual BPF helpers and kfuncs are further restricted by per-program-type verifier allowlists (`get_func_proto` / `btf_kfunc_id_set`).\n- **Bridge Traversal Depth Cap (`--max-bridge-depth`)**: Backward root collection (`get_reachable_syscalls`, `get_reachable_entries`) caps indirect/async bridge hops at `--max-bridge-depth` (default `6`) and direct hops at `20`. If traversal hits this cap with unexplored callers remaining and no root is found, `check_privilege.py` reports `UNREACHABLE (DEPTH-LIMITED)` (`target_info[\"depth_truncated\"] = True`).\n- **Async Context Bucketing (`queries/async_edges.qll`)**: `perf_event.overflow_handler` (PMI/NMI), `kprobe`/`kretprobe` handlers (trap context), and `ftrace_ops.func` (arbitrary function-entry context) are grouped under `mechanism = \"irq\"` (`context = \"hardirq\"`) for backward call-graph bridging.\n\n","kernelctf/rules.md":"# kernelCTF rules\n\n> [!WARNING]\n> These rules apply from 2026-09-04, you can find [the previous version of the rules on Github](https://github.com/google/security-research/blob/88ec1d535b0d147eec404751f0457e7162450aed/kernelctf/rules.md).\n\nkernelCTF is a part of the [Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules) and is focused on making exploiting Linux kernel vulnerabilities harder by inviting security researchers to demonstrate their exploitation techniques on 0-day vulnerabilities.\n\nWe are asking researchers to publish their submissions, helping the community to learn from each other's techniques.\n\n# Reward structure and targets\n\n## Target: Hardened (`hardened-v1-7.x`)\n\nThe target is Linux 7.2-rc5 (x86_64) based on the [COS kernel config](https://cos.googlesource.com/third_party/kernel/+/refs/heads/cos-6.12/arch/x86/configs/lakitu_defconfig) with additional hardenings and a reduced attack surface.\n\n### Configuration changes\n\n* **Mitigation features enabled:**\n  * `kCFI` + `IBT`\n  * `SLAB_VIRTUAL=y`\n  * `KMALLOC_PARTITION_TYPED=y`\n  * `SLAB_MERGE_DEFAULT=n`\n\n* **Disabled subsystems (reduced attack surface):**\n  * `CONFIG_IO_URING=n`\n  * `CONFIG_USER_NS=n`\n  * `CONFIG_TLS=n`\n  * `CONFIG_CRYPTO_USER_API_AEAD=n`\n  * `CONFIG_BPF_UNPRIV_DEFAULT_OFF=y`\n  * `CONFIG_AF_UNIX_OOB=n`\n\n### Requirements\n\n* **Stability:** Submissions must achieve at least 70% stability based on 20 exploit runs. The exploit needs to run within 5 minutes, otherwise it will be counted as a failed run when we measure stability.\n* **Vulnerability works on LTS 6.12:** The underlying vulnerability must be triggerable on the latest LTS 6.12. When executed with the `--vuln-trigger` flag on LTS 6.12, the exploit must crash the system (a full LPE chain is not required on LTS).\n\n### Reward\n\n* **$71,337**\n\nWe have retired separate target tiers and bonus categories in favor of a single static reward per eligible exploit.\n\n### Target updates\n\nOnly one submission is eligible per kernel version. The 7.2 version will generally remain fixed due to the `SLAB_VIRTUAL` porting requirement. However, we will update the LTS version (used for vulnerability freshness testing) when we release new slots, upgrading the LTS kernel version every 2-4 weeks on average.\n\n## Submission evaluation system\n\nOn weeks when a slot is released, the submission window will open on Monday at 12:00 UTC and close on Friday at 12:00 UTC, at which point the winning submission will be selected.\n\nSubmissions are evaluated on both speed and reliability over **20 exploit runs**. The server extracts the pre-compiled `exploit` binary from your `.tar.gz` archive and executes it (without recompilation), awarding a final score based on the following formula:\n\n$$\\text{Score} = 2 \\times (\\text{Stability \\%}) + \\max(100 - \\text{AVG}(\\text{time\\_in\\_sec}), 0)$$\n\n* **Maximum Possible Score:** 300 pts (100% stability, 0-second runtime).\n* **Minimum Passing Score:** 140 pts (70% stability, $\\ge 100$-second runtime).\n* **Winning Criterion:** The submission with the highest overall score wins the reward. If there is a tie, the submission with the earlier flag capture time (the timestamp recorded in the flag) wins. If there is still a tie, the earlier form submission time will be used.\n* **Submission Limits:** Only one submission per researcher is eligible per slot. Researchers may evaluate on the server up to 10 times per slot based on their email address (you can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6)), but only their latest submission before the Friday 12:00 UTC deadline will be used. Please do not use different email addresses to bypass this requirement as payment providers will flag this and it will block the reward payment.\n\n### Connecting to the evaluation system\n\nYou can interact with the evaluation server using `client/cli.py` (from the `server/` directory):\n\n```bash\n# Evaluate exploit against remote server (default target)\npython3 client/cli.py exploit_binary --action evaluate --researcher-token <token>\n```\n\nYou can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6).\n\nIf you do not want to run a full evaluation and only want to test a part of the exploit, you can use:\n* `--action lpe-test`: Test local privilege escalation and flag retrieval on the hardened target.\n* `--action vuln-test`: Test triggering the vulnerability (kernel crash) on the LTS target.\n\nFor a raw interactive connection to the service menu, you can use `client/connect.sh`:\n\n```bash\n./client/connect.sh\n```\n\nFor the full guide and options (such as local testing), see the [`server/README.md` (\"Using `client/cli.py`\" section)](server/README.md#using-clientclipy).\n\nYou can use a maximum of two connections per IPv4 address and the connection will be closed after 60 minutes. Evaluation runs are limited to 10 attempts per researcher per open slot based on your email address.\n\nThe source code running on the server is available [on our Github](https://github.com/google/security-research/tree/master/kernelctf/server).\n\n## Additional eligibility rules\n\n### Vulnerability dupes\n\nOnly the first submission for a vulnerability is eligible for a reward.\n\nThis means: if a vulnerability is exploited on the target by Researcher A, it can no longer be exploited on the target (even if the LTS kernel version is updated).\n\nIf a patch commit fixes multiple vulnerabilities (e.g. by backporting a new version of a component to the stable tree), we assume the root cause is the same and we consider further submissions as duplicates.\n\nIf the same vulnerability is fixed in multiple patch commits (e.g. in commit A in the mainline tree and separately in commit B in the stable tree), then we still consider it as the same vulnerability, thus making further submissions duplicates.\n\nIf you are unsure about eligibility, contact us on the [#kernelctf Discord channel](https://discord.gg/ECS5VnJZys) before making the submission.\n\n# Submission process\n\n_Note: Minor details of the submission process may change from time to time, please make sure you check this page again for updates when you make a new submission._\n\nBefore you start the submission process, please make sure that the submission window is currently open (Monday 12:00 UTC to Friday 12:00 UTC on slot release weeks) and that you are submitting for the active target version by checking the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) or the evaluation server.\n\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n\n  * There is no patch commit in the mainline tree, and\n\n  * The vulnerability is not disclosed in any form (e.g. there is no Syzkaller report about the bug)\n\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although the bug was disclosed by Syzkaller more than 30 days ago, there is no fix and you convince the maintainers to fix the bug)\n\nA submission will not be eligible if the vulnerability details were reported somewhere (e.g. Pwn2Own) other than [security@kernel.org](mailto:security@kernel.org).\n\nThe submission process has two stages to make sure the vulnerability details are not shared with us before the patch is released:\n\n## Stage 1: Initial submission (before patch release)\n\n  0. Compress the compiled `exploit` binary, its source code, and all the build files as a `.tar.gz` file.\n\n     * Save this exact file, you will need to send us this later.\n\n     * Note: The evaluation system will extract the `exploit` binary from the archive and run it without recompilation.\n\n     * Try to keep this file to the minimum necessary, leave out large files like e.g. `vmlinux`, `bzImage` as they can be downloaded separately if needed.\n\n  1. Upload the compressed file to the evaluation system, which will provide a flag upon successful exploitation.\n\n  2. Submit the flag on [this form](https://forms.gle/cjA9M1ZNUSc6adGE6) with the additional details requested.\n\n     * Save the link as you’ll have to edit this form later.\n\n  3. Check the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) after submitting the form and confirm that your submission was added and your score is correct.\n\n  4. Wait until Friday at 12:00 UTC and verify that your submission won the current slot. If there are multiple submissions for the same slot, another submission with a higher score may take the slot (in case of a tie, the earlier flag capture time, and then the earlier form submission time wins). If your submission does not win, you must wait for a new, empty slot to be released (start from Step 1).\n\n  5. Report the vulnerability to security@kernel.org within 7 days of winning the slot.\n\n     * Note: A submission will be considered ineligible if it turns out that this requirement was not respected.\n\n  6. If you are not the author of the patch that fixes the bug, make sure that you are credited in the `Reported-By` tag of the patch that fixes the bug.\n\n     * Do not include the `Reported-By` tag if you both discovered the flaw and authored the patch.\n\n     * Use the same email address in the `Reported-By` tag as you use for the form submission or in the \"Email address used in Reported-By tag\" field of the form.\n\n     * If there is no `Reported-By` tag on a patch commit, then a 0-day submission is eligible only if this is the first 0-day submission for that patch commit (based on the first stage submission date).\n\n     * If it is unclear who reported the bug, then the reward can be split (multiple reporters), reduced, or invalidated at our discretion.\n\n  7. Wait for the patch to land in a release candidate on the mainline tree (and be tagged in Git) or be committed to a stable tree, whichever happens first.\n\n     * Make sure that the patch correctly fixes the vulnerability you reported. If it does not, report the issue to the kernel and wait for the correct patch commit, otherwise your submission will be ineligible.\n\n## Stage 2: After patch release\n\n  1. Modify the form within 7 days by following the previously saved link and fill out the extra vulnerability details.\n\n     * If the 7-day deadline is missed, then the submission may be considered ineligible for reward at our discretion.\n\n  2. Send us your exploit within 90 days with the description of the exploitation technique via a PR to [the security-research repo](https://github.com/google/security-research/) (see required structure below). This is a mandatory step for us to start verification of the vulnerability.\n\n  3. Once the PR's GitHub Actions (GHA) checks pass and we confirm the submission exploits the claimed vulnerability, you receive the first half of the reward. After a manual review and the PR is merged, the second half is issued.\n\n### Google Bughunter's website registration and reward payments\n\nSubmitting reports via [bughunters.google.com](https://bughunters.google.com/) prior to PR submission is **no longer required**; an issue will automatically be created on the portal for winning entries.\n\nHowever, to collect your payout reward:\n  1. You must register once on [bughunters.google.com](https://bughunters.google.com/) so we can send you the reward.\n  2. We highly recommend changing your payment provider to BugCrowd for a better payment process. You can [read here](https://bughunters.google.com/blog/6483936851394560/announcing-bugcrowd-as-a-new-bughunters-google-com-payment-option) how.\n  3. If you'd like to split your reward with another researcher, please [read our FAQ regarding the process](https://bughunters.google.com/about/frequently-asked-questions#q-is-it-possible-to-split-the-reward-for-a-report-with-other-researchers-for-example-if-we-collaborated-on-the-report-).\n\n## Note about making the exploit public\n\nYou have to publish your exploit within 90 days of submitting the patch commit via the Google Form to be eligible for a reward.\n\nWe only process submissions after the exploit becomes public. We can only issue the first half of the reward once the PR passes the automated checks and the initial review confirms that the submission exploits the claimed vulnerability. Following an in-depth review and successful quality checks, the PR will be merged, and the second half of the reward will be issued.\n\nIf you want to delay the publication (within the 90 days window), you could do that, but you would get the money later (we want to encourage you to publish the exploit details sooner than later).\n\nThe above is about the exploit itself, not the vulnerability. We automatically share some limited vulnerability details of the submissions on our [public submission spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml?gid=2095368189), as a CVE, once you submit the extra vulnerability details via the form in Stage 2.\n\n## Exploit PR file structure\n\nThe submission should be put into the `pocs/linux/kernelctf/<cve>_<targets>/` folder within the [security-research repo](https://github.com/google/security-research/), where:\n\n  * `cve` is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\n\n  * `<targets>` is the list of targets separated by underscore (`_`)\n\n    * Valid target names: `hardened-v1-7.x`\n\n  * If there is a conflicting submission directory name, then append `_2` (or `_3`, etc.) after the directory name.\n\nFor example: `pocs/linux/kernelctf/CVE-2023-1872_hardened-v1-7.x/`.\n\nThe structure of this submission folder should be:\n\n  * `original.tar.gz`\n\n    * Required; contains the original exploit (compiled binary and source code used to build it). Its hash must match the one calculated by the evaluation system and encoded within the flag you submitted in the form.\n\n  * `metadata.json`\n\n    * Required, structured metadata information following [this JSON schema (version 3)](metadata.schema.v3.json).\n\n  * `docs/vulnerability.md`\n\n    * Required, description of the vulnerability.\n\n  * `docs/exploit.md`\n\n    * Required, description of how the exploits work. If exploits are too different, then it can also be put next to exploits.\n\n  * `exploit/hardened-v1-7.x/`<br>\n\n    * `exploit.c`\n       * Required, source code of the exploit.\n\n    * `exploit`\n       * Required, compiled exploit which stole the flag.\n\n    * `Makefile`\n       * Required, includes target (`exploit`) to compile `exploit.c` into `exploit` and target (`run`) to run the exploit on the live instance (which steals the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries for the exploit). The exploit can be split into multiple files, although we prefer if it is kept as a single `.c` file.\n\n## Documentation requirements\n\n### Vulnerability\n\nIf possible please include the following information in the vulnerability details:\n\n  * Requirements to trigger the vulnerability:\n    * [Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html)\n    * Kernel configuration\n\n  * Commit which introduced the vulnerability\n\n  * Commit which fixed the vulnerability\n\n  * Affected kernel versions\n\n  * Affected component, subsystem\n\n  * Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n\n  * Which syscalls or syscall parameters are needed to be blocked to prevent triggering the vulnerability? (If there is any easy way to block it.)\n\n### Exploit\n\nEnsure that exploit code follows [kernelCTF code style guide](https://google.github.io/security-research/kernelctf/style_guide).\n\nMake sure that the exploit is properly commented and the accompanying `exploit.md` includes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the following activities, include them as a separate step:\n\n  * Triggering a vulnerability.\n\n  * Converting one attack primitive into another.\n\n  * Spraying or grooming the heap.\n\n  * Executing cross-cache attack.\n\n  * Leaking information (e.g. heap pointer, kASLR base address).\n\n  * Overwriting kernel memory.\n\n  * Getting RIP control.\n\n  * Executing interesting post-RIP approaches.\n\n  * Doing a major step towards a successful exploitation which is not listed above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role (e.g. vulnerable object, victim object), and their respective caches (e.g. `kmalloc-1k`) and the used field members of the object (e.g. getting RIP control via `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n\n  * Non-trivial constant values should be explained, for example:\n    * Flag and enumeration values\n    * Field offsets\n    * Function addresses\n    * ROP gadget offsets\n\n  * ROP chain items should be explained.\n    * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to e.g. `call_usermodehelper_exec`.\n\n  * Fake structures should be explained; i.e. which structure is created and what fields are set.\n    * E.g. `data[0x8] = base + 0x123456`; -> data variable contains a fake `struct file`, the field at 0x8 offset is a `f_inode` pointer which is set to `...`\n\n  * Usage of multi-threading (or forking)\n    * Why is it needed?\n    * If a race condition is exploited, then what code paths are raced.\n    * Communication and synchronization between the two threads (e.g. what data was sent between the threads, and when the threads are waiting on each other).\n\n  * Environmental requirements\n    * If specific climit or cpu affinity settings are required, then explain why they are needed.\n    * Which limit the exploit runs into using the default settings.\n\n  * Namespaces usage and why are they required.\n\n  * Separation between code parts which are needed to trigger the vulnerability and parts which are part of the exploitation process (spraying, heap grooming, cross-cache, converting one primitive to another).\n\n  * Any action (e.g. syscall) where a side-effect of the action is used for the exploit and not the main functionality, for example:\n    * Syscall used for spraying a specific structure, not for its main purpose.\n    * Some calls (e.g. `sleep`) used for a specific side-effect which is not trivial see.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the time during your testing).\n\nYour exploit must support the `--vuln-trigger` argument, which triggers the underlying vulnerability to crash the system (ideally under KASAN) on other versions without requiring a full LPE chain. To stay within [vuln-verify workflow](https://github.com/google/security-research/blob/master/.github/workflows/kernelctf-vuln-verify.yaml) time limits, this mode should skip non-essential steps such as KASLR prefetching.\n\n# Additional information\n\n## Program change notifications and communication\n\nWe announce program changes through [#kernelctf-announcements](https://discord.gg/yXue2RwDEA) Discord channel. All major changes are going to be announced 2 weeks in advance before they take an effect. This document will be updated to reflect current set of kernelCTF rules.\n\n## Questions about program\n\nIf you have any questions regarding kernelCTF, check [the FAQ page](faq.md) and feel free to ask on the [#kernelctf](https://discord.gg/ECS5VnJZys) Discord channel.\n\n## Non-kernel vulnerabilities\n\nIf you are submitting a non-kernel vulnerability affecting our kCTF VRP cluster, please submit the vulnerability to our [kCTF VRP](https://google.github.io/kctf/vrp.html).\n\n## Legal points\n\nkernelCTF is part of Google VRP, so its rules including but not limited to [these Legal points](https://bughunters.google.com/about/rules/google-friends/google-and-alphabet-vulnerability-reward-program-vrp-rules#legal-points) apply.\n\nYou should understand that we can cancel the program at any time and the decision as to whether or not to pay a reward and how much has to be entirely at our discretion.\n"},"items":[{"name":"rules.md","path":"kernelctf/rules.md","rawUrl":"https://raw.githubusercontent.com/google/security-research/HEAD/kernelctf/rules.md","title":"kernelctf - Development & Architecture Rules","category":"root-instruction","format":"markdown","content":"# kernelCTF rules\n\n> [!WARNING]\n> These rules apply from 2026-09-04, you can find [the previous version of the rules on Github](https://github.com/google/security-research/blob/88ec1d535b0d147eec404751f0457e7162450aed/kernelctf/rules.md).\n\nkernelCTF is a part of the [Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules) and is focused on making exploiting Linux kernel vulnerabilities harder by inviting security researchers to demonstrate their exploitation techniques on 0-day vulnerabilities.\n\nWe are asking researchers to publish their submissions, helping the community to learn from each other's techniques.\n\n# Reward structure and targets\n\n## Target: Hardened (`hardened-v1-7.x`)\n\nThe target is Linux 7.2-rc5 (x86_64) based on the [COS kernel config](https://cos.googlesource.com/third_party/kernel/+/refs/heads/cos-6.12/arch/x86/configs/lakitu_defconfig) with additional hardenings and a reduced attack surface.\n\n### Configuration changes\n\n* **Mitigation features enabled:**\n  * `kCFI` + `IBT`\n  * `SLAB_VIRTUAL=y`\n  * `KMALLOC_PARTITION_TYPED=y`\n  * `SLAB_MERGE_DEFAULT=n`\n\n* **Disabled subsystems (reduced attack surface):**\n  * `CONFIG_IO_URING=n`\n  * `CONFIG_USER_NS=n`\n  * `CONFIG_TLS=n`\n  * `CONFIG_CRYPTO_USER_API_AEAD=n`\n  * `CONFIG_BPF_UNPRIV_DEFAULT_OFF=y`\n  * `CONFIG_AF_UNIX_OOB=n`\n\n### Requirements\n\n* **Stability:** Submissions must achieve at least 70% stability based on 20 exploit runs. The exploit needs to run within 5 minutes, otherwise it will be counted as a failed run when we measure stability.\n* **Vulnerability works on LTS 6.12:** The underlying vulnerability must be triggerable on the latest LTS 6.12. When executed with the `--vuln-trigger` flag on LTS 6.12, the exploit must crash the system (a full LPE chain is not required on LTS).\n\n### Reward\n\n* **$71,337**\n\nWe have retired separate target tiers and bonus categories in favor of a single static reward per eligible exploit.\n\n### Target updates\n\nOnly one submission is eligible per kernel version. The 7.2 version will generally remain fixed due to the `SLAB_VIRTUAL` porting requirement. However, we will update the LTS version (used for vulnerability freshness testing) when we release new slots, upgrading the LTS kernel version every 2-4 weeks on average.\n\n## Submission evaluation system\n\nOn weeks when a slot is released, the submission window will open on Monday at 12:00 UTC and close on Friday at 12:00 UTC, at which point the winning submission will be selected.\n\nSubmissions are evaluated on both speed and reliability over **20 exploit runs**. The server extracts the pre-compiled `exploit` binary from your `.tar.gz` archive and executes it (without recompilation), awarding a final score based on the following formula:\n\n$$\\text{Score} = 2 \\times (\\text{Stability \\%}) + \\max(100 - \\text{AVG}(\\text{time\\_in\\_sec}), 0)$$\n\n* **Maximum Possible Score:** 300 pts (100% stability, 0-second runtime).\n* **Minimum Passing Score:** 140 pts (70% stability, $\\ge 100$-second runtime).\n* **Winning Criterion:** The submission with the highest overall score wins the reward. If there is a tie, the submission with the earlier flag capture time (the timestamp recorded in the flag) wins. If there is still a tie, the earlier form submission time will be used.\n* **Submission Limits:** Only one submission per researcher is eligible per slot. Researchers may evaluate on the server up to 10 times per slot based on their email address (you can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6)), but only their latest submission before the Friday 12:00 UTC deadline will be used. Please do not use different email addresses to bypass this requirement as payment providers will flag this and it will block the reward payment.\n\n### Connecting to the evaluation system\n\nYou can interact with the evaluation server using `client/cli.py` (from the `server/` directory):\n\n```bash\n# Evaluate exploit against remote server (default target)\npython3 client/cli.py exploit_binary --action evaluate --researcher-token <token>\n```\n\nYou can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6).\n\nIf you do not want to run a full evaluation and only want to test a part of the exploit, you can use:\n* `--action lpe-test`: Test local privilege escalation and flag retrieval on the hardened target.\n* `--action vuln-test`: Test triggering the vulnerability (kernel crash) on the LTS target.\n\nFor a raw interactive connection to the service menu, you can use `client/connect.sh`:\n\n```bash\n./client/connect.sh\n```\n\nFor the full guide and options (such as local testing), see the [`server/README.md` (\"Using `client/cli.py`\" section)](server/README.md#using-clientclipy).\n\nYou can use a maximum of two connections per IPv4 address and the connection will be closed after 60 minutes. Evaluation runs are limited to 10 attempts per researcher per open slot based on your email address.\n\nThe source code running on the server is available [on our Github](https://github.com/google/security-research/tree/master/kernelctf/server).\n\n## Additional eligibility rules\n\n### Vulnerability dupes\n\nOnly the first submission for a vulnerability is eligible for a reward.\n\nThis means: if a vulnerability is exploited on the target by Researcher A, it can no longer be exploited on the target (even if the LTS kernel version is updated).\n\nIf a patch commit fixes multiple vulnerabilities (e.g. by backporting a new version of a component to the stable tree), we assume the root cause is the same and we consider further submissions as duplicates.\n\nIf the same vulnerability is fixed in multiple patch commits (e.g. in commit A in the mainline tree and separately in commit B in the stable tree), then we still consider it as the same vulnerability, thus making further submissions duplicates.\n\nIf you are unsure about eligibility, contact us on the [#kernelctf Discord channel](https://discord.gg/ECS5VnJZys) before making the submission.\n\n# Submission process\n\n_Note: Minor details of the submission process may change from time to time, please make sure you check this page again for updates when you make a new submission._\n\nBefore you start the submission process, please make sure that the submission window is currently open (Monday 12:00 UTC to Friday 12:00 UTC on slot release weeks) and that you are submitting for the active target version by checking the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) or the evaluation server.\n\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n\n  * There is no patch commit in the mainline tree, and\n\n  * The vulnerability is not disclosed in any form (e.g. there is no Syzkaller report about the bug)\n\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although the bug was disclosed by Syzkaller more than 30 days ago, there is no fix and you convince the maintainers to fix the bug)\n\nA submission will not be eligible if the vulnerability details were reported somewhere (e.g. Pwn2Own) other than [security@kernel.org](mailto:security@kernel.org).\n\nThe submission process has two stages to make sure the vulnerability details are not shared with us before the patch is released:\n\n## Stage 1: Initial submission (before patch release)\n\n  0. Compress the compiled `exploit` binary, its source code, and all the build files as a `.tar.gz` file.\n\n     * Save this exact file, you will need to send us this later.\n\n     * Note: The evaluation system will extract the `exploit` binary from the archive and run it without recompilation.\n\n     * Try to keep this file to the minimum necessary, leave out large files like e.g. `vmlinux`, `bzImage` as they can be downloaded separately if needed.\n\n  1. Upload the compressed file to the evaluation system, which will provide a flag upon successful exploitation.\n\n  2. Submit the flag on [this form](https://forms.gle/cjA9M1ZNUSc6adGE6) with the additional details requested.\n\n     * Save the link as you’ll have to edit this form later.\n\n  3. Check the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) after submitting the form and confirm that your submission was added and your score is correct.\n\n  4. Wait until Friday at 12:00 UTC and verify that your submission won the current slot. If there are multiple submissions for the same slot, another submission with a higher score may take the slot (in case of a tie, the earlier flag capture time, and then the earlier form submission time wins). If your submission does not win, you must wait for a new, empty slot to be released (start from Step 1).\n\n  5. Report the vulnerability to security@kernel.org within 7 days of winning the slot.\n\n     * Note: A submission will be considered ineligible if it turns out that this requirement was not respected.\n\n  6. If you are not the author of the patch that fixes the bug, make sure that you are credited in the `Reported-By` tag of the patch that fixes the bug.\n\n     * Do not include the `Reported-By` tag if you both discovered the flaw and authored the patch.\n\n     * Use the same email address in the `Reported-By` tag as you use for the form submission or in the \"Email address used in Reported-By tag\" field of the form.\n\n     * If there is no `Reported-By` tag on a patch commit, then a 0-day submission is eligible only if this is the first 0-day submission for that patch commit (based on the first stage submission date).\n\n     * If it is unclear who reported the bug, then the reward can be split (multiple reporters), reduced, or invalidated at our discretion.\n\n  7. Wait for the patch to land in a release candidate on the mainline tree (and be tagged in Git) or be committed to a stable tree, whichever happens first.\n\n     * Make sure that the patch correctly fixes the vulnerability you reported. If it does not, report the issue to the kernel and wait for the correct patch commit, otherwise your submission will be ineligible.\n\n## Stage 2: After patch release\n\n  1. Modify the form within 7 days by following the previously saved link and fill out the extra vulnerability details.\n\n     * If the 7-day deadline is missed, then the submission may be considered ineligible for reward at our discretion.\n\n  2. Send us your exploit within 90 days with the description of the exploitation technique via a PR to [the security-research repo](https://github.com/google/security-research/) (see required structure below). This is a mandatory step for us to start verification of the vulnerability.\n\n  3. Once the PR's GitHub Actions (GHA) checks pass and we confirm the submission exploits the claimed vulnerability, you receive the first half of the reward. After a manual review and the PR is merged, the second half is issued.\n\n### Google Bughunter's website registration and reward payments\n\nSubmitting reports via [bughunters.google.com](https://bughunters.google.com/) prior to PR submission is **no longer required**; an issue will automatically be created on the portal for winning entries.\n\nHowever, to collect your payout reward:\n  1. You must register once on [bughunters.google.com](https://bughunters.google.com/) so we can send you the reward.\n  2. We highly recommend changing your payment provider to BugCrowd for a better payment process. You can [read here](https://bughunters.google.com/blog/6483936851394560/announcing-bugcrowd-as-a-new-bughunters-google-com-payment-option) how.\n  3. If you'd like to split your reward with another researcher, please [read our FAQ regarding the process](https://bughunters.google.com/about/frequently-asked-questions#q-is-it-possible-to-split-the-reward-for-a-report-with-other-researchers-for-example-if-we-collaborated-on-the-report-).\n\n## Note about making the exploit public\n\nYou have to publish your exploit within 90 days of submitting the patch commit via the Google Form to be eligible for a reward.\n\nWe only process submissions after the exploit becomes public. We can only issue the first half of the reward once the PR passes the automated checks and the initial review confirms that the submission exploits the claimed vulnerability. Following an in-depth review and successful quality checks, the PR will be merged, and the second half of the reward will be issued.\n\nIf you want to delay the publication (within the 90 days window), you could do that, but you would get the money later (we want to encourage you to publish the exploit details sooner than later).\n\nThe above is about the exploit itself, not the vulnerability. We automatically share some limited vulnerability details of the submissions on our [public submission spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml?gid=2095368189), as a CVE, once you submit the extra vulnerability details via the form in Stage 2.\n\n## Exploit PR file structure\n\nThe submission should be put into the `pocs/linux/kernelctf/<cve>_<targets>/` folder within the [security-research repo](https://github.com/google/security-research/), where:\n\n  * `cve` is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\n\n  * `<targets>` is the list of targets separated by underscore (`_`)\n\n    * Valid target names: `hardened-v1-7.x`\n\n  * If there is a conflicting submission directory name, then append `_2` (or `_3`, etc.) after the directory name.\n\nFor example: `pocs/linux/kernelctf/CVE-2023-1872_hardened-v1-7.x/`.\n\nThe structure of this submission folder should be:\n\n  * `original.tar.gz`\n\n    * Required; contains the original exploit (compiled binary and source code used to build it). Its hash must match the one calculated by the evaluation system and encoded within the flag you submitted in the form.\n\n  * `metadata.json`\n\n    * Required, structured metadata information following [this JSON schema (version 3)](metadata.schema.v3.json).\n\n  * `docs/vulnerability.md`\n\n    * Required, description of the vulnerability.\n\n  * `docs/exploit.md`\n\n    * Required, description of how the exploits work. If exploits are too different, then it can also be put next to exploits.\n\n  * `exploit/hardened-v1-7.x/`<br>\n\n    * `exploit.c`\n       * Required, source code of the exploit.\n\n    * `exploit`\n       * Required, compiled exploit which stole the flag.\n\n    * `Makefile`\n       * Required, includes target (`exploit`) to compile `exploit.c` into `exploit` and target (`run`) to run the exploit on the live instance (which steals the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries for the exploit). The exploit can be split into multiple files, although we prefer if it is kept as a single `.c` file.\n\n## Documentation requirements\n\n### Vulnerability\n\nIf possible please include the following information in the vulnerability details:\n\n  * Requirements to trigger the vulnerability:\n    * [Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html)\n    * Kernel configuration\n\n  * Commit which introduced the vulnerability\n\n  * Commit which fixed the vulnerability\n\n  * Affected kernel versions\n\n  * Affected component, subsystem\n\n  * Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n\n  * Which syscalls or syscall parameters are needed to be blocked to prevent triggering the vulnerability? (If there is any easy way to block it.)\n\n### Exploit\n\nEnsure that exploit code follows [kernelCTF code style guide](https://google.github.io/security-research/kernelctf/style_guide).\n\nMake sure that the exploit is properly commented and the accompanying `exploit.md` includes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the following activities, include them as a separate step:\n\n  * Triggering a vulnerability.\n\n  * Converting one attack primitive into another.\n\n  * Spraying or grooming the heap.\n\n  * Executing cross-cache attack.\n\n  * Leaking information (e.g. heap pointer, kASLR base address).\n\n  * Overwriting kernel memory.\n\n  * Getting RIP control.\n\n  * Executing interesting post-RIP approaches.\n\n  * Doing a major step towards a successful exploitation which is not listed above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role (e.g. vulnerable object, victim object), and their respective caches (e.g. `kmalloc-1k`) and the used field members of the object (e.g. getting RIP control via `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n\n  * Non-trivial constant values should be explained, for example:\n    * Flag and enumeration values\n    * Field offsets\n    * Function addresses\n    * ROP gadget offsets\n\n  * ROP chain items should be explained.\n    * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to e.g. `call_usermodehelper_exec`.\n\n  * Fake structures should be explained; i.e. which structure is created and what fields are set.\n    * E.g. `data[0x8] = base + 0x123456`; -> data variable contains a fake `struct file`, the field at 0x8 offset is a `f_inode` pointer which is set to `...`\n\n  * Usage of multi-threading (or forking)\n    * Why is it needed?\n    * If a race condition is exploited, then what code paths are raced.\n    * Communication and synchronization between the two threads (e.g. what data was sent between the threads, and when the threads are waiting on each other).\n\n  * Environmental requirements\n    * If specific climit or cpu affinity settings are required, then explain why they are needed.\n    * Which limit the exploit runs into using the default settings.\n\n  * Namespaces usage and why are they required.\n\n  * Separation between code parts which are needed to trigger the vulnerability and parts which are part of the exploitation process (spraying, heap grooming, cross-cache, converting one primitive to another).\n\n  * Any action (e.g. syscall) where a side-effect of the action is used for the exploit and not the main functionality, for example:\n    * Syscall used for spraying a specific structure, not for its main purpose.\n    * Some calls (e.g. `sleep`) used for a specific side-effect which is not trivial see.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the time during your testing).\n\nYour exploit must support the `--vuln-trigger` argument, which triggers the underlying vulnerability to crash the system (ideally under KASAN) on other versions without requiring a full LPE chain. To stay within [vuln-verify workflow](https://github.com/google/security-research/blob/master/.github/workflows/kernelctf-vuln-verify.yaml) time limits, this mode should skip non-essential steps such as KASLR prefetching.\n\n# Additional information\n\n## Program change notifications and communication\n\nWe announce program changes through [#kernelctf-announcements](https://discord.gg/yXue2RwDEA) Discord channel. All major changes are going to be announced 2 weeks in advance before they take an effect. This document will be updated to reflect current set of kernelCTF rules.\n\n## Questions about program\n\nIf you have any questions regarding kernelCTF, check [the FAQ page](faq.md) and feel free to ask on the [#kernelctf](https://discord.gg/ECS5VnJZys) Discord channel.\n\n## Non-kernel vulnerabilities\n\nIf you are submitting a non-kernel vulnerability affecting our kCTF VRP cluster, please submit the vulnerability to our [kCTF VRP](https://google.github.io/kctf/vrp.html).\n\n## Legal points\n\nkernelCTF is part of Google VRP, so its rules including but not limited to [these Legal points](https://bughunters.google.com/about/rules/google-friends/google-and-alphabet-vulnerability-reward-program-vrp-rules#legal-points) apply.\n\nYou should understand that we can cancel the program at any time and the decision as to whether or not to pay a reward and how much has to be entirely at our discretion.\n","isInternal":false,"tokens":4782,"sizeBytes":20159},{"name":"rules.md","path":"kvmctf/rules.md","rawUrl":"https://raw.githubusercontent.com/google/security-research/HEAD/kvmctf/rules.md","title":"kvmctf - Development & Architecture Rules","category":"root-instruction","format":"markdown","content":"# kvmCTF Overview\n\nkvmCTF is a part of the\n[Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules)\nand is focused on eliminating VM-reachable Kernel-based Virtual Machine (KVM)\nvulnerabilities in upstream mainline kernel. We invite security researchers to\ndemonstrate their bug hunting and exploitation techniques on an LTS kernel version.\nEventually we might add experimental mitigations to KVM that we would like to see\nif and how researchers can bypass them.\n\nWe are additionally asking researchers to publish their submissions, helping the\ncommunity to learn from each other’s techniques.\n\n# Competition Rules\n\n## Target: Linux LTS KVM\n\nThe host runs v6.1.74 and runs on an Intel(R) Xeon(R) Gold 5222 CPU @ 3.80GHz.\nParticipants will have the option to select whether they want the host to run\nwith `CONFIG_KASAN` disabled or enabled. The complete setup of the host can be\ndownloaded\n[here](https://storage.googleapis.com/kvmctf/latest.tar.gz) in a\ngzip format and contains the following:\n* The kernel patch we applied on the kernel tree.\n* The kernel configuration files.\n* The gcc and binutils versions used to compile the kernel.\n* The virsh version used to run the VM.\n* The produced `vmlinux` images.\n* The produced `bzImage` binaries.\n* The produced `ko` module binaries.\n* The `qemu-kvm` command used to run the guest.\n\nParticipants will be connected to a Debian 12.5 (bookworm) guest that runs on a\n`v6.1.0-21` kernel compiled with the default Debian config.\n\nThe goal is to perform a successful guest-to-host attack. Currently we do not\nreward QEMU, host-to-KVM or CPU/DRAM/HW-based vulnerabilities.\n\nNote: Although our testing environment runs an LTS kernel, vulnerabilities must\nbe reproducible in the upstream Linux mainline master branch to be eligible.\nVulnerabilities that only exist in downstream backports or older LTS trees are\nout of scope.\n\n## Rewards\n| Tier                   | Reward   |\n|------------------------| -------- |\n| Full VM escape         | $250,000 |\n| Arbitrary memory write | $100,000 |\n| Arbitrary memory read  | $50,000  |\n| Relative memory write  | $50,000  |\n| Denial of Service      | $20,000  |\n| Relative memory read   | $10,000  |\n\n\nNote that the above rewards do not stack. For instance, if you submit a full VM\nescape exploit that takes advantage of an arbitrary memory read you will be\nrewarded with $250,000, not $250,000 + $50,000.\n\n## Flags\nYour submission should contain proof that your exploit succeeded in one of the\nabove tiers. This is achieved by providing each tier's corresponding flag (a\n64-bit number). Note that providing the flag does **not** automatically\nguarantee the corresponding reward, your exploit must take advantage of a\nvulnerability of that tier. For instance, if you use an arbitrary memory read\nvulnerability to read the arbitrary memory write flag, you will **not** be\ncompensated with the arbitrary memory write reward.\n### RCE flag\nTo obtain this flag your exploit should read the contents of the\n`/root/rce_flag` file in the host file system.\n### Arbitrary memory accesses\nFor the arbitrary memory write tier your exploit should overwrite the contents\nof the write flag address (its default value is `0xdeadbeef41424344` so your\nexploit should modify any or all of its bits), whereas for the arbitrary memory\nread tier your exploit should read the contents of the read flag address. The\ntarget addresses (both virtual and physical) can be found in the\n`/root/addresses` file in the guest file system. For the arbitrary memory write\ntier, your exploit should first overwrite the contents of the write flag address\nand then call hypercall `#100` which will return the corresponding flag in\n`RAX`. For the arbitrary memory read tier, the flag is the contents of the read\nflag address.\n### Relative memory accesses\nThe relative memory read and relative memory write are available only if the\nhost runs with `CONFIG_KASAN` enabled. The mapping between the KASAN violations\nand the reward tiers is the following:\n\n| Operation     | KASAN violation         | Reward Tier           |\n| ------------  | ----------------------- | ------------------    |\n| Memory Write  | use-after-free          | Relative memory write |\n| Memory Write  | out-of-bounds           | Relative memory write |\n| Memory Write  | slab-out-of-bounds      | Relative memory write |\n| Memory Write  | global-out-of-bounds    | Relative memory write |\n| Memory Write  | stack-out-of-bounds     | Relative memory write |\n| Memory Write  | alloca-out-of-bounds    | Relative memory write |\n| Memory Write  | vmalloc-out-of-bounds   | Relative memory write |\n| Memory Write  | user-memory-access      | Relative memory write |\n| Memory Write  | wild-memory-access      | Relative memory write |\n| *             | double-free             | Relative memory write |\n| *             | invalid-free            | Relative memory write |\n| Memory Read   | use-after-free          | Relative memory read  |\n| Memory Read   | out-of-bounds           | Relative memory read  |\n| Memory Read   | slab-out-of-bounds      | Relative memory read  |\n| Memory Read   | global-out-of-bounds    | Relative memory read  |\n| Memory Read   | stack-out-of-bounds     | Relative memory read  |\n| Memory Read   | alloca-out-of-bounds    | Relative memory read  |\n| Memory Read   | vmalloc-out-of-bounds   | Relative memory read  |\n| Memory Read   | user-memory-access      | Relative memory read  |\n| Memory Read   | wild-memory-access      | Relative memory read  |\n| *             | null-ptr-deref          | Denial of Service     |\n\nFor the relative memory write tier, your exploit should first perform the\noperation that produces the KASAN violation and then call hypercall `#101` which\nwill return the flag in `RAX`.\nSimilarly, for the relative memory read tier, your exploit should first perform\nthe operation to produce the KASAN violation and then call hypercall `#102`\nwhich will return the flag in `RAX`.\n\n### Denial of Service\nThe Denial of Service tier rewards exploits that induce a `null-ptr-deref` KASAN\nviolation, or that make the host panic or otherwise\ncrash. In the former case, your exploit should first perform the operation to\nproduce the KASAN violation and then call hypercall `#103` which will return the\nflag in `RAX`.\nIn the latter case, you do not need to provide a flag: after executing your\nexploit and crashing the host just specify in the submission form that you are\nsubmitting a Denial of Service exploit.\n\n## Process\nTo try your exploit on our server you will have to reserve a time slot. You can\ndo it using the command:\n\n``socat FILE:`tty`,raw,echo=0 ssl:kvmctf.ctfcompetition.com:1337,cafile=server_cert.pem``\n\n`server_cert.pem`:\n```\n-----BEGIN CERTIFICATE-----\nMIIBXTCCAQ+gAwIBAgIUcU+vah86fZls1/1gfDBEotuQTi4wBQYDK2VwMCQxIjAg\nBgNVBAMMGWt2bWN0Zi5jdGZjb21wZXRpdGlvbi5jb20wHhcNMjQwMzI2MTc1MjUw\nWhcNMzQwMzI0MTc1MjUwWjAkMSIwIAYDVQQDDBlrdm1jdGYuY3RmY29tcGV0aXRp\nb24uY29tMCowBQYDK2VwAyEAWiQBWTd51Qej7hPho7MtkLu6gtOJhyGM8lVr4dlf\nr6OjUzBRMB0GA1UdDgQWBBSGgjr7/oy7f72v7fjy+Boe7dmTaTAfBgNVHSMEGDAW\ngBSGgjr7/oy7f72v7fjy+Boe7dmTaTAPBgNVHRMBAf8EBTADAQH/MAUGAytlcANB\nAKwz9VdZ1e81DObSMEmeAm5mBc+Hsu50etwjDQGAPMoag+qcPddvlmlxcmuKY4QO\nOzLhYAILFWvYJrT5uTF0FwU=\n-----END CERTIFICATE-----\n```\n\nand follow the prompts. Note that the reservations are done using the UTC time\nso please convert your desired time to UTC before reserving. You will need to\nprovide an email address and whether you want a KASAN-enabled host, and you will\nbe given a key (both in your terminal and in an email verification). To connect\nto the server during your reserved time slot you can use the same command as\nabove. You will be asked to provide the email address you used to reserve the\ntime slot and the key you received. After verification, you will be redirected\nto the server.\n\n## Additional eligibility rules\nOnly the first submission for a vulnerability is eligible for a reward.\nIf a patch commit fixes multiple vulnerabilities, we assume the root cause is the same\nand we consider further submissions as duplicates.\nIf the same vulnerability is fixed in multiple patch commits, then we\nstill consider it as the same vulnerability, thus making further submissions\nduplicates.\n\n# Submission process\nNote: Minor details of the submission process may change from time to time,\nplease make sure you check this page again for updates when you make a new\nsubmission.\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n* There is no patch commit in the mainline tree, and\n* The vulnerability is not disclosed in any form (e.g. there is no Syzkaller\n  report about the bug)\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although\n      the bug was disclosed by Syzkaller more than 30 days ago, there is no fix\n      and you convince the maintainers to fix the bug)\n\nThe submission process contains two stages. The purpose of the two-stage system\nis to make sure the vulnerability details are not shared with us before the\npatch is released but to still provide a way for 0-day vulnerability finders\nto prove that they found the vulnerability by submitting the flag to us\nin the first stage.\n\n### First stage\n\n1. Exploit the bug and capture the flag from the target environment (the flag is\n   a proof of successful exploitation).\n2. Compress the exploit and its source code as a .tar.gz filei, calculate its\n   SHA256 checksum.\n   * Save this exact file, you will need to send us this later.\n   * Try to keep this file to the minimum necessary, leave out large files like\n     e.g. vmlinux, bzImage as they can be downloaded separately if needed.\n3. Go to\n   [https://bughunters.google.com/report/vrp](https://bughunters.google.com/report/vrp)\n4. Sign in (this helps us identify you and send you a reward)\n5. In the \"Report Description\" field put a summary of the report – please\n   mention \"kvmCTF\", the time slot and the reward tier (e.g. `kvmCTF\n   2025_01_01_00_00: Relative Memory Write`)\n6. Enter `Linux Kernel` into the affected product / website field, select the\n   `My product is not listed in the product list` checkbox.\n7. Enter `kernel.org` into the URL field.\n8. Enter the following information in the `Please describe the technical details\n   of the vulnerability` field:\n   * The first line should be \"kvmCTF\"\n   * The second line should be \"Reward Tier: \" followed by the targeted reward\n     tier.\n   * The third line should be \"Email: \" followed by the email used to reserve\n     the time slot.\n   * The fourth line should be \"Time slot: \" followed by the reserved time slot\n     (e.g. 2025/01/01 00:00).\n   * The fifth line should be the \"Flag: \" followed by the flag you obtained.\n     If your exploit is a \"Denial of Service\" and crashed the host, please fill\n     this line with \"Flag: Host Crash\".\n9. Enter the hash computed at step 2 in the `Please briefly explain who can\n   exploit the vulnerability, and what they gain when doing so` field.\n11. Select `Privilege Escalation` as the Vulnerability Type.\n12. Select `No, this vulnerability is private`.\n13. Select `Yes` on `Do you plan to disclose this bug publicly?`\n14. Set the date (at most 14 days after the date of filling this report) that\n    you plan to report the vulnerability.\n15. You can optionally donate twice the reward to charity if you select\n      \"Donate to charity and double my reward.\"\n16. Submit your report.\n17. We will review your submission and contact you when to proceed with the rest\n    of the steps.\n\n### Second stage\n1. Report the vulnerability to security@kernel.org within 7 days of receiving\n   the notice.\n   * Note: A submission will be considered ineligible if it turns out that this\n     requirement was not respected.\n2. Make sure that you are credited in the Reported-By tag of the patch that\n   fixes the bug.\n   * Use the same email address in the Reported-By tag as you use in the\n     bughunters website or the one you used to reserve the time slot.\n   * If there is no Reported-By tag on a patch commit, then a 0-day submission\n     is eligible only if this is the first 0-day submission for that patch\n     commit (based on the submission time of the bughunters report).\n   * If it is unclear who reported the bug, then we reserve the right to\n     invalidate the submission, change the reward or make a custom decision at\n     our discretion. \n3. Wait for the patch to land in a release candidate on the mainline tree (and\n    tagged in Git).\n4. Contact us within 7 days and provide the following details:\n    * The patch commit, CVE (optionally, if it is already known) and the exact\n    target(s) (e.g. `LTS 6.1.74`).\n    * Describe the vulnerability in detail (see the Documentation requirements\n    section)\n    * Reuse the contents of your `vulnerability.md` if it already exists (see\n    the \"Exploit PR file structure\" section).\n5. Wait for Linux to publish a CVE or publish the vulnerability details\n   yourself on [oss-sec](https://seclists.org/oss-sec/).\n6. After the vulnerability is disclosed via a CVE or oss-sec, wait 30 days\n    (recommendation, see notes below) and send us your exploit with the\n    description of the exploitation technique via a PR to [the security-research\n    repo](https://github.com/google/security-research/) (see required structure\n    below).\n7. Make sure that the PR is merged (this is a requirement to get a reward).\n\nA submission will not be eligible as a 0-day submission if the vulnerability\ndetails were reported somewhere (e.g. Pwn2Own) other than\n[security@kernel.org](mailto:security@kernel.org).\n\n## Note about making the exploit public\nYou have to publish your exploit within 90 days of disclosing the vulnerability\nto be eligible for a reward.\n\nWe recommend publishing the exploit 30 days after\nthe vulnerability was disclosed. This gives the industry time to apply patches.\nRead our stance on the topic in [Google’s disclosure\npolicy](http://about.google/appsecurity).\n\nWe only process submissions after the exploit is public (and we can only issue\nrewards when the submission was processed), but not sooner than 30 days after\nthe vulnerability disclosure.\n\nIf you publish sooner than 30 days, you won’t get the reward faster. If you want\nto delay the publication (disclose later than 30 days but within the 90 days\nwindow), you could do that, but you would get the money later (we want to\nencourage you to publish the exploit details sooner than later).\n\n## Exploit PR file structure\nThe submission should be put into the `pocs/linux/kvmctf/<cve>/` folder within\nthe [security-research](https://github.com/google/security-research/) repo,\nwhere:\n* cve is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\nFor example: `pocs/linux/kvmctf/CVE-2023-1872/`.\n\nThe structure of this submission folder should be:\n* `original.tar.gz`\n  * Required, contains the original exploit. Its hash must match the one\n    submitted initially via the submission (this hash cannot be modified later).\n* `docs/vulnerability.md`\n  * Required, description of the vulnerability.\n* `docs/exploit.md`\n  * Required, description of how the exploits work.\n* `exploit/6.1.x/`\n  * `exploit.c`\n    * Required, source code of the exploit.\n  * `exploit`\n    * Required, compiled exploit which stole the flag.\n  * `Makefile`\n    * Required, includes target (`exploit`) to compile exploit.c into exploit\n      and target (`run`) to run the exploit on the live instance (which steals\n      the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries\nfor the exploit). The exploit can be split into multiple files, although we\nprefer if it is kept as a single `.c` file.\n# Documentation requirements\n## Vulnerability\nIf possible please include the following information in the vulnerability\ndetails:\n* Commit which introduced the vulnerability\n* Commit which fixed the vulnerability\n* Affected kernel versions\n* Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n## Exploit\nMake sure that the exploit is properly commented and the accompanying exploit.md\nincludes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the\nfollowing activities, include them as a separate step:\n* Triggering a vulnerability.\n* Converting one attack primitive into another.\n* Spraying or grooming the heap.\n* Leaking host information.\n* Overwriting host memory.\n* Getting RIP control.\n* Executing interesting post-RIP approaches.\n* Doing a major step towards a successful exploitation which is not listed\n  above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role\n(e.g. vulnerable object, victim object), and their respective caches (e.g.\n`kmalloc-1k`) and the used field members of the object (e.g. getting RIP control\nvia `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n* Non-trivial constant values should be explained, for example:\n  * Flag and enumeration values\n  * Field offsets\n  * Function addresses\n  * ROP gadget offsets\n* ROP chain items should be explained.\n  * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to\n    e.g. `call_usermodehelper_exec`.\n* Fake structures should be explained; i.e. which structure is created and what\n  fields are set.\n  * E.g. `data[0x8] = base + 0x123456;` -> data variable contains a fake `struct\n    file`, the field at 0x8 offset is a `f_inode` pointer which is set to ...\n* Usage of multi-threading (or forking)\n  * Why is it needed?\n  * If a race condition is exploited, then what code paths are raced.\n  * Communication and synchronization between two the threads (e.g. what data\n    was sent between the threads, and when the threads are waiting on each\n    other).\n* Separation between code parts which are needed to trigger the vulnerability\n  and parts which are part of the exploitation process (spraying, heap grooming,\n  cross-cache, converting one primitive to another).\n* Any action (e.g. MSR update, hypercall) where a side-effect of the action is\n  used for the exploit and not the main functionality, for example:\n  * Hypercall used for spraying a specific structure, not for its main purpose.\n  * Change of some MSR value with a non-trivial effect.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the\ntime during your testing).\n# Additional information\n## Program change notifications and communication\nWe announce program changes through\n[#kvmctf-announcements](https://discord.gg/gBrsEgvAUk) Discord channel. This\ndocument is updated to reflect the current set of kvmCTF rules.\n\nIf you have any question regarding kvmCTF, feel free to ask on the\n[#kvmctf](https://discord.gg/c8drZpwYBn) Discord channel.\n","isInternal":false,"tokens":4671,"sizeBytes":18872},{"name":"rules.md","path":"v8ctf/rules.md","rawUrl":"https://raw.githubusercontent.com/google/security-research/HEAD/v8ctf/rules.md","title":"v8ctf - Development & Architecture Rules","category":"root-instruction","format":"markdown","content":"# v8CTF Rules\n\nThe v8CTF is a part of the [Google VRP](https://g.co/vrp) in which we reward successful exploitation attempts against a V8 version running on our infrastructure.\nThis program is orthogonal to the [Chrome VRP](https://g.co/chrome/vrp), if you find a bug and exploit it, you can submit the bug to the Chrome VRP and use the exploit for the v8CTF.\n\n## Rules\n\nThe following rules apply to the eligibility of exploits starting with M156:\n* Your exploit needs to exfiltrate the flag from our v8CTF infrastructure.\n* Every bug used in the submission (e.g. V8 memory corruption, V8 sandbox) must have been found by you as the first reporter.\n* Exploits need to be reasonably fast and stable. We accept submissions with an average runtime of less than 1 minute and at least 80% success rate.\n* Valid submissions get a reward of $20,000.\n\n## Submission Process\n\n1. Make sure to report the bugs first to the [Chrome VRP](https://g.co/chrome/vrp).\n1. Exploit the bug and capture the flag from our v8CTF environment.\n    1. The flag format is v8CTF{$unix_timestamp:$signature}.\n1. Create a .tar.gz archive of your exploit and calculate its sha256, e.g. with `sha256sum exploit.tar.gz`.\n    1. Provide an archive that can be verified using our reproduction setup (see [kctf/challenge-templates/repro-chrome/README.md](kctf/challenge-templates/repro-chrome/README.md))\n    1. Please double check that the exploit doesn’t have any external dependencies.\n1. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLScoWE5-XoF85dXMjWKTIrJGTEfCybFaktsYZMCZ86iFPrW8Ew/viewform?usp=header_link) with the flag and the exploit sha256 sum. You need to use the same email address you reported the bugs from.\n1. A bug in the Google Issue Tracker will be filed on your behalf. Attach the exploit matching the sha256 sum and a short write up to the bug.\n1. Give us a few days to validate your submission.\n\n## Setup\n\nYou can find a description of our v8CTF infrastructure in the [README](https://github.com/google/security-research/blob/master/v8ctf/README.md).\n\n## Communication\n\nWe have two discord channels set up on the [Capture The Flag](https://discord.gg/hqcSdTk6vm) server:\n\n* #v8ctf-announcements: will be used for announcements such as changes to the rules and the start time for n-day submissions.\n* #v8ctf: is open to all. If you have any questions, please ask here.\n\nAnd you can find data about existing submissions in [this sheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vTWvO0tFNl8fJbOmTV1nwGJi4fAy5pDg-6DsHARRubj8I6c7_11RQ36Jv735zj9EQggz6AWjAOaebJh/pubhtml).\n","isInternal":false,"tokens":713,"sizeBytes":2576},{"name":"README.md","path":"analysis/kernel/dashboard/tools/README.md","rawUrl":"https://raw.githubusercontent.com/google/security-research/HEAD/analysis/kernel/dashboard/tools/README.md","title":"tools Documentation","category":"plugin-manifest","format":"markdown","content":"# Kernel Call-Graph & Privilege Analysis CLI Tools (`tools/`)\n\nThis directory contains three command-line analysis tools (`find_paths.py`, `inspect_calls.py`, `check_privilege.py`) backed by shared domain libraries under `tools/lib/` (`callgraph.py`, `metadata.py`, `privilege.py`) that query the unified Dashboard SQLite database (`kernel_dashboard-<version>.db`) and optional Syzkaller coverage database to answer core vulnerability triage and attack-surface questions:\n\n1. **`find_paths.py`** — *\"Which syscalls or non-syscall entry points can reach this line or function, and what is the call chain?\"*\n2. **`inspect_calls.py`** — *\"Who calls this function (directly, asynchronously, or via `ops_targets` function pointers), and what does it call?\"*\n3. **`check_privilege.py`** — *\"Is this line or function reachable from an unprivileged user, or is every path gated by `capable()` / `ns_capable()` / Kconfig / runtime tunables?\"*\n\n```text\n                                                      ┌──► find_paths.py       (Syscall/entry-to-target shortest call chains + coverage)\n                                                      │\nkernel_dashboard-<ver>.db ──► tools/lib/{callgraph,        ┼──► inspect_calls.py    (1-hop & multi-hop caller/callee neighborhood + ops dispatch)\n                                    metadata,         │\n                                    privilege}.py     └──► check_privilege.py  (Dijkstra capability-gate & 2D entry precondition verdict)\n```\n\n---\n\n## 1. Architecture, Shared Libraries & Required SQLite Tables\n\n### Shared Library Modules (`tools/lib/`)\n- **`tools/lib/callgraph.py`**: Database connection & index management (`open_databases`, `ensure_indexes`, `table_exists`, `clean_file_path`), function and span lookup (`get_enclosing_function`, `get_function_by_name`, `load_functions_for_files`), reverse call-graph traversal across direct calls, `ops_targets` function pointers, and `async_edges` callbacks (`get_callers`, `iter_pruned_callers`), syscall and non-syscall entry discovery (`is_syscall_root`, `load_entry_roots`, `is_entry_root`, `load_target_reachable_set`, `get_reachable_syscalls`, `get_reachable_entries`, `select_eval_roots`), and tree banner helpers (`format_root_label`, `format_target_banner`).\n- **`tools/lib/metadata.py`**: Kconfig `#ifdef`/`#else`/Makefile precondition extraction and symbol metadata lookup (`get_line_configs`, `get_kconfig_metadata`), Syzkaller dynamic coverage correlation (`get_syzkaller_coverage`, `is_line_covered_by_syzkaller`), target and call-path step builders (`build_target_info`, `make_path_step`, `make_caller_step`), and shared CLI argument parsing (`add_common_cli_args`, `handle_common_cli_setup`, `extract_reachability_cli_kwargs`).\n- **`tools/lib/privilege.py`**: Dynamic `CAP_*` constant resolution (`load_capability_map`, `format_capability`, `deduplicate_gates`, `add_call_span`), polymorphic `conditions` table parsing across direct call gates, `__guarded_span__:<ns_scope>` line-span guards, `__genl_ops_gate__:<ns_scope>` Generic Netlink flags, `sysctl`, and `module_param` tunables (`load_condition_gates`, `get_call_site_gates`, `load_runtime_tunables`), the 2D entry-precondition model (`get_entry_precondition`), and capability verdict classification (`classify_gates`).\n\n### CLI Tools Summary\n\n| Tool | Core Question Answered | SQLite Tables Used | Output Formats |\n| :--- | :--- | :--- | :--- |\n| **`find_paths.py`** | Finds shortest call paths from `__do_sys_*` syscalls and non-syscall `entry_node` roots to a target `(file, line)` or `function`, traversing direct calls (`edges`), indirect struct function-pointer calls (`ops_targets`), and asynchronous registrations (`async_edges`). | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `tree` (default), `list`, `json`, `mermaid` |\n| **`inspect_calls.py`** | Inspects 1-hop or multi-hop callers (`--callers`), callees (`--callees`), or both (`--both`), resolving indirect ops table dispatches (e.g., `inode_operations->link`, `file_operations->unlocked_ioctl`) and annotating call-site capability gates. | `function_locations`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations` (+ optional Syzkaller DB) | `summary` (default), `tree`, `list`, `json` |\n| **`check_privilege.py`** | Crosses static call paths with control-flow-dominating capability checks (`conditions` + `macroinvocation_locations`), Kconfig guards, runtime tunables, and 2D non-syscall entry floors using a weighted Dijkstra search (`COST_UNGATED=1`, `COST_NS_CAPABLE=10,000`, `COST_CAPABLE=1,000,000`) to find the least-privileged path to a target. | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `summary` (default), `tree`, `paths`, `json` |\n\n> **Automatic Index Creation**: On first run, `callgraph.ensure_indexes()` automatically verifies and creates lightweight traversal indexes (`idx_fl_file_lines`, `idx_fl_name`, `idx_sn_fn`, `idx_sn_sys`, `idx_loc_msg`, `idx_loc_uri_line`, `idx_edges_target`, `idx_edges_source`, `idx_ops_target`, `idx_ops_exprcall`, plus conditional indexes on `configs`, `kconfig_symbols`, `async_edges`, and `entry_node`) if they do not already exist. You can also pre-build them explicitly with `--ensure-indexes`.\n\n---\n\n## 2. Tool 1: Syscall Reachability Path Finder (`find_paths.py`)\n\n### Key Features\n- **Target Resolution**: Accepts either `--file <path> --line <num>` (resolving the enclosing kernel function automatically) or `--function <name>`.\n- **Hybrid Call-Graph Traversal**: Combines direct call edges (`locations` / `edges` from `all-calls.ql`) with indirect ops-table dispatch edges (`ops_targets` from `ops_edges.ql`).\n- **Syzkaller Coverage Correlation**: When `--syzkaller-db` is provided, annotates each step along the call path with dynamic coverage indicators and optional Syzkaller reproduction programs (`--show-repro`).\n\n### CLI Usage & Examples\n```bash\n# Find the shortest syscall path to a specific source line:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --file mm/shmem.c --line 1500\n\n# Find paths to a function across all reachable syscalls (up to 10 syscalls):\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10\n\n# Pin reachability search to a specific syscall and output a Mermaid diagram:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function unix_stream_connect \\\n  --syscall connect \\\n  --format mermaid\n```\n\n---\n\n## 3. Tool 2: Call-Graph Neighborhood Inspector (`inspect_calls.py`)\n\n### Key Features\n- **Bidirectional Inspection**:\n  - `--callers`: Discovers direct callers and indirect callers invoking the function via `ops_targets` struct fields (e.g., `vfs_link` $\\rightarrow$ `inode_operations.link` $\\rightarrow$ `shmem_link`).\n  - `--callees`: Discovers direct calls made by the function and indirect `ExprCall` sites within the function, listing candidate target implementations.\n  - `--both` (default): Displays full 360-degree caller and callee context.\n- **Multi-Hop Expansion**: Use `--depth <N>` to expand caller/callee trees up to `N` hops.\n- **Inline Capability Gate Annotations**: Automatically highlights whether any caller or outgoing call site is guarded by `capable()` / `ns_capable()`.\n\n### CLI Usage & Examples\n```bash\n# Inspect both callers and callees of a function (1-hop summary):\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link\n\n# Inspect 2 hops of callers for a specific file and line in JSON format:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1250 \\\n  --callers --depth 2 --format json\n\n# Show all indirect dispatch candidates without truncation:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function vfs_ioctl \\\n  --callees --all\n```\n\n---\n\n## 4. Tool 3: Capability & Unprivileged Reachability Analyzer (`check_privilege.py`)\n\n### Key Features\n- **Least-Privileged Path Discovery**: Uses Dijkstra's algorithm over the reverse call graph with edge weights penalizing capability checks (`COST_UNGATED = 1`, `COST_NS_CAPABLE = 10,000`, `COST_CAPABLE = 1,000,000`). If *any* unprivileged path exists alongside gated paths, `check_privilege.py` surfaces the ungated route first.\n- **Symbolic `CAP_*` Resolution**: Correlates `conditions` check locations with `macroinvocation_locations` to resolve integer capability constants (`21`, `12`, etc.) into human-readable names (`CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, etc.).\n- **Intra-Procedural Target Line Checks**: When given `--file` and `--line` inside a function body, checks both inter-procedural gates on callers and intra-procedural `IfStmt` capability checks dominating the target line within the enclosing function.\n- **Four Clear Security Verdicts**:\n  - `REACHABLE WITH NO PRIVILEGE (UNGATED)`\n  - `REACHABLE BEHIND USER NAMESPACE CAPABILITY` (`ns_capable(...)`)\n  - `REACHABLE, BUT ONLY BEHIND <CAP_NAME>` (`capable(CAP_SYS_ADMIN)`, etc.)\n  - `UNREACHABLE`\n\n### `conditions` Table Schema & Polymorphic `call` Column Contract\nThe `conditions` table (`condition_type`, `condition_loc`, `if_stmt_loc`, `condition_arg`, `call`, `call_loc`) generated by `queries/condition-graph-direct.ql` uses a polymorphic `call` / `call_loc` encoding to represent three distinct kinds of gate records without schema changes:\n1. **Direct Call-Site Gate Rows**: `call` is the CodeQL call string (e.g., `\"call to foo\"` or `\"call to expression\"`), and `call_loc` is the source location of the guarded `Call` expression.\n2. **Guarded Line-Span Rows (`__guarded_span__:<ns_scope>`)**: `call` starts with `\"__guarded_span__:\"` followed by the classified user-namespace scope (`init_user_ns`, `net_ns`, `s_user_ns`, `mnt_ns`, `f_cred`, or `user_ns`), and `call_loc` encodes the controlled line interval `[minLine, maxLine]` as `\"file://<path>:<minLine>:1:<maxLine>:1\"`. Consumers (`load_condition_gates` in `tools/lib/privilege.py`) use this span to gate any direct call, indirect `ops_targets` dispatch, or `--line` target falling within `[minLine, maxLine]`.\n3. **Generic Netlink Declarative Gate Rows (`__genl_ops_gate__:<ns_scope>`)**: `call` starts with `\"__genl_ops_gate__:\"` followed by `init_user_ns` (`GENL_ADMIN_PERM`) or `net_ns` (`GENL_UNS_ADMIN_PERM`), and `call_loc` encodes the gated Netlink handler function's body span `[startLine, endLine]`. Consumers attach these gates directly to the registered handler function.\n\n> **Caveat on Single-Interval `[minLine, maxLine]` Span Approximation**: Controlled spans for `IfStmt` capability guards are represented as a single contiguous line interval `[minLine, maxLine]` (bounded for early-abort `if (!capable(...)) return/goto` guards by `min(labelLine) - 1`, the next `switch` case label, or the enclosing block end). If an aborting branch has multiple `goto` targets, `min(labelLine)` is a conservative lower bound; conversely, unusual intra-procedural control flow (such as backward jumps or intervening unconditional paths inside the same block) is approximated by line containment rather than full basic-block post-dominance.\n\n### CLI Usage & Examples\n```bash\n# Check whether a specific kernel line is reachable without privileges:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1420\n\n# Evaluate privilege requirements across all reachable syscalls:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10 \\\n  --format tree\n\n# Print compact arrow-separated call chains with gate annotations:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link \\\n  --format paths\n```\n\n---\n\n## 5. Running Unit Tests & Linting (`tools/tests/`)\n\nThe `tools/tests/` directory contains unit and synthetic-database integration tests for both the shared libraries (`test_lib.py`) and all three CLI tools (`test_find_paths.py`, `test_inspect_calls.py`, `test_check_privilege.py`), sharing schema fixtures from `tools/tests/fixtures.py`:\n\n```bash\n# Run the full unit test suite:\npytest tools/tests -v\n\n# Format and run pylint (80-column Google style, zero lint suppressions):\npyformat -i -s 4 tools/*.py tools/lib/*.py tools/tests/*.py\npylint --max-line-length=80 tools/*.py tools/lib/*.py tools/tests/*.py\n```\n\n---\n\n## 6. Known Limitations & Design Tradeoffs\n\n- **Out-of-Line Capability Wrapper Depth (`queries/condition_graph.qll`)**: `DirectCapabilityCheck` resolves up to 2 hops of out-of-line helper wrappers (`f -> g -> capable`). Deeper capability chains (3+ hops) where intermediate helpers perform side effects before returning a boolean are intentionally not treated as pure capability predicates.\n- **Conjunctive vs. Disjunctive Guarded Spans (`__guarded_span__`)**: When a single `if` condition combines multiple capability checks (`if (!capable(A) && !capable(B)) return -EPERM` vs. `if (!capable(A) || !capable(B)) return -EPERM`), both capability checks share the same guarded line span `[minLine, maxLine]`. Consumers union the gates covering a call site rather than solving full boolean SAT over compound branch conditions.\n- **Build-Configuration Scope (`kernel_dashboard-<ver>.db`)**: The CodeQL database reflects a single compiled kernel configuration and architecture (`x86_64`). Code inside `#ifdef CONFIG_X` blocks disabled in that build is not compiled into the AST and will not appear in `function_locations`, `edges`, or `conditions` (though raw `#ifdef` ranges remain visible in `configs`).\n- **User-Namespace Scope (`ns_capable`) is Necessary, Not Sufficient**: When a path is gated by `ns_capable(ns->user_ns, CAP_*)` (`REACHABLE BEHIND USER NAMESPACE CAPABILITY`), unprivileged user-namespace reachability requires *both* the `ns_capable` check and that the object/subsystem can be instantiated inside a non-`init_net` / non-`init_user_ns` namespace. If an earlier caller or ops table binds the path to `init_net` or `init_user_ns`, global privilege is still required.\n- **BPF Verifier Program-Type Allowlists (`bpf_entry`)**: Reachability from a `bpf_entry` root assumes `BPF_PROG_LOAD` succeeds (`CAP_BPF` or `kernel.unprivileged_bpf_disabled=0`), but individual BPF helpers and kfuncs are further restricted by per-program-type verifier allowlists (`get_func_proto` / `btf_kfunc_id_set`).\n- **Bridge Traversal Depth Cap (`--max-bridge-depth`)**: Backward root collection (`get_reachable_syscalls`, `get_reachable_entries`) caps indirect/async bridge hops at `--max-bridge-depth` (default `6`) and direct hops at `20`. If traversal hits this cap with unexplored callers remaining and no root is found, `check_privilege.py` reports `UNREACHABLE (DEPTH-LIMITED)` (`target_info[\"depth_truncated\"] = True`).\n- **Async Context Bucketing (`queries/async_edges.qll`)**: `perf_event.overflow_handler` (PMI/NMI), `kprobe`/`kretprobe` handlers (trap context), and `ftrace_ops.func` (arbitrary function-entry context) are grouped under `mechanism = \"irq\"` (`context = \"hardirq\"`) for backward call-graph bridging.\n\n","isInternal":false,"tokens":3827,"sizeBytes":15444}],"systemPromptSnippet":"<yakaai_skills repo=\"google/security-research\">\n<!-- File: kernelctf/rules.md (Tokens: ~4782 | Category: root-instruction) -->\n# kernelCTF rules\n\n> [!WARNING]\n> These rules apply from 2026-09-04, you can find [the previous version of the rules on Github](https://github.com/google/security-research/blob/88ec1d535b0d147eec404751f0457e7162450aed/kernelctf/rules.md).\n\nkernelCTF is a part of the [Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules) and is focused on making exploiting Linux kernel vulnerabilities harder by inviting security researchers to demonstrate their exploitation techniques on 0-day vulnerabilities.\n\nWe are asking researchers to publish their submissions, helping the community to learn from each other's techniques.\n\n# Reward structure and targets\n\n## Target: Hardened (`hardened-v1-7.x`)\n\nThe target is Linux 7.2-rc5 (x86_64) based on the [COS kernel config](https://cos.googlesource.com/third_party/kernel/+/refs/heads/cos-6.12/arch/x86/configs/lakitu_defconfig) with additional hardenings and a reduced attack surface.\n\n### Configuration changes\n\n* **Mitigation features enabled:**\n  * `kCFI` + `IBT`\n  * `SLAB_VIRTUAL=y`\n  * `KMALLOC_PARTITION_TYPED=y`\n  * `SLAB_MERGE_DEFAULT=n`\n\n* **Disabled subsystems (reduced attack surface):**\n  * `CONFIG_IO_URING=n`\n  * `CONFIG_USER_NS=n`\n  * `CONFIG_TLS=n`\n  * `CONFIG_CRYPTO_USER_API_AEAD=n`\n  * `CONFIG_BPF_UNPRIV_DEFAULT_OFF=y`\n  * `CONFIG_AF_UNIX_OOB=n`\n\n### Requirements\n\n* **Stability:** Submissions must achieve at least 70% stability based on 20 exploit runs. The exploit needs to run within 5 minutes, otherwise it will be counted as a failed run when we measure stability.\n* **Vulnerability works on LTS 6.12:** The underlying vulnerability must be triggerable on the latest LTS 6.12. When executed with the `--vuln-trigger` flag on LTS 6.12, the exploit must crash the system (a full LPE chain is not required on LTS).\n\n### Reward\n\n* **$71,337**\n\nWe have retired separate target tiers and bonus categories in favor of a single static reward per eligible exploit.\n\n### Target updates\n\nOnly one submission is eligible per kernel version. The 7.2 version will generally remain fixed due to the `SLAB_VIRTUAL` porting requirement. However, we will update the LTS version (used for vulnerability freshness testing) when we release new slots, upgrading the LTS kernel version every 2-4 weeks on average.\n\n## Submission evaluation system\n\nOn weeks when a slot is released, the submission window will open on Monday at 12:00 UTC and close on Friday at 12:00 UTC, at which point the winning submission will be selected.\n\nSubmissions are evaluated on both speed and reliability over **20 exploit runs**. The server extracts the pre-compiled `exploit` binary from your `.tar.gz` archive and executes it (without recompilation), awarding a final score based on the following formula:\n\n$$\\text{Score} = 2 \\times (\\text{Stability \\%}) + \\max(100 - \\text{AVG}(\\text{time\\_in\\_sec}), 0)$$\n\n* **Maximum Possible Score:** 300 pts (100% stability, 0-second runtime).\n* **Minimum Passing Score:** 140 pts (70% stability, $\\ge 100$-second runtime).\n* **Winning Criterion:** The submission with the highest overall score wins the reward. If there is a tie, the submission with the earlier flag capture time (the timestamp recorded in the flag) wins. If there is still a tie, the earlier form submission time will be used.\n* **Submission Limits:** Only one submission per researcher is eligible per slot. Researchers may evaluate on the server up to 10 times per slot based on their email address (you can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6)), but only their latest submission before the Friday 12:00 UTC deadline will be used. Please do not use different email addresses to bypass this requirement as payment providers will flag this and it will block the reward payment.\n\n### Connecting to the evaluation system\n\nYou can interact with the evaluation server using `client/cli.py` (from the `server/` directory):\n\n```bash\n# Evaluate exploit against remote server (default target)\npython3 client/cli.py exploit_binary --action evaluate --researcher-token <token>\n```\n\nYou can get your researcher token via [this form](https://forms.gle/Dd8pk7AXW843eDGP6).\n\nIf you do not want to run a full evaluation and only want to test a part of the exploit, you can use:\n* `--action lpe-test`: Test local privilege escalation and flag retrieval on the hardened target.\n* `--action vuln-test`: Test triggering the vulnerability (kernel crash) on the LTS target.\n\nFor a raw interactive connection to the service menu, you can use `client/connect.sh`:\n\n```bash\n./client/connect.sh\n```\n\nFor the full guide and options (such as local testing), see the [`server/README.md` (\"Using `client/cli.py`\" section)](server/README.md#using-clientclipy).\n\nYou can use a maximum of two connections per IPv4 address and the connection will be closed after 60 minutes. Evaluation runs are limited to 10 attempts per researcher per open slot based on your email address.\n\nThe source code running on the server is available [on our Github](https://github.com/google/security-research/tree/master/kernelctf/server).\n\n## Additional eligibility rules\n\n### Vulnerability dupes\n\nOnly the first submission for a vulnerability is eligible for a reward.\n\nThis means: if a vulnerability is exploited on the target by Researcher A, it can no longer be exploited on the target (even if the LTS kernel version is updated).\n\nIf a patch commit fixes multiple vulnerabilities (e.g. by backporting a new version of a component to the stable tree), we assume the root cause is the same and we consider further submissions as duplicates.\n\nIf the same vulnerability is fixed in multiple patch commits (e.g. in commit A in the mainline tree and separately in commit B in the stable tree), then we still consider it as the same vulnerability, thus making further submissions duplicates.\n\nIf you are unsure about eligibility, contact us on the [#kernelctf Discord channel](https://discord.gg/ECS5VnJZys) before making the submission.\n\n# Submission process\n\n_Note: Minor details of the submission process may change from time to time, please make sure you check this page again for updates when you make a new submission._\n\nBefore you start the submission process, please make sure that the submission window is currently open (Monday 12:00 UTC to Friday 12:00 UTC on slot release weeks) and that you are submitting for the active target version by checking the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) or the evaluation server.\n\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n\n  * There is no patch commit in the mainline tree, and\n\n  * The vulnerability is not disclosed in any form (e.g. there is no Syzkaller report about the bug)\n\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although the bug was disclosed by Syzkaller more than 30 days ago, there is no fix and you convince the maintainers to fix the bug)\n\nA submission will not be eligible if the vulnerability details were reported somewhere (e.g. Pwn2Own) other than [security@kernel.org](mailto:security@kernel.org).\n\nThe submission process has two stages to make sure the vulnerability details are not shared with us before the patch is released:\n\n## Stage 1: Initial submission (before patch release)\n\n  0. Compress the compiled `exploit` binary, its source code, and all the build files as a `.tar.gz` file.\n\n     * Save this exact file, you will need to send us this later.\n\n     * Note: The evaluation system will extract the `exploit` binary from the archive and run it without recompilation.\n\n     * Try to keep this file to the minimum necessary, leave out large files like e.g. `vmlinux`, `bzImage` as they can be downloaded separately if needed.\n\n  1. Upload the compressed file to the evaluation system, which will provide a flag upon successful exploitation.\n\n  2. Submit the flag on [this form](https://forms.gle/cjA9M1ZNUSc6adGE6) with the additional details requested.\n\n     * Save the link as you’ll have to edit this form later.\n\n  3. Check the [public spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml) after submitting the form and confirm that your submission was added and your score is correct.\n\n  4. Wait until Friday at 12:00 UTC and verify that your submission won the current slot. If there are multiple submissions for the same slot, another submission with a higher score may take the slot (in case of a tie, the earlier flag capture time, and then the earlier form submission time wins). If your submission does not win, you must wait for a new, empty slot to be released (start from Step 1).\n\n  5. Report the vulnerability to security@kernel.org within 7 days of winning the slot.\n\n     * Note: A submission will be considered ineligible if it turns out that this requirement was not respected.\n\n  6. If you are not the author of the patch that fixes the bug, make sure that you are credited in the `Reported-By` tag of the patch that fixes the bug.\n\n     * Do not include the `Reported-By` tag if you both discovered the flaw and authored the patch.\n\n     * Use the same email address in the `Reported-By` tag as you use for the form submission or in the \"Email address used in Reported-By tag\" field of the form.\n\n     * If there is no `Reported-By` tag on a patch commit, then a 0-day submission is eligible only if this is the first 0-day submission for that patch commit (based on the first stage submission date).\n\n     * If it is unclear who reported the bug, then the reward can be split (multiple reporters), reduced, or invalidated at our discretion.\n\n  7. Wait for the patch to land in a release candidate on the mainline tree (and be tagged in Git) or be committed to a stable tree, whichever happens first.\n\n     * Make sure that the patch correctly fixes the vulnerability you reported. If it does not, report the issue to the kernel and wait for the correct patch commit, otherwise your submission will be ineligible.\n\n## Stage 2: After patch release\n\n  1. Modify the form within 7 days by following the previously saved link and fill out the extra vulnerability details.\n\n     * If the 7-day deadline is missed, then the submission may be considered ineligible for reward at our discretion.\n\n  2. Send us your exploit within 90 days with the description of the exploitation technique via a PR to [the security-research repo](https://github.com/google/security-research/) (see required structure below). This is a mandatory step for us to start verification of the vulnerability.\n\n  3. Once the PR's GitHub Actions (GHA) checks pass and we confirm the submission exploits the claimed vulnerability, you receive the first half of the reward. After a manual review and the PR is merged, the second half is issued.\n\n### Google Bughunter's website registration and reward payments\n\nSubmitting reports via [bughunters.google.com](https://bughunters.google.com/) prior to PR submission is **no longer required**; an issue will automatically be created on the portal for winning entries.\n\nHowever, to collect your payout reward:\n  1. You must register once on [bughunters.google.com](https://bughunters.google.com/) so we can send you the reward.\n  2. We highly recommend changing your payment provider to BugCrowd for a better payment process. You can [read here](https://bughunters.google.com/blog/6483936851394560/announcing-bugcrowd-as-a-new-bughunters-google-com-payment-option) how.\n  3. If you'd like to split your reward with another researcher, please [read our FAQ regarding the process](https://bughunters.google.com/about/frequently-asked-questions#q-is-it-possible-to-split-the-reward-for-a-report-with-other-researchers-for-example-if-we-collaborated-on-the-report-).\n\n## Note about making the exploit public\n\nYou have to publish your exploit within 90 days of submitting the patch commit via the Google Form to be eligible for a reward.\n\nWe only process submissions after the exploit becomes public. We can only issue the first half of the reward once the PR passes the automated checks and the initial review confirms that the submission exploits the claimed vulnerability. Following an in-depth review and successful quality checks, the PR will be merged, and the second half of the reward will be issued.\n\nIf you want to delay the publication (within the 90 days window), you could do that, but you would get the money later (we want to encourage you to publish the exploit details sooner than later).\n\nThe above is about the exploit itself, not the vulnerability. We automatically share some limited vulnerability details of the submissions on our [public submission spreadsheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vS1REdTA29OJftst8xN5B5x8iIUcxuK6bXdzF8G1UXCmRtoNsoQ9MbebdRdFnj6qZ0Yd7LwQfvYC2oF/pubhtml?gid=2095368189), as a CVE, once you submit the extra vulnerability details via the form in Stage 2.\n\n## Exploit PR file structure\n\nThe submission should be put into the `pocs/linux/kernelctf/<cve>_<targets>/` folder within the [security-research repo](https://github.com/google/security-research/), where:\n\n  * `cve` is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\n\n  * `<targets>` is the list of targets separated by underscore (`_`)\n\n    * Valid target names: `hardened-v1-7.x`\n\n  * If there is a conflicting submission directory name, then append `_2` (or `_3`, etc.) after the directory name.\n\nFor example: `pocs/linux/kernelctf/CVE-2023-1872_hardened-v1-7.x/`.\n\nThe structure of this submission folder should be:\n\n  * `original.tar.gz`\n\n    * Required; contains the original exploit (compiled binary and source code used to build it). Its hash must match the one calculated by the evaluation system and encoded within the flag you submitted in the form.\n\n  * `metadata.json`\n\n    * Required, structured metadata information following [this JSON schema (version 3)](metadata.schema.v3.json).\n\n  * `docs/vulnerability.md`\n\n    * Required, description of the vulnerability.\n\n  * `docs/exploit.md`\n\n    * Required, description of how the exploits work. If exploits are too different, then it can also be put next to exploits.\n\n  * `exploit/hardened-v1-7.x/`<br>\n\n    * `exploit.c`\n       * Required, source code of the exploit.\n\n    * `exploit`\n       * Required, compiled exploit which stole the flag.\n\n    * `Makefile`\n       * Required, includes target (`exploit`) to compile `exploit.c` into `exploit` and target (`run`) to run the exploit on the live instance (which steals the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries for the exploit). The exploit can be split into multiple files, although we prefer if it is kept as a single `.c` file.\n\n## Documentation requirements\n\n### Vulnerability\n\nIf possible please include the following information in the vulnerability details:\n\n  * Requirements to trigger the vulnerability:\n    * [Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html)\n    * Kernel configuration\n\n  * Commit which introduced the vulnerability\n\n  * Commit which fixed the vulnerability\n\n  * Affected kernel versions\n\n  * Affected component, subsystem\n\n  * Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n\n  * Which syscalls or syscall parameters are needed to be blocked to prevent triggering the vulnerability? (If there is any easy way to block it.)\n\n### Exploit\n\nEnsure that exploit code follows [kernelCTF code style guide](https://google.github.io/security-research/kernelctf/style_guide).\n\nMake sure that the exploit is properly commented and the accompanying `exploit.md` includes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the following activities, include them as a separate step:\n\n  * Triggering a vulnerability.\n\n  * Converting one attack primitive into another.\n\n  * Spraying or grooming the heap.\n\n  * Executing cross-cache attack.\n\n  * Leaking information (e.g. heap pointer, kASLR base address).\n\n  * Overwriting kernel memory.\n\n  * Getting RIP control.\n\n  * Executing interesting post-RIP approaches.\n\n  * Doing a major step towards a successful exploitation which is not listed above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role (e.g. vulnerable object, victim object), and their respective caches (e.g. `kmalloc-1k`) and the used field members of the object (e.g. getting RIP control via `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n\n  * Non-trivial constant values should be explained, for example:\n    * Flag and enumeration values\n    * Field offsets\n    * Function addresses\n    * ROP gadget offsets\n\n  * ROP chain items should be explained.\n    * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to e.g. `call_usermodehelper_exec`.\n\n  * Fake structures should be explained; i.e. which structure is created and what fields are set.\n    * E.g. `data[0x8] = base + 0x123456`; -> data variable contains a fake `struct file`, the field at 0x8 offset is a `f_inode` pointer which is set to `...`\n\n  * Usage of multi-threading (or forking)\n    * Why is it needed?\n    * If a race condition is exploited, then what code paths are raced.\n    * Communication and synchronization between the two threads (e.g. what data was sent between the threads, and when the threads are waiting on each other).\n\n  * Environmental requirements\n    * If specific climit or cpu affinity settings are required, then explain why they are needed.\n    * Which limit the exploit runs into using the default settings.\n\n  * Namespaces usage and why are they required.\n\n  * Separation between code parts which are needed to trigger the vulnerability and parts which are part of the exploitation process (spraying, heap grooming, cross-cache, converting one primitive to another).\n\n  * Any action (e.g. syscall) where a side-effect of the action is used for the exploit and not the main functionality, for example:\n    * Syscall used for spraying a specific structure, not for its main purpose.\n    * Some calls (e.g. `sleep`) used for a specific side-effect which is not trivial see.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the time during your testing).\n\nYour exploit must support the `--vuln-trigger` argument, which triggers the underlying vulnerability to crash the system (ideally under KASAN) on other versions without requiring a full LPE chain. To stay within [vuln-verify workflow](https://github.com/google/security-research/blob/master/.github/workflows/kernelctf-vuln-verify.yaml) time limits, this mode should skip non-essential steps such as KASLR prefetching.\n\n# Additional information\n\n## Program change notifications and communication\n\nWe announce program changes through [#kernelctf-announcements](https://discord.gg/yXue2RwDEA) Discord channel. All major changes are going to be announced 2 weeks in advance before they take an effect. This document will be updated to reflect current set of kernelCTF rules.\n\n## Questions about program\n\nIf you have any questions regarding kernelCTF, check [the FAQ page](faq.md) and feel free to ask on the [#kernelctf](https://discord.gg/ECS5VnJZys) Discord channel.\n\n## Non-kernel vulnerabilities\n\nIf you are submitting a non-kernel vulnerability affecting our kCTF VRP cluster, please submit the vulnerability to our [kCTF VRP](https://google.github.io/kctf/vrp.html).\n\n## Legal points\n\nkernelCTF is part of Google VRP, so its rules including but not limited to [these Legal points](https://bughunters.google.com/about/rules/google-friends/google-and-alphabet-vulnerability-reward-program-vrp-rules#legal-points) apply.\n\nYou should understand that we can cancel the program at any time and the decision as to whether or not to pay a reward and how much has to be entirely at our discretion.\n\n<!-- File: kvmctf/rules.md (Tokens: ~4671 | Category: root-instruction) -->\n# kvmCTF Overview\n\nkvmCTF is a part of the\n[Google VRP](https://bughunters.google.com/about/rules/6625378258649088/google-and-alphabet-vulnerability-reward-program-vrp-rules)\nand is focused on eliminating VM-reachable Kernel-based Virtual Machine (KVM)\nvulnerabilities in upstream mainline kernel. We invite security researchers to\ndemonstrate their bug hunting and exploitation techniques on an LTS kernel version.\nEventually we might add experimental mitigations to KVM that we would like to see\nif and how researchers can bypass them.\n\nWe are additionally asking researchers to publish their submissions, helping the\ncommunity to learn from each other’s techniques.\n\n# Competition Rules\n\n## Target: Linux LTS KVM\n\nThe host runs v6.1.74 and runs on an Intel(R) Xeon(R) Gold 5222 CPU @ 3.80GHz.\nParticipants will have the option to select whether they want the host to run\nwith `CONFIG_KASAN` disabled or enabled. The complete setup of the host can be\ndownloaded\n[here](https://storage.googleapis.com/kvmctf/latest.tar.gz) in a\ngzip format and contains the following:\n* The kernel patch we applied on the kernel tree.\n* The kernel configuration files.\n* The gcc and binutils versions used to compile the kernel.\n* The virsh version used to run the VM.\n* The produced `vmlinux` images.\n* The produced `bzImage` binaries.\n* The produced `ko` module binaries.\n* The `qemu-kvm` command used to run the guest.\n\nParticipants will be connected to a Debian 12.5 (bookworm) guest that runs on a\n`v6.1.0-21` kernel compiled with the default Debian config.\n\nThe goal is to perform a successful guest-to-host attack. Currently we do not\nreward QEMU, host-to-KVM or CPU/DRAM/HW-based vulnerabilities.\n\nNote: Although our testing environment runs an LTS kernel, vulnerabilities must\nbe reproducible in the upstream Linux mainline master branch to be eligible.\nVulnerabilities that only exist in downstream backports or older LTS trees are\nout of scope.\n\n## Rewards\n| Tier                   | Reward   |\n|------------------------| -------- |\n| Full VM escape         | $250,000 |\n| Arbitrary memory write | $100,000 |\n| Arbitrary memory read  | $50,000  |\n| Relative memory write  | $50,000  |\n| Denial of Service      | $20,000  |\n| Relative memory read   | $10,000  |\n\n\nNote that the above rewards do not stack. For instance, if you submit a full VM\nescape exploit that takes advantage of an arbitrary memory read you will be\nrewarded with $250,000, not $250,000 + $50,000.\n\n## Flags\nYour submission should contain proof that your exploit succeeded in one of the\nabove tiers. This is achieved by providing each tier's corresponding flag (a\n64-bit number). Note that providing the flag does **not** automatically\nguarantee the corresponding reward, your exploit must take advantage of a\nvulnerability of that tier. For instance, if you use an arbitrary memory read\nvulnerability to read the arbitrary memory write flag, you will **not** be\ncompensated with the arbitrary memory write reward.\n### RCE flag\nTo obtain this flag your exploit should read the contents of the\n`/root/rce_flag` file in the host file system.\n### Arbitrary memory accesses\nFor the arbitrary memory write tier your exploit should overwrite the contents\nof the write flag address (its default value is `0xdeadbeef41424344` so your\nexploit should modify any or all of its bits), whereas for the arbitrary memory\nread tier your exploit should read the contents of the read flag address. The\ntarget addresses (both virtual and physical) can be found in the\n`/root/addresses` file in the guest file system. For the arbitrary memory write\ntier, your exploit should first overwrite the contents of the write flag address\nand then call hypercall `#100` which will return the corresponding flag in\n`RAX`. For the arbitrary memory read tier, the flag is the contents of the read\nflag address.\n### Relative memory accesses\nThe relative memory read and relative memory write are available only if the\nhost runs with `CONFIG_KASAN` enabled. The mapping between the KASAN violations\nand the reward tiers is the following:\n\n| Operation     | KASAN violation         | Reward Tier           |\n| ------------  | ----------------------- | ------------------    |\n| Memory Write  | use-after-free          | Relative memory write |\n| Memory Write  | out-of-bounds           | Relative memory write |\n| Memory Write  | slab-out-of-bounds      | Relative memory write |\n| Memory Write  | global-out-of-bounds    | Relative memory write |\n| Memory Write  | stack-out-of-bounds     | Relative memory write |\n| Memory Write  | alloca-out-of-bounds    | Relative memory write |\n| Memory Write  | vmalloc-out-of-bounds   | Relative memory write |\n| Memory Write  | user-memory-access      | Relative memory write |\n| Memory Write  | wild-memory-access      | Relative memory write |\n| *             | double-free             | Relative memory write |\n| *             | invalid-free            | Relative memory write |\n| Memory Read   | use-after-free          | Relative memory read  |\n| Memory Read   | out-of-bounds           | Relative memory read  |\n| Memory Read   | slab-out-of-bounds      | Relative memory read  |\n| Memory Read   | global-out-of-bounds    | Relative memory read  |\n| Memory Read   | stack-out-of-bounds     | Relative memory read  |\n| Memory Read   | alloca-out-of-bounds    | Relative memory read  |\n| Memory Read   | vmalloc-out-of-bounds   | Relative memory read  |\n| Memory Read   | user-memory-access      | Relative memory read  |\n| Memory Read   | wild-memory-access      | Relative memory read  |\n| *             | null-ptr-deref          | Denial of Service     |\n\nFor the relative memory write tier, your exploit should first perform the\noperation that produces the KASAN violation and then call hypercall `#101` which\nwill return the flag in `RAX`.\nSimilarly, for the relative memory read tier, your exploit should first perform\nthe operation to produce the KASAN violation and then call hypercall `#102`\nwhich will return the flag in `RAX`.\n\n### Denial of Service\nThe Denial of Service tier rewards exploits that induce a `null-ptr-deref` KASAN\nviolation, or that make the host panic or otherwise\ncrash. In the former case, your exploit should first perform the operation to\nproduce the KASAN violation and then call hypercall `#103` which will return the\nflag in `RAX`.\nIn the latter case, you do not need to provide a flag: after executing your\nexploit and crashing the host just specify in the submission form that you are\nsubmitting a Denial of Service exploit.\n\n## Process\nTo try your exploit on our server you will have to reserve a time slot. You can\ndo it using the command:\n\n``socat FILE:`tty`,raw,echo=0 ssl:kvmctf.ctfcompetition.com:1337,cafile=server_cert.pem``\n\n`server_cert.pem`:\n```\n-----BEGIN CERTIFICATE-----\nMIIBXTCCAQ+gAwIBAgIUcU+vah86fZls1/1gfDBEotuQTi4wBQYDK2VwMCQxIjAg\nBgNVBAMMGWt2bWN0Zi5jdGZjb21wZXRpdGlvbi5jb20wHhcNMjQwMzI2MTc1MjUw\nWhcNMzQwMzI0MTc1MjUwWjAkMSIwIAYDVQQDDBlrdm1jdGYuY3RmY29tcGV0aXRp\nb24uY29tMCowBQYDK2VwAyEAWiQBWTd51Qej7hPho7MtkLu6gtOJhyGM8lVr4dlf\nr6OjUzBRMB0GA1UdDgQWBBSGgjr7/oy7f72v7fjy+Boe7dmTaTAfBgNVHSMEGDAW\ngBSGgjr7/oy7f72v7fjy+Boe7dmTaTAPBgNVHRMBAf8EBTADAQH/MAUGAytlcANB\nAKwz9VdZ1e81DObSMEmeAm5mBc+Hsu50etwjDQGAPMoag+qcPddvlmlxcmuKY4QO\nOzLhYAILFWvYJrT5uTF0FwU=\n-----END CERTIFICATE-----\n```\n\nand follow the prompts. Note that the reservations are done using the UTC time\nso please convert your desired time to UTC before reserving. You will need to\nprovide an email address and whether you want a KASAN-enabled host, and you will\nbe given a key (both in your terminal and in an email verification). To connect\nto the server during your reserved time slot you can use the same command as\nabove. You will be asked to provide the email address you used to reserve the\ntime slot and the key you received. After verification, you will be redirected\nto the server.\n\n## Additional eligibility rules\nOnly the first submission for a vulnerability is eligible for a reward.\nIf a patch commit fixes multiple vulnerabilities, we assume the root cause is the same\nand we consider further submissions as duplicates.\nIf the same vulnerability is fixed in multiple patch commits, then we\nstill consider it as the same vulnerability, thus making further submissions\nduplicates.\n\n# Submission process\nNote: Minor details of the submission process may change from time to time,\nplease make sure you check this page again for updates when you make a new\nsubmission.\nSubmissions can only target 0-day vulnerabilities.\n\nWe consider a bug 0-day if at the time of the submission:\n* There is no patch commit in the mainline tree, and\n* The vulnerability is not disclosed in any form (e.g. there is no Syzkaller\n  report about the bug)\n    * Note: We may still consider a bug 0-day at our discretion (e.g. although\n      the bug was disclosed by Syzkaller more than 30 days ago, there is no fix\n      and you convince the maintainers to fix the bug)\n\nThe submission process contains two stages. The purpose of the two-stage system\nis to make sure the vulnerability details are not shared with us before the\npatch is released but to still provide a way for 0-day vulnerability finders\nto prove that they found the vulnerability by submitting the flag to us\nin the first stage.\n\n### First stage\n\n1. Exploit the bug and capture the flag from the target environment (the flag is\n   a proof of successful exploitation).\n2. Compress the exploit and its source code as a .tar.gz filei, calculate its\n   SHA256 checksum.\n   * Save this exact file, you will need to send us this later.\n   * Try to keep this file to the minimum necessary, leave out large files like\n     e.g. vmlinux, bzImage as they can be downloaded separately if needed.\n3. Go to\n   [https://bughunters.google.com/report/vrp](https://bughunters.google.com/report/vrp)\n4. Sign in (this helps us identify you and send you a reward)\n5. In the \"Report Description\" field put a summary of the report – please\n   mention \"kvmCTF\", the time slot and the reward tier (e.g. `kvmCTF\n   2025_01_01_00_00: Relative Memory Write`)\n6. Enter `Linux Kernel` into the affected product / website field, select the\n   `My product is not listed in the product list` checkbox.\n7. Enter `kernel.org` into the URL field.\n8. Enter the following information in the `Please describe the technical details\n   of the vulnerability` field:\n   * The first line should be \"kvmCTF\"\n   * The second line should be \"Reward Tier: \" followed by the targeted reward\n     tier.\n   * The third line should be \"Email: \" followed by the email used to reserve\n     the time slot.\n   * The fourth line should be \"Time slot: \" followed by the reserved time slot\n     (e.g. 2025/01/01 00:00).\n   * The fifth line should be the \"Flag: \" followed by the flag you obtained.\n     If your exploit is a \"Denial of Service\" and crashed the host, please fill\n     this line with \"Flag: Host Crash\".\n9. Enter the hash computed at step 2 in the `Please briefly explain who can\n   exploit the vulnerability, and what they gain when doing so` field.\n11. Select `Privilege Escalation` as the Vulnerability Type.\n12. Select `No, this vulnerability is private`.\n13. Select `Yes` on `Do you plan to disclose this bug publicly?`\n14. Set the date (at most 14 days after the date of filling this report) that\n    you plan to report the vulnerability.\n15. You can optionally donate twice the reward to charity if you select\n      \"Donate to charity and double my reward.\"\n16. Submit your report.\n17. We will review your submission and contact you when to proceed with the rest\n    of the steps.\n\n### Second stage\n1. Report the vulnerability to security@kernel.org within 7 days of receiving\n   the notice.\n   * Note: A submission will be considered ineligible if it turns out that this\n     requirement was not respected.\n2. Make sure that you are credited in the Reported-By tag of the patch that\n   fixes the bug.\n   * Use the same email address in the Reported-By tag as you use in the\n     bughunters website or the one you used to reserve the time slot.\n   * If there is no Reported-By tag on a patch commit, then a 0-day submission\n     is eligible only if this is the first 0-day submission for that patch\n     commit (based on the submission time of the bughunters report).\n   * If it is unclear who reported the bug, then we reserve the right to\n     invalidate the submission, change the reward or make a custom decision at\n     our discretion. \n3. Wait for the patch to land in a release candidate on the mainline tree (and\n    tagged in Git).\n4. Contact us within 7 days and provide the following details:\n    * The patch commit, CVE (optionally, if it is already known) and the exact\n    target(s) (e.g. `LTS 6.1.74`).\n    * Describe the vulnerability in detail (see the Documentation requirements\n    section)\n    * Reuse the contents of your `vulnerability.md` if it already exists (see\n    the \"Exploit PR file structure\" section).\n5. Wait for Linux to publish a CVE or publish the vulnerability details\n   yourself on [oss-sec](https://seclists.org/oss-sec/).\n6. After the vulnerability is disclosed via a CVE or oss-sec, wait 30 days\n    (recommendation, see notes below) and send us your exploit with the\n    description of the exploitation technique via a PR to [the security-research\n    repo](https://github.com/google/security-research/) (see required structure\n    below).\n7. Make sure that the PR is merged (this is a requirement to get a reward).\n\nA submission will not be eligible as a 0-day submission if the vulnerability\ndetails were reported somewhere (e.g. Pwn2Own) other than\n[security@kernel.org](mailto:security@kernel.org).\n\n## Note about making the exploit public\nYou have to publish your exploit within 90 days of disclosing the vulnerability\nto be eligible for a reward.\n\nWe recommend publishing the exploit 30 days after\nthe vulnerability was disclosed. This gives the industry time to apply patches.\nRead our stance on the topic in [Google’s disclosure\npolicy](http://about.google/appsecurity).\n\nWe only process submissions after the exploit is public (and we can only issue\nrewards when the submission was processed), but not sooner than 30 days after\nthe vulnerability disclosure.\n\nIf you publish sooner than 30 days, you won’t get the reward faster. If you want\nto delay the publication (disclose later than 30 days but within the 90 days\nwindow), you could do that, but you would get the money later (we want to\nencourage you to publish the exploit details sooner than later).\n\n## Exploit PR file structure\nThe submission should be put into the `pocs/linux/kvmctf/<cve>/` folder within\nthe [security-research](https://github.com/google/security-research/) repo,\nwhere:\n* cve is the CVE number of the vulnerability in the format `CVE-yyyy-NNNNN`\nFor example: `pocs/linux/kvmctf/CVE-2023-1872/`.\n\nThe structure of this submission folder should be:\n* `original.tar.gz`\n  * Required, contains the original exploit. Its hash must match the one\n    submitted initially via the submission (this hash cannot be modified later).\n* `docs/vulnerability.md`\n  * Required, description of the vulnerability.\n* `docs/exploit.md`\n  * Required, description of how the exploits work.\n* `exploit/6.1.x/`\n  * `exploit.c`\n    * Required, source code of the exploit.\n  * `exploit`\n    * Required, compiled exploit which stole the flag.\n  * `Makefile`\n    * Required, includes target (`exploit`) to compile exploit.c into exploit\n      and target (`run`) to run the exploit on the live instance (which steals\n      the flag).\n\nYou can add additional files (e.g. images for writeup or supporting libraries\nfor the exploit). The exploit can be split into multiple files, although we\nprefer if it is kept as a single `.c` file.\n# Documentation requirements\n## Vulnerability\nIf possible please include the following information in the vulnerability\ndetails:\n* Commit which introduced the vulnerability\n* Commit which fixed the vulnerability\n* Affected kernel versions\n* Cause (UAF, BoF, race condition, double free, refcount overflow, etc)\n## Exploit\nMake sure that the exploit is properly commented and the accompanying exploit.md\nincludes all the details, making it easy to understand what the exploit does.\n\nGive a step-by-step overview of the exploitation process. When describing the\nfollowing activities, include them as a separate step:\n* Triggering a vulnerability.\n* Converting one attack primitive into another.\n* Spraying or grooming the heap.\n* Leaking host information.\n* Overwriting host memory.\n* Getting RIP control.\n* Executing interesting post-RIP approaches.\n* Doing a major step towards a successful exploitation which is not listed\n  above.\n\nIn the steps, include the affected objects (e.g. `struct file`), their role\n(e.g. vulnerable object, victim object), and their respective caches (e.g.\n`kmalloc-1k`) and the used field members of the object (e.g. getting RIP control\nvia `file->ops->ioctl`, overwriting `msg_msg->security`).\n\nWe expect the following parts to be properly documented:\n* Non-trivial constant values should be explained, for example:\n  * Flag and enumeration values\n  * Field offsets\n  * Function addresses\n  * ROP gadget offsets\n* ROP chain items should be explained.\n  * E.g. in `rop[0] = base + 0x123456;` explain that 0x123456 is resolved to\n    e.g. `call_usermodehelper_exec`.\n* Fake structures should be explained; i.e. which structure is created and what\n  fields are set.\n  * E.g. `data[0x8] = base + 0x123456;` -> data variable contains a fake `struct\n    file`, the field at 0x8 offset is a `f_inode` pointer which is set to ...\n* Usage of multi-threading (or forking)\n  * Why is it needed?\n  * If a race condition is exploited, then what code paths are raced.\n  * Communication and synchronization between two the threads (e.g. what data\n    was sent between the threads, and when the threads are waiting on each\n    other).\n* Separation between code parts which are needed to trigger the vulnerability\n  and parts which are part of the exploitation process (spraying, heap grooming,\n  cross-cache, converting one primitive to another).\n* Any action (e.g. MSR update, hypercall) where a side-effect of the action is\n  used for the exploit and not the main functionality, for example:\n  * Hypercall used for spraying a specific structure, not for its main purpose.\n  * Change of some MSR value with a non-trivial effect.\n\nIf possible, also include how stable your exploit is (e.g. it worked 90% of the\ntime during your testing).\n# Additional information\n## Program change notifications and communication\nWe announce program changes through\n[#kvmctf-announcements](https://discord.gg/gBrsEgvAUk) Discord channel. This\ndocument is updated to reflect the current set of kvmCTF rules.\n\nIf you have any question regarding kvmCTF, feel free to ask on the\n[#kvmctf](https://discord.gg/c8drZpwYBn) Discord channel.\n\n<!-- File: v8ctf/rules.md (Tokens: ~713 | Category: root-instruction) -->\n# v8CTF Rules\n\nThe v8CTF is a part of the [Google VRP](https://g.co/vrp) in which we reward successful exploitation attempts against a V8 version running on our infrastructure.\nThis program is orthogonal to the [Chrome VRP](https://g.co/chrome/vrp), if you find a bug and exploit it, you can submit the bug to the Chrome VRP and use the exploit for the v8CTF.\n\n## Rules\n\nThe following rules apply to the eligibility of exploits starting with M156:\n* Your exploit needs to exfiltrate the flag from our v8CTF infrastructure.\n* Every bug used in the submission (e.g. V8 memory corruption, V8 sandbox) must have been found by you as the first reporter.\n* Exploits need to be reasonably fast and stable. We accept submissions with an average runtime of less than 1 minute and at least 80% success rate.\n* Valid submissions get a reward of $20,000.\n\n## Submission Process\n\n1. Make sure to report the bugs first to the [Chrome VRP](https://g.co/chrome/vrp).\n1. Exploit the bug and capture the flag from our v8CTF environment.\n    1. The flag format is v8CTF{$unix_timestamp:$signature}.\n1. Create a .tar.gz archive of your exploit and calculate its sha256, e.g. with `sha256sum exploit.tar.gz`.\n    1. Provide an archive that can be verified using our reproduction setup (see [kctf/challenge-templates/repro-chrome/README.md](kctf/challenge-templates/repro-chrome/README.md))\n    1. Please double check that the exploit doesn’t have any external dependencies.\n1. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLScoWE5-XoF85dXMjWKTIrJGTEfCybFaktsYZMCZ86iFPrW8Ew/viewform?usp=header_link) with the flag and the exploit sha256 sum. You need to use the same email address you reported the bugs from.\n1. A bug in the Google Issue Tracker will be filed on your behalf. Attach the exploit matching the sha256 sum and a short write up to the bug.\n1. Give us a few days to validate your submission.\n\n## Setup\n\nYou can find a description of our v8CTF infrastructure in the [README](https://github.com/google/security-research/blob/master/v8ctf/README.md).\n\n## Communication\n\nWe have two discord channels set up on the [Capture The Flag](https://discord.gg/hqcSdTk6vm) server:\n\n* #v8ctf-announcements: will be used for announcements such as changes to the rules and the start time for n-day submissions.\n* #v8ctf: is open to all. If you have any questions, please ask here.\n\nAnd you can find data about existing submissions in [this sheet](https://docs.google.com/spreadsheets/d/e/2PACX-1vTWvO0tFNl8fJbOmTV1nwGJi4fAy5pDg-6DsHARRubj8I6c7_11RQ36Jv735zj9EQggz6AWjAOaebJh/pubhtml).\n\n<!-- File: analysis/kernel/dashboard/tools/README.md (Tokens: ~3827 | Category: plugin-manifest) -->\n# Kernel Call-Graph & Privilege Analysis CLI Tools (`tools/`)\n\nThis directory contains three command-line analysis tools (`find_paths.py`, `inspect_calls.py`, `check_privilege.py`) backed by shared domain libraries under `tools/lib/` (`callgraph.py`, `metadata.py`, `privilege.py`) that query the unified Dashboard SQLite database (`kernel_dashboard-<version>.db`) and optional Syzkaller coverage database to answer core vulnerability triage and attack-surface questions:\n\n1. **`find_paths.py`** — *\"Which syscalls or non-syscall entry points can reach this line or function, and what is the call chain?\"*\n2. **`inspect_calls.py`** — *\"Who calls this function (directly, asynchronously, or via `ops_targets` function pointers), and what does it call?\"*\n3. **`check_privilege.py`** — *\"Is this line or function reachable from an unprivileged user, or is every path gated by `capable()` / `ns_capable()` / Kconfig / runtime tunables?\"*\n\n```text\n                                                      ┌──► find_paths.py       (Syscall/entry-to-target shortest call chains + coverage)\n                                                      │\nkernel_dashboard-<ver>.db ──► tools/lib/{callgraph,        ┼──► inspect_calls.py    (1-hop & multi-hop caller/callee neighborhood + ops dispatch)\n                                    metadata,         │\n                                    privilege}.py     └──► check_privilege.py  (Dijkstra capability-gate & 2D entry precondition verdict)\n```\n\n---\n\n## 1. Architecture, Shared Libraries & Required SQLite Tables\n\n### Shared Library Modules (`tools/lib/`)\n- **`tools/lib/callgraph.py`**: Database connection & index management (`open_databases`, `ensure_indexes`, `table_exists`, `clean_file_path`), function and span lookup (`get_enclosing_function`, `get_function_by_name`, `load_functions_for_files`), reverse call-graph traversal across direct calls, `ops_targets` function pointers, and `async_edges` callbacks (`get_callers`, `iter_pruned_callers`), syscall and non-syscall entry discovery (`is_syscall_root`, `load_entry_roots`, `is_entry_root`, `load_target_reachable_set`, `get_reachable_syscalls`, `get_reachable_entries`, `select_eval_roots`), and tree banner helpers (`format_root_label`, `format_target_banner`).\n- **`tools/lib/metadata.py`**: Kconfig `#ifdef`/`#else`/Makefile precondition extraction and symbol metadata lookup (`get_line_configs`, `get_kconfig_metadata`), Syzkaller dynamic coverage correlation (`get_syzkaller_coverage`, `is_line_covered_by_syzkaller`), target and call-path step builders (`build_target_info`, `make_path_step`, `make_caller_step`), and shared CLI argument parsing (`add_common_cli_args`, `handle_common_cli_setup`, `extract_reachability_cli_kwargs`).\n- **`tools/lib/privilege.py`**: Dynamic `CAP_*` constant resolution (`load_capability_map`, `format_capability`, `deduplicate_gates`, `add_call_span`), polymorphic `conditions` table parsing across direct call gates, `__guarded_span__:<ns_scope>` line-span guards, `__genl_ops_gate__:<ns_scope>` Generic Netlink flags, `sysctl`, and `module_param` tunables (`load_condition_gates`, `get_call_site_gates`, `load_runtime_tunables`), the 2D entry-precondition model (`get_entry_precondition`), and capability verdict classification (`classify_gates`).\n\n### CLI Tools Summary\n\n| Tool | Core Question Answered | SQLite Tables Used | Output Formats |\n| :--- | :--- | :--- | :--- |\n| **`find_paths.py`** | Finds shortest call paths from `__do_sys_*` syscalls and non-syscall `entry_node` roots to a target `(file, line)` or `function`, traversing direct calls (`edges`), indirect struct function-pointer calls (`ops_targets`), and asynchronous registrations (`async_edges`). | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `tree` (default), `list`, `json`, `mermaid` |\n| **`inspect_calls.py`** | Inspects 1-hop or multi-hop callers (`--callers`), callees (`--callees`), or both (`--both`), resolving indirect ops table dispatches (e.g., `inode_operations->link`, `file_operations->unlocked_ioctl`) and annotating call-site capability gates. | `function_locations`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations` (+ optional Syzkaller DB) | `summary` (default), `tree`, `list`, `json` |\n| **`check_privilege.py`** | Crosses static call paths with control-flow-dominating capability checks (`conditions` + `macroinvocation_locations`), Kconfig guards, runtime tunables, and 2D non-syscall entry floors using a weighted Dijkstra search (`COST_UNGATED=1`, `COST_NS_CAPABLE=10,000`, `COST_CAPABLE=1,000,000`) to find the least-privileged path to a target. | `function_locations`, `syscall_node`, `entry_node`, `locations`, `edges`, `ops_targets`, `async_edges`, `conditions`, `macroinvocation_locations`, `configs`, `kconfig_symbols` (+ optional Syzkaller DB) | `summary` (default), `tree`, `paths`, `json` |\n\n> **Automatic Index Creation**: On first run, `callgraph.ensure_indexes()` automatically verifies and creates lightweight traversal indexes (`idx_fl_file_lines`, `idx_fl_name`, `idx_sn_fn`, `idx_sn_sys`, `idx_loc_msg`, `idx_loc_uri_line`, `idx_edges_target`, `idx_edges_source`, `idx_ops_target`, `idx_ops_exprcall`, plus conditional indexes on `configs`, `kconfig_symbols`, `async_edges`, and `entry_node`) if they do not already exist. You can also pre-build them explicitly with `--ensure-indexes`.\n\n---\n\n## 2. Tool 1: Syscall Reachability Path Finder (`find_paths.py`)\n\n### Key Features\n- **Target Resolution**: Accepts either `--file <path> --line <num>` (resolving the enclosing kernel function automatically) or `--function <name>`.\n- **Hybrid Call-Graph Traversal**: Combines direct call edges (`locations` / `edges` from `all-calls.ql`) with indirect ops-table dispatch edges (`ops_targets` from `ops_edges.ql`).\n- **Syzkaller Coverage Correlation**: When `--syzkaller-db` is provided, annotates each step along the call path with dynamic coverage indicators and optional Syzkaller reproduction programs (`--show-repro`).\n\n### CLI Usage & Examples\n```bash\n# Find the shortest syscall path to a specific source line:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --file mm/shmem.c --line 1500\n\n# Find paths to a function across all reachable syscalls (up to 10 syscalls):\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10\n\n# Pin reachability search to a specific syscall and output a Mermaid diagram:\npython3 -m tools.find_paths \\\n  --db /path/to/kernel_dashboard.db \\\n  --function unix_stream_connect \\\n  --syscall connect \\\n  --format mermaid\n```\n\n---\n\n## 3. Tool 2: Call-Graph Neighborhood Inspector (`inspect_calls.py`)\n\n### Key Features\n- **Bidirectional Inspection**:\n  - `--callers`: Discovers direct callers and indirect callers invoking the function via `ops_targets` struct fields (e.g., `vfs_link` $\\rightarrow$ `inode_operations.link` $\\rightarrow$ `shmem_link`).\n  - `--callees`: Discovers direct calls made by the function and indirect `ExprCall` sites within the function, listing candidate target implementations.\n  - `--both` (default): Displays full 360-degree caller and callee context.\n- **Multi-Hop Expansion**: Use `--depth <N>` to expand caller/callee trees up to `N` hops.\n- **Inline Capability Gate Annotations**: Automatically highlights whether any caller or outgoing call site is guarded by `capable()` / `ns_capable()`.\n\n### CLI Usage & Examples\n```bash\n# Inspect both callers and callees of a function (1-hop summary):\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link\n\n# Inspect 2 hops of callers for a specific file and line in JSON format:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1250 \\\n  --callers --depth 2 --format json\n\n# Show all indirect dispatch candidates without truncation:\npython3 -m tools.inspect_calls \\\n  --db /path/to/kernel_dashboard.db \\\n  --function vfs_ioctl \\\n  --callees --all\n```\n\n---\n\n## 4. Tool 3: Capability & Unprivileged Reachability Analyzer (`check_privilege.py`)\n\n### Key Features\n- **Least-Privileged Path Discovery**: Uses Dijkstra's algorithm over the reverse call graph with edge weights penalizing capability checks (`COST_UNGATED = 1`, `COST_NS_CAPABLE = 10,000`, `COST_CAPABLE = 1,000,000`). If *any* unprivileged path exists alongside gated paths, `check_privilege.py` surfaces the ungated route first.\n- **Symbolic `CAP_*` Resolution**: Correlates `conditions` check locations with `macroinvocation_locations` to resolve integer capability constants (`21`, `12`, etc.) into human-readable names (`CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, etc.).\n- **Intra-Procedural Target Line Checks**: When given `--file` and `--line` inside a function body, checks both inter-procedural gates on callers and intra-procedural `IfStmt` capability checks dominating the target line within the enclosing function.\n- **Four Clear Security Verdicts**:\n  - `REACHABLE WITH NO PRIVILEGE (UNGATED)`\n  - `REACHABLE BEHIND USER NAMESPACE CAPABILITY` (`ns_capable(...)`)\n  - `REACHABLE, BUT ONLY BEHIND <CAP_NAME>` (`capable(CAP_SYS_ADMIN)`, etc.)\n  - `UNREACHABLE`\n\n### `conditions` Table Schema & Polymorphic `call` Column Contract\nThe `conditions` table (`condition_type`, `condition_loc`, `if_stmt_loc`, `condition_arg`, `call`, `call_loc`) generated by `queries/condition-graph-direct.ql` uses a polymorphic `call` / `call_loc` encoding to represent three distinct kinds of gate records without schema changes:\n1. **Direct Call-Site Gate Rows**: `call` is the CodeQL call string (e.g., `\"call to foo\"` or `\"call to expression\"`), and `call_loc` is the source location of the guarded `Call` expression.\n2. **Guarded Line-Span Rows (`__guarded_span__:<ns_scope>`)**: `call` starts with `\"__guarded_span__:\"` followed by the classified user-namespace scope (`init_user_ns`, `net_ns`, `s_user_ns`, `mnt_ns`, `f_cred`, or `user_ns`), and `call_loc` encodes the controlled line interval `[minLine, maxLine]` as `\"file://<path>:<minLine>:1:<maxLine>:1\"`. Consumers (`load_condition_gates` in `tools/lib/privilege.py`) use this span to gate any direct call, indirect `ops_targets` dispatch, or `--line` target falling within `[minLine, maxLine]`.\n3. **Generic Netlink Declarative Gate Rows (`__genl_ops_gate__:<ns_scope>`)**: `call` starts with `\"__genl_ops_gate__:\"` followed by `init_user_ns` (`GENL_ADMIN_PERM`) or `net_ns` (`GENL_UNS_ADMIN_PERM`), and `call_loc` encodes the gated Netlink handler function's body span `[startLine, endLine]`. Consumers attach these gates directly to the registered handler function.\n\n> **Caveat on Single-Interval `[minLine, maxLine]` Span Approximation**: Controlled spans for `IfStmt` capability guards are represented as a single contiguous line interval `[minLine, maxLine]` (bounded for early-abort `if (!capable(...)) return/goto` guards by `min(labelLine) - 1`, the next `switch` case label, or the enclosing block end). If an aborting branch has multiple `goto` targets, `min(labelLine)` is a conservative lower bound; conversely, unusual intra-procedural control flow (such as backward jumps or intervening unconditional paths inside the same block) is approximated by line containment rather than full basic-block post-dominance.\n\n### CLI Usage & Examples\n```bash\n# Check whether a specific kernel line is reachable without privileges:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --file net/core/sock.c --line 1420\n\n# Evaluate privilege requirements across all reachable syscalls:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function sk_setsockopt \\\n  --all-syscalls --limit-syscalls 10 \\\n  --format tree\n\n# Print compact arrow-separated call chains with gate annotations:\npython3 -m tools.check_privilege \\\n  --db /path/to/kernel_dashboard.db \\\n  --function shmem_link \\\n  --format paths\n```\n\n---\n\n## 5. Running Unit Tests & Linting (`tools/tests/`)\n\nThe `tools/tests/` directory contains unit and synthetic-database integration tests for both the shared libraries (`test_lib.py`) and all three CLI tools (`test_find_paths.py`, `test_inspect_calls.py`, `test_check_privilege.py`), sharing schema fixtures from `tools/tests/fixtures.py`:\n\n```bash\n# Run the full unit test suite:\npytest tools/tests -v\n\n# Format and run pylint (80-column Google style, zero lint suppressions):\npyformat -i -s 4 tools/*.py tools/lib/*.py tools/tests/*.py\npylint --max-line-length=80 tools/*.py tools/lib/*.py tools/tests/*.py\n```\n\n---\n\n## 6. Known Limitations & Design Tradeoffs\n\n- **Out-of-Line Capability Wrapper Depth (`queries/condition_graph.qll`)**: `DirectCapabilityCheck` resolves up to 2 hops of out-of-line helper wrappers (`f -> g -> capable`). Deeper capability chains (3+ hops) where intermediate helpers perform side effects before returning a boolean are intentionally not treated as pure capability predicates.\n- **Conjunctive vs. Disjunctive Guarded Spans (`__guarded_span__`)**: When a single `if` condition combines multiple capability checks (`if (!capable(A) && !capable(B)) return -EPERM` vs. `if (!capable(A) || !capable(B)) return -EPERM`), both capability checks share the same guarded line span `[minLine, maxLine]`. Consumers union the gates covering a call site rather than solving full boolean SAT over compound branch conditions.\n- **Build-Configuration Scope (`kernel_dashboard-<ver>.db`)**: The CodeQL database reflects a single compiled kernel configuration and architecture (`x86_64`). Code inside `#ifdef CONFIG_X` blocks disabled in that build is not compiled into the AST and will not appear in `function_locations`, `edges`, or `conditions` (though raw `#ifdef` ranges remain visible in `configs`).\n- **User-Namespace Scope (`ns_capable`) is Necessary, Not Sufficient**: When a path is gated by `ns_capable(ns->user_ns, CAP_*)` (`REACHABLE BEHIND USER NAMESPACE CAPABILITY`), unprivileged user-namespace reachability requires *both* the `ns_capable` check and that the object/subsystem can be instantiated inside a non-`init_net` / non-`init_user_ns` namespace. If an earlier caller or ops table binds the path to `init_net` or `init_user_ns`, global privilege is still required.\n- **BPF Verifier Program-Type Allowlists (`bpf_entry`)**: Reachability from a `bpf_entry` root assumes `BPF_PROG_LOAD` succeeds (`CAP_BPF` or `kernel.unprivileged_bpf_disabled=0`), but individual BPF helpers and kfuncs are further restricted by per-program-type verifier allowlists (`get_func_proto` / `btf_kfunc_id_set`).\n- **Bridge Traversal Depth Cap (`--max-bridge-depth`)**: Backward root collection (`get_reachable_syscalls`, `get_reachable_entries`) caps indirect/async bridge hops at `--max-bridge-depth` (default `6`) and direct hops at `20`. If traversal hits this cap with unexplored callers remaining and no root is found, `check_privilege.py` reports `UNREACHABLE (DEPTH-LIMITED)` (`target_info[\"depth_truncated\"] = True`).\n- **Async Context Bucketing (`queries/async_edges.qll`)**: `perf_event.overflow_handler` (PMI/NMI), `kprobe`/`kretprobe` handlers (trap context), and `ftrace_ops.func` (arbitrary function-entry context) are grouped under `mechanism = \"irq\"` (`context = \"hardirq\"`) for backward call-graph bridging.\n</yakaai_skills>"}