Date: Mon, 11 Nov 2002 16:41:19 -0800 (PST) From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 20981 for review Message-ID: <200211120041.gAC0fJAV012669@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=20981 Change 20981 by rwatson@rwatson_tislabs on 2002/11/11 16:41:03 Introduce a condition variable to avoid returning EBUSY when the MAC policy list is busy during a load or unload attempt. We assert no locks held during the cv wait, meaning we should be fairly deadlock-safe. Because of the cv model and busy count, it's possible for a cv waiter waiting for exclusive access to the policy list to be starved by active and long-lived access control/labeling events. For now, we accept that as a necessary tradeoff. Largely extracted from: amigus_mac_userland Affected files ... .. //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#356 edit Differences ... ==== //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#356 (text+ko) ==== @@ -46,6 +46,7 @@ #include "opt_devfs.h" #include <sys/param.h> +#include <sys/condvar.h> #include <sys/extattr.h> #include <sys/imgact.h> #include <sys/kernel.h> @@ -233,12 +234,14 @@ * and that this is not yet done for relabel requests. */ static struct mtx mac_policy_list_lock; +static struct cv mac_policy_list_not_busy; static LIST_HEAD(, mac_policy_conf) mac_policy_list; static int mac_policy_list_busy; #define MAC_POLICY_LIST_LOCKINIT() do { \ mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL, \ MTX_DEF); \ + cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \ } while (0) #define MAC_POLICY_LIST_LOCK() do { \ @@ -249,6 +252,14 @@ mtx_unlock(&mac_policy_list_lock); \ } while (0) +#define MAC_POLICY_LIST_EXCLUSIVE() do { \ + WITNESS_SLEEP(1, NULL); \ + mtx_lock(&mac_policy_list_lock); \ + while (mac_policy_list_busy != 0) \ + cv_wait(&mac_policy_list_not_busy, \ + &mac_policy_list_lock); \ +} while (0) + #define MAC_POLICY_LIST_BUSY() do { \ MAC_POLICY_LIST_LOCK(); \ mac_policy_list_busy++; \ @@ -258,8 +269,9 @@ #define MAC_POLICY_LIST_UNBUSY() do { \ MAC_POLICY_LIST_LOCK(); \ mac_policy_list_busy--; \ - if (mac_policy_list_busy < 0) \ - panic("Extra mac_policy_list_busy--"); \ + KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK")); \ + if (mac_policy_list_busy == 0) \ + cv_signal(&mac_policy_list_not_busy); \ MAC_POLICY_LIST_UNLOCK(); \ } while (0) @@ -474,11 +486,7 @@ struct mac_policy_conf *tmpc; int slot; - MAC_POLICY_LIST_LOCK(); - if (mac_policy_list_busy > 0) { - MAC_POLICY_LIST_UNLOCK(); - return (EBUSY); - } + MAC_POLICY_LIST_EXCLUSIVE(); LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { MAC_POLICY_LIST_UNLOCK(); @@ -518,7 +526,7 @@ * to see if we did the run-time registration, and if not, * silently succeed. */ - MAC_POLICY_LIST_LOCK(); + MAC_POLICY_LIST_EXCLUSIVE(); if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { MAC_POLICY_LIST_UNLOCK(); return (0); @@ -540,23 +548,14 @@ MAC_POLICY_LIST_UNLOCK(); return (EBUSY); } - /* - * Right now, we EBUSY if the list is in use. In the future, - * for reliability reasons, we might want to sleep and wakeup - * later to try again. - */ - if (mac_policy_list_busy > 0) { - MAC_POLICY_LIST_UNLOCK(); - return (EBUSY); - } if (mpc->mpc_ops->mpo_destroy != NULL) (*(mpc->mpc_ops->mpo_destroy))(mpc); LIST_REMOVE(mpc, mpc_list); + mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; + MAC_POLICY_LIST_UNLOCK(); - mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; - printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, mpc->mpc_name); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200211120041.gAC0fJAV012669>