gduncan@uvicctr.UUCP (Gary Duncan) (09/12/86)
Index: bin/passwd.c 4.2BSD Description: The precautions taken by the passwd program (and also the ucb/chsh, ucb/chfn programs) to prevent multiple update trashing of the passwd file are not adequate enough. (I believe the vipw program is fine though). The program works by creating a temporary copy of the updated passwd file by opening /etc/ptmp in exclusive-use mode then copying and modifying entries from the original. No problem so far. The program then: 1. renames the temporary file to /etc/passwd 2. closes the stream pointer for the file. Unfortunately the exclusive-use mode is lost on rename before the stream buffers have been flushed. If a process switch occurs between #1 and #2, another process could update the now truncated passwd file and havoc may ensue. Corruption is very unlikely to occur in practice, but is possible. Apologies if this has been posted before. Credit for finding this bug really belongs to Nigel Horspool. Repeat-By: Invoke passwd twice and be very lucky (or unlucky depending on how you view it) with the timing of the processes. You can simulate the bug by extending the time between the rename and fclose (ie. with a sleep or read from the terminal -- you may also want to remove the SIGSTP ignore signal so you can ^Z) and starting up a second passwd at this point. Fix: Add a fflush(tf) immediately before the rename to flush the buffers. *** passwd.c.old Sun Jul 10 17:55:46 1983 --- passwd.c Thu Sep 11 15:44:09 1986 *************** *** 166,171 pwd->pw_shell); } endpwent(); if (rename(temp, passwd) < 0) { fprintf(stderr, "passwd: "); perror("rename"); unlink(temp); --- 166,172 ----- pwd->pw_shell); } endpwent(); + fflush(tf); if (rename(temp, passwd) < 0) { fprintf(stderr, "passwd: "); perror("rename"); unlink(temp);
chris@umcp-cs.UUCP (Chris Torek) (09/17/86)
In article <185@uvicctr.UUCP> gduncan@uvicctr.UUCP (Gary Duncan) writes: >Description: > the passwd program ... works by creating a temporary copy of the > updated passwd file by opening /etc/ptmp in exclusive-use mode then > copying and modifying entries from the original. No problem so far. > The program then: > 1. renames the temporary file to /etc/passwd > 2. closes the stream pointer for the file. > Unfortunately the exclusive-use mode is lost on rename before the > stream buffers have been flushed. ... >Fix: > Add a fflush(tf) immediately before the rename to flush the buffers. > > endpwent(); >+ fflush(tf); > if (rename(temp, passwd) < 0) { It would also be a very good idea to check for ferror(tf), in case the root file system is full. Make that: endpwent(); (void) fflush(tf); if (ferror(tf)) /* do something */ This, too, is quite unlikely, but could have drastic consequences. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu