diff options
Diffstat (limited to 'kernel/kmod.c')
| -rw-r--r-- | kernel/kmod.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index 05698a7415fe..ff2c7cb86d77 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
| @@ -221,13 +221,12 @@ fail: | |||
| 221 | return 0; | 221 | return 0; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | void call_usermodehelper_freeinfo(struct subprocess_info *info) | 224 | static void call_usermodehelper_freeinfo(struct subprocess_info *info) |
| 225 | { | 225 | { |
| 226 | if (info->cleanup) | 226 | if (info->cleanup) |
| 227 | (*info->cleanup)(info); | 227 | (*info->cleanup)(info); |
| 228 | kfree(info); | 228 | kfree(info); |
| 229 | } | 229 | } |
| 230 | EXPORT_SYMBOL(call_usermodehelper_freeinfo); | ||
| 231 | 230 | ||
| 232 | static void umh_complete(struct subprocess_info *sub_info) | 231 | static void umh_complete(struct subprocess_info *sub_info) |
| 233 | { | 232 | { |
| @@ -410,7 +409,7 @@ EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); | |||
| 410 | 409 | ||
| 411 | /** | 410 | /** |
| 412 | * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled. | 411 | * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled. |
| 413 | * depth: New value to assign to usermodehelper_disabled. | 412 | * @depth: New value to assign to usermodehelper_disabled. |
| 414 | * | 413 | * |
| 415 | * Change the value of usermodehelper_disabled (under umhelper_sem locked for | 414 | * Change the value of usermodehelper_disabled (under umhelper_sem locked for |
| 416 | * writing) and wakeup tasks waiting for it to change. | 415 | * writing) and wakeup tasks waiting for it to change. |
| @@ -479,6 +478,7 @@ static void helper_unlock(void) | |||
| 479 | * structure. This should be passed to call_usermodehelper_exec to | 478 | * structure. This should be passed to call_usermodehelper_exec to |
| 480 | * exec the process and free the structure. | 479 | * exec the process and free the structure. |
| 481 | */ | 480 | */ |
| 481 | static | ||
| 482 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | 482 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, |
| 483 | char **envp, gfp_t gfp_mask) | 483 | char **envp, gfp_t gfp_mask) |
| 484 | { | 484 | { |
| @@ -494,7 +494,6 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | |||
| 494 | out: | 494 | out: |
| 495 | return sub_info; | 495 | return sub_info; |
| 496 | } | 496 | } |
| 497 | EXPORT_SYMBOL(call_usermodehelper_setup); | ||
| 498 | 497 | ||
| 499 | /** | 498 | /** |
| 500 | * call_usermodehelper_setfns - set a cleanup/init function | 499 | * call_usermodehelper_setfns - set a cleanup/init function |
| @@ -512,6 +511,7 @@ EXPORT_SYMBOL(call_usermodehelper_setup); | |||
| 512 | * Function must be runnable in either a process context or the | 511 | * Function must be runnable in either a process context or the |
| 513 | * context in which call_usermodehelper_exec is called. | 512 | * context in which call_usermodehelper_exec is called. |
| 514 | */ | 513 | */ |
| 514 | static | ||
| 515 | void call_usermodehelper_setfns(struct subprocess_info *info, | 515 | void call_usermodehelper_setfns(struct subprocess_info *info, |
| 516 | int (*init)(struct subprocess_info *info, struct cred *new), | 516 | int (*init)(struct subprocess_info *info, struct cred *new), |
| 517 | void (*cleanup)(struct subprocess_info *info), | 517 | void (*cleanup)(struct subprocess_info *info), |
| @@ -521,7 +521,6 @@ void call_usermodehelper_setfns(struct subprocess_info *info, | |||
| 521 | info->init = init; | 521 | info->init = init; |
| 522 | info->data = data; | 522 | info->data = data; |
| 523 | } | 523 | } |
| 524 | EXPORT_SYMBOL(call_usermodehelper_setfns); | ||
| 525 | 524 | ||
| 526 | /** | 525 | /** |
| 527 | * call_usermodehelper_exec - start a usermode application | 526 | * call_usermodehelper_exec - start a usermode application |
| @@ -535,6 +534,7 @@ EXPORT_SYMBOL(call_usermodehelper_setfns); | |||
| 535 | * asynchronously if wait is not set, and runs as a child of keventd. | 534 | * asynchronously if wait is not set, and runs as a child of keventd. |
| 536 | * (ie. it runs with full root capabilities). | 535 | * (ie. it runs with full root capabilities). |
| 537 | */ | 536 | */ |
| 537 | static | ||
| 538 | int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) | 538 | int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) |
| 539 | { | 539 | { |
| 540 | DECLARE_COMPLETION_ONSTACK(done); | 540 | DECLARE_COMPLETION_ONSTACK(done); |
| @@ -576,7 +576,25 @@ unlock: | |||
| 576 | helper_unlock(); | 576 | helper_unlock(); |
| 577 | return retval; | 577 | return retval; |
| 578 | } | 578 | } |
| 579 | EXPORT_SYMBOL(call_usermodehelper_exec); | 579 | |
| 580 | int call_usermodehelper_fns( | ||
| 581 | char *path, char **argv, char **envp, int wait, | ||
| 582 | int (*init)(struct subprocess_info *info, struct cred *new), | ||
| 583 | void (*cleanup)(struct subprocess_info *), void *data) | ||
| 584 | { | ||
| 585 | struct subprocess_info *info; | ||
| 586 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; | ||
| 587 | |||
| 588 | info = call_usermodehelper_setup(path, argv, envp, gfp_mask); | ||
| 589 | |||
| 590 | if (info == NULL) | ||
| 591 | return -ENOMEM; | ||
| 592 | |||
| 593 | call_usermodehelper_setfns(info, init, cleanup, data); | ||
| 594 | |||
| 595 | return call_usermodehelper_exec(info, wait); | ||
| 596 | } | ||
| 597 | EXPORT_SYMBOL(call_usermodehelper_fns); | ||
| 580 | 598 | ||
| 581 | static int proc_cap_handler(struct ctl_table *table, int write, | 599 | static int proc_cap_handler(struct ctl_table *table, int write, |
| 582 | void __user *buffer, size_t *lenp, loff_t *ppos) | 600 | void __user *buffer, size_t *lenp, loff_t *ppos) |
