From: David Howells Add 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. Signed-off-by: David Howells Cc: Trond Myklebust Cc: Alexander Zangerl Signed-off-by: Andrew Morton --- 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(-) diff -puN Documentation/keys.txt~keys-permit-key-expiry-time-to-be-set Documentation/keys.txt --- devel/Documentation/keys.txt~keys-permit-key-expiry-time-to-be-set 2005-11-16 18:08:54.000000000 -0800 +++ devel-akpm/Documentation/keys.txt 2005-11-16 18:08:54.000000000 -0800 @@ -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 =============== diff -puN include/linux/keyctl.h~keys-permit-key-expiry-time-to-be-set include/linux/keyctl.h --- devel/include/linux/keyctl.h~keys-permit-key-expiry-time-to-be-set 2005-11-16 18:08:54.000000000 -0800 +++ devel-akpm/include/linux/keyctl.h 2005-11-16 18:08:54.000000000 -0800 @@ -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 */ diff -puN security/keys/compat.c~keys-permit-key-expiry-time-to-be-set security/keys/compat.c --- devel/security/keys/compat.c~keys-permit-key-expiry-time-to-be-set 2005-11-16 18:08:54.000000000 -0800 +++ devel-akpm/security/keys/compat.c 2005-11-16 18:08:54.000000000 -0800 @@ -74,6 +74,9 @@ asmlinkage long compat_sys_keyctl(u32 op case KEYCTL_SET_REQKEY_KEYRING: return keyctl_set_reqkey_keyring(arg2); + case KEYCTL_SET_TIMEOUT: + return keyctl_set_timeout(arg2, arg3); + default: return -EOPNOTSUPP; } diff -puN security/keys/internal.h~keys-permit-key-expiry-time-to-be-set security/keys/internal.h --- devel/security/keys/internal.h~keys-permit-key-expiry-time-to-be-set 2005-11-16 18:08:54.000000000 -0800 +++ devel-akpm/security/keys/internal.h 2005-11-16 18:08:54.000000000 -0800 @@ -136,6 +136,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); /* diff -puN security/keys/keyctl.c~keys-permit-key-expiry-time-to-be-set security/keys/keyctl.c --- devel/security/keys/keyctl.c~keys-permit-key-expiry-time-to-be-set 2005-11-16 18:08:54.000000000 -0800 +++ devel-akpm/security/keys/keyctl.c 2005-11-16 18:08:54.000000000 -0800 @@ -967,6 +967,46 @@ long keyctl_set_reqkey_keyring(int reqke /*****************************************************************************/ /* + * set or clear the timeout for a key + */ +long keyctl_set_timeout(key_serial_t id, unsigned timeout) +{ + struct timespec now; + struct key *key; + key_ref_t key_ref; + time_t expiry; + long ret; + + key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); + goto error; + } + + key = key_ref_to_ptr(key_ref); + + /* make the changes with the locks held to prevent races */ + down_write(&key->sem); + + expiry = 0; + if (timeout > 0) { + now = current_kernel_time(); + expiry = now.tv_sec + timeout; + } + + key->expiry = expiry; + + up_write(&key->sem); + key_put(key); + + ret = 0; +error: + return ret; + +} /* end keyctl_set_timeout() */ + +/*****************************************************************************/ +/* * the key control system call */ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, @@ -1038,6 +1078,10 @@ asmlinkage long sys_keyctl(int option, u case KEYCTL_SET_REQKEY_KEYRING: return keyctl_set_reqkey_keyring(arg2); + case KEYCTL_SET_TIMEOUT: + return keyctl_set_timeout((key_serial_t) arg2, + (unsigned) arg3); + default: return -EOPNOTSUPP; } _