Skip to content

Commit

Permalink
KEYS: Alter use of key instantiation link-to-keyring argument
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: James Morris <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
dhowells authored and James Morris committed Nov 13, 2008
1 parent e9e349b commit 8bbf497
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 121 deletions.
16 changes: 8 additions & 8 deletions include/linux/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,11 @@ extern void key_fsuid_changed(struct task_struct *tsk);
extern void key_fsgid_changed(struct task_struct *tsk);
extern void key_init(void);

#define __install_session_keyring(tsk, keyring) \
({ \
struct key *old_session = tsk->signal->session_keyring; \
tsk->signal->session_keyring = keyring; \
old_session; \
#define __install_session_keyring(keyring) \
({ \
struct key *old_session = current->signal->session_keyring; \
current->signal->session_keyring = keyring; \
old_session; \
})

#else /* CONFIG_KEYS */
Expand All @@ -302,11 +302,11 @@ extern void key_init(void);
#define key_revoke(k) do { } while(0)
#define key_put(k) do { } while(0)
#define key_ref_put(k) do { } while(0)
#define make_key_ref(k, p) ({ NULL; })
#define key_ref_to_ptr(k) ({ NULL; })
#define make_key_ref(k, p) NULL
#define key_ref_to_ptr(k) NULL
#define is_key_possessed(k) 0
#define switch_uid_keyring(u) do { } while(0)
#define __install_session_keyring(t, k) ({ NULL; })
#define __install_session_keyring(k) ({ NULL; })
#define copy_keys(f,t) 0
#define copy_thread_group_keys(t) 0
#define exit_keys(t) do { } while(0)
Expand Down
4 changes: 3 additions & 1 deletion include/linux/keyctl.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* keyctl.h: keyctl command IDs
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
* Copyright (C) 2004, 2008 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* This program is free software; you can redistribute it and/or
Expand All @@ -20,6 +20,7 @@
#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
#define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */

/* request-key default keyrings */
#define KEY_REQKEY_DEFL_NO_CHANGE -1
Expand All @@ -30,6 +31,7 @@
#define KEY_REQKEY_DEFL_USER_KEYRING 4
#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5
#define KEY_REQKEY_DEFL_GROUP_KEYRING 6
#define KEY_REQKEY_DEFL_REQUESTOR_KEYRING 7

/* keyctl commands */
#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
Expand Down
2 changes: 1 addition & 1 deletion kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static int ____call_usermodehelper(void *data)
/* Unblock all signals and set the session keyring. */
new_session = key_get(sub_info->ring);
spin_lock_irq(&current->sighand->siglock);
old_session = __install_session_keyring(current, new_session);
old_session = __install_session_keyring(new_session);
flush_signal_handlers(current, 1);
sigemptyset(&current->blocked);
recalc_sigpending();
Expand Down
12 changes: 7 additions & 5 deletions security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ extern key_ref_t search_process_keyrings(struct key_type *type,

extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);

extern int install_thread_keyring(struct task_struct *tsk);
extern int install_process_keyring(struct task_struct *tsk);
extern int install_user_keyrings(void);
extern int install_thread_keyring(void);
extern int install_process_keyring(void);

extern struct key *request_key_and_link(struct key_type *type,
const char *description,
Expand All @@ -120,8 +121,7 @@ extern struct key *request_key_and_link(struct key_type *type,
struct key *dest_keyring,
unsigned long flags);

extern key_ref_t lookup_user_key(struct task_struct *context,
key_serial_t id, int create, int partial,
extern key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
key_perm_t perm);

extern long join_session_keyring(const char *name);
Expand Down Expand Up @@ -152,6 +152,7 @@ static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
*/
struct request_key_auth {
struct key *target_key;
struct key *dest_keyring;
struct task_struct *context;
void *callout_info;
size_t callout_len;
Expand All @@ -161,7 +162,8 @@ struct request_key_auth {
extern struct key_type key_type_request_key_auth;
extern struct key *request_key_auth_new(struct key *target,
const void *callout_info,
size_t callout_len);
size_t callout_len,
struct key *dest_keyring);

extern struct key *key_get_instantiation_authkey(key_serial_t target_id);

Expand Down
Loading

0 comments on commit 8bbf497

Please sign in to comment.