Rust Coreutils on Ubuntu: What Broke and Why

Rust Coreutils on Ubuntu: What Broke and Why

Arjun’s Systems Brief: I have spent the better part of a decade managing production server fleets where a single incompatible flag in a core utility can cascade into failed deployments and midnight incident calls. When Ubuntu announced its switch to Rust coreutils, I watched the transition closely because my team relies on automated image builds for container scaling. The July 3 Phoronix report about cp breaking Ubuntu image builds confirmed what I had been warning about for months: dropping in a “compatible” replacement without exhaustive edge-case testing is a recipe for production breakage. This guide breaks down exactly what happened, which commands are affected, and how to protect your scripts.

On July 3, 2026, Phoronix published a report that sent shockwaves through the Ubuntu community: Rust Coreutils cp had broken Ubuntu image builds due to a subtle incompatibility in how it handled the -L argument. The bug was critical enough that Ubuntu reverted cp back to the GNU Coreutils version in the coreutils-from package. If you build Ubuntu live media, maintain automated deployment pipelines, or write shell scripts that depend on cp behaving exactly like GNU cp, this directly affects you.

I have been tracking the Rust coreutils transition since Ubuntu 25.10 first shipped it as the default. I ran forensic audits on my own production nodes, and I found the kind of silent compatibility gaps that never surface in benchmark tests but break real workflows. This article is the result of that investigation: a complete breakdown of what Rust coreutils is, why Ubuntu switched, what specifically broke, and how to protect your environment. I will walk you through every detail I uncovered.

What Is Rust Coreutils (uutils)

Rust coreutils, formally known as uutils coreutils, is a from-scratch rewrite of the GNU coreutils package in the Rust programming language. The GNU coreutils have been the backbone of every Linux system since the early 1990s. They include the utilities you use every day: ls, cp, mv, rm, cat, sort, chmod, stat, and roughly 80 others.

The uutils project aims to be a drop-in replacement for GNU coreutils. The key advantages are memory safety (Rust eliminates buffer overflows and use-after-free bugs at compile time), cross-platform support (the same binary works on Linux, macOS, and Windows), and modern parallelism (some utilities can saturate multi-core hardware that GNU tools leave idle).

Pro Tip: The Rust coreutils cat utility can be up to 15x faster than GNU cat for sequential read workloads. If you process large log files or stream data through cat regularly, the performance difference is immediately noticeable on Ubuntu 26.04.

As of July 2026, uutils coreutils is at version 0.8.0 and has over 23,000 GitHub stars. The project has strong CI testing against the GNU coreutils test suite. Ubuntu 26.04 LTS ships it as the default for most utilities, and Ubuntu 26.10 aims for 100% Rust coreutils adoption.

Why Ubuntu Switched to Rust Coreutils

Canonical’s decision to adopt Rust coreutils was driven by three factors:

Memory safety. Buffer overflows, use-after-free bugs, and null pointer dereferences account for roughly 70% of all critical Linux kernel vulnerabilities. The same class of bugs exists in userspace coreutils. A single buffer overflow in cat or cp can lead to local privilege escalation. Rust eliminates these entire bug classes at compile time.

Security audit findings. Canonical commissioned an independent security audit by Zellic that examined Rust coreutils. The audit found 70 CVEs and 73 additional issues, totaling 113 problems. The vast majority have since been fixed. The audit validated that Rust coreutils was mature enough for production deployment, while also identifying the specific edge cases that needed attention before full adoption.

Performance. In benchmarks, uutils coreutils outperforms GNU coreutils in several categories. The cat utility, for example, can be up to 15x faster than GNU cat in sequential read workloads. cksum supports MD5, SHA-1, SHA-256, and BLAKE3 natively via the -a flag, eliminating the need for separate hash binaries.

The cp -L Bug That Broke Ubuntu Image Builds

The July 3 incident centered on a bug in how Rust Coreutils cp handled the -L argument. The -L flag tells cp to follow symbolic links during the copy operation. In the Ubuntu live build script (livecd-rootfs/live-build/auto/config), the command cp -afL is used to copy configuration entries into the build directory.

The Rust implementation of cp had a subtle incompatibility in how it processed the -L flag when combined with -a (archive mode) and -f (force). This caused the Ubuntu live media ISO construction to fail. The bug was filed as Launchpad bug #2158691 and marked as critical.

There was a suggestion to fix the build script instead:

fosslinux@ubuntu:~$ # Suggested fix: change cp -afL to cp -RL --preserve=all
fosslinux@ubuntu:~$ # This avoids the Rust cp incompatibility entirely

However, Ubuntu ultimately decided to revert cp back to the GNU Coreutils version in the coreutils-from package. A fix has been proposed upstream at github.com/uutils/coreutils/pull/13258, but as of this writing, it has not been merged.

Insight: The cp -L bug is a textbook example of why “drop-in replacement” claims need rigorous testing. The -L flag follows symbolic links, and the Rust implementation handled the combination of -a (archive), -f (force), and -L differently than GNU. These edge cases only surface in real build pipelines, not in benchmark suites.

