summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys.txt15
-rw-r--r--include/linux/keyctl.h1
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/keyctl.c44
5 files changed, 63 insertions, 1 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 6304db59bfe4..c17c4ca74302 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -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 --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 8d7c59a29e09..ec8f3d622a8d 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -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 --git a/security/keys/compat.c b/security/keys/compat.c
index 3303673c636e..e8e7ef4a290c 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -74,6 +74,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
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 --git a/security/keys/internal.h b/security/keys/internal.h
index 39cba97c5eb9..51f37c0bdb32 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -136,6 +136,7 @@ extern long keyctl_instantiate_key(key_serial_t, const void __user *,
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 --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index b7a468fabdf9..299f0ae11cf0 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -967,6 +967,46 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
/*****************************************************************************/
/*
+ * 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, unsigned long arg2, unsigned long arg3,
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;
}