aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-29 05:24:28 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-29 13:26:20 -0400
commit4e54f08543d05e519e601368571cc3787fefae96 (patch)
tree0cd9d982e5bb25abcb9251d26c36ff11e7dc81a5
parent94583779e6625154e8d7fce33d097ae7d089e9de (diff)
[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>
-rw-r--r--Documentation/keys-request-key.txt54
-rw-r--r--Documentation/keys.txt29
-rw-r--r--include/linux/key.h8
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/keys/request_key.c44
6 files changed, 108 insertions, 30 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 22488d791168..c1f64fdf84cb 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -3,16 +3,23 @@
3 =================== 3 ===================
4 4
5The key request service is part of the key retention service (refer to 5The key request service is part of the key retention service (refer to
6Documentation/keys.txt). This document explains more fully how that the 6Documentation/keys.txt). This document explains more fully how the requesting
7requesting algorithm works. 7algorithm works.
8 8
9The process starts by either the kernel requesting a service by calling 9The process starts by either the kernel requesting a service by calling
10request_key(): 10request_key*():
11 11
12 struct key *request_key(const struct key_type *type, 12 struct key *request_key(const struct key_type *type,
13 const char *description, 13 const char *description,
14 const char *callout_string); 14 const char *callout_string);
15 15
16or:
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
16Or by userspace invoking the request_key system call: 23Or by userspace invoking the request_key system call:
17 24
18 key_serial_t request_key(const char *type, 25 key_serial_t request_key(const char *type,
@@ -20,16 +27,26 @@ Or by userspace invoking the request_key system call:
20 const char *callout_info, 27 const char *callout_info,
21 key_serial_t dest_keyring); 28 key_serial_t dest_keyring);
22 29
23The main difference between the two access points is that the in-kernel 30The main difference between the access points is that the in-kernel interface
24interface does not need to link the key to a keyring to prevent it from being 31does not need to link the key to a keyring to prevent it from being immediately
25immediately destroyed. The kernel interface returns a pointer directly to the 32destroyed. The kernel interface returns a pointer directly to the key, and
26key, and it's up to the caller to destroy the key. 33it's up to the caller to destroy the key.
34
35The request_key_with_auxdata() call is like the in-kernel request_key() call,
36except that it permits auxiliary data to be passed to the upcaller (the default
37is NULL). This is only useful for those key types that define their own upcall
38mechanism rather than using /sbin/request-key.
27 39
28The userspace interface links the key to a keyring associated with the process 40The userspace interface links the key to a keyring associated with the process
29to prevent the key from going away, and returns the serial number of the key to 41to prevent the key from going away, and returns the serial number of the key to
30the caller. 42the caller.
31 43
32 44
45The following example assumes that the key types involved don't define their
46own upcall mechanisms. If they do, then those should be substituted for the
47forking and execution of /sbin/request-key.
48
49
33=========== 50===========
34THE PROCESS 51THE PROCESS
35=========== 52===========
@@ -40,8 +57,8 @@ A request proceeds in the following manner:
40 interface]. 57 interface].
41 58
42 (2) request_key() searches the process's subscribed keyrings to see if there's 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 60 a suitable key there. If there is, it returns the key. If there isn't,
44 callout_info is not set, an error is returned. Otherwise the process 61 and callout_info is not set, an error is returned. Otherwise the process
45 proceeds to the next step. 62 proceeds to the next step.
46 63
47 (3) request_key() sees that A doesn't have the desired key yet, so it creates 64 (3) request_key() sees that A doesn't have the desired key yet, so it creates
@@ -62,7 +79,7 @@ A request proceeds in the following manner:
62 instantiation. 79 instantiation.
63 80
64 (7) The program may want to access another key from A's context (say a 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 search notes that the session keyring has auth key V in its bottom level. 83 search notes that the session keyring has auth key V in its bottom level.
67 84
68 This will permit it to then search the keyrings of process A with the 85 This will permit it to then search the keyrings of process A with the
@@ -79,10 +96,11 @@ A request proceeds in the following manner:
79(10) The program then exits 0 and request_key() deletes key V and returns key 96(10) The program then exits 0 and request_key() deletes key V and returns key
80 U to the caller. 97 U to the caller.
81 98
82This also extends further. If key W (step 7 above) didn't exist, key W would be 99This also extends further. If key W (step 7 above) didn't exist, key W would
83created uninstantiated, another auth key (X) would be created (as per step 3) 100be created uninstantiated, another auth key (X) would be created (as per step
84and another copy of /sbin/request-key spawned (as per step 4); but the context 1013) and another copy of /sbin/request-key spawned (as per step 4); but the
85specified by auth key X will still be process A, as it was in auth key V. 102context specified by auth key X will still be process A, as it was in auth key
103V.
86 104
87This is because process A's keyrings can't simply be attached to 105This is because process A's keyrings can't simply be attached to
88/sbin/request-key at the appropriate places because (a) execve will discard two 106/sbin/request-key at the appropriate places because (a) execve will discard two
@@ -118,17 +136,17 @@ A search of any particular keyring proceeds in the following fashion:
118 136
119 (2) It considers all the non-keyring keys within that keyring and, if any key 137 (2) It considers all the non-keyring keys within that keyring and, if any key
120 matches the criteria specified, calls key_permission(SEARCH) on it to see 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 not, the search continues, and the error code is retained if of higher 140 not, the search continues, and the error code is retained if of higher
123 priority than the one currently set. 141 priority than the one currently set.
124 142
125 (3) It then considers all the keyring-type keys in the keyring it's currently 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 grants permission, it recurses, executing steps (2) and (3) on that 145 grants permission, it recurses, executing steps (2) and (3) on that
128 keyring. 146 keyring.
129 147
130The process stops immediately a valid key is found with permission granted to 148The process stops immediately a valid key is found with permission granted to
131use it. Any error from a previous match attempt is discarded and the key is 149use it. Any error from a previous match attempt is discarded and the key is
132returned. 150returned.
133 151
134When search_process_keyrings() is invoked, it performs the following searches 152When search_process_keyrings() is invoked, it performs the following searches
@@ -153,7 +171,7 @@ The moment one succeeds, all pending errors are discarded and the found key is
153returned. 171returned.
154 172
155Only if all these fail does the whole thing fail with the highest priority 173Only if all these fail does the whole thing fail with the highest priority
156error. Note that several errors may have come from LSM. 174error. Note that several errors may have come from LSM.
157 175
158The error priority is: 176The error priority is:
159 177
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 61c0fad2fe2f..e373f0212843 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -780,6 +780,17 @@ payload contents" for more information.
780 See also Documentation/keys-request-key.txt. 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(*) When it is no longer required, the key should be released using: 794(*) When it is no longer required, the key should be released using:
784 795
785 void key_put(struct key *key); 796 void key_put(struct key *key);
@@ -1031,6 +1042,24 @@ The structure has a number of fields, some of which are mandatory:
1031 as might happen when the userspace buffer is accessed. 1042 as might happen when the userspace buffer is accessed.
1032 1043
1033 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*().
1061
1062
1034============================ 1063============================
1035REQUEST-KEY CALLBACK SERVICE 1064REQUEST-KEY CALLBACK SERVICE
1036============================ 1065============================
diff --git a/include/linux/key.h b/include/linux/key.h
index e693e729bc92..169f05e4863e 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -177,7 +177,8 @@ struct key {
177/* 177/*
178 * kernel managed key type definition 178 * kernel managed key type definition
179 */ 179 */
180typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, const char *op); 180typedef int (*request_key_actor_t)(struct key *key, struct key *authkey,
181 const char *op, void *aux);
181 182
182struct key_type { 183struct key_type {
183 /* name of the type */ 184 /* name of the type */
@@ -285,6 +286,11 @@ extern struct key *request_key(struct key_type *type,
285 const char *description, 286 const char *description,
286 const char *callout_info); 287 const char *callout_info);
287 288
289extern struct key *request_key_with_auxdata(struct key_type *type,
290 const char *description,
291 const char *callout_info,
292 void *aux);
293
288extern int key_validate(struct key *key); 294extern int key_validate(struct key *key);
289 295
290extern key_ref_t key_create_or_update(key_ref_t keyring, 296extern key_ref_t key_create_or_update(key_ref_t keyring,
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 3c2877f0663e..1bb416f4bbce 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -99,6 +99,7 @@ extern int install_process_keyring(struct task_struct *tsk);
99extern struct key *request_key_and_link(struct key_type *type, 99extern struct key *request_key_and_link(struct key_type *type,
100 const char *description, 100 const char *description,
101 const char *callout_info, 101 const char *callout_info,
102 void *aux,
102 struct key *dest_keyring, 103 struct key *dest_keyring,
103 unsigned long flags); 104 unsigned long flags);
104 105
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 329411cf8768..d9ca15c109cc 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -183,7 +183,7 @@ asmlinkage long sys_request_key(const char __user *_type,
183 } 183 }
184 184
185 /* do the search */ 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 key_ref_to_ptr(dest_ref), 187 key_ref_to_ptr(dest_ref),
188 KEY_ALLOC_IN_QUOTA); 188 KEY_ALLOC_IN_QUOTA);
189 if (IS_ERR(key)) { 189 if (IS_ERR(key)) {
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 58d1efd4fc2c..f573ac189a0a 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
1/* request_key.c: request a key from userspace 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 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -33,7 +33,8 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
33 */ 33 */
34static int call_sbin_request_key(struct key *key, 34static int call_sbin_request_key(struct key *key,
35 struct key *authkey, 35 struct key *authkey,
36 const char *op) 36 const char *op,
37 void *aux)
37{ 38{
38 struct task_struct *tsk = current; 39 struct task_struct *tsk = current;
39 key_serial_t prkey, sskey; 40 key_serial_t prkey, sskey;
@@ -127,6 +128,7 @@ error_alloc:
127static struct key *__request_key_construction(struct key_type *type, 128static struct key *__request_key_construction(struct key_type *type,
128 const char *description, 129 const char *description,
129 const char *callout_info, 130 const char *callout_info,
131 void *aux,
130 unsigned long flags) 132 unsigned long flags)
131{ 133{
132 request_key_actor_t actor; 134 request_key_actor_t actor;
@@ -164,7 +166,7 @@ static struct key *__request_key_construction(struct key_type *type,
164 actor = call_sbin_request_key; 166 actor = call_sbin_request_key;
165 if (type->request_key) 167 if (type->request_key)
166 actor = type->request_key; 168 actor = type->request_key;
167 ret = actor(key, authkey, "create"); 169 ret = actor(key, authkey, "create", aux);
168 if (ret < 0) 170 if (ret < 0)
169 goto request_failed; 171 goto request_failed;
170 172
@@ -258,8 +260,9 @@ alloc_failed:
258 */ 260 */
259static struct key *request_key_construction(struct key_type *type, 261static struct key *request_key_construction(struct key_type *type,
260 const char *description, 262 const char *description,
261 struct key_user *user,
262 const char *callout_info, 263 const char *callout_info,
264 void *aux,
265 struct key_user *user,
263 unsigned long flags) 266 unsigned long flags)
264{ 267{
265 struct key_construction *pcons; 268 struct key_construction *pcons;
@@ -284,7 +287,7 @@ static struct key *request_key_construction(struct key_type *type,
284 } 287 }
285 288
286 /* see about getting userspace to construct the key */ 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 flags); 291 flags);
289 error: 292 error:
290 kleave(" = %p", key); 293 kleave(" = %p", key);
@@ -392,6 +395,7 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
392struct key *request_key_and_link(struct key_type *type, 395struct key *request_key_and_link(struct key_type *type,
393 const char *description, 396 const char *description,
394 const char *callout_info, 397 const char *callout_info,
398 void *aux,
395 struct key *dest_keyring, 399 struct key *dest_keyring,
396 unsigned long flags) 400 unsigned long flags)
397{ 401{
@@ -399,8 +403,9 @@ struct key *request_key_and_link(struct key_type *type,
399 struct key *key; 403 struct key *key;
400 key_ref_t key_ref; 404 key_ref_t key_ref;
401 405
402 kenter("%s,%s,%s,%p,%lx", 406 kenter("%s,%s,%s,%p,%p,%lx",
403 type->name, description, callout_info, dest_keyring, flags); 407 type->name, description, callout_info, aux,
408 dest_keyring, flags);
404 409
405 /* search all the process keyrings for a key */ 410 /* search all the process keyrings for a key */
406 key_ref = search_process_keyrings(type, description, type->match, 411 key_ref = search_process_keyrings(type, description, type->match,
@@ -433,8 +438,8 @@ struct key *request_key_and_link(struct key_type *type,
433 /* ask userspace (returns NULL if it waited on a key 438 /* ask userspace (returns NULL if it waited on a key
434 * being constructed) */ 439 * being constructed) */
435 key = request_key_construction(type, description, 440 key = request_key_construction(type, description,
436 user, callout_info, 441 callout_info, aux,
437 flags); 442 user, flags);
438 if (key) 443 if (key)
439 break; 444 break;
440 445
@@ -491,8 +496,27 @@ struct key *request_key(struct key_type *type,
491 const char *callout_info) 496 const char *callout_info)
492{ 497{
493 return request_key_and_link(type, description, callout_info, NULL, 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} /* end request_key() */ 501} /* end request_key() */
497 502
498EXPORT_SYMBOL(request_key); 503EXPORT_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 */
512struct 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
522EXPORT_SYMBOL(request_key_with_auxdata);