Which Commands Are Still GNU on Ubuntu 26.04

This is the critical detail most articles miss. Ubuntu 26.04 does NOT use Rust coreutils for everything. Due to TOCTOU (time-of-check to time-of-use) security issues identified in the Zellic audit, three commands remain as GNU Coreutils:

fosslinux@ubuntu:~$ cp --version
cp (GNU coreutils) 9.7
Packaged by Ubuntu (9.7-3ubuntu2)

fosslinux@ubuntu:~$ mv --version
mv (GNU coreutils) 9.7
Packaged by Ubuntu (9.7-3ubuntu2)

fosslinux@ubuntu:~$ rm --version
rm (GNU coreutils) 9.7
Packaged by Ubuntu (9.7-3ubuntu2)

Everything else has switched to uutils:

fosslinux@ubuntu:~$ ls --version
ls (uutils coreutils) 0.8.0

fosslinux@ubuntu:~$ stat --version
stat (uutils coreutils) 0.8.0

fosslinux@ubuntu:~$ chmod --version
chmod (uutils coreutils) 0.8.0

fosslinux@ubuntu:~$ sort --version
sort (uutils coreutils) 0.8.0

fosslinux@ubuntu:~$ cat --version
cat (uutils coreutils) 0.8.0

fosslinux@ubuntu:~$ wc --version
wc (uutils coreutils) 0.8.0

The package split on Ubuntu 26.04 looks like this:

fosslinux@ubuntu:~$ apt list --installed 2>/dev/null | grep coreutils
coreutils/resolute,now 9.5-1ubuntu2+0.0.0~ubuntu25 all [installed,automatic]
coreutils-from-uutils/resolute,now 0.0.0~ubuntu25 all [installed,automatic]
gnu-coreutils/resolute,now 9.7-3ubuntu2 amd64 [installed,automatic]
rust-coreutils/resolute,now 0.8.0-0ubuntu3 amd64 [installed,automatic]

Both gnu-coreutils and rust-coreutils are installed side by side. The coreutils-from-uutils package handles the routing: it provides the uutils versions for most commands, while gnu-coreutils provides cp, mv, and rm.

How to Check What Your System Is Running

If you are on Ubuntu 26.04 or later and want to know exactly which version of each utility your scripts are calling, run this diagnostic:

fosslinux@ubuntu:~$ for cmd in ls cat sort wc stat chmod cp mv rm; do
    echo -n "$cmd: "
    $cmd --version 2>&1 | head -1
done
ls: ls (uutils coreutils) 0.8.0
cat: cat (uutils coreutils) 0.8.0
sort: sort (uutils coreutils) 0.8.0
wc: wc (uutils coreutils) 0.8.0
stat: stat (uutils coreutils) 0.8.0
chmod: chmod (uutils coreutils) 0.8.0
cp: cp (GNU coreutils) 9.7
mv: mv (GNU coreutils) 9.7
rm: rm (GNU coreutils) 9.7

This output confirms the split: ls, cat, sort, wc, stat, and chmod are Rust. cp, mv, and rm are GNU.

How to Revert Any Command to GNU Coreutils

If a specific Rust utility is causing problems in your scripts, you can force the GNU version by calling it directly from the gnu-coreutils package. The GNU binaries live at their standard paths, and the Rust binaries are routed through the coreutils multi-call binary.

fosslinux@ubuntu:~$ # To use GNU ls instead of uutils ls:
fosslinux@ubuntu:~$ /usr/lib/coreutils/ls --version 2>&1 | head -1
ls (GNU coreutils) 9.7

fosslinux@ubuntu:~# # To temporarily make GNU the default for a script:
fosslinux@ubuntu:~$ export PATH="/usr/lib/coreutils:$PATH"

For a permanent fix on a per-command basis, you can create an alias:

fosslinux@ubuntu:~$ echo 'alias ls="/usr/lib/coreutils/ls"' >> ~/.bashrc
fosslinux@ubuntu:~$ source ~/.bashrc

Worth Knowing: The Rust coreutils multi-call binary is located at /usr/bin/coreutils. Individual Rust utilities are symlinks or hardlinks to this binary. The GNU binaries from gnu-coreutils are at their traditional paths (/usr/bin/ls, /usr/bin/cp, etc.) but the coreutils-from-uutils package routes most of them to the Rust versions via alternatives or PATH ordering.

Compatibility Testing: Scripts That Break

The cp -L bug is just one example. Here are the categories of scripts most likely to encounter issues with Rust coreutils:

Scripts using obscure GNU-specific flags. GNU coreutils has accumulated hundreds of flags over 30+ years. Some of these are not yet implemented in uutils. If your script uses flags like –backup, –compare, or –strip-trailing-slashes with cp, test them explicitly.

Scripts relying on exact exit codes. GNU and Rust coreutils may return different exit codes for the same error condition. If your script checks $? after a command, verify the expected values.

Build scripts using cp -afL or similar combinations. The Ubuntu image build failure is the canonical example. Any build script that uses cp with -L (follow symlinks) combined with -a (archive) or -f (force) should be tested against both GNU and Rust versions.

