mysterious locking issue

Konstantin Belousov kostikbel at gmail.com
Sat Jul 27 06:12:13 UTC 2013


On Sat, Jul 27, 2013 at 12:46:09AM -0400, ret val wrote:
> 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.
Kernel startup is single-threaded and owns the Giant.  You are trying
to call kern_execve() from the startup thread, which is the immediate
cause of your problem.

If you think about this some more, you would see that this cannot work
when module is initialized at the boot. Because kernel is not fully
initialized yet, the scheduler and usermode does not work, and there
is no filesystem mounted from which to execute the image. Much worse
is that you are trying to change the executing image of the usermode
program for a situation where there is no usermode and the process which
is executing is the kernel startup.

FWIW, your code also does not quite work for the kldload case as well.
You are execing in the context of the kldload, not allowing the normal
kldload operation to finish.

> 
> 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.
This is not fixable.

> 
> 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);

> _______________________________________________
> freebsd-drivers at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-drivers
> To unsubscribe, send any mail to "freebsd-drivers-unsubscribe at freebsd.org"

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-drivers/attachments/20130727/05eadd06/attachment.sig>


More information about the freebsd-drivers mailing list