*BSD News Article 3193


Return to BSD News archive

Xref: sserve comp.unix.bsd:3237 comp.bugs.4bsd:1869
Path: sserve!manuel!munnari.oz.au!news.hawaii.edu!ames!olivea!uunet!iWarp.intel.com|ichips!intelhf!agora!davidg
From: davidg@agora.rain.com (David Greenman)
Newsgroups: comp.unix.bsd,comp.bugs.4bsd
Subject: Patches for kernel namelist db bugs and kvm.c bugs (386BSD)
Message-ID: <1992Aug6.070211.23697@agora.uucp>
Date: 6 Aug 92 07:02:11 GMT
Sender: davidg@agora.uucp (David Greenman)
Organization: Open Communications Forum
Lines: 291


   There are several bugs in the kernel namelist db creation/use and
bugs in kvm.c which causes ps and several other utils to fail to work
correctly.

The kvm.c patches are based in part on, but supersede, the patches posted
on usenet by pk@cs.few.eur.nl (Paul Kranenburg) [which introduced bugs of
its own].
In order for kvm_mkdb to work correctly, vers.o MUST be the first object
linked in the kernel. The Makefile.i386 should read:
SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X vers.o ${SYSTEM_OBJS}

(or vers.o should be first in SYSTEM_OBJS)

And, of course all things that depend on libutil.a will have to be rebuilt.
I should also like to point out that the bug which causes a Floating Point
Exception with 'ps aux' doesn't seem to be in 'ps'. It appears that, under
some conditions, some of the pages in the process data region become write
protected. This is the symptom as it appears to me...I might be completely
wrong :-). I can't explain it any other way. Specifically, the statement
"_pw_keynum = 0;" in setpassent() is usually where the FP exception occurs
for ps. The variable is in valid data space, and gcc produces valid "mov" 
assem. I should also note that ps aux often works just after bootup, but
once it starts failing, it is consistant.

The following are the fixes for kvm.c, & kvm_mkdb:

*** /usr/src/lib/libutil/kvm.c.01orig	Mon Jul 13 02:20:51 1992
--- /usr/src/lib/libutil/kvm.c	Wed Aug  5 03:41:16 1992
***************
*** 309,315 ****
  	 * read version out of database
  	 */
  	bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
! 	key.dsize = (sizeof ("VERSION") - 1) + 1;
  	data = dbm_fetch(db, key);
  	if (data.dptr == NULL)
  		goto hard1;
--- 309,315 ----
  	 * read version out of database
  	 */
  	bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
! 	key.dsize = (sizeof ("VERSION") - 1);
  	data = dbm_fetch(db, key);
  	if (data.dptr == NULL)
  		goto hard1;
***************
*** 319,325 ****
  	 * read version string from kernel memory
  	 */
  	bcopy("_version", symbuf, sizeof ("_version")-1);
! 	key.dsize = (sizeof ("_version")-1) + 1;
  	data = dbm_fetch(db, key);
  	if (data.dptr == NULL)
  		goto hard1;
--- 319,325 ----
  	 * read version string from kernel memory
  	 */
  	bcopy("_version", symbuf, sizeof ("_version")-1);
! 	key.dsize = (sizeof ("_version")-1);
  	data = dbm_fetch(db, key);
  	if (data.dptr == NULL)
  		goto hard1;
***************
*** 356,362 ****
  			return (-1);
  		}
  		(void)strcpy(symbuf, n->n_name);
! 		key.dsize = len + 1;
  		data = dbm_fetch(db, key);
  		if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
  			continue;
--- 356,362 ----
  			return (-1);
  		}
  		(void)strcpy(symbuf, n->n_name);
! 		key.dsize = len;
  		data = dbm_fetch(db, key);
  		if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
  			continue;
***************
*** 634,639 ****
--- 634,644 ----
  	}
  }
  
+ #ifdef i386
+ /* See also ./sys/kern/kern_execve.c */
+ #define ARGSIZE		(roundup(ARG_MAX, NBPG))
+ #endif
+ 
  #ifdef NEWVM
  struct user *
  kvm_getu(p)
***************
*** 691,713 ****
  #endif
  
  #ifdef i386
!       if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) {
!               struct pde pde;
  
!               klseek(kmem,
!                       (long)(kp->kp_eproc.e_vm.vm_pmap.pm_pdir + UPTDI), 0);
!               if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde &&
!                       pde.pd_v) {
! 
!                       struct pte pte;
! 
!                       lseek(mem, (long)ctob(pde.pd_pfnum) +
!                               (ptei(USRSTACK-CLBYTES) * sizeof pte), 0);
!                       if (read(mem, (char *)&pte, sizeof pte) == sizeof pte && +                               pte.pg_v) {
!                               argaddr1 = (long)ctob(pte.pg_pfnum);
!                       }
!               }
!       }
  #endif
  	return(&user.user);
  }
--- 696,727 ----
  #endif
  
  #ifdef i386
! 	if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) {
! 		struct pde pde;
! 		u_int vaddr = USRSTACK-ARGSIZE;
! 
! 		if ((u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ < USRSTACK)
! 			vaddr -= MAXSSIZ;
! #if 0
! 		klseek(kmem,
! 			(long)(kp->kp_eproc.e_vm.vm_pmap.pm_pdir + UPTDI), 0);
! #else
! 		klseek(kmem,
! 		(long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(vaddr)]), 0);
! #endif
! 		if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde
! 				&& pde.pd_v) {
  
! 			struct pte pte;
! 
! 			lseek(mem, (long)ctob(pde.pd_pfnum) +
! 				(ptei(vaddr) * sizeof pte), 0);
! 			if (read(mem, (char *)&pte, sizeof pte) == sizeof pte
! 					&& pte.pg_v) {
! 				argaddr1 = (long)ctob(pte.pg_pfnum);
! 			}
! 		}
! 	}
  #endif
  	return(&user.user);
  }
***************
*** 786,796 ****
--- 800,819 ----
  	const struct proc *p;
  	const struct user *up;
  {
+ #ifdef i386
+ 	/* See also ./sys/kern/kern_execve.c */
+ 	static char cmdbuf[ARGSIZE];
+ 	static union {
+ 		char	argc[ARGSIZE];
+ 		int	argi[ARGSIZE/sizeof (int)];
+ 	} argspac;
+ #else
  	static char cmdbuf[CLBYTES*2];
  	static union {
  		char	argc[CLBYTES*2];
  		int	argi[CLBYTES*2/sizeof (int)];
  	} argspac;
+ #endif
  	register char *cp;
  	register int *ip;
  	char c;
***************
*** 824,829 ****
--- 847,857 ----
  		file = swapf;
  #endif
  	} else {
+ #ifdef i386
+ 		lseek(mem, (long)argaddr1, 0);
+ 		if (read(mem, &argspac.argc[0], ARGSIZE) != ARGSIZE)
+ 			goto bad;
+ #else
  		if (argaddr0) {
  			lseek(mem, (long)argaddr0, 0);
  			if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES)
***************
*** 833,842 ****
  		lseek(mem, (long)argaddr1, 0);
  		if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES)
  			goto bad;
  		file = (char *) memf;
  	}
  #ifdef i386
! 	ip = &argspac.argi[(CLBYTES + CLBYTES/2)/sizeof (int)];
  #else
  	ip = &argspac.argi[CLBYTES*2/sizeof (int)];
  	ip -= 2;                /* last arg word and .long 0 */
--- 861,874 ----
  		lseek(mem, (long)argaddr1, 0);
  		if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES)
  			goto bad;
+ #endif
  		file = (char *) memf;
  	}
  #ifdef i386
! 	ip = &argspac.argi[(ARGSIZE-ARG_MAX)/sizeof (int)];
! 
! 	nbad = 0;
! 	for (cp = (char *)ip; cp < &argspac.argc[ARGSIZE-stkoff]; cp++) {
  #else
  	ip = &argspac.argi[CLBYTES*2/sizeof (int)];
  	ip -= 2;                /* last arg word and .long 0 */
***************
*** 848,865 ****
  	*(char *)ip = ' ';
  	ip++;
  	nbad = 0;
! #endif
  	for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
! 		c = *cp & 0177;
! 		if (c == 0)
  			*cp = ' ';
  		else if (c < ' ' || c > 0176) {
! 			if (++nbad >= 5*(0+1)) {	/* eflg -> 0 XXX */
! 				*cp++ = ' ';
  				break;
  			}
  			*cp = '?';
! 		} else if (0 == 0 && c == '=') {	/* eflg -> 0 XXX */
  			while (*--cp != ' ')
  				if (cp <= (char *)ip)
  					break;
--- 880,901 ----
  	*(char *)ip = ' ';
  	ip++;
  	nbad = 0;
! 
  	for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
! #endif
! 		c = *cp;
! 		if (c == 0) {	/* convert null between arguments to space */
  			*cp = ' ';
+ 			if (*(cp+1) == 0) break;	/* if null argument follows then no more args */
+ 			}
  		else if (c < ' ' || c > 0176) {
! 			if (++nbad >= 5*(0+1)) {	/* eflg -> 0 XXX */ /* limit number of bad chars to 5 */
! 				*cp++ = '?';
  				break;
  			}
  			*cp = '?';
! 		}
! 		else if (0 == 0 && c == '=') {		/* eflg -> 0 XXX */
  			while (*--cp != ' ')
  				if (cp <= (char *)ip)
  					break;
***************
*** 870,876 ****
  	while (*--cp == ' ')
  		*cp = 0;
  	cp = (char *)ip;
! 	(void) strncpy(cmdbuf, cp, &argspac.argc[CLBYTES*2] - cp);
  	if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
  		(void) strcat(cmdbuf, " (");
  		(void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
--- 906,912 ----
  	while (*--cp == ' ')
  		*cp = 0;
  	cp = (char *)ip;
! 	(void) strcpy(cmdbuf, cp);
  	if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
  		(void) strcat(cmdbuf, " (");
  		(void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));

*** /usr/src/usr.sbin/kvm_mkdb/nlist.c.01orig	Sat Apr 27 16:23:58 1991
--- /usr/src/usr.sbin/kvm_mkdb/nlist.c	Wed Aug  5 03:39:37 1992
***************
*** 138,143 ****
--- 138,146 ----
  #ifdef vax
  			rel_off = nbuf.n_value & ~KERNBASE;
  #endif
+ #ifdef i386
+ 			rel_off = ((nbuf.n_value & ~KERNBASE) + CLBYTES);
+ #endif
  			/*
  			 * When loaded, data is rounded to next page cluster
  			 * after text, but not in file.