imgact_binmisc: abstract away the list lock (NFC)
This module handles relatively few execs (initial qemu-user-static, then qemu-user-static handles exec'ing itself for binaries it's already running), but all execs pay the price of at least taking the relatively expensive sx/slock to check for a match when this module is loaded. Future work will almost certainly swap this out for another lock, perhaps an rmslock. The RLOCK/WLOCK phrasing was chosen based on what the callers are really wanting, rather than using the verbiage typically appropriate for an sx. MFC after: 1 week
This commit is contained in:
parent
3701068b5d
commit
2192cd125f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=367444
@ -98,6 +98,16 @@ static int interp_list_entry_count;
|
|||||||
|
|
||||||
static struct sx interp_list_sx;
|
static struct sx interp_list_sx;
|
||||||
|
|
||||||
|
#define INTERP_LIST_WLOCK() sx_xlock(&interp_list_sx)
|
||||||
|
#define INTERP_LIST_RLOCK() sx_slock(&interp_list_sx)
|
||||||
|
#define INTERP_LIST_WUNLOCK() sx_xunlock(&interp_list_sx)
|
||||||
|
#define INTERP_LIST_RUNLOCK() sx_sunlock(&interp_list_sx)
|
||||||
|
|
||||||
|
#define INTERP_LIST_LOCK_INIT() sx_init(&interp_list_sx, KMOD_NAME)
|
||||||
|
#define INTERP_LIST_LOCK_DESTROY() sx_destroy(&interp_list_sx)
|
||||||
|
|
||||||
|
#define INTERP_LIST_ASSERT_LOCKED() sx_assert(&interp_list_sx, SA_LOCKED)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Populate the entry with the information about the interpreter.
|
* Populate the entry with the information about the interpreter.
|
||||||
*/
|
*/
|
||||||
@ -198,7 +208,7 @@ imgact_binmisc_find_entry(char *name)
|
|||||||
{
|
{
|
||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
|
|
||||||
sx_assert(&interp_list_sx, SA_LOCKED);
|
INTERP_LIST_ASSERT_LOCKED();
|
||||||
|
|
||||||
SLIST_FOREACH(ibe, &interpreter_list, link) {
|
SLIST_FOREACH(ibe, &interpreter_list, link) {
|
||||||
if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0)
|
if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0)
|
||||||
@ -256,9 +266,9 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sx_xlock(&interp_list_sx);
|
INTERP_LIST_WLOCK();
|
||||||
if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) {
|
if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) {
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
return (EEXIST);
|
return (EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +277,7 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
|
|||||||
|
|
||||||
SLIST_INSERT_HEAD(&interpreter_list, ibe, link);
|
SLIST_INSERT_HEAD(&interpreter_list, ibe, link);
|
||||||
interp_list_entry_count++;
|
interp_list_entry_count++;
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -281,14 +291,14 @@ imgact_binmisc_remove_entry(char *name)
|
|||||||
{
|
{
|
||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
|
|
||||||
sx_xlock(&interp_list_sx);
|
INTERP_LIST_WLOCK();
|
||||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
}
|
}
|
||||||
SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link);
|
SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link);
|
||||||
interp_list_entry_count--;
|
interp_list_entry_count--;
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
|
|
||||||
imgact_binmisc_destroy_entry(ibe);
|
imgact_binmisc_destroy_entry(ibe);
|
||||||
|
|
||||||
@ -304,14 +314,14 @@ imgact_binmisc_disable_entry(char *name)
|
|||||||
{
|
{
|
||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
|
|
||||||
sx_xlock(&interp_list_sx);
|
INTERP_LIST_WLOCK();
|
||||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ibe->ibe_flags &= ~IBF_ENABLED;
|
ibe->ibe_flags &= ~IBF_ENABLED;
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -325,14 +335,14 @@ imgact_binmisc_enable_entry(char *name)
|
|||||||
{
|
{
|
||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
|
|
||||||
sx_xlock(&interp_list_sx);
|
INTERP_LIST_WLOCK();
|
||||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ibe->ibe_flags |= IBF_ENABLED;
|
ibe->ibe_flags |= IBF_ENABLED;
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -343,8 +353,7 @@ imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe,
|
|||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
sx_assert(&interp_list_sx, SA_LOCKED);
|
INTERP_LIST_ASSERT_LOCKED();
|
||||||
|
|
||||||
memset(xbe, 0, sizeof(*xbe));
|
memset(xbe, 0, sizeof(*xbe));
|
||||||
strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX);
|
strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX);
|
||||||
|
|
||||||
@ -375,14 +384,14 @@ imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe)
|
|||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
sx_slock(&interp_list_sx);
|
INTERP_LIST_RLOCK();
|
||||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
|
||||||
sx_sunlock(&interp_list_sx);
|
INTERP_LIST_RUNLOCK();
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = imgact_binmisc_populate_xbe(xbe, ibe);
|
error = imgact_binmisc_populate_xbe(xbe, ibe);
|
||||||
sx_sunlock(&interp_list_sx);
|
INTERP_LIST_RUNLOCK();
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -397,7 +406,7 @@ imgact_binmisc_get_all_entries(struct sysctl_req *req)
|
|||||||
imgact_binmisc_entry_t *ibe;
|
imgact_binmisc_entry_t *ibe;
|
||||||
int error = 0, count;
|
int error = 0, count;
|
||||||
|
|
||||||
sx_slock(&interp_list_sx);
|
INTERP_LIST_RLOCK();
|
||||||
count = interp_list_entry_count;
|
count = interp_list_entry_count;
|
||||||
xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_WAITOK|M_ZERO);
|
xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_WAITOK|M_ZERO);
|
||||||
|
|
||||||
@ -407,7 +416,7 @@ imgact_binmisc_get_all_entries(struct sysctl_req *req)
|
|||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sx_sunlock(&interp_list_sx);
|
INTERP_LIST_RUNLOCK();
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count);
|
error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count);
|
||||||
@ -546,7 +555,7 @@ imgact_binmisc_find_interpreter(const char *image_header)
|
|||||||
int i;
|
int i;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sx_assert(&interp_list_sx, SA_LOCKED);
|
INTERP_LIST_ASSERT_LOCKED();
|
||||||
|
|
||||||
SLIST_FOREACH(ibe, &interpreter_list, link) {
|
SLIST_FOREACH(ibe, &interpreter_list, link) {
|
||||||
if (!(IBF_ENABLED & ibe->ibe_flags))
|
if (!(IBF_ENABLED & ibe->ibe_flags))
|
||||||
@ -584,7 +593,7 @@ imgact_binmisc_exec(struct image_params *imgp)
|
|||||||
|
|
||||||
sname = NULL;
|
sname = NULL;
|
||||||
/* Do we have an interpreter for the given image header? */
|
/* Do we have an interpreter for the given image header? */
|
||||||
sx_slock(&interp_list_sx);
|
INTERP_LIST_RLOCK();
|
||||||
if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) {
|
if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto done;
|
goto done;
|
||||||
@ -702,7 +711,7 @@ imgact_binmisc_exec(struct image_params *imgp)
|
|||||||
imgp->interpreter_name = imgp->args->begin_argv;
|
imgp->interpreter_name = imgp->args->begin_argv;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
sx_sunlock(&interp_list_sx);
|
INTERP_LIST_RUNLOCK();
|
||||||
if (sname)
|
if (sname)
|
||||||
sbuf_delete(sname);
|
sbuf_delete(sname);
|
||||||
return (error);
|
return (error);
|
||||||
@ -712,7 +721,7 @@ static void
|
|||||||
imgact_binmisc_init(void *arg)
|
imgact_binmisc_init(void *arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
sx_init(&interp_list_sx, KMOD_NAME);
|
INTERP_LIST_LOCK_INIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -721,15 +730,15 @@ imgact_binmisc_fini(void *arg)
|
|||||||
imgact_binmisc_entry_t *ibe, *ibe_tmp;
|
imgact_binmisc_entry_t *ibe, *ibe_tmp;
|
||||||
|
|
||||||
/* Free all the interpreters. */
|
/* Free all the interpreters. */
|
||||||
sx_xlock(&interp_list_sx);
|
INTERP_LIST_WLOCK();
|
||||||
SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) {
|
SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) {
|
||||||
SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry,
|
SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry,
|
||||||
link);
|
link);
|
||||||
imgact_binmisc_destroy_entry(ibe);
|
imgact_binmisc_destroy_entry(ibe);
|
||||||
}
|
}
|
||||||
sx_xunlock(&interp_list_sx);
|
INTERP_LIST_WUNLOCK();
|
||||||
|
|
||||||
sx_destroy(&interp_list_sx);
|
INTERP_LIST_LOCK_DESTROY();
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init,
|
SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init,
|
||||||
|
Loading…
Reference in New Issue
Block a user