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

[PATCH] Keys: Allow in-kernel key requestor to pass auxiliary data to upcaller

The proposed NFS key type uses its own method of passing key requests to
userspace (upcalling) rather than invoking /sbin/request-key. This is
because the responsible userspace daemon should already be running and will
be contacted through rpc_pipefs.

This patch permits the NFS filesystem to pass auxiliary data to the upcall
operation (struct key_type::request_key) so that the upcaller can use a
pre-existing communications channel more easily.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-By: Kevin Coffman <kwc@citi.umich.edu>
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
4e54f085 94583779

+108 -30
+36 -18
Documentation/keys-request-key.txt
··· 3 3 =================== 4 4 5 5 The key request service is part of the key retention service (refer to 6 - Documentation/keys.txt). This document explains more fully how that the 7 - requesting algorithm works. 6 + Documentation/keys.txt). This document explains more fully how the requesting 7 + algorithm works. 8 8 9 9 The process starts by either the kernel requesting a service by calling 10 - request_key(): 10 + request_key*(): 11 11 12 12 struct key *request_key(const struct key_type *type, 13 13 const char *description, 14 14 const char *callout_string); 15 + 16 + or: 17 + 18 + struct key *request_key_with_auxdata(const struct key_type *type, 19 + const char *description, 20 + const char *callout_string, 21 + void *aux); 15 22 16 23 Or by userspace invoking the request_key system call: 17 24 ··· 27 20 const char *callout_info, 28 21 key_serial_t dest_keyring); 29 22 30 - The main difference between the two access points is that the in-kernel 31 - interface does not need to link the key to a keyring to prevent it from being 32 - immediately destroyed. The kernel interface returns a pointer directly to the 33 - key, and it's up to the caller to destroy the key. 23 + The main difference between the access points is that the in-kernel interface 24 + does not need to link the key to a keyring to prevent it from being immediately 25 + destroyed. The kernel interface returns a pointer directly to the key, and 26 + it's up to the caller to destroy the key. 27 + 28 + The request_key_with_auxdata() call is like the in-kernel request_key() call, 29 + except that it permits auxiliary data to be passed to the upcaller (the default 30 + is NULL). This is only useful for those key types that define their own upcall 31 + mechanism rather than using /sbin/request-key. 34 32 35 33 The userspace interface links the key to a keyring associated with the process 36 34 to prevent the key from going away, and returns the serial number of the key to 37 35 the caller. 36 + 37 + 38 + The following example assumes that the key types involved don't define their 39 + own upcall mechanisms. If they do, then those should be substituted for the 40 + forking and execution of /sbin/request-key. 38 41 39 42 40 43 =========== ··· 57 40 interface]. 58 41 59 42 (2) request_key() searches the process's subscribed keyrings to see if there's 60 - a suitable key there. If there is, it returns the key. If there isn't, and 61 - callout_info is not set, an error is returned. Otherwise the process 43 + a suitable key there. If there is, it returns the key. If there isn't, 44 + and callout_info is not set, an error is returned. Otherwise the process 62 45 proceeds to the next step. 63 46 64 47 (3) request_key() sees that A doesn't have the desired key yet, so it creates ··· 79 62 instantiation. 80 63 81 64 (7) The program may want to access another key from A's context (say a 82 - Kerberos TGT key). It just requests the appropriate key, and the keyring 65 + Kerberos TGT key). It just requests the appropriate key, and the keyring 83 66 search notes that the session keyring has auth key V in its bottom level. 84 67 85 68 This will permit it to then search the keyrings of process A with the ··· 96 79 (10) The program then exits 0 and request_key() deletes key V and returns key 97 80 U to the caller. 98 81 99 - This also extends further. If key W (step 7 above) didn't exist, key W would be 100 - created uninstantiated, another auth key (X) would be created (as per step 3) 101 - and another copy of /sbin/request-key spawned (as per step 4); but the context 102 - specified by auth key X will still be process A, as it was in auth key V. 82 + This also extends further. If key W (step 7 above) didn't exist, key W would 83 + be created uninstantiated, another auth key (X) would be created (as per step 84 + 3) and another copy of /sbin/request-key spawned (as per step 4); but the 85 + context specified by auth key X will still be process A, as it was in auth key 86 + V. 103 87 104 88 This is because process A's keyrings can't simply be attached to 105 89 /sbin/request-key at the appropriate places because (a) execve will discard two ··· 136 118 137 119 (2) It considers all the non-keyring keys within that keyring and, if any key 138 120 matches the criteria specified, calls key_permission(SEARCH) on it to see 139 - if the key is allowed to be found. If it is, that key is returned; if 121 + if the key is allowed to be found. If it is, that key is returned; if 140 122 not, the search continues, and the error code is retained if of higher 141 123 priority than the one currently set. 142 124 143 125 (3) It then considers all the keyring-type keys in the keyring it's currently 144 - searching. It calls key_permission(SEARCH) on each keyring, and if this 126 + searching. It calls key_permission(SEARCH) on each keyring, and if this 145 127 grants permission, it recurses, executing steps (2) and (3) on that 146 128 keyring. 147 129 148 130 The process stops immediately a valid key is found with permission granted to 149 - use it. Any error from a previous match attempt is discarded and the key is 131 + use it. Any error from a previous match attempt is discarded and the key is 150 132 returned. 151 133 152 134 When search_process_keyrings() is invoked, it performs the following searches ··· 171 153 returned. 172 154 173 155 Only if all these fail does the whole thing fail with the highest priority 174 - error. Note that several errors may have come from LSM. 156 + error. Note that several errors may have come from LSM. 175 157 176 158 The error priority is: 177 159
+29
Documentation/keys.txt
··· 780 780 See also Documentation/keys-request-key.txt. 781 781 782 782 783 + (*) To search for a key, passing auxiliary data to the upcaller, call: 784 + 785 + struct key *request_key_with_auxdata(const struct key_type *type, 786 + const char *description, 787 + const char *callout_string, 788 + void *aux); 789 + 790 + This is identical to request_key(), except that the auxiliary data is 791 + passed to the key_type->request_key() op if it exists. 792 + 793 + 783 794 (*) When it is no longer required, the key should be released using: 784 795 785 796 void key_put(struct key *key); ··· 1040 1029 prevent the key's payload changing. It is not necessary to use RCU locking 1041 1030 when accessing the key's payload. It is safe to sleep in this method, such 1042 1031 as might happen when the userspace buffer is accessed. 1032 + 1033 + 1034 + (*) int (*request_key)(struct key *key, struct key *authkey, const char *op, 1035 + void *aux); 1036 + 1037 + This method is optional. If provided, request_key() and 1038 + request_key_with_auxdata() will invoke this function rather than 1039 + upcalling to /sbin/request-key to operate upon a key of this type. 1040 + 1041 + The aux parameter is as passed to request_key_with_auxdata() or is NULL 1042 + otherwise. Also passed are the key to be operated upon, the 1043 + authorisation key for this operation and the operation type (currently 1044 + only "create"). 1045 + 1046 + This function should return only when the upcall is complete. Upon return 1047 + the authorisation key will be revoked, and the target key will be 1048 + negatively instantiated if it is still uninstantiated. The error will be 1049 + returned to the caller of request_key*(). 1043 1050 1044 1051 1045 1052 ============================
+7 -1
include/linux/key.h
··· 177 177 /* 178 178 * kernel managed key type definition 179 179 */ 180 - typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, const char *op); 180 + typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, 181 + const char *op, void *aux); 181 182 182 183 struct key_type { 183 184 /* name of the type */ ··· 285 284 extern struct key *request_key(struct key_type *type, 286 285 const char *description, 287 286 const char *callout_info); 287 + 288 + extern struct key *request_key_with_auxdata(struct key_type *type, 289 + const char *description, 290 + const char *callout_info, 291 + void *aux); 288 292 289 293 extern int key_validate(struct key *key); 290 294
+1
security/keys/internal.h
··· 99 99 extern struct key *request_key_and_link(struct key_type *type, 100 100 const char *description, 101 101 const char *callout_info, 102 + void *aux, 102 103 struct key *dest_keyring, 103 104 unsigned long flags); 104 105
+1 -1
security/keys/keyctl.c
··· 183 183 } 184 184 185 185 /* do the search */ 186 - key = request_key_and_link(ktype, description, callout_info, 186 + key = request_key_and_link(ktype, description, callout_info, NULL, 187 187 key_ref_to_ptr(dest_ref), 188 188 KEY_ALLOC_IN_QUOTA); 189 189 if (IS_ERR(key)) {
+34 -10
security/keys/request_key.c
··· 1 1 /* request_key.c: request a key from userspace 2 2 * 3 - * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 33 33 */ 34 34 static int call_sbin_request_key(struct key *key, 35 35 struct key *authkey, 36 - const char *op) 36 + const char *op, 37 + void *aux) 37 38 { 38 39 struct task_struct *tsk = current; 39 40 key_serial_t prkey, sskey; ··· 128 127 static struct key *__request_key_construction(struct key_type *type, 129 128 const char *description, 130 129 const char *callout_info, 130 + void *aux, 131 131 unsigned long flags) 132 132 { 133 133 request_key_actor_t actor; ··· 166 164 actor = call_sbin_request_key; 167 165 if (type->request_key) 168 166 actor = type->request_key; 169 - ret = actor(key, authkey, "create"); 167 + ret = actor(key, authkey, "create", aux); 170 168 if (ret < 0) 171 169 goto request_failed; 172 170 ··· 260 258 */ 261 259 static struct key *request_key_construction(struct key_type *type, 262 260 const char *description, 263 - struct key_user *user, 264 261 const char *callout_info, 262 + void *aux, 263 + struct key_user *user, 265 264 unsigned long flags) 266 265 { 267 266 struct key_construction *pcons; ··· 287 284 } 288 285 289 286 /* see about getting userspace to construct the key */ 290 - key = __request_key_construction(type, description, callout_info, 287 + key = __request_key_construction(type, description, callout_info, aux, 291 288 flags); 292 289 error: 293 290 kleave(" = %p", key); ··· 395 392 struct key *request_key_and_link(struct key_type *type, 396 393 const char *description, 397 394 const char *callout_info, 395 + void *aux, 398 396 struct key *dest_keyring, 399 397 unsigned long flags) 400 398 { ··· 403 399 struct key *key; 404 400 key_ref_t key_ref; 405 401 406 - kenter("%s,%s,%s,%p,%lx", 407 - type->name, description, callout_info, dest_keyring, flags); 402 + kenter("%s,%s,%s,%p,%p,%lx", 403 + type->name, description, callout_info, aux, 404 + dest_keyring, flags); 408 405 409 406 /* search all the process keyrings for a key */ 410 407 key_ref = search_process_keyrings(type, description, type->match, ··· 438 433 /* ask userspace (returns NULL if it waited on a key 439 434 * being constructed) */ 440 435 key = request_key_construction(type, description, 441 - user, callout_info, 442 - flags); 436 + callout_info, aux, 437 + user, flags); 443 438 if (key) 444 439 break; 445 440 ··· 496 491 const char *callout_info) 497 492 { 498 493 return request_key_and_link(type, description, callout_info, NULL, 499 - KEY_ALLOC_IN_QUOTA); 494 + NULL, KEY_ALLOC_IN_QUOTA); 500 495 501 496 } /* end request_key() */ 502 497 503 498 EXPORT_SYMBOL(request_key); 499 + 500 + /*****************************************************************************/ 501 + /* 502 + * request a key with auxiliary data for the upcaller 503 + * - search the process's keyrings 504 + * - check the list of keys being created or updated 505 + * - call out to userspace for a key if supplementary info was provided 506 + */ 507 + struct key *request_key_with_auxdata(struct key_type *type, 508 + const char *description, 509 + const char *callout_info, 510 + void *aux) 511 + { 512 + return request_key_and_link(type, description, callout_info, aux, 513 + NULL, KEY_ALLOC_IN_QUOTA); 514 + 515 + } /* end request_key_with_auxdata() */ 516 + 517 + EXPORT_SYMBOL(request_key_with_auxdata);