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:
- Using LLMs to find Python C-extension bugs: exploring how to find and fix bugs using LLMs without contributing to maintainer burnout.
- The 7.0 scheduler regression that wasn't: reports of a regression caused by the lazy-preemption mode were greatly exaggerated.
- One Sized trait does not fit all: a proposal to add a hierarchy of Sized traits to Rust.
- Dependency-cooldown discussions warm up: a debate about the best ways to avoid supply-chain attacks.
- The first half of the 7.1 merge window: a peek at what's coming in the next kernel release.
- A more efficient implementation of Shor's algorithm: researchers publish proof of a breakthrough without sharing their methods.
- Digging into drama at The Document Foundation: the nonprofit behind LibreOffice is in the spotlight for unfortunate reasons.
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.
Using LLMs to find Python C-extension bugs
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.
The 7.0 scheduler regression that wasn't
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.
One Sized trait does not fit all
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.
Dependency-cooldown discussions warm up
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.]
The first half of the 7.1 merge window
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.
A more efficient implementation of Shor's algorithm
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.
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.
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.
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.
Digging into drama at The Document Foundation
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.
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.
