From owner-svn-src-projects@FreeBSD.ORG Tue Feb 16 00:05:53 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DBF401065670; Tue, 16 Feb 2010 00:05:53 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CB0378FC08; Tue, 16 Feb 2010 00:05:53 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o1G05rn5054404; Tue, 16 Feb 2010 00:05:53 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o1G05rG9054401; Tue, 16 Feb 2010 00:05:53 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201002160005.o1G05rG9054401@svn.freebsd.org> From: Lawrence Stewart Date: Tue, 16 Feb 2010 00:05:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r203939 - projects/tcp_cc_head/sys/netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Feb 2010 00:05:53 -0000 Author: lstewart Date: Tue Feb 16 00:05:53 2010 New Revision: 203939 URL: http://svn.freebsd.org/changeset/base/203939 Log: Add a simple refcount to helpers to resolve the possibility of use-after-free on unload of a module that still had data blocks in active use. Something better should probably be devised eventually. Modified: projects/tcp_cc_head/sys/netinet/helper.c projects/tcp_cc_head/sys/netinet/helper.h Modified: projects/tcp_cc_head/sys/netinet/helper.c ============================================================================== --- projects/tcp_cc_head/sys/netinet/helper.c Mon Feb 15 23:44:48 2010 (r203938) +++ projects/tcp_cc_head/sys/netinet/helper.c Tue Feb 16 00:05:53 2010 (r203939) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -81,11 +82,12 @@ init_helper_dblocks(struct helper_dblock M_NOWAIT | M_ZERO); if (hdbs->blocks != NULL) { - printf("Malloced ptr %p for %d data blocks\n", hdbs->blocks, - num_dblocks); + /*printf("Malloced ptr %p for %d data blocks\n", hdbs->blocks, + num_dblocks);*/ STAILQ_FOREACH(h, &helpers, h_next) { if (h->h_flags & HELPER_NEEDS_DBLOCK) { dblock = hdbs->blocks+i; + /*printf("Current dblock ptr: %p\n", dblock);*/ dblock->hd_block = uma_zalloc(h->h_zone, M_NOWAIT); /* @@ -96,9 +98,10 @@ init_helper_dblocks(struct helper_dblock } */ dblock->hd_id = h->h_id; - printf("dblock[%d]: id=%d, block=%p\n", i, - dblock->hd_id, dblock->hd_block); + /*printf("dblock[%d]: id=%d, block=%p\n", i, + dblock->hd_id, dblock->hd_block);*/ i++; + refcount_acquire(&h->h_refcount); } } hdbs->nblocks = i; @@ -118,8 +121,12 @@ destroy_helper_dblocks(struct helper_dbl HELPER_LIST_WLOCK(); for (nblocks--; nblocks >= 0; nblocks--) { - if ((h = get_helper(hdbs->blocks[nblocks].hd_id)) != NULL) + if ((h = get_helper(hdbs->blocks[nblocks].hd_id)) != NULL) { + refcount_release(&h->h_refcount); + /*printf("destroy() freeing hdbs->blocks[%d] with ptr %p\n", + nblocks, hdbs->blocks[nblocks].hd_block);*/ uma_zfree(h->h_zone, hdbs->blocks[nblocks].hd_block); + } } HELPER_LIST_WUNLOCK(); @@ -130,23 +137,22 @@ destroy_helper_dblocks(struct helper_dbl int register_helper(struct helper *h) { - printf("Register helper %p\n", h); - HELPER_LIST_WLOCK(); - if (h->h_flags | HELPER_NEEDS_DBLOCK) num_dblocks++; + refcount_init(&h->h_refcount, 0); h->h_id = helper_id++; STAILQ_INSERT_TAIL(&helpers, h, h_next); HELPER_LIST_WUNLOCK(); + printf("Registered \"%s\" helper (mem %p)\n", h->h_name, h); return (0); } int deregister_helper(struct helper *h) { - printf("Deregister helper %p\n", h); + int error = 0; /* HHOOK_WLOCK @@ -155,11 +161,17 @@ deregister_helper(struct helper *h) */ HELPER_LIST_WLOCK(); - STAILQ_REMOVE(&helpers, h, helper, h_next); - if (h->h_flags | HELPER_NEEDS_DBLOCK) - num_dblocks--; + if (h->h_refcount > 0) + error = EBUSY; + + if (!error) { + STAILQ_REMOVE(&helpers, h, helper, h_next); + if (h->h_flags | HELPER_NEEDS_DBLOCK) + num_dblocks--; + printf("Deregistered \"%s\" helper (mem %p)\n", h->h_name, h); + } HELPER_LIST_WUNLOCK(); - return (0); + return (error); } int32_t @@ -244,9 +256,12 @@ helper_modevent(module_t mod, int event_ case MOD_QUIESCE: error = deregister_helper(hmd->helper); - uma_zdestroy(hmd->helper->h_zone); - if (!error && hmd->helper->mod_destroy != NULL) - hmd->helper->mod_destroy(); + if (!error) { + uma_zdestroy(hmd->helper->h_zone); + if (hmd->helper->mod_destroy != NULL) + hmd->helper->mod_destroy(); + } else + printf("Helper's refcount != 0, can't unload\n"); break; case MOD_SHUTDOWN: @@ -254,7 +269,7 @@ helper_modevent(module_t mod, int event_ break; default: - return EINVAL; + error = EINVAL; break; } Modified: projects/tcp_cc_head/sys/netinet/helper.h ============================================================================== --- projects/tcp_cc_head/sys/netinet/helper.h Mon Feb 15 23:44:48 2010 (r203938) +++ projects/tcp_cc_head/sys/netinet/helper.h Tue Feb 16 00:05:53 2010 (r203939) @@ -54,6 +54,7 @@ struct helper { uint16_t h_flags; uint32_t h_class; int32_t h_id; + volatile uint32_t h_refcount; STAILQ_ENTRY(helper) h_next; };