lepreau@utah-cs.UUCP (06/02/83)
I recently discovered a serious mail locking problem which affects every 4.1 system which has a non-777 /usr/spool/mail, and probably some other systems as well (v7 and 2.8 likely, maybe USG, but haven't checked). The lock files created by the setuid deliverer (binmail) and the non-setuid user agents (Mail, emacs rmail, etc) are created in /usr/spool/mail! So if it's not 777 the user Mail programs merrily go along after their mktemps and links fail, certainly clobbering mail files sometimes. The locking scheme UCB uses is general enough that it is trivially changed to do locking on /tmp. Of course all the programs must be changed "at once," but that took me all of about two minutes a program, as binmail and Mail use almost identical code. MH uses a less general scheme but that could easily be changed to use this scheme. (WARNING to emacs users: as distributed, Gosling's emacs collectmail does only kernel-level locking via CMU's flock ioctl, and if that's not present then it doesn't even pretend to lock. Installation is easily made in it also.) 4.2's locking primitives should be used except they are non-portable. The Berkeley people may or may not get around to fixing this before the release (or ever), so watch for it later also. It appears to me that the check for multiple links in UCB's current binmail, along with the kernel's reseting the setuid bit on chown() plugs the obvious security holes with a 777 mail dir. But we still don't like it for a variety of obvious reasons, including some naive user doing rm -f * there. I remember back over a year and a half ago the discussion on wizards about security, and many many people indicated how easy it was to make the mail mods to protect the spool dir, but no one mentioned the locking protocol. I'm sure this problem is widespread. Fix it now! Diff of mail.c follows; changes in Mail/lock.c are almost identical. -Jay Lepreau lepreau@utah-cs.ARPA, harpo!utah-cs!lepreau *** /tmp/,RCSt1004008 Fri May 13 17:13:18 1983 --- mail.c Thu Apr 7 09:43:12 1983 *************** *** 11,13 static char RCSid[] = ! "$Header: RCS/mail.c,v 1.4 83/04/07 09:01:38 lepreau Exp $"; /* Version 4.13 less 4.9 and 4.11 (4.1c changes) */ --- 11,13 ----- static char RCSid[] = ! "$Header: RCS/mail.c,v 1.6 83/04/07 09:42:55 lepreau Exp $"; /* Version 4.13 less 4.9 and 4.11 (4.1c changes) */ *************** *** 39,40 char *index(); char lettmp[] = "/tmp/maXXXXX"; --- 39,41 ----- char *index(); + char *rindex(); char lettmp[] = "/tmp/maXXXXX"; *************** *** 680,681 * Otherwise, we wait for 5 seconds and try again. */ --- 681,683 ----- * Otherwise, we wait for 5 seconds and try again. + * Lock file is "/tmp/username.lock". */ *************** *** 683,685 char *maillock = ".lock"; /* Lock suffix for mailname */ ! char *lockname = "/usr/spool/mail/tmXXXXXX"; char locktmp[30]; /* Usable lock temporary */ --- 685,688 ----- char *maillock = ".lock"; /* Lock suffix for mailname */ ! char *lockname = "/tmp/tmXXXXXX"; /* target for link */ ! char *lockdir = "/tmp/"; /* where it all happens */ char locktmp[30]; /* Usable lock temporary */ *************** *** 695,696 int statfailed; --- 698,700 ----- int statfailed; + register char *p; *************** *** 698,700 return(0); ! strcpy(curlock, file); strcat(curlock, maillock); --- 702,709 ----- return(0); ! if ((p = rindex(file, '/')) == NULL) /* point to last component */ ! p = file; ! else ! p++; ! strcpy(curlock, lockdir); ! strcat(curlock, p); strcat(curlock, maillock);