mysterious locking issue
ret val
retval42 at gmail.com
Sat Jul 27 04:46:10 UTC 2013
I'm working on porting a driver form Linux that uses the usermode helper
API to call a user land program from the driver. Yes, I know this is ugly.
Yes, I'm sure sure there would of been many better other ways to go about
this... For right now I'm just doing a straight port.
Anyway, I working on my own routine for this but unfortunately I get a
kernel panic on boot when my module is loaded. Oddly enough it works fine
if I load it by hand after boot. I get the following: panic: mutex Giant
owned at /usr/src/sys/kern/kern_thread.c:616
The backtrace looks like:
panic
_mtx_assert
thread_single
kern_execve
event_handler
Ive tried switching to SI_SUB_EXEC without any luck. Does anyone know how
to go about fixing this? I cant seem to wrap my head around this.
Incase I cant attach my code, here it is:
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/syscallsubr.h>
#include <sys/imgact.h>
#include <vm/vm_extern.h>
#include <sys/kthread.h>
#include <sys/proc.h>
int DEBUG=1;
static int make_args(struct image_args *args, char *fname, char **argv,
char **envv) {
int i;
size_t length;
memset(args, 0, sizeof(struct image_args));
if(exec_alloc_args(args) != 0) {
if(DEBUG) {
printf("exec_alloc_args() failed\n");
uprintf("exec_alloc_args() failed\n");
}
return ENOMEM;
}
// fname
args->fname = args->buf;
length = 1 + strlen(fname);
memcpy(args->fname, fname, length);
// args
args->begin_argv = args->buf + 1 + strlen(fname);
args->endp = args->begin_argv;
for(i = 0; argv[i] != NULL; ++i) {
length = 1 + strlen(argv[i]);
memcpy(args->endp, argv[i], length);
args->stringspace -= length;
args->endp += length;
(args->argc)++;
}
// envv
args->begin_envv = args->endp;
args->endp = args->begin_envv;
for(i = 0; envv[i] != NULL; ++i) {
length = 1 + strlen(envv[i]);
memcpy(args->endp, envv[i], length);
args->stringspace -= length;
args->endp += length;
(args->envc)++;
}
return 0;
}
static int runapp_init(void) {
int error;
char *argv[] = { "/usr/bin/logger", "it works", NULL };
char *envv[] = { NULL };
struct image_args args;
error = make_args(&args, argv[0], argv, envv);
if(error != 0) {
return error;
}
error = kern_execve(curthread, &args, NULL);
if(error != 0) {
if(DEBUG) {
printf("kern_execve() failed\n");
uprintf("kern_execve() failed\n");
}
return error;
}
return 0;
}
static int event_handler(struct module *module, int event, void *arg) {
switch(event) {
case MOD_LOAD:
printf("Hello, World! I'm loaded!\n");
uprintf("Hello, World! I'm loaded!\n");
return runapp_init();
case MOD_UNLOAD:
case MOD_QUIESCE:
printf("Bye Bye Cruel World!\n");
printf("Bye Bye Cruel World!\n");
return 0;
}
return EOPNOTSUPP;
}
static moduledata_t runapp_conf = {
"runapp", /* module name */
event_handler, /* event handler */
NULL /* extra data */
};
DECLARE_MODULE(runapp, runapp_conf, SI_SUB_DRIVERS, SI_ORDER_ANY);
More information about the freebsd-drivers
mailing list