Changeset View
Standalone View
sys/kern/imgact_binmisc.c
/*- | /*- | ||||
* Copyright (c) 2013, Stacey D. Son | * Copyright (c) 2013-15, Stacey D. Son | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
Show All 23 Lines | |||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
#include <sys/exec.h> | #include <sys/exec.h> | ||||
#include <sys/imgact.h> | #include <sys/imgact.h> | ||||
#include <sys/imgact_binmisc.h> | #include <sys/imgact_binmisc.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/libkern.h> | #include <sys/libkern.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mutex.h> | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/sx.h> | |||||
#include <machine/atomic.h> | |||||
/** | /** | ||||
* Miscellaneous binary interpreter image activator. | * Miscellaneous binary interpreter image activator. | ||||
* | * | ||||
* If the given target executable's header matches 'xbe_magic' field in the | * If the given target executable's header matches 'xbe_magic' field in the | ||||
* 'interpreter_list' then it will use the user-level interpreter specified in | * 'interpreter_list' then it will use the user-level interpreter specified in | ||||
* the 'xbe_interpreter' field to execute the binary. The 'xbe_magic' field may | * the 'xbe_interpreter' field to execute the binary. The 'xbe_magic' field may | ||||
* be adjusted to a given offset using the value in the 'xbe_moffset' field | * be adjusted to a given offset using the value in the 'xbe_moffset' field | ||||
* and bits of the header may be masked using the 'xbe_mask' field. The | * and bits of the header may be masked using the 'xbe_mask' field. The | ||||
Show All 38 Lines | |||||
MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator"); | MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator"); | ||||
/* The interpreter list. */ | /* The interpreter list. */ | ||||
static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list = | static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list = | ||||
SLIST_HEAD_INITIALIZER(interpreter_list); | SLIST_HEAD_INITIALIZER(interpreter_list); | ||||
static int interp_list_entry_count = 0; | static int interp_list_entry_count = 0; | ||||
static struct mtx interp_list_mtx; | static struct sx interp_list_sx; | ||||
jhb: Maybe call it 'interp_list_lock'? | |||||
Not Done Inline ActionsI don't think I'm going to do this. sbruno: I don't think I'm going to do this. | |||||
int imgact_binmisc_exec(struct image_params *imgp); | int imgact_binmisc_exec(struct image_params *imgp); | ||||
/* | /* | ||||
* Populate the entry with the information about the interpreter. | * Populate the entry with the information about the interpreter. | ||||
*/ | */ | ||||
static void | static void | ||||
imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe) | imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe) | ||||
{ | { | ||||
uint32_t len = 0, argc = 1; | uint32_t len = 0, argc = 1; | ||||
char t[IBE_INTERP_LEN_MAX]; | char t[IBE_INTERP_LEN_MAX]; | ||||
char *sp, *tp; | char *sp, *tp; | ||||
bzero(t, sizeof(t)); | memset(t, 0, sizeof(t)); | ||||
/* | /* | ||||
* Normalize interpreter string. Replace white space between args with | * Normalize interpreter string. Replace white space between args with | ||||
* single space. | * single space. | ||||
*/ | */ | ||||
sp = str; tp = t; | sp = str; tp = t; | ||||
while (*sp != '\0') { | while (*sp != '\0') { | ||||
if (*sp == ' ' || *sp == '\t') { | if (*sp == ' ' || *sp == '\t') { | ||||
Show All 24 Lines | |||||
* Allocate memory and populate a new entry for the interpreter table. | * Allocate memory and populate a new entry for the interpreter table. | ||||
*/ | */ | ||||
static imgact_binmisc_entry_t * | static imgact_binmisc_entry_t * | ||||
imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe) | imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe = NULL; | imgact_binmisc_entry_t *ibe = NULL; | ||||
size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX); | size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX); | ||||
mtx_assert(&interp_list_mtx, MA_NOTOWNED); | |||||
ibe = malloc(sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO); | ibe = malloc(sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO); | ||||
ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO); | ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO); | ||||
strlcpy(ibe->ibe_name, xbe->xbe_name, namesz); | strlcpy(ibe->ibe_name, xbe->xbe_name, namesz); | ||||
imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe); | imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe); | ||||
ibe->ibe_magic = malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO); | ibe->ibe_magic = malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO); | ||||
Show All 33 Lines | |||||
* Find the interpreter in the list by the given name. Return NULL if not | * Find the interpreter in the list by the given name. Return NULL if not | ||||
* found. | * found. | ||||
*/ | */ | ||||
static imgact_binmisc_entry_t * | static imgact_binmisc_entry_t * | ||||
imgact_binmisc_find_entry(char *name) | imgact_binmisc_find_entry(char *name) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
mtx_assert(&interp_list_mtx, MA_OWNED); | sx_assert(&interp_list_sx, SA_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) | ||||
return (ibe); | return (ibe); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
Show All 40 Lines | while (1) { | ||||
case 0: | case 0: | ||||
default: | default: | ||||
/* Anything besides the above is invalid. */ | /* Anything besides the above is invalid. */ | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
mtx_lock(&interp_list_mtx); | /* Preallocate a new entry. */ | ||||
ibe = imgact_binmisc_new_entry(xbe); | |||||
if (!ibe) | |||||
return (ENOMEM); | |||||
again: | |||||
sx_slock(&interp_list_sx); | |||||
if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { | if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
imgact_binmisc_destroy_entry(ibe); | |||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
mtx_unlock(&interp_list_mtx); | |||||
Done Inline ActionsWith an sx lock you can use the old logic order since you can hold it across the malloc(). jhb: With an sx lock you can use the old logic order since you can hold it across the malloc(). | |||||
Done Inline Actionsoh ... is this a potential race here if we *do not* hold the lock across the call to imgact_binmisc_new_entry() call (e.g. we don't restore the old lock order?) sbruno: oh ... is this a potential race here if we *do not* hold the lock across the call to… | |||||
Done Inline ActionsNo, there is no race here. It is just imgact_binmisc_new_entry() mallocs a new entry but if it doesn't need the entry it free()'s it. With sleep locks we can malloc() it while holding the lock and, therefore, don't have to go to the trouble of pre-allocating a new entry. sson: No, there is no race here. It is just imgact_binmisc_new_entry() mallocs a new entry but if it… | |||||
ibe = imgact_binmisc_new_entry(xbe); | if (sx_try_upgrade(&interp_list_sx) == 0) { | ||||
if (!ibe) | sx_sunlock(&interp_list_sx); | ||||
return (ENOMEM); | goto again; | ||||
} | |||||
mtx_lock(&interp_list_mtx); | |||||
SLIST_INSERT_HEAD(&interpreter_list, ibe, link); | SLIST_INSERT_HEAD(&interpreter_list, ibe, link); | ||||
interp_list_entry_count++; | interp_list_entry_count++; | ||||
mtx_unlock(&interp_list_mtx); | sx_xunlock(&interp_list_sx); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Remove the interpreter in the list with the given name. Return ENOENT | * Remove the interpreter in the list with the given name. Return ENOENT | ||||
* if not found. | * if not found. | ||||
*/ | */ | ||||
static int | static int | ||||
imgact_binmisc_remove_entry(char *name) | imgact_binmisc_remove_entry(char *name) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
mtx_lock(&interp_list_mtx); | again: | ||||
sx_slock(&interp_list_sx); | |||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
if (sx_try_upgrade(&interp_list_sx) == 0) { | |||||
sx_sunlock(&interp_list_sx); | |||||
goto again; | |||||
} | |||||
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--; | ||||
mtx_unlock(&interp_list_mtx); | sx_xunlock(&interp_list_sx); | ||||
imgact_binmisc_destroy_entry(ibe); | imgact_binmisc_destroy_entry(ibe); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Disable the interpreter in the list with the given name. Return ENOENT | * Disable the interpreter in the list with the given name. Return ENOENT | ||||
* if not found. | * if not found. | ||||
*/ | */ | ||||
static int | static int | ||||
imgact_binmisc_disable_entry(char *name) | imgact_binmisc_disable_entry(char *name) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
mtx_lock(&interp_list_mtx); | sx_slock(&interp_list_sx); | ||||
Done Inline ActionsIt would seem simpler to just use an xlock here and use plain ops for updating ibe_flags since my guess is that enabling/disabling entries isn't really a hot path? jhb: It would seem simpler to just use an xlock here and use plain ops for updating ibe_flags since… | |||||
Done Inline Actionshrm ... don't we need to make this atomic because we *REALLY* want to make sure this happens during a review of the interpret list? sbruno: hrm ... don't we need to make this atomic because we *REALLY* want to make sure this happens… | |||||
Done Inline ActionsYes, this is really a hot path and we could just exclusively lock it here and not use the atomics to clear the flag. sson: Yes, this is really a hot path and we could just exclusively lock it here and not use the… | |||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
ibe->ibe_flags &= ~IBF_ENABLED; | atomic_clear_32(&ibe->ibe_flags, IBF_ENABLED); | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Enable the interpreter in the list with the given name. Return ENOENT | * Enable the interpreter in the list with the given name. Return ENOENT | ||||
* if not found. | * if not found. | ||||
*/ | */ | ||||
static int | static int | ||||
imgact_binmisc_enable_entry(char *name) | imgact_binmisc_enable_entry(char *name) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
mtx_lock(&interp_list_mtx); | sx_slock(&interp_list_sx); | ||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
ibe->ibe_flags |= IBF_ENABLED; | atomic_set_32(&ibe->ibe_flags, IBF_ENABLED); | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, | imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, | ||||
imgact_binmisc_entry_t *ibe) | imgact_binmisc_entry_t *ibe) | ||||
{ | { | ||||
uint32_t i; | uint32_t i; | ||||
mtx_assert(&interp_list_mtx, MA_OWNED); | sx_assert(&interp_list_sx, SA_LOCKED); | ||||
bzero(xbe, 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); | ||||
/* Copy interpreter string. Replace NULL breaks with space. */ | /* Copy interpreter string. Replace NULL breaks with space. */ | ||||
memcpy(xbe->xbe_interpreter, ibe->ibe_interpreter, | memcpy(xbe->xbe_interpreter, ibe->ibe_interpreter, | ||||
ibe->ibe_interp_length); | ibe->ibe_interp_length); | ||||
for(i = 0; i < (ibe->ibe_interp_length - 1); i++) | for(i = 0; i < (ibe->ibe_interp_length - 1); i++) | ||||
if (xbe->xbe_interpreter[i] == '\0') | if (xbe->xbe_interpreter[i] == '\0') | ||||
xbe->xbe_interpreter[i] = ' '; | xbe->xbe_interpreter[i] = ' '; | ||||
Show All 13 Lines | |||||
* ximgact_binmisc_entry structure. Return ENOENT if not found. | * ximgact_binmisc_entry structure. Return ENOENT if not found. | ||||
*/ | */ | ||||
static int | static int | ||||
imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe) | 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; | ||||
mtx_lock(&interp_list_mtx); | sx_slock(&interp_list_sx); | ||||
if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
error = imgact_binmisc_populate_xbe(xbe, ibe); | error = imgact_binmisc_populate_xbe(xbe, ibe); | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Get a snapshot of all the interpreter entries in the list. | * Get a snapshot of all the interpreter entries in the list. | ||||
*/ | */ | ||||
static int | static int | ||||
imgact_binmisc_get_all_entries(struct sysctl_req *req) | imgact_binmisc_get_all_entries(struct sysctl_req *req) | ||||
{ | { | ||||
ximgact_binmisc_entry_t *xbe, *xbep; | ximgact_binmisc_entry_t *xbe, *xbep; | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
int error = 0, count; | int error = 0, count; | ||||
mtx_lock(&interp_list_mtx); | sx_slock(&interp_list_sx); | ||||
count = interp_list_entry_count; | count = interp_list_entry_count; | ||||
/* Don't block in malloc() while holding lock. */ | /* Don't block in malloc() while holding lock. */ | ||||
xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_NOWAIT|M_ZERO); | xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_NOWAIT|M_ZERO); | ||||
if (!xbe) { | if (!xbe) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
xbep = xbe; | xbep = xbe; | ||||
SLIST_FOREACH(ibe, &interpreter_list, link) { | SLIST_FOREACH(ibe, &interpreter_list, link) { | ||||
error = imgact_binmisc_populate_xbe(xbep++, ibe); | error = imgact_binmisc_populate_xbe(xbep++, ibe); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
} | } | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
if (!error) | if (!error) | ||||
error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count); | error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count); | ||||
free(xbe, M_BINMISC); | free(xbe, M_BINMISC); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | |||||
static imgact_binmisc_entry_t * | static imgact_binmisc_entry_t * | ||||
imgact_binmisc_find_interpreter(const char *image_header) | imgact_binmisc_find_interpreter(const char *image_header) | ||||
{ | { | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
const char *p; | const char *p; | ||||
int i; | int i; | ||||
size_t sz; | size_t sz; | ||||
mtx_assert(&interp_list_mtx, MA_OWNED); | sx_assert(&interp_list_sx, SA_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)) | ||||
continue; | continue; | ||||
p = image_header + ibe->ibe_moffset; | p = image_header + ibe->ibe_moffset; | ||||
sz = ibe->ibe_msize; | sz = ibe->ibe_msize; | ||||
if (IBF_USE_MASK & ibe->ibe_flags) { | if (IBF_USE_MASK & ibe->ibe_flags) { | ||||
Show All 20 Lines | imgact_binmisc_exec(struct image_params *imgp) | ||||
const char *fname = NULL; | const char *fname = NULL; | ||||
int error = 0; | int error = 0; | ||||
size_t offset, l; | size_t offset, l; | ||||
imgact_binmisc_entry_t *ibe; | imgact_binmisc_entry_t *ibe; | ||||
struct sbuf *sname; | struct sbuf *sname; | ||||
char *s, *d; | char *s, *d; | ||||
/* Do we have an interpreter for the given image header? */ | /* Do we have an interpreter for the given image header? */ | ||||
mtx_lock(&interp_list_mtx); | sx_slock(&interp_list_sx); | ||||
if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) { | if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* No interpreter nesting allowed. */ | /* No interpreter nesting allowed. */ | ||||
if (imgp->interpreted & IMGACT_BINMISC) { | if (imgp->interpreted & IMGACT_BINMISC) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
} | } | ||||
imgp->interpreted |= IMGACT_BINMISC; | imgp->interpreted |= IMGACT_BINMISC; | ||||
if (imgp->args->fname != NULL) { | if (imgp->args->fname != NULL) { | ||||
fname = imgp->args->fname; | fname = imgp->args->fname; | ||||
sname = NULL; | sname = NULL; | ||||
Show All 31 Lines | while (1) { | ||||
case ISM_OLD_ARGV0: | case ISM_OLD_ARGV0: | ||||
/* "#a" -> (old argv0): increase offset to fit fname */ | /* "#a" -> (old argv0): increase offset to fit fname */ | ||||
offset += strlen(fname) - 2; | offset += strlen(fname) - 2; | ||||
break; | break; | ||||
default: | default: | ||||
/* Hmm... This shouldn't happen. */ | /* Hmm... This shouldn't happen. */ | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
printf("%s: Unknown macro #%c sequence in " | printf("%s: Unknown macro #%c sequence in " | ||||
"interpreter string\n", KMOD_NAME, *(s + 1)); | "interpreter string\n", KMOD_NAME, *(s + 1)); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
s++; | s++; | ||||
} | } | ||||
/* Check to make sure we won't overrun the stringspace. */ | /* Check to make sure we won't overrun the stringspace. */ | ||||
if (offset > imgp->args->stringspace) { | if (offset > imgp->args->stringspace) { | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
error = E2BIG; | error = E2BIG; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* Make room for the interpreter */ | /* Make room for the interpreter */ | ||||
bcopy(imgp->args->begin_argv, imgp->args->begin_argv + offset, | memcpy(imgp->args->begin_argv + offset, imgp->args->begin_argv, | ||||
Done Inline ActionsThis should stay a bcopy() since it is an overlaying copy. memcpy() doesn't do well with that. sson: This should stay a bcopy() since it is an overlaying copy. memcpy() doesn't do well with that. | |||||
Done Inline Actionsyepper, done. sbruno: yepper, done. | |||||
Done Inline ActionsWhitespace diff? jhb: Whitespace diff? | |||||
Done Inline ActionsNo, this was memcpy() but memcpy() doesn't do play well overlapping memory which is required here. Sean changed it to bcopy() so now it looks like a whitespace diff. sson: No, this was memcpy() but memcpy() doesn't do play well overlapping memory which is required… | |||||
imgp->args->endp - imgp->args->begin_argv); | imgp->args->endp - imgp->args->begin_argv); | ||||
/* Adjust everything by the offset. */ | /* Adjust everything by the offset. */ | ||||
imgp->args->begin_envv += offset; | imgp->args->begin_envv += offset; | ||||
imgp->args->endp += offset; | imgp->args->endp += offset; | ||||
imgp->args->stringspace -= offset; | imgp->args->stringspace -= offset; | ||||
/* Add the new argument(s) in the count. */ | /* Add the new argument(s) in the count. */ | ||||
Show All 37 Lines | while(*s != '\0') { | ||||
default: | default: | ||||
*d++ = *s; | *d++ = *s; | ||||
break; | break; | ||||
} | } | ||||
s++; | s++; | ||||
} | } | ||||
*d = '\0'; | *d = '\0'; | ||||
mtx_unlock(&interp_list_mtx); | sx_sunlock(&interp_list_sx); | ||||
if (!error) | if (!error) | ||||
imgp->interpreter_name = imgp->args->begin_argv; | imgp->interpreter_name = imgp->args->begin_argv; | ||||
done: | done: | ||||
if (sname) | if (sname) | ||||
sbuf_delete(sname); | sbuf_delete(sname); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
imgact_binmisc_init(void *arg) | imgact_binmisc_init(void *arg) | ||||
{ | { | ||||
mtx_init(&interp_list_mtx, KMOD_NAME, NULL, MTX_DEF); | sx_init(&interp_list_sx, KMOD_NAME); | ||||
} | } | ||||
static void | static void | ||||
imgact_binmisc_fini(void *arg) | 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. */ | ||||
mtx_lock(&interp_list_mtx); | sx_xlock(&interp_list_sx); | ||||
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); | ||||
} | } | ||||
mtx_unlock(&interp_list_mtx); | sx_xunlock(&interp_list_sx); | ||||
mtx_destroy(&interp_list_mtx); | sx_destroy(&interp_list_sx); | ||||
} | } | ||||
SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, 0); | SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, 0); | ||||
SYSUNINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_fini, 0); | SYSUNINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_fini, 0); | ||||
/* | /* | ||||
* Tell kern_execve.c about it, with a little help from the linker. | * Tell kern_execve.c about it, with a little help from the linker. | ||||
*/ | */ | ||||
static struct execsw imgact_binmisc_execsw = { imgact_binmisc_exec, KMOD_NAME }; | static struct execsw imgact_binmisc_execsw = { imgact_binmisc_exec, KMOD_NAME }; | ||||
EXEC_SET(imgact_binmisc, imgact_binmisc_execsw); | EXEC_SET(imgact_binmisc, imgact_binmisc_execsw); |
Maybe call it 'interp_list_lock'?