mike@tredysvr.Tredydev.Unisys.COM (Mike Marciniszyn) (05/26/90)
We are running into some problems with our B2.11 news software. We are running System V3.1/386 on a PC/AT platform. Here is an emumeration of three problems I have found. 1). expire -r must be run as root or NEWSUSR even if the a.out is setuid to NEWSUSR. (At least on SYSV). if (nohistory) { ohfd = xfopen(ACTIVE, "r"); if (dorebuild) { /* Allocate initial space for multiple newsgroup (for an article) array */ multhist = (struct multhist *)calloc (SPACE_INCREMENT, sizeof (struct multhist)); mh_size = SPACE_INCREMENT; (void) sprintf(afline, "exec sort -t\t +1.6 -2 +1 >%s", NARTFILE); if ((nhfd = popen(afline, "w")) == NULL) xerror("Cannot exec %s", afline); } else nhfd = xfopen("/dev/null", "w"); } else { ohfd = xfopen(ARTFILE, "r"); nhfd = xfopen(NARTFILE, "w"); } The code will then supply the new history file into the pipe opened by the popen(). The NARTFILE file created by the shell under popen() (and written by sort) ends up being open'ed by the real user instead of the effective user. Later inews attempts fail because they cannot write history. This is the most minor of the problems as there is an obvious detour. The fix would seem to be to test to see if the NARTFILE is owned by NEWSUSR. If it is not, play some setuid games, and chown's to cause the file to be owned by NEWSUSR. 2). The LOCKF record locking code in inode.c tests for lock procure failure incorrectly. The code is as follows: if (lockf(fileno(actfp), F_TLOCK, 0) < 0 && errno == EAGAIN) The SVID (issue 2) says the the lock failure errno is EACCES but that SVID conformant programs should OR test both EACCES and EAGAIN. 3). When LOCKF is defined at compile time, and the above errno check is corrected, any news coming in during an expire gets put into the /usr/spool/news/.rnews (as expected). The batches put there get trashed by the rnews -U and the rnews -U ends up in an infinite loop invoking rnews -p trying to spool and unspool 0 length files forever. Here is some of the code involved in inews.c: actfp = xfopen(ACTIVE, "r+"); #ifdef BSD4_2 if (flock(fileno(actfp), LOCK_SH|LOCK_NB) < 0 && errno == EWOULDBLOCK) #else /* !BSD4_2 */ #ifdef LOCKF if (lockf(fileno(actfp), F_TLOCK, 0) < 0 && (errno == EAGAIN || errno == EACCES) ) #else /* !LOCKF */ sprintf(bfr, "%s.lock", ACTIVE); if (LINK(ACTIVE,bfr) < 0 && errno == EEXIST) #endif /* V7 */ #endif /* !BSD4_2 */ spool_news = TRUE; else { #ifdef SPOOLNEWS if (argc > 1 && !strcmp(*(argv+1), "-S")) { argc--; argv++; } else spool_news = TRUE; #endif /* SPOOLNEWS */ #if !defined(BSD4_2) && !defined(LOCKF) (void) UNLINK(bfr); #endif /* !BSD4_2 && !LOCKF */ } if (argc > 1 && !strcmp(*(argv+1), "-U")) { dounspool(); /* NOT REACHED */ } if (!strncmp(ptr+1, "rnews", 5)) { mode = PROC; if (spool_news) { dospool((char *)NULL, FALSE); /* NOT REACHED */ } #ifdef NICENESS nice(NICENESS); #endif /* NICENESS */ } else if (argc < 2) goto usage; The rnews -U procures the record lock and dounspool() goes into a loop invoking rnews -S -p xxxxxx via system(). After the system() completes it removes the file passed by the -p. The rnews subprocess runs through the same above code, detects the lock failure, sets spool_news, calls dospool(), and creates a zero length file (because stdin is /dev/null) and exits. The rnews -U then continues to unlink all of the real batches that are being replaced with zero length files. It continues to run rnews -S -p xxxxxx with the zero length files forever. The locking code seems to have a difference between the file based locking and the record based locking. When file based locking is being used (!BSD4_2 && !LOCKF), the link is attempted with ACTIVE.lock and if sucessfull, it is then unlinked. (See the UNLINK just above the test for the -U argument.) The record lock versions would continue to hold the record lock, causing the above problem. If the code should be doing a momentary test for an expire (as in the file lock case), what prevents an expire from starting just after the test? Could the history or active files be trashed? If the code really should hold on to the lock, either it has to released at an appropriate time, or the child rnews programs have to realize that they are being run from rnews -U and that the lock test is not relevant. If any one is aware of fixes to these problems or archives of fixes to B2.11 in general please let me know. Our code came from the CSNET info archives and is perhaps a year old. Mike Marciniszyn UNISYS Tredyffrin PA. UUCP: tredysvr!mike DOMAIN: mike@tredysvr.tredydev.unisys.COM