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