Commit 685bfd2c48bb3284d31e73ff3151c957d76deda9

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent 898b374af6

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>

Showing 5 changed files with 34 additions and 37 deletions Side-by-side Diff

include/linux/kmod.h
... ... @@ -72,8 +72,6 @@
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),
... ... @@ -110,21 +108,6 @@
110 108 {
111 109 return call_usermodehelper_fns(path, argv, envp, wait,
112 110 NULL, NULL, NULL);
113   -}
114   -
115   -static inline int
116   -call_usermodehelper_keys(char *path, char **argv, char **envp,
117   - struct key *session_keyring, enum umh_wait wait)
118   -{
119   - struct subprocess_info *info;
120   - gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
121   -
122   - info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
123   - if (info == NULL)
124   - return -ENOMEM;
125   -
126   - call_usermodehelper_setkeys(info, session_keyring);
127   - return call_usermodehelper_exec(info, wait);
128 111 }
129 112  
130 113 extern void usermodehelper_init(void);
... ... @@ -367,24 +367,6 @@
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
security/keys/internal.h
... ... @@ -124,6 +124,7 @@
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,
security/keys/process_keys.c
... ... @@ -216,8 +216,7 @@
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;
security/keys/request_key.c
... ... @@ -58,6 +58,38 @@
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>"