diff options
author | julian <julian@FreeBSD.org> | 2001-01-24 21:29:57 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 2001-01-24 21:29:57 +0000 |
commit | 222035d6b123a02eab80f14e5165f2cf38dfda82 (patch) | |
tree | 0c56ce5f5bf42809a788da2c890b5a9b55f49e15 /sys/netgraph | |
parent | 43df074e7c5ac8d62a9cdc1e1506fea5e1ae0151 (diff) | |
download | FreeBSD-src-222035d6b123a02eab80f14e5165f2cf38dfda82.zip FreeBSD-src-222035d6b123a02eab80f14e5165f2cf38dfda82.tar.gz |
Don't crash the kernel if the user tries to load a netgraph
module with the wrong version number.
Diffstat (limited to 'sys/netgraph')
-rw-r--r-- | sys/netgraph/ng_base.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 8b14e90..78b4aaa 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -1142,11 +1142,11 @@ ng_newtype(struct ng_type *tp) return (EEXIST); } - tp->refs = 0; /* Link in new type */ mtx_enter(&ng_typelist_mtx, MTX_DEF); LIST_INSERT_HEAD(&ng_typelist, tp, types); + tp->refs = 1; /* first ref is linked list */ mtx_exit(&ng_typelist_mtx, MTX_DEF); return (0); } @@ -2678,7 +2678,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook) break; } strncpy(tp->type_name, type->name, NG_TYPELEN); - tp->numnodes = type->refs; + tp->numnodes = type->refs - 1; /* don't count list */ tl->numtypes++; } mtx_exit(&ng_typelist_mtx, MTX_DEF); @@ -2909,6 +2909,7 @@ ng_mod_event(module_t mod, int event, void *data) if (type->mod_event != NULL) if ((error = (*type->mod_event)(mod, event, data))) { mtx_enter(&ng_typelist_mtx, MTX_DEF); + type->refs--; /* undo it */ LIST_REMOVE(type, types); mtx_exit(&ng_typelist_mtx, MTX_DEF); } @@ -2917,9 +2918,14 @@ ng_mod_event(module_t mod, int event, void *data) case MOD_UNLOAD: s = splnet(); - if (type->refs != 0) /* make sure no nodes exist! */ + if (type->refs > 1) { /* make sure no nodes exist! */ error = EBUSY; - else { + } else { + if (type->refs == 0) { + /* failed load, nothing to undo */ + splx(s); + break; + } if (type->mod_event != NULL) { /* check with type */ error = (*type->mod_event)(mod, event, data); if (error != 0) { /* type refuses.. */ |