aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/request_key.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:14 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:14 -0500
commit8bbf4976b59fc9fc2861e79cab7beb3f6d647640 (patch)
tree9bd621217cbdfcf94aca5b220de7363254d7fc23 /security/keys/request_key.c
parente9e349b051d98799b743ebf248cc2d986fedf090 (diff)
KEYS: Alter use of key instantiation link-to-keyring argument
Alter the use of the key instantiation and negation functions' link-to-keyring arguments. Currently this specifies a keyring in the target process to link the key into, creating the keyring if it doesn't exist. This, however, can be a problem for copy-on-write credentials as it means that the instantiating process can alter the credentials of the requesting process. This patch alters the behaviour such that: (1) If keyctl_instantiate_key() or keyctl_negate_key() are given a specific keyring by ID (ringid >= 0), then that keyring will be used. (2) If keyctl_instantiate_key() or keyctl_negate_key() are given one of the special constants that refer to the requesting process's keyrings (KEY_SPEC_*_KEYRING, all <= 0), then: (a) If sys_request_key() was given a keyring to use (destringid) then the key will be attached to that keyring. (b) If sys_request_key() was given a NULL keyring, then the key being instantiated will be attached to the default keyring as set by keyctl_set_reqkey_keyring(). (3) No extra link will be made. Decision point (1) follows current behaviour, and allows those instantiators who've searched for a specifically named keyring in the requestor's keyring so as to partition the keys by type to still have their named keyrings. Decision point (2) allows the requestor to make sure that the key or keys that get produced by request_key() go where they want, whilst allowing the instantiator to request that the key is retained. This is mainly useful for situations where the instantiator makes a secondary request, the key for which should be retained by the initial requestor: +-----------+ +--------------+ +--------------+ | | | | | | | Requestor |------->| Instantiator |------->| Instantiator | | | | | | | +-----------+ +--------------+ +--------------+ request_key() request_key() This might be useful, for example, in Kerberos, where the requestor requests a ticket, and then the ticket instantiator requests the TGT, which someone else then has to go and fetch. The TGT, however, should be retained in the keyrings of the requestor, not the first instantiator. To make this explict an extra special keyring constant is also added. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r--security/keys/request_key.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 91953c81449..8e9d93b4a40 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -76,6 +76,10 @@ static int call_sbin_request_key(struct key_construction *cons,
76 76
77 kenter("{%d},{%d},%s", key->serial, authkey->serial, op); 77 kenter("{%d},{%d},%s", key->serial, authkey->serial, op);
78 78
79 ret = install_user_keyrings();
80 if (ret < 0)
81 goto error_alloc;
82
79 /* allocate a new session keyring */ 83 /* allocate a new session keyring */
80 sprintf(desc, "_req.%u", key->serial); 84 sprintf(desc, "_req.%u", key->serial);
81 85
@@ -165,7 +169,8 @@ error_alloc:
165 * - we ignore program failure and go on key status instead 169 * - we ignore program failure and go on key status instead
166 */ 170 */
167static int construct_key(struct key *key, const void *callout_info, 171static int construct_key(struct key *key, const void *callout_info,
168 size_t callout_len, void *aux) 172 size_t callout_len, void *aux,
173 struct key *dest_keyring)
169{ 174{
170 struct key_construction *cons; 175 struct key_construction *cons;
171 request_key_actor_t actor; 176 request_key_actor_t actor;
@@ -179,7 +184,8 @@ static int construct_key(struct key *key, const void *callout_info,
179 return -ENOMEM; 184 return -ENOMEM;
180 185
181 /* allocate an authorisation key */ 186 /* allocate an authorisation key */
182 authkey = request_key_auth_new(key, callout_info, callout_len); 187 authkey = request_key_auth_new(key, callout_info, callout_len,
188 dest_keyring);
183 if (IS_ERR(authkey)) { 189 if (IS_ERR(authkey)) {
184 kfree(cons); 190 kfree(cons);
185 ret = PTR_ERR(authkey); 191 ret = PTR_ERR(authkey);
@@ -207,27 +213,48 @@ static int construct_key(struct key *key, const void *callout_info,
207} 213}
208 214
209/* 215/*
210 * link a key to the appropriate destination keyring 216 * get the appropriate destination keyring for the request
211 * - the caller must hold a write lock on the destination keyring 217 * - we return whatever keyring we select with an extra reference upon it which
218 * the caller must release
212 */ 219 */
213static void construct_key_make_link(struct key *key, struct key *dest_keyring) 220static void construct_get_dest_keyring(struct key **_dest_keyring)
214{ 221{
222 struct request_key_auth *rka;
215 struct task_struct *tsk = current; 223 struct task_struct *tsk = current;
216 struct key *drop = NULL; 224 struct key *dest_keyring = *_dest_keyring, *authkey;
217 225
218 kenter("{%d},%p", key->serial, dest_keyring); 226 kenter("%p", dest_keyring);
219 227
220 /* find the appropriate keyring */ 228 /* find the appropriate keyring */
221 if (!dest_keyring) { 229 if (dest_keyring) {
230 /* the caller supplied one */
231 key_get(dest_keyring);
232 } else {
233 /* use a default keyring; falling through the cases until we
234 * find one that we actually have */
222 switch (tsk->jit_keyring) { 235 switch (tsk->jit_keyring) {
223 case KEY_REQKEY_DEFL_DEFAULT: 236 case KEY_REQKEY_DEFL_DEFAULT:
237 case KEY_REQKEY_DEFL_REQUESTOR_KEYRING:
238 if (tsk->request_key_auth) {
239 authkey = tsk->request_key_auth;
240 down_read(&authkey->sem);
241 rka = authkey->payload.data;
242 if (!test_bit(KEY_FLAG_REVOKED,
243 &authkey->flags))
244 dest_keyring =
245 key_get(rka->dest_keyring);
246 up_read(&authkey->sem);
247 if (dest_keyring)
248 break;
249 }
250
224 case KEY_REQKEY_DEFL_THREAD_KEYRING: 251 case KEY_REQKEY_DEFL_THREAD_KEYRING:
225 dest_keyring = tsk->thread_keyring; 252 dest_keyring = key_get(tsk->thread_keyring);
226 if (dest_keyring) 253 if (dest_keyring)
227 break; 254 break;
228 255
229 case KEY_REQKEY_DEFL_PROCESS_KEYRING: 256 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
230 dest_keyring = tsk->signal->process_keyring; 257 dest_keyring = key_get(tsk->signal->process_keyring);
231 if (dest_keyring) 258 if (dest_keyring)
232 break; 259 break;
233 260
@@ -236,17 +263,16 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)
236 dest_keyring = key_get( 263 dest_keyring = key_get(
237 rcu_dereference(tsk->signal->session_keyring)); 264 rcu_dereference(tsk->signal->session_keyring));
238 rcu_read_unlock(); 265 rcu_read_unlock();
239 drop = dest_keyring;
240 266
241 if (dest_keyring) 267 if (dest_keyring)
242 break; 268 break;
243 269
244 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 270 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
245 dest_keyring = tsk->user->session_keyring; 271 dest_keyring = key_get(tsk->user->session_keyring);
246 break; 272 break;
247 273
248 case KEY_REQKEY_DEFL_USER_KEYRING: 274 case KEY_REQKEY_DEFL_USER_KEYRING:
249 dest_keyring = tsk->user->uid_keyring; 275 dest_keyring = key_get(tsk->user->uid_keyring);
250 break; 276 break;
251 277
252 case KEY_REQKEY_DEFL_GROUP_KEYRING: 278 case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -255,10 +281,9 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)
255 } 281 }
256 } 282 }
257 283
258 /* and attach the key to it */ 284 *_dest_keyring = dest_keyring;
259 __key_link(dest_keyring, key); 285 kleave(" [dk %d]", key_serial(dest_keyring));
260 key_put(drop); 286 return;
261 kleave("");
262} 287}
263 288
264/* 289/*
@@ -288,8 +313,7 @@ static int construct_alloc_key(struct key_type *type,
288 313
289 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); 314 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
290 315
291 if (dest_keyring) 316 down_write(&dest_keyring->sem);
292 down_write(&dest_keyring->sem);
293 317
294 /* attach the key to the destination keyring under lock, but we do need 318 /* attach the key to the destination keyring under lock, but we do need
295 * to do another check just in case someone beat us to it whilst we 319 * to do another check just in case someone beat us to it whilst we
@@ -301,12 +325,10 @@ static int construct_alloc_key(struct key_type *type,
301 if (!IS_ERR(key_ref)) 325 if (!IS_ERR(key_ref))
302 goto key_already_present; 326 goto key_already_present;
303 327
304 if (dest_keyring) 328 __key_link(dest_keyring, key);
305 construct_key_make_link(key, dest_keyring);
306 329
307 mutex_unlock(&key_construction_mutex); 330 mutex_unlock(&key_construction_mutex);
308 if (dest_keyring) 331 up_write(&dest_keyring->sem);
309 up_write(&dest_keyring->sem);
310 mutex_unlock(&user->cons_lock); 332 mutex_unlock(&user->cons_lock);
311 *_key = key; 333 *_key = key;
312 kleave(" = 0 [%d]", key_serial(key)); 334 kleave(" = 0 [%d]", key_serial(key));
@@ -348,21 +370,26 @@ static struct key *construct_key_and_link(struct key_type *type,
348 if (!user) 370 if (!user)
349 return ERR_PTR(-ENOMEM); 371 return ERR_PTR(-ENOMEM);
350 372
373 construct_get_dest_keyring(&dest_keyring);
374
351 ret = construct_alloc_key(type, description, dest_keyring, flags, user, 375 ret = construct_alloc_key(type, description, dest_keyring, flags, user,
352 &key); 376 &key);
353 key_user_put(user); 377 key_user_put(user);
354 378
355 if (ret == 0) { 379 if (ret == 0) {
356 ret = construct_key(key, callout_info, callout_len, aux); 380 ret = construct_key(key, callout_info, callout_len, aux,
381 dest_keyring);
357 if (ret < 0) 382 if (ret < 0)
358 goto construction_failed; 383 goto construction_failed;
359 } 384 }
360 385
386 key_put(dest_keyring);
361 return key; 387 return key;
362 388
363construction_failed: 389construction_failed:
364 key_negate_and_link(key, key_negative_timeout, NULL, NULL); 390 key_negate_and_link(key, key_negative_timeout, NULL, NULL);
365 key_put(key); 391 key_put(key);
392 key_put(dest_keyring);
366 return ERR_PTR(ret); 393 return ERR_PTR(ret);
367} 394}
368 395