Fixing a Buffer Overflow in UNIX v4 Like It’s 1973
Introduction
In 2025, the only known copy of UNIX v4 surfaced on a magnetic tape. This version marks a pivotal moment in computer history: the rewriting of UNIX into C. Enthusiasts quickly recovered the data and successfully ran the system on a PDP-11 simulator.
Fascinated by this artifact, I set up an instance to explore it. Because the distribution includes the source code, I examined the implementation of several core utilities. While auditing the su(1) program, I identified a bug. Let’s fix it.
The UNIX v4 su(1) program
Although more than 50 years old, the su program functions similarly to its modern variant. As a setuid-root executable, it validates the root password. If the user provides the correct credentials, the program spawns a root shell, allowing an unprivileged user to escalate privileges.
The source file, su.c , contains fewer than 50 lines of code.
/* su -- become super-user */ char password [ 100 ]; char pwbuf [ 100 ]; int ttybuf [ 3 ]; main () { register char * p , * q ; extern fin ; if ( getpw ( 0 , pwbuf )) goto badpw ; ( & fin )[ 1 ] = 0 ; p = pwbuf ; while ( * p != ':' ) if ( * p ++ == '\0' ) goto badpw ; if ( *++ p == ':' ) goto ok ; gtty ( 0 , ttybuf ); ttybuf [ 2 ] =& ~ 010 ; stty ( 0 , ttybuf ); printf ( "password: " ); q = password ; while (( * q = getchar ()) != '
' ) if ( * q ++ == '\0' ) return ; * q = '\0' ; ttybuf [ 2 ] =| 010 ; stty ( 0 , ttybuf ); printf ( "
" ); q = crypt ( password ); while ( * q ++ == * p ++ ); if ( *-- q == '\0' && *-- p == ':' ) goto ok ; goto error ; badpw : printf ( "bad password file
... continue reading