|
|
Log in / Subscribe / Register

LWN.net Weekly Edition for April 23, 2026

Welcome to the LWN.net Weekly Edition for April 23, 2026

This edition contains the following feature content:

This week's edition also includes these inner pages:

  • Brief items: Brief news items from throughout the community.
  • Announcements: Newsletters, conferences, security updates, patches, and more.

Please enjoy this week's edition, and, as always, thank you for supporting LWN.net.

Comments (none posted)

Using LLMs to find Python C-extension bugs

By Jake Edge
April 21, 2026

The open-source world is currently awash in reports of LLM-discovered bugs and vulnerabilities, which makes for a lot more work for maintainers, but many of the current crop are being reported responsibly with an eye toward minimizing that impact. A recent report on an effort to systematically find bugs in Python extensions written in C has followed that approach. Hobbyist Daniel Diniz used Claude Code to find more than 500 bugs of various sorts across nearly a million lines of code in 44 extensions; he has been working with maintainers to get fixes upstream and his methodology serves as a great example of how to keep the human in the loop—and the maintainers out of burnout—when employing LLMs.

The numbers are fairly eye-opening: "575+ confirmed bugs (~10-15% false positive rate after review, ~140 reproduced from Python) and fixes already merged in 14 projects". The types of the bugs range widely: "from hard crashes and memory corruption to correctness issues and spec violations". Meanwhile, Diniz would like to work with maintainers to make the effort "more useful and scalable for maintainers"; the goal is to provide high-quality reports of "a large class of non-trivial bugs" that are difficult to find manually.

To do that, Diniz created a Claude Code plugin, cext-review-toolkit, that is tuned for Python-specific problems that might be found in C extensions, such as problems with reference counts, in handling the global interpreter lock (GIL), and with exception state. It uses "13 specialized analysis agents analyzing the C extension source code in parallel, with each agent targeting a different bug class".

Results

The lengthy report is worth reading in its entirety, but we will highlight a few parts of it here. The tool found lots of bugs, as noted, many of which resulted in bug reports and pull requests (PRs). There are lots of links to both for more than a dozen different C extension projects, including Cython, Guppy 3, regex, Pillow, and more. The Guppy 3 maintainer, YiFei Zhu, was highlighted for digging into the extensive report for that project, fixing 24 of 30 issues found, and finding "additional bugs the tool missed". In addition, the feedback provided in the umbrella issue for the findings was "invaluable", leading to improvements to the tools to reduce false positives.

The report describes how the tool and process work: the agents are run for a project, the findings are reviewed, pure-Python reproducers are created when possible, and then a report is shared with the maintainers via a secret GitHub gist. There is another document that describes techniques for creating reproducers in Python and the report itself describes the specific types of bugs targeted by the agents.

More importantly, given the widespread problems with maintainers being buried under slop bug reports and PRs, Diniz is clearly trying to ensure that his work is worthwhile to the projects:

Reports like these can be time and energy-intensive for maintainers to investigate. Historically, automated bug-finding tools have produced far more false positives than useful information, and AI can make those false positives look incredibly convincing.

[...] When a maintainer points out a false positive, I immediately update the agents' prompts so that specific pattern is avoided in the future.

Beyond polishing the tools, I try to communicate in a non-invasive, helpful manner. The maintainer always holds the reins: I ask them how they prefer to receive the information (an umbrella issue? individual issues? direct PRs? or do nothing at all) and let them decide exactly what to do with the findings.

There is more to the report, including an example of a bug and reproducer, a look at things that did not work, and so on. He ended with a set of questions for the community about whether it is useful, how to improve the tools and reports, and ideas for future tools. He mentions several other projects he is working on, such as an analysis tool aimed at C extensions with regard to free-threaded Python and another tool to analyze the CPython source code.

Reaction

The reaction has been quite positive—no surprise—with a few Python developers and maintainers popping up to talk about the experience and to suggest ideas for further refinements. James Parrott wondered about the number of bugs that would be eliminated if Rust had been used instead. Cython maintainer David Woods thought that Rust could eliminate things like reference-counting problems, but probably not the exception-handling bugs that were prevalent in the report for Cython. Diniz prompted Claude Code with the Rust question, which stated that 60-70% would not be prevented by Rust; Diniz cautioned that "given LLM's troubles with numbers and estimates, I wouldn't trust the percentages too much". But even the broad categorization may be suspect, as Matthias Urlichs said that he thought Rust could prevent more types of problems "if the Rust API is designed safely (in the Rust sense) instead of literally following the C API".

Parrott also suggested using the GitHub Actions system to reproduce the bugs. That would improve the tool's reports, which are less than ideal for him: "I don't want to have to read a huge machine generated report and work out what's what." Diniz was appreciative of the suggestions and thought that he could implement them relatively easily. In particular, customizing reports is already on his radar: "I'd like to tailor the reports to what maintainers need, some like having reproducers and suggested fixes, others would prefer just a short description and code locations."

Eric Soroos, one of the Pillow maintainers, thought it was "one of the better sets of reports that we've gotten about potential security/correctness issues". He did note that the coverage was incomplete, as he spotted similar bugs in related functions that were not found. Some of the bugs were difficult to reproduce because they required a memory-allocation failure to occur in a specific place, leading to a tooling suggestion:

It would be interesting as a test run to have a fuzzer that used coverage guidance to fail mallocs (or c-api python methods) to test the error handling in those cases. It would need to run under valgrind to catch memory leaks or invalid accesses. This could give better code coverage for the repetitive if(ptr==null) {free everything allocated in the function} c level error handling.

The idea was met with approval, so Soroos expanded on it some later in the thread.

The severity of the bugs being found, and whether they are worth the maintainer attention needed to fix them, may also factor into the question about the reports, as Maurycy Pawłowski-Wieroński noted. He had tried using Diniz's LLM tool for CPython and had mixed results, in part because some of the bugs are only reproducible in ways that users are unlikely to ever hit:

Unless the issue is critical (even if perfectly reproducible), many fixes are just distracting. Maintainers have their own projects, plans, schedules etc., and some pathological refleak is not really that important. I believe that such PRs used to make it in the past, because they were seen as an investment (education) in a potential maintainer, a future colleague. Now, it's "Contributor" badge hunting.

Diniz had a, seemingly characteristic, thoughtful reply, agreeing that "not all findings are worth fixing". Maintainers will draw their own lines of what warrants a fix, so he is not in a position to decide which bugs merit addressing. "The best I can do is offer a listing of what the tools find and let them decide what to fix." He said that so far he has not gotten much feedback on whether "tiny PRs targeting nits, leaks, etc." are valuable or not, but he is open to discussing it.

This issue is likely to recur. Finding and fixing memory-allocation-failure handling, for example, is certainly important, but it may well not be as important as other things that maintainers are trying to accomplish. Tuning LLMs to prioritize their reports based on the likelihood of real-world exploitation would be another helpful step. Those who are using these tools for ill are surely pointing them toward exploitable bugs; LLM providers could potentially use those prompts (or share them) for defensive purposes. The LLM providers just might have their own tools and models that could be loosed on such a task as well.

Keeping maintainers fully in control is perhaps the most important element of this effort; giving them the ability to opt out is particularly key. There is a balance to be struck there, of course, because there may be bugs found that need escalation even when the project and its maintainers are not interested in the machine-generated reports. These are the early days for LLM bug-finding—and machines can generate far more reports than mere humans can process—so we are likely to see a variety of approaches, both good and ill. For now, this seems like a nice example of the "good" side of the coin.

Comments (14 posted)

The 7.0 scheduler regression that wasn't

By Jonathan Corbet
April 17, 2026
One of the more significant changes in the 7.0 kernel release is to use the lazy-preemption mode by default in the CPU scheduler. The scheduler developers have wanted to reduce the number of preemption modes for years, and lazy preemption looks like a step toward that goal. But then there came this report from Salvatore Dipietro that lazy preemption caused a 50% performance regression on a PostgreSQL benchmark. Investigation showed that the situation is not actually so grave, but the episode highlights just how sensitive some workloads can be to configuration changes; there may be surprises in store for other users as well.

One of the key decisions a CPU scheduler must make is when to remove a running process from the CPU to allow another to run. Preempting processes quickly when there is higher-priority work to do can produce quicker response times and, thus, lower latency. Aggressive preemption comes with a cost, though, in terms of the overall throughput of the system. Rapid switching of tasks can lead to more scheduler overhead, worse cache utilization, and more lock contention. It is hard to find a solution that works for every workload, a fact that has made it hard to remove the variety of preemption modes from the scheduler.

The lazy-preemption mode was designed with an eye toward the needs of both latency-sensitive and throughput-driven workloads. Unlike the full-preemption or realtime modes, lazy preemption will normally allow a task to run for a while even after the need for preemption has been detected. That preemption will be deferred until the task exhausts its time slice, blocks for some other reason, or until the next scheduler tick occurs. That leads to a quicker preemption than would happen with the PREEMPT_NONE mode (which only preempts a process at the end of its time slice), but still allows the task to run for a while before the preemption occurs.

Dipietro reported that the PostgreSQL performance regression was caused by a large increase in lock contention. PostgreSQL uses user-space spinlocks for much of its concurrency control; one problem with such locks is that, if a lock holder is preempted before the lock can be released, other processes will spin on a lock that may remain held for a long time. An increase in the frequency of preemption could indeed cause this to happen; more preemptions mean more chances to sideline a process before it is able to release a contended lock.

At a first glance, that seemed to be exactly what was happening here, leading scheduler developer Peter Zijlstra to suggest that the proper fix was for PostgreSQL to use time-slice extension to protect lock holders from preemption. This feature allows a process to request that it not be preempted for a short period while it completes the execution of a critical section and releases its locks. It is a useful feature for a situation like this but, as PostgreSQL developer Andres Freund pointed out, time-slice extension was only added in the 7.0 kernel; "requiring the use of a new low level facility that was introduced in the 7.0 kernel, to address a regression that exists only in 7.0+, seems not great". It would also not be a simple change, he said, so backporting any such fix to released versions of PostgreSQL was unlikely to happen.

Zijlstra, faced with the prospect of having to revert a scheduler change that had been years in the making, was clearly reluctant to do so. He suggested that anybody who updates the kernel on a system running PostgreSQL could be expected to update the database manager as well. This is the sort of forced update scenario that the kernel's regression policy is meant to avoid, but Zijlstra remarked "sometimes you have to break eggs to make cake :-)". If a revert was needed, he said, it would be "a very temporary thing". The plan is to eventually remove PREEMPT_NONE entirely, eliminating a fair amount of complexity in the scheduler.

Meanwhile, though, Freund was unable to reproduce the problem, and had a hard time understanding how it could come about. A little while later, though, he figured it out. In his test systems, he had enabled the use of transparent huge pages (THPs), "as that is the only sane thing to do with 10s to 100s of GB of shared memory and thus part of all my benchmarking infrastructure". When he disabled huge pages, the problem reported by Dipietro surfaced immediately. That revelation removed the urgency from this regression:

I don't see a reason to particularly care about the regression if that's the sole way to trigger it. Using a buffer pool of ~100GB without huge pages is not an interesting workload. With a smaller buffer pool the problem would not happen either.

He added that, even in the absence of the spinlock contention, avoiding huge pages was going to have bad performance effects.

Freund had expressed confusion about how there could be contention on the lock that Dipietro pointed out, since the critical section it protects is quite short. But, when huge pages are not in use, that section will take longer to execute. The extra pressure on the translation lookaside buffer (TLB) caused by using small pages will be a part of the problem, but a bigger part is almost certainly just the greatly increased number of page faults that will occur in that configuration. These effects will increase the execution time in the critical section, increasing the chances that a PREEMPT_LAZY kernel will take control away from a lock-holding process. That slowdown is far less likely to happen when huge pages are in use.

One conclusion from that diagnosis is that time-slice extension would be of little help; Freund confirmed that the performance regression happened even when user-space spinlocks are taken out of the picture. That said, he did acknowledge that the feature was worth looking into on its own merits, saying it looks "nice for performance regardless of using spinlocks".

Dipietro confirmed that enabling huge pages caused the regression to disappear. With that report, thoughts of reverting the scheduler change also seemed to disappear. That may be a bit premature, though. There are likely to be systems in the wild running under less-than-optimal configurations that will show regressions when hit with this kind of change. That prospect, in turn, may cause distributors to shy away from lazy preemption in their kernels, regardless of what the scheduler developers might like. An immediate revert might not be in the cards, but the grand plan to remove PREEMPT_NONE may have a longer path to completion than some would like.

Comments (13 posted)

One Sized trait does not fit all

By Daroc Alden
April 22, 2026

In Rust, types either possess a constant size known at compile time, or a dynamically calculated size known at run time. That is fine for most purposes, but recent proposals for the language have shown the need for a more fine-grained hierarchy. RFC 3729 from David Wood and Rémy Rakic would add a hierarchy of traits to describe types with sizes known under different circumstances. While the idea has been subject to discussion for many years, a growing number of use cases for the feature have come to light.

The need for more sizes

The two existing categories of type, colloquially called "sized" and "unsized", might seem to cover all of the possibilities. Unfortunately, some architectures are quite strange. For example, BPF programs can use "compile once — run everywhere" (CO-RE) relocations to adapt programs to different kernel versions. In such a program, the size and layout of a structure may be unknown at compile time, but effectively static at run time. This puts those structures between Rust's existing classes: accesses can't be reduced to offsets at compile time, but some of the same optimizations used for static offsets apply. Currently, Rust programs targeting BPF are simply not allowed to use CO-RE relocations — a substantial limitation that the Rust developers would like to relax if possible.

Another example comes from the vector extensions for Arm and RISC-V. These extensions define "single instruction, multiple data" (SIMD) instructions that operate over registers of a CPU-dependent size; the same instruction could correspond to 128-bit, 256-bit, or 512-bit registers depending on the specific CPU being used. Rust has support for working with these extensions through some built-in functions, but could potentially generate better code by exploiting the fact that the size of the relevant registers doesn't change at run time.

Finally, there is another proposal (RFC 1861) to add "extern types", which would be completely opaque to Rust's type system. Some C libraries have pointers to declared-but-not-defined structures that are expected to be passed back into library functions untouched; C++ libraries, which are more difficult to integrate directly into Rust code, present similar challenges. Currently, Rust programmers have a few tricks for representing these pointers in external interfaces, all of which can cause problems for the type system when used without care. Modeling opaque pointers to unknown C types as extern types would let these values be handled safely by Rust's type system — at the cost of introducing types that have no known size at all, not even at run time. These same kinds of opaque types also come up when compiling for WebAssembly or some GPU targets.

The proposal

Currently, types with a compile-time-known size are automatically made to implement the Sized trait by the compiler. All other types are assumed to have sizes dynamically calculated at run time. Wood and Rakic's proposal would add two new automatically implemented traits capturing finer distinctions. A new trait called SizeOfVal would apply to types that can have their size determined by examining pointer metadata at run time. Another, called Pointee, would apply to types that had no known size at all, and therefore could only be used through a pointer.

This hierarchy is sufficient to support extern types, but is not quite enough to represent vector-extension types or types with CO-RE relocations. To handle those, the proposal's authors suggest that it could be combined with another experimental Rust feature: const traits.

These traits allow Rust programmers to control whether methods of a trait are callable at compile time (in a "const context") or not. Objects that have a size known at compile time would be "const Sized", while those with a size that is only known at run time (but which is constant for the entire life of the program, for all values of that type) would just be "Sized". If a thing can be calculated at compile time, it can also be calculated at run time, so types that implement const Trait automatically implement Trait as well. Values that have a size that can be known at compile time, but that might be different for separate instances of a type would be "const SizeOfVal", while those that can vary from object to object and across runs of the program would be plain "SizeOfVal". Objects about which nothing is known would remain Pointee.

Rust currently allows types without a known size to be used as the last member of a structure — an analogue to C's flexible array members. The compiler does assume that the size of these members can be calculated at run time. Splitting Pointee out allows the compiler to distinguish between structures that can in principle be safely stored on the stack (SizeOfVal) and those that can't (Pointee). The rules for returning compound values on the stack are more stringent, however: the calling function needs to allocate a known amount of space for a returned value, so only Sized values can be returned in that way. Any other values need to be moved to the heap and returned behind a pointer.

Types that implement the const version of these traits are potentially eligible for more compiler optimizations: the compiler can work out exactly which offsets will be used, which makes it easier for the optimizer to split structures into individual components that can be stored in registers. Types that are Sized but not const Sized can't be handled in this way, but can at least avoid the overhead of repeatedly recalculating and storing size information by using relocations to patch the binary at run time.

To summarize, here are the different traits being discussed and their meanings:

Trait Known at compile time? Same for all values of the type? Size never changes once calculated? Optimizer-friendly? Can be non-last member in a structure? Can be used ... Example
const Sized Yes Yes Yes Yes Yes Anywhere A normal Rust type
Sized No Yes Yes Less so Yes Anywhere A foreign kernel type with a CO-RE relocation
const SizeOfVal Yes No Yes Yes No Not returned on the stack A slice with bounds calculated in a const context
SizeOfVal No No No No No Not returned on the stack A dynamically sized slice
Pointee No No No No No Not on the stack A foreign C type without a fully known layout

Trait bounds

When a Rust programmer is writing generic code, they can specify which of these features a type needs to have using a bound such as "where T: SizeOfVal". Most existing code doesn't have any such bounds, however. Instead, the Rust compiler assumes that every generic type is meant to be Sized unless explicitly opted-out, since the vast majority of types do have a known size. The current syntax for opting out is "where T: ?Sized". With this proposal, that would be changed to be syntactic sugar for "where T: SizeOfVal". Since no existing types implement Pointee yet, that change is backward-compatible.

Whenever the compiler sees an explicit bound for Sized, SizeOfVal, or Pointee, it would remove the implicit Sized assumption. In the next edition of Rust, the "?Sized" syntax could be removed entirely, making the language simpler.

Next steps

