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--