
TL;DR
A ripgrep musl binary crashing during very-large searches turned out to be a suspected Linux 7.0 kernel race - a thread's own store vanishing mid-function. The reporter's instrumentation pinned it, and a kernel-hardening maintainer posted a one-line fix candidate for testing.
Ripgrep 15.2.0's musl build occasionally segfaults during very-large multi-threaded searches. That was the bug report, filed July 26 against the ripgrep issue tracker. What followed is the best kind of debugging saga: the reporter pinned the crash to an exact instruction sequence, eliminated every in-process explanation, and landed on a suspected Linux kernel bug introduced in the 7.0 series. On August 1, a kernel-hardening maintainer posted a one-line patch candidate based on an upstream kernel list analysis, and the reporter is testing it as of this writing.
The original report came from a developer who first hit the crash in the ripgrep binary bundled inside a popular AI coding tool, then reproduced it with the vanilla ripgrep 15.2.0 musl release - the bundled binary was byte-for-byte identical. The crash signature is a SIGSEGV inside musl's mallocng allocator, in a get_meta() integrity assertion, reached via calloc called from opendir while ripgrep's directory walker spawns threads.
Reproduction needs a genuinely large tree: about 20 GiB across 1.84 million files, searched in a loop for a literal string that is never present. On the reporter's 24-core Threadripper machine running openSUSE Tumbleweed's 7.0.12 kernel, the crash landed every 1 to 3 minutes, always early in the walk (about 1.6 seconds in, versus 7.6 seconds for a clean run). Two things stood out immediately: glibc builds never crashed, and four other machines - including a Threadripper 9970X that is a microarchitectural match for the original CPU - running kernels 6.8 through 6.19 never reproduced it. The bug tracked the kernel version, not the hardware.
The reporter then published a full analysis repository with instrumented builds, patches, and scripts. The key finding is a "self-tear": a thread stores a value into a freshly-faulted anonymous page inside musl's allocator, then reloads the same address about ten instructions later and reads zero.
The evidence chain is unusually rigorous:
closedir -> free -> munmap.The conclusion: the per-VMA-lock anonymous-fault fast path publishes a new PTE while a concurrent munmap is mid-teardown, and the TLB-shootdown IPI lands after the publish, transiently exposing a zero-page translation to a thread that just wrote there. A source-level diff across v6.19, v7.0, v7.1 and mainline pins the change on the munmap side: v7.0 (January 2026) reworked PTE-table reclaim during zap in three commits (4c640eb4181c, fb4ddf208511, eda8c5e77622), and that rework is absent from 6.19, present through 7.2-rc1, and matches the reproduce/no-reproduce machine split. The analysis is honest about confidence: the observed behavior is kernel-caused with high confidence; the specific commit is a strong correlation awaiting kernel review.
From the archive
Aug 1, 2026 • 11 min read
Aug 1, 2026 • 5 min read
Aug 1, 2026 • 7 min read
Aug 1, 2026 • 10 min read
On August 1, a maintainer known for a prominent kernel-hardening patch series posted a patch candidate on the issue, based on an upstream kernel list find by Andy Lutomirski: in mm/memory.c, the PTE-table-free call inside zap_pte_range passes the current PTE address where it should pass the range start. One line changes from pte_free_tlb(tlb, pmd_pgtable(pmdval), addr) to pte_free_tlb(tlb, pmd_pgtable(pmdval), start). The reporter is testing it against the 7.0 kernel now. As of publication the bug is not fixed in mainline.
The discussion around this story split into four distinct camps.
The first debated the writeup itself. The report and analysis are visibly LLM-assisted, and readers divided sharply: one side called the style unreadable and overwrought, the other called it close to the ideal bug report - detailed, organized, and self-verifying. The argument itself became a signal about how technical communication is changing.
The second camp argued kernel specifics. Several readers pointed out that an extra TLB flush is never an error - the CPU may flush whenever it likes - so the flush itself is not the bug; the mystery is how a zero-page PTE ends up present where it should not be. The reporter's prefault control experiment answered the deeper question of specificity, but the source-level mechanism remains the open item.
The third camp tried to make it a Rust-versus-C argument. That did not survive contact: the crash is in musl (C) and the kernel (C), the allocator that failed is C, and the exchange ended with the blunt observation that the bug is in the C code Rust interacts with.
The fourth camp surfaced the practical allocator gotcha: ripgrep sets jemalloc as its global allocator, but that override only covers Rust-side allocations. C library calls like opendir's calloc still run through musl mallocng, so the crash lived in an allocator most users never think about. And the original symptom - broken search inside an AI coding tool that bundles musl ripgrep - made the reach of static musl binaries concrete.
Three lessons worth keeping.
First, this is a masterclass in debugging an invisible race: instrument the allocator, split the store-to-reload window with probes, read pagemap as ground truth, use pre-faulting as a mechanism-based control, capture a core without tracing, then diff kernel versions. The whole playbook is in the analysis repo, reusable by anyone chasing a heisenbug. The investigation is a model of what a good bug report looks like when the reporter controls every variable.
Second, shipping static musl binaries means inheriting kernel bugs through libc paths you do not audit. Ripgrep is a fast, mature, massively deployed tool; its musl build is the default for containers and bundled tools. A race in kernel page-table teardown surfaced as a crash in a search tool, not in anything near the kernel. If you ship musl static builds, the calloc inside opendir is part of your surface area.
Third, for the Linux crowd, the v7.0 PTE-reclaim rework is the suspect and the fix may be one line. Kernel regressions this deep usually surface as heisenbugs months later, in userspace tools nobody expects to be crashy. When the reproducer is this tight and the kernel-version correlation this clean, the fix follows fast - the test is running now.
Read next
A use-after-free bug in the Linux kernel's real-time mutex implementation has existed since 2011. Researchers earned $92,337 from Google's kernelCTF for discovering and exploiting it.
7 min readOpen-source tool gives Claude Code, Codex, and other agents their own isolated Linux VM on your machine - network firewall included, no cloud account required.
6 min readGitHub open-sourced casefold, a Rust crate that folds the case of every byte Blackbird indexes at memory bandwidth. The counterintuitive trick: delete the early-exit, kill the branches, and fold Unicode as byte arithmetic.
8 min readTechnical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.
Open-source AI agent built in Rust, now governed by the Agentic AI Foundation at the Linux Foundation. Desktop app, CLI,...
View ToolPrivate local AI chatbot by Nomic. 250K+ monthly users, 65K GitHub stars. LocalDocs feature lets you chat with your own...
View ToolTerminal emulator built in Zig with platform-native UI and GPU acceleration. 2ms key-to-screen latency. Metal on macOS,...
View ToolOpen-source cloud sandboxes for AI agents. Isolated environments that start in under 200ms, run code in Python, JavaScri...
View ToolHold-to-record voice input on macOS, Linux, and Windows.
Claude CodeFilesystem and network isolation for Bash tool calls on Linux and macOS.
Claude CodeA complete, citation-backed Claude Code course with setup, prompting systems, MCP, CI, security, cost controls, and capstone workflows.
ai-development
GitHub open-sourced casefold, a Rust crate that folds the case of every byte Blackbird indexes at memory bandwidth. The...

A developer built a complete X11 server in 20,000 lines of assembly language using Claude as a compiler, running Firefox...

Days after getting caught uploading entire codebases to xAI servers, Grok Build is now open source on GitHub. The HN com...

Open-source tool gives Claude Code, Codex, and other agents their own isolated Linux VM on your machine - network firewa...

A use-after-free bug in the Linux kernel's real-time mutex implementation has existed since 2011. Researchers earned $92...

The HashiCorp co-founder explains why he chose Zig over Rust for Ghostty, the technical challenges of terminal emulator...

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.