QUOTE: |
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) { struct gss_domain *new; struct auth_domain *test; int stat = -ENOMEM; new = kmalloc(sizeof(*new), GFP_KERNEL); if (!new) goto out; kref_init(&new->h.ref); new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); if (!new->h.name) goto out_free_dom; strcpy(new->h.name, name); new->h.flavour = &svcauthops_gss; new->pseudoflavor = pseudoflavor; test = auth_domain_lookup(name, &new->h); if (test != &new->h) { /* XXX Duplicate registration? */ auth_domain_put(&new->h); // <<<<---------- kernel panic here /* dangling ref-count... */ goto out; } return 0; out_free_dom: kfree(new); out: return stat; } |
QUOTE: |
void auth_domain_put(struct auth_domain *dom) { if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) { hlist_del(&dom->hash); // <<<----------- looking here dom->flavour->domain_release(dom); } } |
QUOTE: |
static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); // <<-------- pay attention n->next = LIST_POISON1; n->pprev = LIST_POISON2; } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; // <<--------- pprev get a wrong value *pprev = next; // <<-------- use this wrong pointer will cause unknow result if (next) next->pprev = pprev; } |
QUOTE: |
struct auth_domain * auth_domain_lookup(char *name, struct auth_domain *new) { struct auth_domain *hp; struct hlist_head *head; struct hlist_node *np; head = &auth_domain_table[hash_str(name, DN_HASHBITS)]; spin_lock(&auth_domain_lock); hlist_for_each_entry(hp, np, head, hash) { if (strcmp(hp->name, name)==0) { kref_get(&hp->ref); spin_unlock(&auth_domain_lock); return hp; // <<---------- if name is duplicated, no operation to the new parameter } } if (new) { // <<---------- if name is fresh for the list, run here hlist_add_head(&new->hash, head); kref_get(&new->ref); } spin_unlock(&auth_domain_lock); return new; } |
[火星人 ] CentOS 5 rpcsec_gss_krb5模塊卸載再重載入后導致kernel panic原因分析已經有717次圍觀