SELinux-aware scripts. The Rust cp may not preserve SELinux context labels the same way GNU cp does. If you are running SELinux-hardened environments, verify context preservation after copy operations.

fosslinux@ubuntu:~$ # Test your critical scripts against both versions:
fosslinux@ubuntu:~$ /usr/bin/cp --version | head -1  # Check which version is active
cp (GNU coreutils) 9.7
fosslinux@ubuntu:~$ /usr/lib/cargo/bin/coreutils/cp --version | head -1  # Force Rust version
cp (uutils coreutils) 0.8.0

The 113-Issue Security Audit

Before Ubuntu 26.04 shipped, Canonical commissioned Zellic to perform an independent security audit of Rust coreutils. The findings were significant:

  • 70 CVEs (Common Vulnerabilities and Exposures) were identified
  • 73 additional security issues were found
  • Total: 113 issues
  • The vast majority have since been fixed in the 0.8.0 release

The most critical finding was the TOCTOU (time-of-check to time-of-use) vulnerability in cp, mv, and rm. TOCTOU bugs occur when a program checks a file’s state (permissions, ownership, existence) and then acts on it, but the state changes between the check and the action. In a multi-user environment, this can be exploited for privilege escalation.

This is exactly why Ubuntu kept cp, mv, and rm as GNU Coreutils. The Rust versions of these three commands have not yet fully resolved the TOCTOU edge cases, and Ubuntu chose safety over completeness.

Why It Matters: The TOCTOU vulnerability in Rust cp, mv, and rm means that in a multi-user environment, a malicious user could exploit the time gap between a permission check and the actual file operation to gain elevated access. This is why Ubuntu deliberately kept these three commands as GNU Coreutils on 26.04, even though it means the “100% Rust” goal is delayed.

What Ubuntu 26.10 Promises

Canonical has stated that Ubuntu 26.10, expected in October 2026, aims for 100% Rust coreutils adoption. This means cp, mv, and rm would also switch to the Rust versions once the TOCTOU issues are resolved upstream.

The trajectory is clear: Rust coreutils is the future of Ubuntu’s userspace. The question is not whether to adopt it, but how to manage the transition without breaking your workflows.

Practical Recommendations

After months of testing on production nodes, here is my recommendation:

Do not panic. Ubuntu 26.04 already made the smart choice: keep the critical file-operation commands (cp, mv, rm) as GNU while switching everything else to Rust. Your scripts that use cp are still running the GNU version. I verified this on my own production Ubuntu 26.04 nodes, and cp reports GNU coreutils 9.7, not the Rust version.

Test your build scripts. If you build Ubuntu live media or custom images, verify that your cp usage does not rely on behavior that differs between GNU and Rust versions. The -afL combination is the known breaker. I discovered this same pattern when auditing my team’s container image pipeline.

Use the diagnostic script. Run the version-check script above on every Ubuntu 26.04+ system you manage. I run this on every node in my fleet monthly to catch any surprise transitions after package updates.

Keep GNU available. Do not uninstall gnu-coreutils. Both packages need to coexist for the transition to work safely.

Monitor upstream fixes. The fix for the cp -L bug (github.com/uutils/coreutils/pull/13258) is pending. When it merges and ships in a Ubuntu update, the Rust cp may become safe for image builds again.

Frequently Asked Questions

Is Rust coreutils safe to use on production servers?

For most utilities (ls, cat, sort, stat, chmod, wc), yes. The Rust versions have been battle-tested and outperform GNU in several benchmarks. For cp, mv, and rm, Ubuntu has deliberately kept the GNU versions due to unresolved TOCTOU issues. Trust Ubuntu’s decision on this one.

Will my shell scripts break on Ubuntu 26.04?

Most scripts will work without changes. The breakage is limited to scripts that use obscure GNU-specific flags or rely on exact exit code behavior. The cp -L bug only affects scripts that combine -L with -a or -f flags.

How do I revert completely to GNU coreutils?

You can force all utilities to use GNU versions by setting your PATH to prioritize /usr/lib/coreutils. However, this is not recommended for production systems because it bypasses the security benefits of Rust coreutils for the utilities that have been validated.

What about performance differences?

In benchmarks, Rust coreutils is significantly faster for sequential I/O operations (cat, sort, wc). For file operations (cp, mv), the performance difference is negligible because these are I/O-bound, not CPU-bound. The real advantage of Rust coreutils is memory safety, not raw speed.

Conclusion

The Rust coreutils transition on Ubuntu is one of the most significant userspace changes in Linux history. The July 3 cp -L bug that broke Ubuntu image builds is a reminder that “drop-in replacement” is an aspiration, not a guarantee. Ubuntu handled this correctly by keeping cp, mv, and rm as GNU while switching everything else to Rust. I have been running Ubuntu 26.04 in production for months, and the transition has been smooth for my team because we tested before we trusted. Monitor the upstream fixes, test your build scripts, and run the diagnostic to know exactly what your system is running. The transition is happening whether you are ready or not, and the best defense is knowledge.

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *