DF-2962 / fix.diff
--- a/sys/kern/subr_kobj.c 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/kern/subr_kobj.c 2026-10-26 00:25:42.789042927 +0000 @@ -135,11 +135,15 @@ } static kobj_method_t * -kobj_lookup_method_mi(kobj_class_t cls, kobjop_desc_t desc) +kobj_lookup_method_mi(kobj_class_t cls, kobjop_desc_t desc, int depth) { kobj_method_t *ce; kobj_class_t *basep; + /* cycle guard: cyclic baseclass graphs must not recurse forever */ + if (depth > 8) + return(NULL); + ce = kobj_lookup_method_class(cls, desc); if (ce) return(ce); @@ -147,7 +151,7 @@ basep = cls->baseclasses; if (basep) { for (; *basep; basep++) { - ce = kobj_lookup_method_mi(*basep, desc); + ce = kobj_lookup_method_mi(*basep, desc, depth + 1); if (ce) return(ce); } @@ -163,7 +167,7 @@ { kobj_method_t *ce; - ce = kobj_lookup_method_mi(cls, desc); + ce = kobj_lookup_method_mi(cls, desc, 0); if (!ce) ce = &desc->deflt; *cep = ce; @@ -256,6 +260,13 @@ void kobj_init(kobj_t obj, kobj_class_t cls) { + /* + * Re-initializing an already-initialized object used to leak a + * permanent class reference (pinning a KLD class forever). + * Release the previous reference instead. + */ + if (obj->ops != NULL) + kobj_class_uninstantiate(obj->ops->cls); kobj_class_instantiate(cls); obj->ops = cls->ops; } @@ -263,7 +274,10 @@ void kobj_delete(kobj_t obj, struct malloc_type *mtype) { - kobj_class_t cls = obj->ops->cls; + kobj_class_t cls; + + KKASSERT(obj->ops != NULL); + cls = obj->ops->cls; kobj_class_uninstantiate(cls); |