Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site bu-cs.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!bu-cs!root From: root@bu-cs.UUCP (Barry Shein) Newsgroups: net.bugs.4bsd Subject: Re: The definitive fix for tips' lock file problem Message-ID: <476@bu-cs.UUCP> Date: Tue, 9-Jul-85 17:25:33 EDT Article-I.D.: bu-cs.476 Posted: Tue Jul 9 17:25:33 1985 Date-Received: Thu, 11-Jul-85 08:28:04 EDT References: <1942@ukma.UUCP> Organization: Boston Univ Comp. Sci. Lines: 170 >RE: fix for tip involving keeping parent around setuid() to remove lock Well, I see the fix and there is nothing wrong with it per se *but* I still prefer my fix I mentioned earlier to this list: To leave the lock files around always and fix the uucp lock routines to use soft file locks on those files (lockf() in 4.2 and SYSVR2.) This solves two and one half problems at once: First, if the process dies for *any* reason the lock is freed, regardless of UID, sys crash, etc (suid might only be needed on startup to create the lock or something in rc could make sure it's there, or it just oughta be there like /etc/init oughta be there, it's part of installing a line as available.) Second, it gets rid of the original suid problem, you can probably run w/o setuid entirely on most systems (give or take tty and /etc/phones access), and 'half' it eliminates the need for touching the lock file at all as locked is locked and the only conclusion is there is an active process out there that will have to be killed or respected to free it. Adherence to this fixes all sorts of software which use these psuedo locks (with the initial nuisance of having to re-compile it all.) 1. Yes, I realize that not all unices have soft file locks yet, but now that SYSV has it as well as 4.2 I think it can be accepted as the standard method. Obviously software developers should probably #ifdef this for a while, possibly using the suggested fine fix for deficient systems. 2. Yeah, ya gotta have the source. but you have to in order to implement the other fix so no objection here. Isn't this the kind of thing soft locks were added for? Not a flame, but when something came across as if it should be the standard fix, I thought I would put my 2c in. At any rate, here's the relevant fixed code from my uucplock.c in the tip dir: (yow, have I violated my source license yet? in deference to this concern most of the code is *not* here, just the two small subrs involved, I didn't have the old source around to diff.) For SYSV the fixes (which I have not yet installed) are similar. As I suggested, this should probably incorporate the previously suggested fixes if soft locks are not available and conditionally compile one way or the other. Note: Looking this over now a couple of years later it is still not ideal, there is no reason to unlink and re-create the file which would still require suid but you get the idea. (ie. not definitive, just instructive.) -Barry Shein, Boston University (from ../src/usr.bin/tip/uucplock.c): ------------------ #define LOCKPRE "/usr/spool/uucp/LCK." /* * This code is taken almost directly from uucp and follows the same * conventions. This is important since uucp and tip should * respect each others locks. * * MODIFICATION: (BZS@BU-CS) The way this was written if /usr/spool/uucp * mode did not allow any user to delete files then TIP could * not delete the lock (!!) as it had already done a setuid(getuid()). * The best fix I could think of (which is actually perfect and * solves the vagaries of an 'old' lock) was to keep a soft * lock on the file via flock(2). The problem is it is not * portable to systems that do not support this. For this reason * it is a condtl compilation and the worst case is you get * what everyone else gets and figure out a solution on your * system...at least I warned you of the problem. What UNIX * really needs is temporary files which go * away if the process dies. This is 99% of that except for the * little turd it leaves in the file system. */ #define FLOCK 1 /* file locking supported */ /* remember, gotta do this to UUCP also */ /* ulockf 3.2 10/26/79 11:40:29 */ /* #include "uucp.h" */ #include#include #include #ifdef FLOCK #include #endif /******* * ulockf(file, atime) * char *file; * time_t atime; * * ulockf - this routine will create a lock file (file). * If one already exists, the create time is checked for * older than the age time (atime). * If it is older, an attempt will be made to unlink it * and create a new one. * * return codes: 0 | FAIL */ static ulockf(file, atime) char *file; time_t atime; { struct stat stbuf; time_t ptime; int ret; static int pid = -1; static char tempfile[NAMESIZE]; #ifdef FLOCK int fd ; #endif if (pid < 0) { pid = getpid(); sprintf(tempfile, "/usr/spool/uucp/LTMP.%d", pid); } if (onelock(pid, tempfile, file) == -1) { /* lock file exists */ #ifndef FLOCK /* get status to check age of the lock file */ ret = stat(file, &stbuf); if (ret != -1) { time(&ptime); if ((ptime - stbuf.st_ctime) < atime) { /* file not old enough to delete */ return (FAIL); } } ret = unlink(file); #else if((fd = open(file,O_RDONLY)) < 0) return(FAIL) ; /* shouldn't happen */ if(flock(fd,LOCK_EX | LOCK_NB)) /* get exclusive lock */ { close(fd) ; return(FAIL) ; /* nope, someone really out there */ } flock(fd,LOCK_UN) ; /* probably not necessary */ close(fd) ; unlink(file) ; #endif ret = onelock(pid, tempfile, file); if (ret != 0) return (FAIL); } stlock(file); return (0); } ...stuff excised... static onelock(pid, tempfile, name) char *tempfile, *name; { int fd; fd = creat(tempfile, 0444); ...stuff excised... unlink(tempfile); #ifdef FLOCK if((fd = open(name,O_RDONLY)) < 0 || flock(fd,LOCK_EX | LOCK_NB)) return(-1) ; #endif return (0); }