Commit 4e54f08543d05e519e601368571cc3787fefae96

Authored by David Howells
Committed by Linus Torvalds
1 parent 94583779e6

[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>

Showing 6 changed files with 108 additions and 30 deletions Side-by-side Diff

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