Commit 938e4b22e2a7d0f6f3962e601339347b2d8e09f5
Committed by
Linus Torvalds
1 parent
17afab1de4
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
usermodehelper: export call_usermodehelper_exec() and call_usermodehelper_setup()
call_usermodehelper_setup() + call_usermodehelper_exec() need to be called instead of call_usermodehelper_fns() when the cleanup function needs to be called even when an ENOMEM error occurs. In this case using call_usermodehelper_fns() the user can't distinguish if the cleanup function was called or not. [akpm@linux-foundation.org: export call_usermodehelper_setup() to modules] Signed-off-by: Lucas De Marchi <lucas.demarchi@profusion.mobi> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: David Howells <dhowells@redhat.com> Cc: James Morris <james.l.morris@oracle.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Tejun Heo <tj@kernel.org> Cc: "Rafael J. Wysocki" <rjw@sisk.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 32 additions and 33 deletions Side-by-side Diff
include/linux/kmod.h
... | ... | @@ -71,6 +71,14 @@ |
71 | 71 | int (*init)(struct subprocess_info *info, struct cred *new), |
72 | 72 | void (*cleanup)(struct subprocess_info *), void *data); |
73 | 73 | |
74 | +extern struct subprocess_info * | |
75 | +call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask, | |
76 | + int (*init)(struct subprocess_info *info, struct cred *new), | |
77 | + void (*cleanup)(struct subprocess_info *), void *data); | |
78 | + | |
79 | +extern int | |
80 | +call_usermodehelper_exec(struct subprocess_info *info, int wait); | |
81 | + | |
74 | 82 | static inline int |
75 | 83 | call_usermodehelper(char *path, char **argv, char **envp, int wait) |
76 | 84 | { |
kernel/kmod.c
... | ... | @@ -502,14 +502,28 @@ |
502 | 502 | * @argv: arg vector for process |
503 | 503 | * @envp: environment for process |
504 | 504 | * @gfp_mask: gfp mask for memory allocation |
505 | + * @cleanup: a cleanup function | |
506 | + * @init: an init function | |
507 | + * @data: arbitrary context sensitive data | |
505 | 508 | * |
506 | 509 | * Returns either %NULL on allocation failure, or a subprocess_info |
507 | 510 | * structure. This should be passed to call_usermodehelper_exec to |
508 | 511 | * exec the process and free the structure. |
512 | + * | |
513 | + * The init function is used to customize the helper process prior to | |
514 | + * exec. A non-zero return code causes the process to error out, exit, | |
515 | + * and return the failure to the calling process | |
516 | + * | |
517 | + * The cleanup function is just before ethe subprocess_info is about to | |
518 | + * be freed. This can be used for freeing the argv and envp. The | |
519 | + * Function must be runnable in either a process context or the | |
520 | + * context in which call_usermodehelper_exec is called. | |
509 | 521 | */ |
510 | -static | |
511 | 522 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, |
512 | - char **envp, gfp_t gfp_mask) | |
523 | + char **envp, gfp_t gfp_mask, | |
524 | + int (*init)(struct subprocess_info *info, struct cred *new), | |
525 | + void (*cleanup)(struct subprocess_info *info), | |
526 | + void *data) | |
513 | 527 | { |
514 | 528 | struct subprocess_info *sub_info; |
515 | 529 | sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask); |
516 | 530 | |
517 | 531 | |
... | ... | @@ -520,38 +534,16 @@ |
520 | 534 | sub_info->path = path; |
521 | 535 | sub_info->argv = argv; |
522 | 536 | sub_info->envp = envp; |
537 | + | |
538 | + sub_info->cleanup = cleanup; | |
539 | + sub_info->init = init; | |
540 | + sub_info->data = data; | |
523 | 541 | out: |
524 | 542 | return sub_info; |
525 | 543 | } |
544 | +EXPORT_SYMBOL(call_usermodehelper_setup); | |
526 | 545 | |
527 | 546 | /** |
528 | - * call_usermodehelper_setfns - set a cleanup/init function | |
529 | - * @info: a subprocess_info returned by call_usermodehelper_setup | |
530 | - * @cleanup: a cleanup function | |
531 | - * @init: an init function | |
532 | - * @data: arbitrary context sensitive data | |
533 | - * | |
534 | - * The init function is used to customize the helper process prior to | |
535 | - * exec. A non-zero return code causes the process to error out, exit, | |
536 | - * and return the failure to the calling process | |
537 | - * | |
538 | - * The cleanup function is just before ethe subprocess_info is about to | |
539 | - * be freed. This can be used for freeing the argv and envp. The | |
540 | - * Function must be runnable in either a process context or the | |
541 | - * context in which call_usermodehelper_exec is called. | |
542 | - */ | |
543 | -static | |
544 | -void call_usermodehelper_setfns(struct subprocess_info *info, | |
545 | - int (*init)(struct subprocess_info *info, struct cred *new), | |
546 | - void (*cleanup)(struct subprocess_info *info), | |
547 | - void *data) | |
548 | -{ | |
549 | - info->cleanup = cleanup; | |
550 | - info->init = init; | |
551 | - info->data = data; | |
552 | -} | |
553 | - | |
554 | -/** | |
555 | 547 | * call_usermodehelper_exec - start a usermode application |
556 | 548 | * @sub_info: information about the subprocessa |
557 | 549 | * @wait: wait for the application to finish and return status. |
... | ... | @@ -563,7 +555,6 @@ |
563 | 555 | * asynchronously if wait is not set, and runs as a child of keventd. |
564 | 556 | * (ie. it runs with full root capabilities). |
565 | 557 | */ |
566 | -static | |
567 | 558 | int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) |
568 | 559 | { |
569 | 560 | DECLARE_COMPLETION_ONSTACK(done); |
... | ... | @@ -615,6 +606,7 @@ |
615 | 606 | helper_unlock(); |
616 | 607 | return retval; |
617 | 608 | } |
609 | +EXPORT_SYMBOL(call_usermodehelper_exec); | |
618 | 610 | |
619 | 611 | /* |
620 | 612 | * call_usermodehelper_fns() will not run the caller-provided cleanup function |
621 | 613 | |
... | ... | @@ -630,12 +622,11 @@ |
630 | 622 | struct subprocess_info *info; |
631 | 623 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; |
632 | 624 | |
633 | - info = call_usermodehelper_setup(path, argv, envp, gfp_mask); | |
625 | + info = call_usermodehelper_setup(path, argv, envp, gfp_mask, | |
626 | + init, cleanup, data); | |
634 | 627 | |
635 | 628 | if (info == NULL) |
636 | 629 | return -ENOMEM; |
637 | - | |
638 | - call_usermodehelper_setfns(info, init, cleanup, data); | |
639 | 630 | |
640 | 631 | return call_usermodehelper_exec(info, wait); |
641 | 632 | } |