Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

umh: creds: convert call_usermodehelper_keys() to use subprocess_info->init()

call_usermodehelper_keys() uses call_usermodehelper_setkeys() to change
subprocess_info->cred in advance. Now that we have info->init() we can
change this code to set tgcred->session_keyring in context of execing
kernel thread.

Note: since currently call_usermodehelper_keys() is never called with
UMH_NO_WAIT, call_usermodehelper_keys()->key_get() and umh_keys_cleanup()
are not really needed, we could rely on install_session_keyring_to_cred()
which does key_get() on success.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Oleg Nesterov and committed by
Linus Torvalds
685bfd2c 898b374a

+34 -37
-17
include/linux/kmod.h
··· 72 72 char **envp, gfp_t gfp_mask); 73 73 74 74 /* Set various pieces of state into the subprocess_info structure */ 75 - void call_usermodehelper_setkeys(struct subprocess_info *info, 76 - struct key *session_keyring); 77 75 void call_usermodehelper_setfns(struct subprocess_info *info, 78 76 int (*init)(struct subprocess_info *info), 79 77 void (*cleanup)(struct subprocess_info *info), ··· 108 110 { 109 111 return call_usermodehelper_fns(path, argv, envp, wait, 110 112 NULL, NULL, NULL); 111 - } 112 - 113 - static inline int 114 - call_usermodehelper_keys(char *path, char **argv, char **envp, 115 - struct key *session_keyring, enum umh_wait wait) 116 - { 117 - struct subprocess_info *info; 118 - gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; 119 - 120 - info = call_usermodehelper_setup(path, argv, envp, gfp_mask); 121 - if (info == NULL) 122 - return -ENOMEM; 123 - 124 - call_usermodehelper_setkeys(info, session_keyring); 125 - return call_usermodehelper_exec(info, wait); 126 113 } 127 114 128 115 extern void usermodehelper_init(void);
-18
kernel/kmod.c
··· 367 367 EXPORT_SYMBOL(call_usermodehelper_setup); 368 368 369 369 /** 370 - * call_usermodehelper_setkeys - set the session keys for usermode helper 371 - * @info: a subprocess_info returned by call_usermodehelper_setup 372 - * @session_keyring: the session keyring for the process 373 - */ 374 - void call_usermodehelper_setkeys(struct subprocess_info *info, 375 - struct key *session_keyring) 376 - { 377 - #ifdef CONFIG_KEYS 378 - struct thread_group_cred *tgcred = info->cred->tgcred; 379 - key_put(tgcred->session_keyring); 380 - tgcred->session_keyring = key_get(session_keyring); 381 - #else 382 - BUG(); 383 - #endif 384 - } 385 - EXPORT_SYMBOL(call_usermodehelper_setkeys); 386 - 387 - /** 388 370 * call_usermodehelper_setfns - set a cleanup/init function 389 371 * @info: a subprocess_info returned by call_usermodehelper_setup 390 372 * @cleanup: a cleanup function
+1
security/keys/internal.h
··· 124 124 extern int install_user_keyrings(void); 125 125 extern int install_thread_keyring_to_cred(struct cred *); 126 126 extern int install_process_keyring_to_cred(struct cred *); 127 + extern int install_session_keyring_to_cred(struct cred *, struct key *); 127 128 128 129 extern struct key *request_key_and_link(struct key_type *type, 129 130 const char *description,
+1 -2
security/keys/process_keys.c
··· 216 216 /* 217 217 * install a session keyring directly to a credentials struct 218 218 */ 219 - static int install_session_keyring_to_cred(struct cred *cred, 220 - struct key *keyring) 219 + int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) 221 220 { 222 221 unsigned long flags; 223 222 struct key *old;
+32
security/keys/request_key.c
··· 58 58 } 59 59 EXPORT_SYMBOL(complete_request_key); 60 60 61 + static int umh_keys_init(struct subprocess_info *info) 62 + { 63 + struct cred *cred = (struct cred*)current_cred(); 64 + struct key *keyring = info->data; 65 + /* 66 + * This is called in context of freshly forked kthread before 67 + * kernel_execve(), we can just change our ->session_keyring. 68 + */ 69 + return install_session_keyring_to_cred(cred, keyring); 70 + } 71 + 72 + static void umh_keys_cleanup(struct subprocess_info *info) 73 + { 74 + struct key *keyring = info->data; 75 + key_put(keyring); 76 + } 77 + 78 + static int call_usermodehelper_keys(char *path, char **argv, char **envp, 79 + struct key *session_keyring, enum umh_wait wait) 80 + { 81 + gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; 82 + struct subprocess_info *info = 83 + call_usermodehelper_setup(path, argv, envp, gfp_mask); 84 + 85 + if (!info) 86 + return -ENOMEM; 87 + 88 + call_usermodehelper_setfns(info, umh_keys_init, umh_keys_cleanup, 89 + key_get(session_keyring)); 90 + return call_usermodehelper_exec(info, wait); 91 + } 92 + 61 93 /* 62 94 * request userspace finish the construction of a key 63 95 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"