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

[PATCH] Keys: Pass session keyring to call_usermodehelper()

The attached patch makes it possible to pass a session keyring through to the
process spawned by call_usermodehelper(). This allows patch 3/3 to pass an
authorisation key through to /sbin/request-key, thus permitting better access
controls when doing just-in-time key creation.

Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

David Howells and committed by
Linus Torvalds
7888e7ff 76d8aeab

+35 -7
+9 -1
include/linux/key.h
··· 273 273 extern void key_fsgid_changed(struct task_struct *tsk); 274 274 extern void key_init(void); 275 275 276 + #define __install_session_keyring(tsk, keyring) \ 277 + ({ \ 278 + struct key *old_session = tsk->signal->session_keyring; \ 279 + tsk->signal->session_keyring = keyring; \ 280 + old_session; \ 281 + }) 282 + 276 283 #else /* CONFIG_KEYS */ 277 284 278 285 #define key_validate(k) 0 279 286 #define key_serial(k) 0 280 - #define key_get(k) NULL 287 + #define key_get(k) ({ NULL; }) 281 288 #define key_put(k) do { } while(0) 282 289 #define alloc_uid_keyring(u) 0 283 290 #define switch_uid_keyring(u) do { } while(0) 291 + #define __install_session_keyring(t, k) ({ NULL; }) 284 292 #define copy_keys(f,t) 0 285 293 #define copy_thread_group_keys(t) 0 286 294 #define exit_keys(t) do { } while(0)
+12 -1
include/linux/kmod.h
··· 19 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 20 */ 21 21 22 + #include <linux/stddef.h> 22 23 #include <linux/config.h> 23 24 #include <linux/errno.h> 24 25 #include <linux/compiler.h> ··· 35 34 #endif 36 35 37 36 #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) 38 - extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); 37 + 38 + struct key; 39 + extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[], 40 + struct key *session_keyring, int wait); 41 + 42 + static inline int 43 + call_usermodehelper(char *path, char **argv, char **envp, int wait) 44 + { 45 + return call_usermodehelper_keys(path, argv, envp, NULL, wait); 46 + } 47 + 39 48 extern void usermodehelper_init(void); 40 49 41 50 #endif /* __LINUX_KMOD_H__ */
+13 -4
kernel/kmod.c
··· 120 120 char *path; 121 121 char **argv; 122 122 char **envp; 123 + struct key *ring; 123 124 int wait; 124 125 int retval; 125 126 }; ··· 131 130 static int ____call_usermodehelper(void *data) 132 131 { 133 132 struct subprocess_info *sub_info = data; 133 + struct key *old_session; 134 134 int retval; 135 135 136 - /* Unblock all signals. */ 136 + /* Unblock all signals and set the session keyring. */ 137 + key_get(sub_info->ring); 137 138 flush_signals(current); 138 139 spin_lock_irq(&current->sighand->siglock); 140 + old_session = __install_session_keyring(current, sub_info->ring); 139 141 flush_signal_handlers(current, 1); 140 142 sigemptyset(&current->blocked); 141 143 recalc_sigpending(); 142 144 spin_unlock_irq(&current->sighand->siglock); 145 + 146 + key_put(old_session); 143 147 144 148 /* We can run anywhere, unlike our parent keventd(). */ 145 149 set_cpus_allowed(current, CPU_MASK_ALL); ··· 217 211 } 218 212 219 213 /** 220 - * call_usermodehelper - start a usermode application 214 + * call_usermodehelper_keys - start a usermode application 221 215 * @path: pathname for the application 222 216 * @argv: null-terminated argument list 223 217 * @envp: null-terminated environment list 218 + * @session_keyring: session keyring for process (NULL for an empty keyring) 224 219 * @wait: wait for the application to finish and return status. 225 220 * 226 221 * Runs a user-space application. The application is started ··· 231 224 * Must be called from process context. Returns a negative error code 232 225 * if program was not execed successfully, or 0. 233 226 */ 234 - int call_usermodehelper(char *path, char **argv, char **envp, int wait) 227 + int call_usermodehelper_keys(char *path, char **argv, char **envp, 228 + struct key *session_keyring, int wait) 235 229 { 236 230 DECLARE_COMPLETION(done); 237 231 struct subprocess_info sub_info = { ··· 240 232 .path = path, 241 233 .argv = argv, 242 234 .envp = envp, 235 + .ring = session_keyring, 243 236 .wait = wait, 244 237 .retval = 0, 245 238 }; ··· 256 247 wait_for_completion(&done); 257 248 return sub_info.retval; 258 249 } 259 - EXPORT_SYMBOL(call_usermodehelper); 250 + EXPORT_SYMBOL(call_usermodehelper_keys); 260 251 261 252 void __init usermodehelper_init(void) 262 253 {
+1 -1
security/keys/request_key.c
··· 88 88 argv[i] = NULL; 89 89 90 90 /* do it */ 91 - return call_usermodehelper(argv[0], argv, envp, 1); 91 + return call_usermodehelper_keys(argv[0], argv, envp, NULL, 1); 92 92 93 93 } /* end call_request_key() */ 94 94