Keys: Permit key expiry time to be set
Subsystems (4)
David Howells
maintainerPATCH 1/1 Keys: Permit key expiry time to be set
The attached patch adds a new keyctl function that allows the expiry time to be set on a key or removed from a key, provided the caller has attribute modification access.
---
warthog>diffstat keys-expiry-2615rc1.diff
Documentation/keys.txt | 15 ++++++++++++++- include/linux/keyctl.h | 1 + security/keys/compat.c | 3 +++ security/keys/internal.h | 1 + security/keys/keyctl.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-)
Documentation/keys.txt +14 -1
@@ -498,7 +498,7 @@ The keyctl syscall functions are: keyring is full, error ENFILE will result. The link procedure checks the nesting of the keyrings, returning ELOOP if - it appears to deep or EDEADLK if the link would introduce a cycle. + it appears too deep or EDEADLK if the link would introduce a cycle. (*) Unlink a key or keyring from another keyring:
@@ -628,6 +628,19 @@ The keyctl syscall functions are: there is one, otherwise the user default session keyring. + (*) Set the timeout on a key. + + long keyctl(KEYCTL_SET_TIMEOUT, key_serial_t key, unsigned timeout); + + This sets or clears the timeout on a key. The timeout can be 0 to clear + the timeout or a number of seconds to set the expiry time that far into + the future. + + The process must have attribute modification access on a key to set its + timeout. Timeouts may not be set with this function on negative, revoked + or expired keys. + + =============== KERNEL SERVICES ===============
include/linux/keyctl.h +1 -0
@@ -46,5 +46,6 @@#define KEYCTL_INSTANTIATE 12/* instantiate a partially constructed key */ #define KEYCTL_NEGATE 13/* negate a partially constructed key */ #define KEYCTL_SET_REQKEY_KEYRING 14/* set default request-key keyring */ +#define KEYCTL_SET_TIMEOUT 15/* set key timeout */ #endif /* _LINUX_KEYCTL_H */
security/keys/compat.c +3 -0
@@ -74,6 +74,9 @@ asmlinkage long compat_sys_keyctl(u32 opcase KEYCTL_SET_REQKEY_KEYRING :return keyctl_set_reqkey_keyring (arg2); +case KEYCTL_SET_TIMEOUT : +return keyctl_set_timeout (arg2, arg3); +default :return -EOPNOTSUPP ; }
security/keys/internal.h +1 -0
@@ -137,6 +137,7 @@ extern long keyctl_instantiate_key(key_s size_t, key_serial_t);extern long keyctl_negate_key (key_serial_t ,unsigned ,key_serial_t );extern long keyctl_set_reqkey_keyring (int ); +extern long keyctl_set_timeout (key_serial_t ,unsigned );/*
security/keys/keyctl.c +44 -0
56 lines not on this page · raw message
David Howells
maintainerPATCH 1/1 Keys: Discard duplicate keys from a keyring on link
The attached patch causes any links within a keyring to keys that match a key to be linked into that keyring to be discarded as a link to the new key is added. The match is contingent on the type and description strings being the same.
This permits requests, adds and searches to displace negative, expired, revoked and dead keys easily. After some discussion it was concluded that duplicate valid keys should probably be discarded also as they would otherwise hide the new key.
Since request_key() is intended to be the primary method by which keys are added to a keyring, duplicate valid keys wouldn't be an issue there as that function would return an existing match in preference to creating a new key.
---
warthog>diffstat keys-multilink-2615rc1.diff
Documentation/keys.txt | 4 ++ security/keys/keyring.c | 87 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 68 insertions(+), 23 deletions(-)
Documentation/keys.txt +4 -0
@@ -500,6 +500,10 @@ The keyctl syscall functions are: The link procedure checks the nesting of the keyrings, returning ELOOP if it appears too deep or EDEADLK if the link would introduce a cycle. + Any links within the keyring to keys that match the new key in terms of + type and description will be discarded from the keyring as the new one is + added. + (*) Unlink a key or keyring from another keyring:
security/keys/keyring.c +64 -23
130 lines not on this page · raw message
David Howells
maintainerPATCH 1/1 Keys: Permit running process to instantiate keys
The attached patch makes it possible for a running process (such as gssapid) to be able to instantiate a key, as was requested by Trond Myklebust for NFS4.
The patch makes the following changes:
(1) A new, optional key type method has been added. This permits a key type to intercept requests at the point /sbin/request-key is about to be spawned and do something else with them - passing them over the rpc_pipefs files or netlink sockets for instance.
The uninstantiated key, the authorisation key and the intended operation name are passed to the method.
(2) The callout_info is no longer passed as an argument to /sbin/request-key to prevent unauthorised viewing of this data using ps or by looking in /proc/pid/cmdline.
This means that the old /sbin/request-key program will not work with the patched kernel as it will expect to see an extra argument that is no longer there.
A revised keyutils package will be made available tomorrow.
(3) The callout_info is now attached to the authorisation key. Reading this key will retrieve the information.
(4) A new field has been added to the task_struct. This holds the authorisation key currently active for a thread. Searches now look here for the caller's set of keys rather than looking for an auth key in the lowest level of the session keyring.
This permits a thread to be servicing multiple requests at once and to switch between them. Note that this is per-thread, not per-process, and so is usable in multithreaded programs.
The setting of this field is inherited across fork and exec.
(5) A new keyctl function (KEYCTL_ASSUME_AUTHORITY) has been added that permits a thread to assume the authority to deal with an uninstantiated key. Assumption is only permitted if the authorisation key associated with the uninstantiated key is somewhere in the thread's keyrings.
This function can also clear the assumption.
(6) A new magic key specifier has been added to refer to the currently assumed authorisation key (KEY_SPEC_REQKEY_AUTH_KEY).
(7) Instantiation will only proceed if the appropriate authorisation key is assumed first. The assumed authorisation key is discarded if instantiation is successful.
(8) key_validate() is moved from the file of request_key functions to the file of permissions functions.
(9) The documentation is updated.
---
warthog>diffstat -p1 keys-reqkey-2615rc1.diff
Documentation/keys-request-key.txt | 22 ++-- Documentation/keys.txt | 24 ++++ include/linux/key.h | 12 ++ include/linux/keyctl.h | 2 include/linux/sched.h | 1 security/keys/compat.c | 3 security/keys/internal.h | 4 security/keys/keyctl.c | 107 ++++++++++++++++---- security/keys/keyring.c | 45 -------- security/keys/permission.c | 32 ++++++ security/keys/process_keys.c | 71 +++++++------ security/keys/request_key.c | 108 +++++++++----------- security/keys/request_key_auth.c | 192 ++++++++++++++++++++++--------------- 13 files changed, 378 insertions(+), 245 deletions(-)
Documentation/keys-request-key.txt +12 -10
@@ -56,10 +56,12 @@ A request proceeds in the following mann (4) request_key() then forks and executes /sbin/request-key with a new session keyring that contains a link to auth key V. - (5) /sbin/request-key execs an appropriate program to perform the actual + (5) /sbin/request-key assumes the authority associated with key U. + + (6) /sbin/request-key execs an appropriate program to perform the actual instantiation. - (6) The program may want to access another key from A's context (say a + (7) The program may want to access another key from A's context (say a Kerberos TGT key). It just requests the appropriate key, and the keyring search notes that the session keyring has auth key V in its bottom level.
@@ -67,19 +69,19 @@ A request proceeds in the following mann UID, GID, groups and security info of process A as if it was process A, and come up with key W. - (7) The program then does what it must to get the data with which to + (8) The program then does what it must to get the data with which to instantiate key U, using key W as a reference (perhaps it contacts a Kerberos server using the TGT) and then instantiates key U. - (8) Upon instantiating key U, auth key V is automatically revoked so that it + (9) Upon instantiating key U, auth key V is automatically revoked so that it may not be used again. - (9) The program then exits 0 and request_key() deletes key V and returns key +(10) The program then exits 0 and request_key() deletes key V and returns key U to the caller. -This also extends further. If key W (step 5 above) didn't exist, key W would be -created uninstantiated, another auth key (X) would be created [as per step 3] -and another copy of /sbin/request-key spawned [as per step 4]; but the context +This also extends further. If key W (step 7 above) didn't exist, key W would be +created uninstantiated, another auth key (X) would be created (as per step 3) +and another copy of /sbin/request-key spawned (as per step 4); but the context specified by auth key X will still be process A, as it was in auth key V. This is because process A's keyrings can't simply be attached to
@@ -138,8 +140,8 @@ until one succeeds: (3) The process's session keyring is searched. - (4) If the process has a request_key() authorisation key in its session - keyring then: + (4) If the process has assumed the authority associated with a request_key() + authorisation key then: (a) If extant, the calling process's thread keyring is searched.
Documentation/keys.txt +24 -0
@@ -308,6 +308,8 @@ process making the call: KEY_SPEC_USER_KEYRING -4 UID-specific keyring KEY_SPEC_USER_SESSION_KEYRING -5 UID-session keyring KEY_SPEC_GROUP_KEYRING -6 GID-specific keyring + KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key() + authorisation key The main syscalls are:
@@ -645,6 +647,28 @@ The keyctl syscall functions are: or expired keys. + (*) Assume the authority granted to instantiate a key + + long keyctl(KEYCTL_ASSUME_AUTHORITY, key_serial_t key); + + This assumes or divests the authority required to instantiate the + specified key. Authority can only be assumed if the thread has the + authorisation key associated with the specified key in its keyrings + somewhere. + + Once authority is assumed, searches for keys will also search the + requester's keyrings using the requester's security label, UID, GID and + groups. + + If the requested authority is unavailable, error EPERM will be returned, + likewise if the authority has been revoked because the target key is + already instantiated. + + If the specified key is 0, then any assumed authority will be divested. + + The assumed authorititive key is inherited across fork and exec. + + =============== KERNEL SERVICES ===============
include/linux/keyctl.h +2 -0
@@ -19,6 +19,7 @@#define KEY_SPEC_USER_KEYRING -4/* - key ID for UID-specific keyring */ #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 */ /* request-key default keyrings */ #define KEY_REQKEY_DEFL_NO_CHANGE -1
@@ -47,5 +48,6 @@#define KEYCTL_NEGATE 13/* negate a partially constructed key */ #define KEYCTL_SET_REQKEY_KEYRING 14/* set default request-key keyring */ #define KEYCTL_SET_TIMEOUT 15/* set key timeout */ +#define KEYCTL_ASSUME_AUTHORITY 16/* assume request_key() authorisation */ #endif /* _LINUX_KEYCTL_H */
include/linux/key.h +12 -0
@@ -177,6 +177,8 @@ struct key {/* * kernel managed key type definition */ +typedef int (*request_key_actor_t )(struct key *key,struct key *authkey,const char *op); +struct key_type {/* name of the type */ const char *name;
@@ -226,6 +228,16 @@ struct key_type {*/ long (*read)(const struct key *key,char __user *buffer,size_t buflen); +/* handle request_key() for this type instead of invoking +* /sbin/request-key (optional) +* - key is the key to instantiate +* - authkey is the authority to assume when instantiating this key +* - op is the operation to be done, usually "create" +* - the call must not return until the instantiation process has run +* its course +*/ +request_key_actor_t request_key; +/* internal fields */ struct list_head link;/* link in types list */ };
include/linux/sched.h +1 -0
@@ -776,6 +776,7 @@ struct task_struct { unsigned keep_capabilities:1;struct user_struct *user;#ifdef CONFIG_KEYS +struct key *request_key_auth;/* assumed request_key authority */ struct key *thread_keyring;/* keyring private to this thread */ unsigned char jit_keyring;/* default keyring to attach requested keys to */ #endif
security/keys/compat.c +3 -0
@@ -77,6 +77,9 @@ asmlinkage long compat_sys_keyctl(u32 opcase KEYCTL_SET_TIMEOUT :return keyctl_set_timeout (arg2, arg3); +case KEYCTL_ASSUME_AUTHORITY : +return keyctl_assume_authority (arg2); +default :return -EOPNOTSUPP ; }
security/keys/internal.h +3 -1
@@ -108,12 +108,13 @@ extern struct key *request_key_and_link(struct request_key_auth {struct key *target_key;struct task_struct *context; +const char *callout_info;pid_t pid; };extern struct key_type key_type_request_key_auth;extern struct key *request_key_auth_new (struct key *target, -struct key **_rkakey); +const char *callout_info);extern struct key *key_get_instantiation_authkey (key_serial_t target_id);
@@ -138,6 +139,7 @@ extern long keyctl_instantiate_key(key_sextern long keyctl_negate_key (key_serial_t ,unsigned ,key_serial_t );extern long keyctl_set_reqkey_keyring (int );extern long keyctl_set_timeout (key_serial_t ,unsigned ); +extern long keyctl_assume_authority (key_serial_t );/*
security/keys/keyctl.c +84 -23
165 lines not on this page · raw message
security/keys/keyring.c +0 -45
51 lines not on this page · raw message
security/keys/permission.c +32 -0
@@ -73,3 +73,35 @@ use_these_perms: }/* end key_task_permission() */ EXPORT_SYMBOL (key_task_permission); + +/*****************************************************************************/ +/* +* validate a key +*/ +int key_validate (struct key *key) +{ +struct timespec now; +int ret =0 ; + +if (key) { +/* check it's still accessible */ + ret = -EKEYREVOKED ; +if (test_bit (KEY_FLAG_REVOKED , &key->flags) || +test_bit (KEY_FLAG_DEAD , &key->flags)) + goto error; + +/* check it hasn't expired */ + ret =0 ; +if (key->expiry) { + now =current_kernel_time (); +if (now.tv_sec >= key->expiry) + ret = -EKEYEXPIRED ; + } + } + + error: +return ret; + +}/* end key_validate() */ + +EXPORT_SYMBOL (key_validate);
security/keys/process_keys.c +38 -33
120 lines not on this page · raw message
security/keys/request_key_auth.c +117 -75
269 lines not on this page · raw message
security/keys/request_key.c +50 -58
181 lines not on this page · raw message
Quoted 4 lines · David Howells
The attached patch adds a new keyctl function that allows the expiry time to be set on a key or removed from a key, provided the caller has attribute modification access.
There is no need for the ability to query a key's timeout setting?
David Howells
maintainerI've stuck an updated keyutils tarball and SRPM on:
http://people.redhat.com/~dhowells/keyutils/keyutils-0.3-2.tar.bz2 http://people.redhat.com/~dhowells/keyutils/keyutils-0.3-2.src.rpm
For those who want to play with the new facilities.
Alexander Zangerl: I've incorporated my take on your patch by which /sbin/request-key can be made to dangle a slave program at the ends of a pair of pipes to do the work. The callout_info is passed to stdin and the payload data retrieved via stdout. You configure it by sticking a '|' symbol in front of the program name in /etc/request-key.conf. Can you test it please. That bit compiles, but I haven't had time to test it yet, so it may not work.
David
David Howells
maintainerDavid Howells <[email protected]> wrote:
I've stuck an updated keyutils tarball and SRPM on:
http://people.redhat.com/~dhowells/keyutils/keyutils-0.3-3.tar.bz2 http://people.redhat.com/~dhowells/keyutils/keyutils-0.3-3.src.rpm
For those who want to play with the new facilities.
David