💾 Archived View for thrig.me › blog › 2024 › 07 › 05 › rcs-surprise.gmi captured on 2024-07-09 at 01:45:35. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
RCS uses getlogin(2) to "lock" a checkout to a particular account,
$ grep getlogin /usr/src/usr.bin/rcs/co.c if ((author = getlogin()) == NULL) err(1, "getlogin"); if ((username = getlogin()) == NULL) err(1, "getlogin");
which means a checked out file may end up with a conflicting username in it, if checked out by a regular user but then checked in by a process that runs as, say, root:
$ touch foo $ ci -minitial -t-test foo foo,v <-- foo initial revision: 1.1 done $ co -l -q foo $ sed -n '/^lock/{n;p;q;}' foo,v jhqdoe:1.1; strict; $ ci -q foo $ doas co -l -q foo $ sed -n '/^lock/{n;p;q;}' foo,v jhqdoe:1.1; strict; $ echo 'ci foo 2>log' | doas at now ... $ cat log foo,v <-- foo ci: foo,v: no lock set by root
The at(1) trick shows one method by which a root login can be obtained, as the getlogin value may persist where one might not expect it to.
$ perl -E 'say getlogin' jhqdoe $ doas perl -E 'say getlogin' jhqdoe $ su -l root Password: # perl -E 'say getlogin' jhqdoe
Another trick, or kluge, is to rewrite the login to the account the cron jobs or whatever will run as. Note that there's a literal tab within the sed command, not a bunch of spaces before "root". (You did look at the file with a hex viewer to confirm what all the bytes are, right?)
$ sed -i '/^locks/{n;s/^[^:]*/ root/;}' foo,v
This will need to be made more complicated if "^locks" can match somewhere else in the initial file, as in that case the above may mangle the file content:
$ printf 'locks\nfoo\nlocks\nbar\n' | sed '/^locks/{n;s/[a-z]*/mangle/;}' locks mangle locks mangle $ printf 'locks\nfoo\nlocks\nbar\n' | perl -ne \ 'if(/^locks/ and !$d){print;$_=readline;s/[a-z]*/first/;$d=1};print' locks first locks bar
Or configuration management could install the right foo and foo,v files at the beginning, in which case the bootstrap would only need to happen when the starting files are put into the configuration management repository.