Subject: Re: kern/33630: pool corrupt (pretty reproducable for me)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Martin Husemann <martin@duskware.de>
List: netbsd-bugs
Date: 06/20/2006 08:45:04
The following reply was made to PR kern/33630; it has been noted by GNATS.

From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/33630: pool corrupt (pretty reproducable for me)
Date: Tue, 20 Jun 2006 10:44:18 +0200

 --Qxx1br4bt0+wmkIi
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Ok, still not found - for the record, with the patch below the system
 is rock solid. I wonder if we have some bogon in the pool code?
 
 Martin
 
 
 --Qxx1br4bt0+wmkIi
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=patch
 
 Index: sys/kauth.h
 ===================================================================
 RCS file: /cvsroot/src/sys/sys/kauth.h,v
 retrieving revision 1.3
 diff -u -p -r1.3 kauth.h
 --- sys/kauth.h	28 May 2006 06:49:27 -0000	1.3
 +++ sys/kauth.h	20 Jun 2006 08:40:05 -0000
 @@ -81,6 +81,7 @@ typedef int (*kauth_scope_callback_t)(ka
  /*
   * Prototypes.
   */
 +void kauth_cred_verify(kauth_cred_t);
  void kauth_init(void);
  kauth_scope_t kauth_register_scope(const char *, kauth_scope_callback_t, void *);
  void kauth_deregister_scope(kauth_scope_t);
 Index: kern/kern_auth.c
 ===================================================================
 RCS file: /cvsroot/src/sys/kern/kern_auth.c,v
 retrieving revision 1.8
 diff -u -p -r1.8 kern_auth.c
 --- kern/kern_auth.c	13 Jun 2006 22:56:46 -0000	1.8
 +++ kern/kern_auth.c	20 Jun 2006 08:40:05 -0000
 @@ -45,6 +45,8 @@
  #include <sys/kauth.h>
  #include <sys/acct.h>
  #include <sys/sysctl.h>
 +#include <uvm/uvm_km.h>
 +#include <sys/malloc.h>
  
  /* 
   * Credentials.
 @@ -60,6 +62,7 @@ struct kauth_cred {
  	gid_t cr_svgid;			/* saved effective group id */
  	uint16_t cr_ngroups;		/* number of groups */
  	gid_t cr_groups[NGROUPS];	/* group memberships */
 +	u_int32_t magic2;
  };
  
  /*
 @@ -87,8 +90,16 @@ static POOL_INIT(kauth_scope_pool, sizeo
  	  "kauth_scopepl", &pool_allocator_nointr);
  static POOL_INIT(kauth_listener_pool, sizeof(struct kauth_listener), 0, 0, 0,
  	  "kauth_listenerpl", &pool_allocator_nointr);
 +#if 0
  static POOL_INIT(kauth_cred_pool, sizeof(struct kauth_cred), 0, 0, 0,
  	  "kauth_credpl", &pool_allocator_nointr);
 +#else
 +struct cred_free_list_item {
 +	struct kauth_cred *cred;
 +	struct cred_free_list_item *next;
 +};
 +static struct cred_free_list_item *cred_free_list;
 +#endif
  
  /* List of scopes and its lock. */
  static SIMPLEQ_HEAD(, kauth_scope) scope_list;
 @@ -98,16 +109,69 @@ static struct simplelock scopes_lock;
  static kauth_scope_t kauth_builtin_scope_generic;
  static kauth_scope_t kauth_builtin_scope_process;
  
 +// #define KCMAGIC1	0x05040311
 +#define	KCMAGIC2	0x11568322
 +
 +void
 +kauth_cred_verify(kauth_cred_t c)
 +{
 +	int p = 0;
 +	if (c->cr_refcnt <= 0) {
 +		p = 1;
 +		printf("\nrefcount = %d\n", c->cr_refcnt);
 +	}
 +/*
 +	if (c->magic1 != KCMAGIC1) {
 +		p = 1;
 +		printf("\nmagic1: 0x%x (should be 0x%x)\n", c->magic1, KCMAGIC1);
 +	}
 +*/
 +	if (c->magic2 != KCMAGIC2) {
 +		p = 1;
 +		printf("\nmagic2: 0x%x (should be 0x%x)\n", c->magic2, KCMAGIC2);
 +	}
 +
 +	if (p) panic("kauth_cred bad magic");
 +}
 +
  /* Allocate new, empty kauth credentials. */
  kauth_cred_t
  kauth_cred_alloc(void)
  {
 -	kauth_cred_t cred;
 +	kauth_cred_t cred = NULL;
 +
 +#if 1
 +	if (cred_free_list) {
 +		int s = splhigh();
 +		if (cred_free_list) {
 +			struct cred_free_list_item *p = cred_free_list->next;
 +			cred = cred_free_list->cred;
 +			free(cred_free_list, M_TEMP);
 +			cred_free_list = p;
 +		}
 +		splx(s);
 +	}
 +	if (!cred) {
 +		vaddr_t pages;
 +
 +		pages = uvm_km_alloc(kernel_map, PAGE_SIZE*2, 0, 
 +		    UVM_KMF_WIRED|UVM_KMF_ZERO);
 +		uvm_km_pgremove_intrsafe(pages, pages+PAGE_SIZE);
 +		pmap_kremove(pages, PAGE_SIZE);
 +		pmap_update(pmap_kernel());
  
 +		cred = (void*)(pages+PAGE_SIZE);
 +	}
 +#else
  	cred = pool_get(&kauth_cred_pool, PR_WAITOK);
 +#endif
  	memset(cred, 0, sizeof(*cred));
  	simple_lock_init(&cred->cr_lock);
  	cred->cr_refcnt = 1;
 +	// cred->magic1 = KCMAGIC1;
 +	cred->magic2 = KCMAGIC2;
 +
 +	kauth_cred_verify(cred);
  
  	return (cred);
  }
 @@ -118,23 +182,47 @@ kauth_cred_hold(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
          simple_lock(&cred->cr_lock);
          cred->cr_refcnt++;
          simple_unlock(&cred->cr_lock);
 +	kauth_cred_verify(cred);
  }
  
  /* Decrease reference count to cred. If reached zero, free it. */
  void
  kauth_cred_free(kauth_cred_t cred)
  {
 +#if 0
 +	vaddr_t pages;
 +#endif
 +
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	simple_lock(&cred->cr_lock);
  	cred->cr_refcnt--;
  	simple_unlock(&cred->cr_lock);
  
 -	if (cred->cr_refcnt == 0)
 +	if (cred->cr_refcnt == 0) {
 +		// cred->magic1 = 0xdeadbeef;
 +		cred->magic2 = 0xcdcdcdcd;
 +#if 0
  		pool_put(&kauth_cred_pool, cred);
 +#else
 +		/*
 +		pages = (vaddr_t)cred - PAGE_SIZE;
 +		uvm_km_free(kernel_map, pages, PAGE_SIZE*2, UVM_KMF_WIRED);
 +		*/
 +		struct cred_free_list_item *item = malloc(sizeof(struct cred_free_list_item),
 +		    M_TEMP, M_WAITOK);
 +		int s = splhigh();
 +		item->cred = cred;
 +		item->next = cred_free_list;
 +		cred_free_list = item;
 +		splx(s);
 +#endif
 +	}
  }
  
  void
 @@ -143,6 +231,8 @@ kauth_cred_clone(kauth_cred_t from, kaut
  	KASSERT(from != NULL);
  	KASSERT(to != NULL);
  
 +	kauth_cred_verify(from);
 +	kauth_cred_verify(to);
  	to->cr_uid = from->cr_uid;
  	to->cr_euid = from->cr_euid;
  	to->cr_svuid = from->cr_svuid;
 @@ -152,6 +242,8 @@ kauth_cred_clone(kauth_cred_t from, kaut
  	to->cr_ngroups = from->cr_ngroups;
  	memcpy(to->cr_groups, from->cr_groups,
  	       sizeof(to->cr_groups));
 +	kauth_cred_verify(from);
 +	kauth_cred_verify(to);
  }
  
  /*
 @@ -164,9 +256,12 @@ kauth_cred_dup(kauth_cred_t cred)
  
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	new_cred = kauth_cred_alloc();
  
  	kauth_cred_clone(cred, new_cred);
 +	kauth_cred_verify(cred);
 +	kauth_cred_verify(new_cred);
  
  	return (new_cred);
  }
 @@ -181,6 +276,7 @@ kauth_cred_copy(kauth_cred_t cred)
  	kauth_cred_t new_cred;
  
  	KASSERT(cred != NULL);
 +	kauth_cred_verify(cred);
  
  	/* If the provided credentials already have one reference, use them. */
  	if (cred->cr_refcnt == 1)
 @@ -192,6 +288,7 @@ kauth_cred_copy(kauth_cred_t cred)
  
  	kauth_cred_free(cred);
  
 +	kauth_cred_verify(new_cred);
  	return (new_cred);
  }
  
 @@ -200,6 +297,7 @@ kauth_cred_getuid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_uid);
  }
  
 @@ -208,6 +306,7 @@ kauth_cred_geteuid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_euid);
  }
  
 @@ -216,6 +315,7 @@ kauth_cred_getsvuid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_svuid);
  }
  
 @@ -224,6 +324,7 @@ kauth_cred_getgid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_gid);
  }
  
 @@ -232,6 +333,7 @@ kauth_cred_getegid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_egid);
  }
  
 @@ -240,6 +342,7 @@ kauth_cred_getsvgid(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_svgid);
  }
  
 @@ -248,6 +351,7 @@ kauth_cred_setuid(kauth_cred_t cred, uid
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_uid = uid;
  }
  
 @@ -256,6 +360,7 @@ kauth_cred_seteuid(kauth_cred_t cred, ui
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_euid = uid;
  }
  
 @@ -264,6 +369,7 @@ kauth_cred_setsvuid(kauth_cred_t cred, u
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_svuid = uid;
  }
  
 @@ -272,6 +378,7 @@ kauth_cred_setgid(kauth_cred_t cred, gid
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_gid = gid;
  }
  
 @@ -280,6 +387,7 @@ kauth_cred_setegid(kauth_cred_t cred, gi
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_egid = gid;
  }
  
 @@ -288,7 +396,9 @@ kauth_cred_setsvgid(kauth_cred_t cred, g
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_svgid = gid;
 +	kauth_cred_verify(cred);
  }
  
  /* Checks if gid is a member of the groups in cred. */
 @@ -302,11 +412,13 @@ kauth_cred_ismember_gid(kauth_cred_t cre
  
  	*resultp = 0;
  
 +	kauth_cred_verify(cred);
  	for (i = 0; i < cred->cr_ngroups; i++)
  		if (cred->cr_groups[i] == gid) {
  			*resultp = 1;
  			break;
  		}
 +	kauth_cred_verify(cred);
  
  	return (0);
  }
 @@ -316,6 +428,7 @@ kauth_cred_ngroups(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_ngroups);
  }
  
 @@ -328,6 +441,7 @@ kauth_cred_group(kauth_cred_t cred, uint
  	KASSERT(cred != NULL);
  	KASSERT(idx < cred->cr_ngroups);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_groups[idx]);
  }
  
 @@ -338,6 +452,7 @@ kauth_cred_setgroups(kauth_cred_t cred, 
  	KASSERT(cred != NULL);
  	KASSERT(len < sizeof(cred->cr_groups) / sizeof(cred->cr_groups[0]));
  
 +	kauth_cred_verify(cred);
  	simple_lock(&cred->cr_lock);
  
  	if (len)
 @@ -348,6 +463,7 @@ kauth_cred_setgroups(kauth_cred_t cred, 
  	cred->cr_ngroups = len;
  
  	simple_unlock(&cred->cr_lock);
 +	kauth_cred_verify(cred);
  
  	return (0);
  }
 @@ -358,10 +474,12 @@ kauth_cred_getgroups(kauth_cred_t cred, 
  	KASSERT(cred != NULL);
  	KASSERT(len <= cred->cr_ngroups);
  
 +	kauth_cred_verify(cred);
  	memset(grbuf, 0xff, sizeof(*grbuf) * len);
  	simple_lock(&cred->cr_lock);
  	memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len);
  	simple_unlock(&cred->cr_lock);
 +	kauth_cred_verify(cred);
  
  	return (0);
  }
 @@ -377,6 +495,8 @@ kauth_cred_uidmatch(kauth_cred_t cred1, 
  	KASSERT(cred1 != NULL);
  	KASSERT(cred2 != NULL);
  
 +	kauth_cred_verify(cred1);
 +	kauth_cred_verify(cred2);
  	/* Are we root? */
  	if (cred1->cr_euid == 0)
  		return (1);
 @@ -395,6 +515,7 @@ kauth_cred_getrefcnt(kauth_cred_t cred)
  {
  	KASSERT(cred != NULL);
  
 +	kauth_cred_verify(cred);
  	return (cred->cr_refcnt);
  }
  
 @@ -408,6 +529,7 @@ kauth_cred_uucvt(kauth_cred_t cred, cons
  	KASSERT(cred != NULL);
  	KASSERT(uuc != NULL);
  
 +	kauth_cred_verify(cred);
  	cred->cr_refcnt = 1;
  	cred->cr_uid = uuc->cr_uid;
  	cred->cr_euid = uuc->cr_uid;
 @@ -418,6 +540,7 @@ kauth_cred_uucvt(kauth_cred_t cred, cons
  	cred->cr_ngroups = min(uuc->cr_ngroups, NGROUPS);
  	kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups),
  	    cred->cr_ngroups, -1);
 +	kauth_cred_verify(cred);
  }
  
  /*
 @@ -430,6 +553,7 @@ kauth_cred_uucmp(kauth_cred_t cred, cons
  	KASSERT(cred != NULL);
  	KASSERT(uuc != NULL);
  
 +	kauth_cred_verify(cred);
  	if (cred->cr_euid == uuc->cr_uid &&
  	    cred->cr_egid == uuc->cr_gid &&
  	    cred->cr_ngroups == uuc->cr_ngroups) {
 @@ -461,12 +585,14 @@ kauth_cred_toucred(kauth_cred_t cred, st
  	KASSERT(cred != NULL);
  	KASSERT(uc != NULL);
  
 +	kauth_cred_verify(cred);
  	uc->cr_uid = cred->cr_euid;
  	uc->cr_gid = cred->cr_egid;
  	uc->cr_ngroups = min(cred->cr_ngroups,
  			     sizeof(uc->cr_groups) / sizeof(uc->cr_groups[0]));
  	memcpy(uc->cr_groups, cred->cr_groups,
  	       uc->cr_ngroups * sizeof(uc->cr_groups[0]));
 +	kauth_cred_verify(cred);
  }
  
  /*
 @@ -479,12 +605,14 @@ kauth_cred_topcred(kauth_cred_t cred, st
  	KASSERT(cred != NULL);
  	KASSERT(pc != NULL);
  
 +	kauth_cred_verify(cred);
  	pc->pc_ucred = (struct ucred *)cred; /* XXX this is just wrong */
  	pc->p_ruid = cred->cr_uid;
  	pc->p_svuid = cred->cr_svuid;
  	pc->p_rgid = cred->cr_gid;
  	pc->p_svgid = cred->cr_svgid;
  	pc->p_refcnt = cred->cr_refcnt;
 +	kauth_cred_verify(cred);
  }
  
  /*
 @@ -493,6 +621,7 @@ kauth_cred_topcred(kauth_cred_t cred, st
  kauth_cred_t
  kauth_cred_get(void)
  {
 +	kauth_cred_verify(curproc->p_cred);
  	return (curproc->p_cred);
  }
  
 @@ -805,6 +934,8 @@ int
  kauth_authorize_process(kauth_cred_t cred, kauth_action_t action,
      struct proc *p, void *arg1, void *arg2, void *arg3)
  {
 +	kauth_cred_verify(cred);
 +
  	return (kauth_authorize_action(kauth_builtin_scope_process, cred,
  	    action, p, arg1, arg2, arg3));
  }
 
 --Qxx1br4bt0+wmkIi--