Rust's RFC process involves a long period of discussion and reflection before a final call for comments. The sized trait hierarchy RFC (3729), for example, has been in discussion since November 2024, and has not yet had a final call for comments. There are a growing number of use cases for the feature, however. For example, the extern types RFC (1861) has been accepted, and it depends on adding something like Pointee to the language. Wood and Rakic helpfully include a dependency diagram showing which other in-progress RFCs depend on having a hierarchy of size traits:

    rfcs#3729: Sized Hierarchy (this RFC)
      │
      │──→ `const Sized` Hierarchy ──→ Scalable Vectors (rfcs#3838)
      │
      │──→ Custom DSTs
      │
      │──→ Alignment traits/`DataSizeOf`/`DataAlignOf` (size != stride)
      │
      └──→ wasm `externref` types

It's hard to say whether this RFC will be adopted in its current state; the fine distinctions it introduces are something that the Rust community has been struggling with for years. My impression from reading the discussion is that it may reach a conclusion relatively soon, perhaps after some in-person discussion at the Rust all-hands meeting at RustWeek in May — stay tuned for LWN's coverage of that event. In any case, the growing pressure to find some resolution to the problem will likely see this proposal or something like it adopted eventually, as the language continues to accrue the features necessary for smooth cross-language interoperability.

Comments (8 posted)

Dependency-cooldown discussions warm up

By Joe Brockmeier
April 22, 2026

Efforts to introduce malicious code into the open-source supply chain have been on the rise in recent years, and there is no indication that they will abate anytime soon. These attacks are often found quickly, but not quickly enough to prevent the compromised code from being automatically injected into other projects or code deployed by users where it can wreak havoc. One method of avoiding supply-chain attacks is to add a delay of a few days before pulling updates in what is known as a "dependency cooldown". That tactic is starting to find favor with users and some language ecosystem package managers. While this practice is considered a reasonable response by many, others are complaining that those employing dependency cooldowns are free-riding on the larger community by letting others take the risk.

Everybody cool down

In November 2025, William Woodruff published a blog post advocating the use of dependency cooldowns to mitigate supply-chain attacks that affected open-source projects. In the post he looked at ten of the prominent supply-chain attacks that had taken place in 2024 and 2025, including the XZ backdoor, the attack on the Python ultralytics package, and the npm debug/chalk supply-chain attacks.

Each attack had the same basic structure: attack preparation, window of opportunity, detection of the attack, disabling of the compromised package, and then remediation. He said that the key thing to observe is that "once the attacker has moved into the actual exploitation phase, their window of opportunity to cause damage" is usually less than a week before the attack is detected by security vendors or other researchers.

Therefore, developers could avoid the bulk of the attacks by instituting a cooldown on dependencies of seven days. Woodruff also encouraged open-source projects to adopt cooldowns using dependency-management tools like Dependabot, and for packaging ecosystems to "invest in first-class support for cooldowns directly in their package managers". While not a perfect solution, he said, it would be a major improvement:

Cooldowns are, obviously, not a panacea: some attackers will evade detection, and delaying the inclusion of potentially malicious dependencies by a week (or two) does not fundamentally alter the fact that supply chain security is a social trust problem, not a purely technical one. Still, an 80-90% reduction in exposure through a technique that is free and easy seems hard to beat.

His blog post appeared on Hacker News, Lobste.rs, and elsewhere; it caught quite a few people's attention. In December, he published a follow-up that addressed common questions and objections.

For example, some people asked if cooldowns would be self-defeating. If everybody adopts them, then wouldn't the window of opportunity just include the cooldown period, thus negating the benefits? Woodruff countered with the observation that there are parties in the system—security vendors, open-source maintainers, and the package-index maintainers—with strong incentives to detect attacks before they reach users. In addition, universal adoption of cooldowns was "clearly not realistic: there are always going to be people who live at the edge. If those people want to be the proverbial canaries in the coalmine, that's their prerogative!"

He also listed a number of language ecosystems that had added or were exploring support for cooldowns in some of their tools, including Go, JavaScript, Python, and Rust. In March, Andrew Nesbitt did another round-up of the state of cooldown support in language package managers, dependency-update tools, and so forth. He looked at the package managers that currently support cooldowns, are in the process of adding support, as well as ecosystems where he couldn't find any evidence of plans to implement the feature. He noted that cooldowns are called "at least ten different configuration names across the tools that do support it", which made writing about the topic nearly as hard as the implementation of cooldowns in projects with multiple languages.

On April 6, the Python Package Index (PyPI) published an incident report following a supply-chain attack that affected the LiteLLM and Telnyx packages. The report included a section on how developers could protect themselves, which included dependency cooldowns as one way to avoid malware.

Wrong approach

On April 13, Cal Paterson published an argument against dependency cooldowns. He worried that the practice was being "fast-tracked into the basket of 'industry standard best practices'". It might look like an effective approach on the surface, he said, but cooldowns do not address what he felt was the core issue: "publishing and distribution are different things and it's not clear why they have to be coupled together".

He had a few complaints about cooldowns; for example, he argued that the cooldowns work "by free-riding on the pain and suffering of others" by treating those who grabbed updates right away as "unpaid, inadvertent beta testers for newly released packages". Even if the system works for individuals, he called it impossible to sustain "as a sensible or moral system" for an entire ecosystem to observe. Paterson also pointed out that it would require great effort on behalf of people who have to implement cooldown features:

Python has multiple package managers at this point (how many now? 8?). All must implement dependency cooldowns. And every project ever created has to configure the cooldown - which often isn't particularly easy or clear given that package managers often choose completely different ways to do it.

Upload queues

Instead of the cooldown approach, he argued that "the obvious alternative" was an upload queue: "Make new packages wait some period of time after they are published, before they are distributed." Publication would mean sending a release (a tarball, Ruby gem, Python wheel, etc.) to the central index for distributing packages. Distribution would be when the index begins serving packages to the public.

There would be an interim period where the package could be subject to automatic security scans, reviewed by the public, even downloaded by willing test subjects, but not widely distributed. He pointed to how Debian handles package distribution as a successful example of upload queues:

Debian stable effectively is an upload queue - the whole point is that it's made up of older releases that have already been subject to a QA process. The upload queue for language-oriented package managers need not be so comprehensive - but I do think there is something to take from the Debian example.

Debian, of course, has actual upload queues such as the new queue, but his larger point still stands. Upload queues not only provide more time to examine releases; the practice would also reduce the value of stealing release credentials. Many of the supply-chain attacks involved more than the insertion of malicious code, they also involve theft of release credentials so that the attacker can perform an unauthorized release of the package. If a package has to sit around for a few days, he said, the value of stealing release credentials goes down.

The wait period would serve to reduce or remove what he called "the entirely unnecessary element of surprise" when a new package release appears. Users would get advance notice of new releases.

And it's not just users who need advance knowledge. The upload queue period is also a good time to notify maintainers, to make sure that they are all indeed aware of the forthcoming release. "Notification: Release 2.4.1 has entered the upload queue" would be just the wake-up call required to avert a supply chain attack getting rolled out in many cases.

He acknowledged that cooldowns were useful in some situations and admitted he doesn't always want to be the first to upgrade: "the family TV set-top box is mission critical infra in my household". But he was against dependency cooldowns becoming community best practices. "I don't want my security to depend on someone else getting hacked first".

Paterson's post also picked up steam and made it to discussion sites. In the Lobste.rs thread about his post, Woodruff responded that Paterson's response was "directionally accurate" but missed a key part of the argument. "You're not free-riding on other maintainers, but instead on a number of 'supply chain security' companies that are financially incentivized to find malware as quickly as possible". He also agreed that upload queues were more desirable, and that instant distribution was a problem, but "it's also not something that's easy to take away now that it's been established as the norm for publishing language specific packages".

For now, since package indexes like PyPI have not announced plans to implement upload queues, users will need to rely on dependency cooldowns as a way to avoid being the victim of a supply-chain attack. It will be interesting to see what kind of progress is made over the next few years in implementing dependency-cooldown tooling across language ecosystems. Of course, attackers are also going to be watching and adapting their strategies as well—scanning for vulnerabilities during a cooldown period may catch many attempts to slip in malware, but it would be optimistic to bank on cooldowns working all the time.

[Thanks to Paul Wise for the topic suggestion.]

Comments (92 posted)

The first half of the 7.1 merge window

By Jonathan Corbet
April 16, 2026
The 7.1 merge window opened on April 12 with the release of the 7.0 kernel. Since then, 3,855 non-merge changesets have been pulled into the mainline repository for the next release. This merge window is thus just getting started, but there has still been a fair amount of interesting work moving into the mainline.

Some of the more interesting changes merged so far include:

Architecture-specific

  • The amd-pstate power-management subsystem has gained support for dynamic performance preference, changing the system's power-management behavior depending on whether the system is running on AC or battery power. See this commit for some documentation.
  • Support for some old and unused 486 subarchitectures (specifically M486, M486SX, and ELAN) has been removed.
  • Intel's Flexible Return and Event Delivery (FRED) "defines new control-flow transitions (generally between privilege levels) that replace existing transitions (such as event delivery through the IDT and return using IRET)." This feature has been supported since the 6.9 release but disabled by default; as of 7.1, FRED will, instead, be enabled by default.
  • Support for NVIDIA Tegra410 memory-latency performance-monitoring units has been added. See the documentation added in this commit and this commit for details.
  • The Arm 9.6 LSUI feature adds instructions allowing the kernel to access user-space memory without disabling the "privileged access never" mode first; 7.1 uses these instructions to accelerate futex operations.
  • Support for Arm's Memory Partitioning and Monitoring (MPAM) feature has been improved and exposed to user space. See Documentation/arch/arm64/mpam.rst for more information.
  • The BPF just-in-time compiler on PowerPC systems has improved, with support for private stacks, fsession support, indirect jumps, and more.
  • The s390 architecture has also gained BPF fsession support.

Core kernel

  • There are three new flags to the clone3() system call. CLONE_AUTOREAP causes a process to automatically reap itself on exit rather than becoming a zombie and waiting for the parent to do the work. CLONE_NNP sets the no new privileges flag on the newly created process. And CLONE_PIDFD_AUTOKILL will cause the created child to be killed immediately when the pidfd given to its parent is closed. See this article for more information on all of these flags.
  • There is a new file, import_ns, for each loaded module in its associated /sys/module directory; it shows which symbol namespaces the module in question has imported.
  • The io_uring subsystem has gained BPF support, allowing the main dispatch loop to be replaced by a BPF program.
  • The high-resolution-timer core has been substantially rewritten for better performance; see this merge log for details. Among other things, the improvements mean that the scheduler can use high-resolution timers with no performance loss relative to a scheduler using coarse timers.
  • The project to add proxy execution to the kernel continues with the merging of part of the donor migration patch set, which will eventually enable the movement of donor tasks between CPUs to facilitate the donation of CPU time to a lock holder. This work is not yet complete, but is getting closer.
  • The way stack liveness is tracked in the BPF verifier has changed, yielding much faster verification for many programs. See this merge log for more information.

Filesystems and block I/O

  • The new FSMOUNT_NAMESPACE option to fsmount() will cause a new namespace to be created to hold the newly mounted filesystem. The clone3() and unshare() system calls have also gained flags to return a new mount namespace containing only a single nullfs mount.
  • The kernel can now generate and verify T10 protection information at the filesystem level. The block layer has had this capability for a while, but moving it to the filesystems improves efficiency (especially for reads) and will facilitate the eventual addition of this support to io_uring.
  • The ublk user-space block driver has gained support for zero-copy I/O; this commit contains some documentation on how to use this feature, and this one provides a self-test for it.
  • SED-OPAL is a specification for self-encrypting block devices. Support for SED-OPAL has been enhanced by a number of rigorously undocumented ioctl() operations for single-user mode support; see this patch posting for an overview.
  • The Btrfs shutdown operation, which stops all I/O operations until the subject filesystem is unmounted, was added in 6.19; in 7.1, it will lose its "experimental" status and become generally available.
  • The exfat filesystem now supports pre-allocation with fallocate().
  • The CIFS client filesystem now supports the creation of temporary files with the O_TMPFILE option.

Hardware support

  • Networking: Spacemit DWMAC Ethernet controllers, Nuvoton MA35 series Ethernet controllers, and Microchip PIC64-HPSC/HX MDIO interfaces.

Networking

  • Unix-domain sockets created directly via socket() (as opposed to being accessed via a filesystem) have traditionally not supported extended attributes. As of 7.1, these sockets include support for the user.* extended-attribute space. As described in this merge log, the driving use case for this feature is the ability to annotate sockets with extended attributes to document the protocol that the endpoints expect to use.
  • UDP Lite support has been removed; this move was announced in 2023 after it became clear that nobody was actually using this feature. See this merge log for more information.
  • The ability to build IPv6 support as a module has been removed; this protocol is either built directly into the kernel or disabled altogether.

Security-related

  • A set of configuration options was added for the 6.12 release to control whether accesses to the /proc/PID/mem file could override memory permissions; by default, that overriding is allowed since that is what the kernel traditionally did. As of 7.1, though, the default will switch to PROC_MEM_FORCE_PTRACE, meaning that permissions can be overridden by an active ptrace() user but not otherwise.
  • There is a new set of security-module hooks meant to facilitate the implementation of policies for overlay filesystems. The documentation is evidently too secret for inclusion in the kernel, but this changelog gives an overview of the hooks.
  • There is also a new hook controlling access to Unix-domain sockets in the filesystem. The Landlock security module uses this hook to provide new policy options for those sockets.
  • The growing, meticulously undocumented libcrypto library, which provides faster and easier access to cryptographic algorithms than the kernel's older crypto subsystem, has gained support for a number of new algorithms; see this merge message for a list.

Internal kernel changes

  • The i_ino field of the inode structure is now 64 bits wide on all architectures.
  • The way that symbols exported to modules are represented in the kernel binary has changed to a more efficient format.
  • The minimum version of Rust needed to build the kernel is now 1.85.0 (and bindgen 0.71.1); this change follows the decision made at the 2025 Maintainers Summit to require the versions provided by the latest Debian stable release. See the pull request for other Rust-related changes.
  • The kernel-doc tool, which is used to build the kernel documentation from comments in the code, has been significantly rewritten to use a proper C tokenizer and fewer gnarly regular expressions.
  • There have been a number of improvements around correct lock usage, including the addition of support for context analysis (formerly capability analysis) for rwsems, mutexes, and rtmutexes.

As of this writing, there are still nearly 9,000 non-merge changesets waiting to move from linux-next into the mainline, so expect to see a lot more interesting material in this development cycle. If the usual schedule holds, this merge window can be expected to close on April 26; tune in after that for a look at what all those changesets brought in.

Comments (6 posted)

A more efficient implementation of Shor's algorithm

By Daroc Alden
April 17, 2026

Shor's algorithm is the main practical example of an algorithm that runs more quickly on a quantum computer than a classical computer — at least in theory. Shor's algorithm allows large numbers to be factored into their component prime factors quickly. In reality, existing quantum computers do not have nearly enough memory to factor interesting numbers using Shor's algorithm, despite decades of research. A new paper provides a major step in that direction, however. While still impractical on today's quantum computers, the recent discovery cuts the amount of memory needed to attack 256-bit elliptic-curve cryptography by a factor of 20. More interesting, however, is that the researchers chose to publish a zero-knowledge proof demonstrating that they know a quantum circuit that shows these improvements, rather than publishing the actual knowledge of how to do it.

Quantum background

Quantum computers store their information in qubits, each of which essentially stores a two dimensional vector with length one — a superposition. Quantum logic gates can do operations such as rotating a qubit or reflecting it around some other vector. Together, these operations can be chained together to create a quantum circuit that performs a useful operation in the same way that logic gates in a classical computer are combined into a circuit. The exact result that is measured at the end of a quantum circuit, however, can be quite sensitive to noise from the environment. This is the major practical challenge in building a quantum computer: isolating it from the environment sufficiently well that the information stored in its qubits doesn't degrade to the point of uselessness. The difficulty of this isolation goes up with the size and complexity of the quantum circuit, and with the number of qubits.

Other recent research has shown how to break 256-bit elliptic-curve cryptography using only 1,098 logical qubits, but that paper used 238 quantum gates to do it. This requires a circuit that is roughly eight orders of magnitude larger than modern quantum computers can handle.

One technique that is used to reduce the precise tolerances required inside a quantum computer is error correction. A quantum error-correction scheme works a bit like ECC memory: it emulates a single "logical" qubit using a group of less-precise "physical" qubits, in the same way that ECC memory produces more reliable memory storage by combining multiple potentially noisy memory cells. The nine researchers behind the new paper — who come from Google, the University of California Berkeley, the Ethereum Foundation, and Stanford University — have produced a quantum circuit for factoring 256-bit elliptic-curve signatures using fewer than 1,200 logical qubits and 90 million quantum gates. Depending on architecture, this corresponds to around 500,000 physical qubits. IBM's Condor quantum computer, among the largest publicly known quantum computers, has 1,121 physical qubits, meaning that engineers will need to give quantum computers around 500 times more memory before an attack using the new technique becomes practical. They'll also need to increase the number of gates, but that is believed to be less of a limiting factor.

[Readers who are not interested in the details of how the researcher's proved that they had such a breakthrough may wish to skip to the conclusion.]

Zero-knowledge proofs

It isn't possible to say the exact number of logical or physical qubits needed, however, because the researchers have not published their actual improved quantum circuit. Citing concerns that bad actors could use the research to attack digital security, including the security of the Bitcoin blockchain, they instead chose to publish a machine-verifiable proof that they know a particular circuit that lives up to their claims. This is not new territory for mathematics; 16th century mathematicians would keep their breakthroughs secret and challenge each other to "duels" where they proved that they knew an analytical solution to a complex equation by quickly solving difficult instances of the problem.

It is new in the modern era of mathematics, however. This is the first quantum-computing paper to use this style of zero-knowledge proof. The way the proof works is quite interesting. The researchers wrote a simulator for quantum circuits (available from their published reproduction data) that reads in a quantum circuit, generates thousands of random inputs, simulates the behavior of the circuit on those inputs, and checks it against a reference implementation. Ordinarily, this would not suffice to prove that the circuit was correct — what if it was correct for 99% of inputs, but incorrect for the remaining 1%? In this case, however, that doesn't matter. Shor's algorithm is, by design, robust to occasional small errors in its intermediate computations; therefore, it doesn't matter whether the quantum circuit being simulated is right in every case, only that it is right in a sufficiently high number of cases. The researchers target a circuit that is accurate in 99% of cases. As long as the researchers cannot cherry-pick the "random" inputs, running enough random trials shows that it is correct enough.

In order to ensure the inputs are really random, the researchers use a pseudorandom-number generator seeded from the hash of the description of the circuit being tested. As long as the hash function in question (SHA-256 in this case) and the pseudorandom-number generator are both secure, this ensures that the researchers couldn't have manipulated the randomly chosen test inputs.

So, in theory, running this program and feeding it the unreleased quantum circuit would prove that the circuit was good enough for use inside Shor's algorithm. But how can the researchers prove that they did run the experiment correctly if nobody else has access to the input to the program? The solution is SP1, a "zero-knowledge virtual machine" that allows users to produce cryptographically secure proofs (STARKs, or "scalable transparent arguments of knowledge") that they ran a program and that it produced a given output, without revealing what the input to the program was. SP1 works by emulating a RISC-V chip that produces a trace of the CPU's execution as it goes, and then proving that the trace must correspond to a valid execution of the corresponding RISC-V program regardless of what the input values were.

Note that the functions discussed in this section all operate over a cyclic multiplicative subgroup of a finite field — so the "fast Fourier transform" is actually a discrete Fourier transform over a ring. This detail doesn't invalidate general intuitions about the behavior of a Fourier transform, however.

SP1's CPU trace lists, for every register and memory location, what its value was at each time step. Taking the inverse fast Fourier transform of each list produces a "trace polynomial" for each register. The trace polynomials are a representation of how the register changes over time; by combining these polynomials in the right way, SP1 produces "constraint polynomials". These polynomials represent whether the rules of the emulated RISC-V CPU were violated. They include constraints such as "the output of the arithmetic logic unit must be A + B when the mode is set to addition" or "the next program counter must be one more than the previous, unless there was a jump instruction". Each constraint polynomial is constructed such that it must be zero at every time step. At this point, if the person constructing the zero-knowledge proof could show that property held, they would have demonstrated that they executed the program correctly.

To show this, the person constructing the proof can divide the combined constraint polynomials by a (fixed) polynomial that equals zero at each time step. If they were telling the truth, the result is still a polynomial. If they were lying about any of the time steps, the division results in a rational function that can eventually be distinguished from a proper polynomial. Imagine a heavily simplified example where the constraint polynomial is just "x - 1" and the fixed polynomial is also "x - 1". Dividing one by the other gives a linear function (a kind of polynomial) with a hole at the point x = 1. On the other hand, if the constraint polynomial had been "x + 1", then the result of the division wouldn't be a polynomial: it would have an asymptote at x = 1. Since those functions have different shapes, it's easier to construct a protocol that reliably distinguishes them.

In order to prove that the result of the division is a polynomial, the prover splits the function into even (symmetrical about the y-axis) and odd (symmetrical about the origin) parts, multiplies the odd part by a randomly chosen constant, squares the inputs to both parts, and adds them back together — an operation known as folding. If the input to this folding was indeed a polynomial, this produces a polynomial with a smaller finite domain; if the input to this operation was a rational function, however, the resulting function is still a rational function with high probability. Eventually, the domain shrinks down to a single point and the function becomes a constant function.

To demonstrate that they are performing the folding correctly, the prover picks random points and writes down what the function evaluates to there. Importantly, the hashes of these points are incorporated in later steps of the proof, ensuring that the prover cannot go back and modify them afterward. Later, someone interested in verifying the proof can challenge them for some of these randomly chosen points and check how they relate to one another before and after folding, making it difficult for the prover to get away with folding the function incorrectly. By repeatedly folding the function, the prover can eventually produce a single number that is shared as part of the proof. As long as the random numbers were indeed chosen randomly, it is probabilistically difficult for the prover to create a matching chain of folds that ends at the publicly shared constant without having a valid polynomial to start with.

Obtaining properly random numbers is the same problem that the researchers faced above, and is solved in the same way: the random numbers are generated according to a hash of the publicly-known portion of the proof (including the machine-code of the RISC-V program, and the hashes of the random numbers used at previous steps of the proof). This lets the verifier take the input, the list of commitments, and the final output, and check that each of the folding steps was performed correctly. If each of the folding steps were performed correctly and the results match, the verifier learns that the RISC-V program was emulated correctly, without learning details about the actual register values.

There is one problem, however: for a program that executes millions of RISC-V instructions, the generated trace and the resulting proof can be quite large — too large for people to verify quickly on their own computers. So, the researchers perform one more transformation of the data to compress the proof into a minimal form that is more efficiently checkable.

STARK to SNARK

There is a different kind of zero-knowledge proof called a succinct non-interactive argument of knowledge (SNARK) that is less flexible than STARKs. Instead of being able to handle arbitrary computations, it only handles computations that can be expressed in a limited domain. In this case, the researchers used a SNARK system called Groth16, which only handles computations that can be expressed as a set of constraints on values in an abstract circuit made from classical logic gates where each constraint involves at most one multiplication operation. It also requires a completely random (not pseudorandom, as above) number to be securely agreed upon, used to create a kind of public key, and then completely forgotten. In exchange for this loss of flexibility, SNARKs produce much shorter, simpler proofs. In particular, the size of a SNARK proof is constant, regardless of what it is proving.

As it turns out, however, the process of validating a STARK proof can be expressed as a circuit diagram that Groth16 can handle. Unlike running the RISC-V simulator program (which runs for a variable number of time steps depending on the input), the process of validating a STARK can be formulated to take a constant amount of time, letting it be represented as a fixed circuit. The researchers took a verifier that could check the large existing proof, and compiled it to a set of Groth16 constraints. Evaluating this system of constraints produces values for each intermediate wire in the circuit (the analog of the CPU trace in a more complicated STARK proof). These intermediate values are converted to polynomials in much the same way as the trace polynomials inside a STARK. These polynomials are again combined into a single function such that if all of the constraints were satisfied, the function remains a polynomial — but if any were violated, it becomes a rational function instead.

Ironically, an adversary who can break 256-bit elliptic-curve cryptography using a quantum computer is also able to forge SNARK proofs, since the security of the unknown random location depends on the same hardness assumption.

The method by which the verifier checks that the resulting function is a polynomial is fairly different, however. The prover uses the publicly known key referenced above to calculate three values, each of which is a different way of combining information from the trace of the circuit with elements of the public key referenced above. The public key consists of precomputed numbers that can be used to evaluate a polynomial at a specific random location that nobody knows. The public key is structured such that the numbers can't be used to derive what the unknown location was (without being able to efficiently factor large numbers). The verifier can then check the relationship between the public key and the three generated numbers to show that the prover's function, minus a polynomial, evaluated at that unknown random location, equals zero. According to the Schwartz-Zippel lemma, this is incredibly unlikely to happen by chance unless the prover's function was a polynomial to begin with.

The security of that construction hinges heavily on the random location being truly unknown — an adversary who did know it could just evaluate the function directly at that location in order to fake a SNARK proof. In this case, the researchers used the key generated by a secure multi-party computation done by Aztec Labs as part of setting up their Ethereum-based cryptocurrency. That computation was a joint venture in late 2019 between 176 different people: each one generated a random number and added it to a communal pool of randomness that was used to calculate the necessary public key using a distributed algorithm. As long as at least one of those people was diligent enough to properly erase their random number after the process was conducted, the random location used to construct and validate these Groth16 SNARKs is unrecoverable.

The result of all of this complexity is a 1.7MB proof file that (in conjunction with the source code of their simulator) shows that the researchers behind this paper did actually produce a usable quantum circuit meeting their stated claims. Of course, I had to try this out for myself. Downloading and compiling their source code was straightforward, and verifying the proof took just under 14 minutes of CPU time on my laptop. The code for the simulator, prover, and verifier comes to just under 1,500 lines of Rust — but there are over 2,800 external libraries used in support of that code, so auditing the code remains somewhat daunting. The correctness of the verifier code is not something that can be guaranteed cryptographically; it relies on the normal process of publishing the artifacts and letting interested people point out any problems.

In summary: assuming that the publicly published source code the researchers shared is correct, and that at least one person out of a list of 176 cryptography enthusiasts in 2019 was honest, then it is almost certainly the case that the verifier in the paper's reproduction data was fed a valid STARK transcript. In turn, that means that it was almost certainly the case that their simulator, when fed some input known only to the researchers, validated that the input was a quantum circuit that provides a substantial speedup over prior work on Shor's algorithm. Here "almost certainly" means that it is not theoretically impossible that they could have created a forgery by random chance — but doing so would be as difficult as breaking many other well-trusted cryptographic systems by chance. Winning the lottery 1068 times in a row would be more likely.

Now what?

I am personally delighted by this kind of careful, complicated cryptographic construction, but it does raise some concerns for the future of open mathematics. If the paper's authors had chosen to release their circuit, they would certainly have been recognized for the important progress they made in the science of quantum computing. Other researchers would have gone on to build on their work, and the entire scientific community would be richer for it.

As it is, the researchers haven't really published a breakthrough. Instead, they have published a cryptographic proof that they have a breakthrough, but they aren't going to share it. It's certainly exciting to know that more efficient quantum circuits for Shor's algorithm exist — but do the researchers deserve the same level of praise for finding it, when the rest of the scientific community won't be able to learn from and build on their work?

Worse, it's impossible to say how their work combines with other advances in the field. Another paper, published the same week, introduced an exciting technique for reducing the number of physical qubits required to simulate a logical qubit in some circumstances — albeit in a slightly convoluted way that increases the number of required quantum gates. Does that work apply to the unknown quantum circuit? If so, it could reduce the number of required physical qubits to attack 256-bit elliptic-curve cryptography to around 25,000 — still 25 times larger than any existing quantum computers, but much smaller than the best estimates from a year ago. It's impossible to say for sure whether the potential reduction in physical qubits applies, since the details of the new quantum circuit are unknown.

Practical quantum computers always seem to be years away. This paper probably doesn't change that, but it does make it much harder to tell exactly how many years away they may be. Perhaps the best we can do is continue working to adopt post-quantum cryptography, and hope that when practical quantum computers become available we get an actual explanation of how they work, and not just a cryptographic proof that they do.

Comments (18 posted)

Digging into drama at The Document Foundation

By Joe Brockmeier
April 20, 2026

The Document Foundation (TDF) is the nonprofit entity behind the LibreOffice productivity suite. Most of the time, the software takes the spotlight, but that has changed in the past few weeks, and not for pleasant reasons. TDF has revoked foundation membership status from about 30 people who work for or have contracting status with Collabora. In response, Collabora has announced plans to focus on a "entirely new, cut-down, differentiated Collabora Office" project and reduce its involvement with LibreOffice. TDF's representatives claim that its actions were necessary to maintain the foundation's nonprofit status, while other community members assert that this is part of a power grab. The facts seem to indicate that there are legitimate issues to be addressed, but it is unclear that TDF needed to go so far as to disenfranchise all Collabora-affiliated contributors.

Membership and contribution

Understanding the current dispute requires going into the weeds of the foundation's governance, and its relationship with Collabora. TDF is a Stiftung, a type of nonprofit foundation, that was incorporated in Berlin in 2012. The foundation's objective is to support the development of open-source office software and to promote its use. To facilitate that, TDF holds LibreOffice assets such as its trademarks, as well as funds to support development, put on community events, and so forth.

Its statutes outline three bodies; the board of trustees (TDF's members), the membership committee, and the board of directors. The trustees elect the membership committee and board of directors; the membership committee oversees membership applications and renewals, as well as the board of directors elections. Note that this article quotes from the English version of the statutes provided for convenience; the German text is the legally binding version, and it is possible there are subtle differences.

To become a member, a contributor has to submit an application to the membership committee. For the application to be approved, the committee must be able to verify that a person has dedicated "more than three months of verifiable time and intellectual work" toward the foundation's goals; this can be any non-trivial programming, translation, documentation, creating marketing material, or other tasks. In addition, the applicant has to indicate that they plan to continue contributing for at least six months. If approved, the membership term lasts one year, and renewal is not automatic; those who wish to continue their membership have to apply to renew each year, and the committee can simply let a person's membership lapse.

A person does not have to be a member of the foundation to contribute to LibreOffice; but being a member is necessary to have a say in TDF governance by standing for the board, membership committee, or voting for the same. The board is responsible for deciding how the foundation's assets are used and how money is spent, which in turn influences the direction of LibreOffice overall.

Collabora's Productivity division was formed in 2013 when the company took over SUSE's LibreOffice business and the team that had worked on LibreOffice for SUSE joined the company. It committed to contribute 100% of its improvements to LibreOffice back upstream to TDF. To date, it has been the largest corporate contributor to the project. It currently offers products and services based on LibreOffice, including Collabora Online, which is a web-based office suite, a mobile version for Android or iOS, and a desktop version. The Online product has been at the center of controversy in the past and is again; LWN covered Collabora moving its development efforts away from LibreOffice Online to Collabora Online in 2020. TDF froze work on LibreOffice Online in 2022, and recently brought it out of retirement.

Public discussion

A blog post by Italo Vignoli, in response to Collabora's announcement, acknowledged that TDF had revoked membership from those affiliated with Collabora. It was fairly light on details, but said that TDF's community bylaws "require that employees of companies involved in legal disputes" with the foundation be removed from TDF's membership "because, in the past, people made decisions in the interest of their employers rather than in the interest of The Document Foundation". It did not, however, provide any detail about the nature of any legal disputes with Collabora. The hint that there might be an ongoing lawsuit between TDF and Collabora caused a great deal of speculation about what might be going on.

After the members were ejected, the board-discuss section of the foundation's Discourse forum was flooded with messages, such as this, pointedly thanking the removed members for their work on LibreOffice. In addition, Collabora's announcement ensured that the news spread quickly; however, while what had happened was widely known, why the TDF would take such action was still a mystery to many.

On April 5, Vignoli posted a follow-up titled "Let's put an end to the speculation" with additional details. He said that the organization would have liked to avoid discussing the events that led to ejecting members affiliated with Collabora.

Vignoli said that there were decisions made by previous TDF boards of directors "found to be incorrect for reasons relating to the nonprofit law" by the foundation's lawyers. The decisions in question were the awarding of contracts ("tenders") for LibreOffice work to companies that, at the time, had representatives on TDF's board of directors, and that "companies in the ecosystem" (presumably referring to Collabora and CIB) were improperly granted free use of the LibreOffice trademarks for the purpose of selling the suite through Apple and Microsoft's online stores.

In a Q&A post published on April 10, Vignoli addressed the question of legal disputes with Collabora. There is not an ongoing lawsuit, but there is mediation of some sort happening:

There are legal consultations between TDF lawyers and Collabora lawyers about situations in the past where Collabora representatives elected to the Board of Directors of The Document Foundation and with a clear Conflict of Interest have taken decision in the interest of the company and not in the interest of the non-profit foundation, creating the risk of loss of non-profit status to the foundation itself.

TDF's board has seven members as well as up to three substitute members ("deputies") who can take the place of a board member who can no longer serve for some reason. The board seated at the time period that Vignoli specified (the end of 2021 to mid-2022) included three people affiliated with the companies said to improperly benefit from board decisions: Thorsten Behrens, Michael Meeks, and Cor Nouws. At the time, Behrens was affiliated with CIB which also provides LibreOffice-based software. Meeks and Nouws were employed by Collabora. Behrens is now also employed by Collabora following his move to allotropia which later merged with Collabora in May 2025.

In response to questions via email, Behrens acknowledged that he was CEO of one of the companies that had received a trademark license to publish LibreOffice on the Windows store. TDF wanted to publish on the Apple and Windows stores but did not want to provide free downloads, he said. Thus it turned to ecosystem companies (Collabora and CIB) to do the work of putting LibreOffice in the stores. The trademark policy was changed to allow blocking "the massive amount of scam offers on those stores" around LibreOffice that were difficult for TDF to counter. The new policy, he said, allowed TDF to ask Apple and Microsoft to handle takedowns of scam offers.

So, bottom line: nobody did anything illegal, everything was done to support TDF & LibreOffice. But good intentions don't much matter, if a lawyer says you're doing it wrong - so we stopped this immediately in 2022, after we had learned about the **potential problems** with non-profit laws.

This was possible then for TDF to continue, since the work to get LibreOffice ready for the stores **had already been done by the ecosystem companies**, and it was considered less risky to do business on the stores (despite being a charity), rather than continue the [trademark] agreements.

Vignoli's blog post, however, claimed that matters raised by TDF's lawyers could have been resolved quickly, but the board failed to make any progress due to "years of discussions marked by accusations and finger-pointing". At some point, he said, German authorities requested an audit "whose results confirmed that resolving the issues was absolutely necessary to avoid losing non-profit status". According to the blog post, there were three audits; the first audit (in 2023) "raised concerns", and the second (in 2024) confirmed them.

Fortunately, the introduction of restrictive measures – such as the decision to forfeit TDF membership status of Collabora employees – and the freezing of tenders, alongside the introduction of a robust procurement policy for development, has resulted in a positive outcome for the third audit. At least, the [board of directors] has demonstrated a willingness to break the deadlock that has persisted since 2022.

TDF has not made the results of the audits public, and it is unclear if they have been widely shared with the membership; I have exchanged several emails with Vignoli and spoke to him by video chat while researching this article. In one exchange I asked if the foundation would publish the audits or even confirm the audit firms that it had worked with. He said that the foundation "cannot share the audits and names of the auditors in public". On April 17, Meeks posted an update in which he wrote that TDF is making misleading claims: "there is no confirmed misuse of funds in the most up-to-date audit".

Non-renewals

Some snippets from an audit, however, appear to have leaked out via public conversations on the forum in a discussion started by Dennis Roczek in January 2025. The topic of the discussion was the membership committee deciding not to renew the memberships of three active contributors, including Nouws and Bjoern Michaelsen; the audit results were used as part of the justification to deny renewals.

Nouws shared an email sent by Gustavo Buzzatti Pacheco that included findings from the 2023 audit report that match up with more general statements published by Vignoli. According to Pacheco, the auditor listed several problems. For example, his email stated that the audit concluded there was a misuse of funds in the amount of €20,599.62, and the board may have misused funds in previous years. In addition, he wrote that it found that the board had contacted a new law firm "to provide advice that did not serve the foundations' statutory purpose".

The problems identified in the report meant that there was a possibility that the foundation's status as a nonprofit entity could be revoked, and it could face tax payments and penalties that might jeopardize the foundation altogether. Pacheco said that, since Nouws had been involved in the decisions "that led to the unacceptably serious situation TDF faces today", the committee had chosen not to renew his membership.

Simon Phipps, who had at one time been on the membership committee and is currently serving as deputy chairperson of the board, questioned the committee's decision. He cited the membership requirements and said the only grounds in the statutes for non-renewal were "the absence of an application or the failure to indicate the intention to participate".

Board member Paolo Vecchi replied that "the bylaws provide the MC with full authority over this". Phipps argued that TDF's statutes did not grant the committee the power to withhold membership if a person met the requirements, and that expulsion of a member required a separate process with a hearing. Eyal Rozenberg pointed out that the document Vecchi cited was not valid community bylaws, and complained that the membership committee had not held a hearing or communicated its intent to expel the members. "So, they have done nothing wrong which merits an expulsion, in the sense no process within the TDF has demonstrated any such wrongdoing."

The discussion continued off and on through April 2025. At one point Vecchi argued that the situation was complex "as we have to consider the German Stock Corporation Act" for matters not clearly stated in TDF's statutes. He argued that the committee could have revoked the memberships while the individuals were on the board, "due to acts that looked like they were going pretty much against TDF's best interests", but that it had only received written confirmation of that, in the form of the audits, during the current board term.

Let's anyway evaluate the situation as if it were an expulsion, which [it] is not, and hear what the person has to say. The MC still has an audit confirming the acts that justify the expulsion so what would be the point of a hearing?

Rozenberg replied that the matter is not complex, and said that "a foundation is not a Stock Corporation". He said that Vecchi had "put quite a bit of effort in making [the situation] more complex and troubling", and called for him to be "taken out of the [board of directors] as soon as possible".

Delayed elections and new bylaws

According to the usual election schedule, TDF members were supposed to have an opportunity to elect a new board at the end of 2025, with the changes to take effect in February 2026. That has not happened, however, for reasons we will get into shortly. According to the statutes, the foundation should hold elections every two years for the board of directors and membership committee.

The board and membership committee elections are generally offset by a year; the most recent membership committee election was held in 2024. The most recent board election was held in 2023, and directors took office in February 2024. Vecchi was initially a deputy on the board; he was seated as a full member after another board member resigned. The election process should have begun in October 2025; the current board's term expired in February of this year.

The membership committee did not begin the board election process, however, and did not announce its intention to delay the election. While the election should have been ongoing, the board was working on new bylaws. In November 2025, board member Sophie Gautier announced an initial version of additional bylaws ("community bylaws") to extend TDF's statutes, which included a section dealing with revocation of membership. It included some fairly standard reasons a person might lose membership, such as abusing other members on TDF discussion forums, violating the code of conduct, and (of course) members could voluntarily notify the committee that they wish to resign for whatever reason.

The proposed bylaws also featured a somewhat unusual condition: a requirement that members affiliated with "a company/organization having a dispute or case with TDF" must resign immediately. Failing that, the committee can cancel the person's membership and block reapplication "for a suitable time frame". The nature of a dispute or case was not defined. Unsurprisingly, there was a fair amount of debate about the proposed bylaws in the announcement thread.

A final version was submitted for a vote on January 15 as a joint proposal from Gautier and Vecchi; she said that TDF urgently needed to show a change in behavior, and that the bylaws were part of that. Meeks said that it was "deeply unfortunate to vote these through in this profoundly flawed form", and that there was an important question left unanswered:

Has this text been checked and confirmed as being fully compatible with the statutes by a qualified and insured Rechtsanwalt in Germany who has suitable liability insurance and is a member of the bar?

No one, to date, has given a direct answer to that question. I posed the question to Vignoli by email; he responded that the bylaws had been reviewed "by lawyers", but did not confirm that the lawyers were practicing in Germany or licensed to practice there.

Meeks also quoted the final text of the bylaws (ODF document) which now state that members "involved in legal claims for endangering the foundation" must resign their membership by notifying the membership committee; in addition, the bylaws also state that if a member is affiliated with a company or organization involved in a legal claim, then the member must resign as well. If a member does not resign voluntarily, the membership committee can revoke the membership, and the person is not eligible to apply again "for a period of no less than three years". Meeks asked if the board could specify which organizations that would apply to and said: "It would be good to know whom the board thinks should resign from the membership before the next elections start."

Phipps objected to the vote and called for the motion to be withdrawn. It was not, and on January 19, TDF's executive director Florian Effenberger announced that the vote had passed with five in favor and one opposed, no abstentions. There was a great deal of further debate over the fact that Phipps's vote was not counted because, according to Effenberger, the vote included a conditional and was not valid.

Vignoli said in an email that the members who were removed were informed in advance with two separate messages before their memberships were revoked. "So, the suspension did not come out of the blue." He said that no one was happy about applying this new rule to the members, but it was "a necessary evil, to prevent unforeseen consequences for the foundation." The behavior of many people from both parties had led to a situation that was difficult to solve. "At the moment, the focus is on a solution, not on details (and in this case the three years of suspension are a detail, although important, but still a detail)".

Old wounds and old problems

Many of the people involved in this current situation were part of the formation of TDF and have been participating in its development since the beginning; indeed, even before its beginning, in the days before Sun Microsystems was bought by Oracle, and OpenOffice.org was sent to languish at the Apache Software Foundation. It is clear from reading the public discussions, both new and old threads, as well as communicating with people involved in TDF and those removed from its membership, that there are differing opinions about how to achieve the foundation's goals, the roles that ecosystem companies should play in developing LibreOffice, as well as some deep personal grievances between members of the various factions that have evolved over the years.

For example, in 2019 there was a plan approved by the board to create a community benefit company called The Document Collective (TDC) that would conduct "commercial activities that complement the community's work" (begins at slide 19). It was controversial at the time and never got off the ground; in July 2024, the board's decision was revoked, effectively killing it for good. But it has remained at the forefront of the current discussions.

The problems around trademark usage and use of funds stem from efforts over the years to find ways to fund LibreOffice development and effectively promote its usage in an ever-changing market. In 2020, Meeks outlined problems faced by "ecosystem companies" in a message that is worth reading in full. As he noted, he looked at the problem from a vendor's point of view, but the problems he identified are real ones that are common where open-source projects and vendors meet. Collabora has had a hard time finding ways to differentiate its products against LibreOffice in order to monetize its work to ensure that it can continue to contribute to the project.

In a discussion in 2023, Jean-Baptiste Faure complained about conflicts of interest and said that companies with members on the board of directors "should not be allowed to respond to a call for tenders from TDF". Meeks responded that the issue of conflicts of interest in awarding tenders was overstated, and that board members were "completely recused" on matters related to competing tenders and provided some context:

Let me put some rough, perhaps not already public, numbers to this - [Collabora] has bid on ~24 tenders and won ~7 - ie. under 1/3rd of them. We've been in business for ~10 years. A rough adding up of what TDF has paid in total comes to some small (single digit?) %age of both TDF's income, and Collabora's. That seems neither excessive nor under-contested to me.

In an email to me, Meeks said: "TDF are by a very long distance our worst ever customer, the staggering expense of dealing with all of this angst wipes out any commercial benefit."

Despite any angst in dealing with TDF, Collabora has had a huge hand in LibreOffice development through the years. According to a state of the project blog post published on April 9, Collabora was the largest single contributor to LibreOffice in the last 12 months based on Git data; 47 people employed by Collabora contributed 43% of the patches, while eight developers employed by TDF were responsible for 37% of the patches. Thus, TDF has effectively removed many of its most prolific contributors from any say in governance of the foundation. It has not barred them from contributing if they so choose, but it does not seem likely to motivate future contributions from individuals or Collabora.

TDF had anticipated that, however. In the "end to speculation" blog post, Vignoli said that the foundation had been "preparing for some time for Collabora's announcement, by hiring developers and exploring new partnership opportunities". LWN covered some of the tensions about hiring its own developers in 2022. Vignoli elaborated on what he meant by preparing in a post on April 17:

It would be a mistake to read the current moment as purely defensive. While managing a governance crisis that it did not choose, TDF has continued to invest in the software and the community that give the foundation its purpose.

In the past twelve months, TDF's eight staff developers contributed 4,077 patches to LibreOffice. Two additional developers have recently joined TDF staff, with one specifically assigned to LibreOffice Base, a module that has been under-resourced for years. Also, work is underway on deeper code modernization: architectural improvements that have accumulated for decades and that require sustained, focused effort rather than feature-driven patch contributions. Announcements on this work are forthcoming.

TDF's income is primarily in the form of donations; according to the public ledgers, it received more than €1,976,000 in donations in the 2025 calendar year. It spent about €590,000 on contractors ("freelancers"), and about €500,000 on employee salaries and taxes during the same period. Time will tell how the foundation's strategy to bring more development in-house works out.

It is still an open question whether TDF's nuclear option of removing all Collabora-affiliated members was actually something specifically recommended by auditors or legal counsel. Behrens does not think so, and said this in an email:

I consider the expulsion without apology of so many long-time contributors to LibreOffice to be deeply hurtful. They are also likely illegal, disproportionate & in no way useful to solve any of TDF's past or future problems. Instead, it seems to be the power-grab of a desperate & unpopular board, ahead of elections.

Vignoli's April 17 blog post, however, claims the move is "a governance safeguard doing exactly what governance safeguards are designed to do". He also said "a foundation even partially governed by the people associated with its largest commercial contributor is not a foundation but a subsidiary". That is, to say the least, an unusual view. Plenty of open-source foundations and similar bodies have representation from their largest commercial contributors. At any rate, TDF had already demonstrated the ability to block someone from serving on the membership committee despite being voted into the office by trustees.

Specifically, in 2024, the board decided not to seat Nouws on the membership committee despite the fact that he garnered enough votes. Instead, the board voted (five in favor, two against) to pass him over and appoint another candidate on the basis of conflicts of interest and Nouws's past actions. The announcement included board member László Németh's objection to the decision as a comment. He said that one of the board's directors had "bypassed official channels" to seek legal advice about whether Nouws's "past actions as a director [are] to be taken in consideration by this board to evaluate if he should ever again become [a] member of one of TDF's bodies?"

Effenberger has announced that the board will hold meetings on April 20 and April 22 for strategic planning "regarding the next steps of the LibreOffice development". Those calls will be private, but he said that the board would keep the community posted on next steps and engage in a public discussion. At some point, presumably, the membership committee should be announcing the overdue board election. Meeks said that he hopes TDF "will engage constructively in mediation" to solve the disagreements between the parties. "There have been a number of generous offers around this on the table for months or even years now. I look forward to engaging with them there."

There is little doubt that this will be an eventful year for TDF and LibreOffice. Its next election, when it finally arrives, is bound to stir up some pointed conversations. It will also be interesting to see what comes from Collabora's plans of a streamlined Collabora Office and whether it can build a community around its own fork. We will, of course, be covering things along the way.

Comments (25 posted)

Page editor: Joe Brockmeier

Inside this week's LWN.net Weekly Edition

  • Briefs: Firefox zero-days; kernel code removal; reproduceible Arch; Debian election; Firefox 150; Forgejo 15.0; Git 2.54.0; KDE Gear 26.04; LillyPond 2.26.0; Rust 1.95.0; Quotes; ...
  • Announcements: Newsletters, conferences, security updates, patches, and more.
Next page: Brief items>>

Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds