[news.software.b] B2.11 News Problems

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