diff options
-rw-r--r-- | include/linux/kmod.h | 17 | ||||
-rw-r--r-- | kernel/kmod.c | 18 | ||||
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/keys/process_keys.c | 3 | ||||
-rw-r--r-- | security/keys/request_key.c | 32 |
5 files changed, 34 insertions, 37 deletions
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 5c05877..d876dce 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -72,8 +72,6 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask); /* Set various pieces of state into the subprocess_info structure */ -void call_usermodehelper_setkeys(struct subprocess_info *info, - struct key *session_keyring); void call_usermodehelper_setfns(struct subprocess_info *info, int (*init)(struct subprocess_info *info), void (*cleanup)(struct subprocess_info *info), @@ -112,21 +110,6 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) NULL, NULL, NULL); } -static inline int -call_usermodehelper_keys(char *path, char **argv, char **envp, - struct key *session_keyring, enum umh_wait wait) -{ - struct subprocess_info *info; - gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; - - info = call_usermodehelper_setup(path, argv, envp, gfp_mask); - if (info == NULL) - return -ENOMEM; - - call_usermodehelper_setkeys(info, session_keyring); - return call_usermodehelper_exec(info, wait); -} - extern void usermodehelper_init(void); extern int usermodehelper_disable(void); diff --git a/kernel/kmod.c b/kernel/kmod.c index d154454..743d388 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -367,24 +367,6 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, EXPORT_SYMBOL(call_usermodehelper_setup); /** - * call_usermodehelper_setkeys - set the session keys for usermode helper - * @info: a subprocess_info returned by call_usermodehelper_setup - * @session_keyring: the session keyring for the process - */ -void call_usermodehelper_setkeys(struct subprocess_info *info, - struct key *session_keyring) -{ -#ifdef CONFIG_KEYS - struct thread_group_cred *tgcred = info->cred->tgcred; - key_put(tgcred->session_keyring); - tgcred->session_keyring = key_get(session_keyring); -#else - BUG(); -#endif -} -EXPORT_SYMBOL(call_usermodehelper_setkeys); - -/** * call_usermodehelper_setfns - set a cleanup/init function * @info: a subprocess_info returned by call_usermodehelper_setup * @cleanup: a cleanup function diff --git a/security/keys/internal.h b/security/keys/internal.h index 5d4402a..38783dc 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -124,6 +124,7 @@ extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); extern int install_user_keyrings(void); extern int install_thread_keyring_to_cred(struct cred *); extern int install_process_keyring_to_cred(struct cred *); +extern int install_session_keyring_to_cred(struct cred *, struct key *); extern struct key *request_key_and_link(struct key_type *type, const char *description, diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 20a38fe..6b8e4ff 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -216,8 +216,7 @@ static int install_process_keyring(void) /* * install a session keyring directly to a credentials struct */ -static int install_session_keyring_to_cred(struct cred *cred, - struct key *keyring) +int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) { unsigned long flags; struct key *old; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index f656e9c..f5ec9ac 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -58,6 +58,38 @@ void complete_request_key(struct key_construction *cons, int error) } EXPORT_SYMBOL(complete_request_key); +static int umh_keys_init(struct subprocess_info *info) +{ + struct cred *cred = (struct cred*)current_cred(); + struct key *keyring = info->data; + /* + * This is called in context of freshly forked kthread before + * kernel_execve(), we can just change our ->session_keyring. + */ + return install_session_keyring_to_cred(cred, keyring); +} + +static void umh_keys_cleanup(struct subprocess_info *info) +{ + struct key *keyring = info->data; + key_put(keyring); +} + +static int call_usermodehelper_keys(char *path, char **argv, char **envp, + struct key *session_keyring, enum umh_wait wait) +{ + gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; + struct subprocess_info *info = + call_usermodehelper_setup(path, argv, envp, gfp_mask); + + if (!info) + return -ENOMEM; + + call_usermodehelper_setfns(info, umh_keys_init, umh_keys_cleanup, + key_get(session_keyring)); + return call_usermodehelper_exec(info, wait); +} + /* * request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" |