#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
+#include <linux/key.h>
#include <linux/keyctl.h>
#include <linux/fs.h>
#include <linux/capability.h>
keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
+
+ /* Root is permitted to invalidate certain special keyrings */
+ if (capable(CAP_SYS_ADMIN)) {
+ keyring_ref = lookup_user_key(ringid, 0, 0);
+ if (IS_ERR(keyring_ref))
+ goto error;
+ if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR,
+ &key_ref_to_ptr(keyring_ref)->flags))
+ goto clear;
+ goto error_put;
+ }
+
goto error;
}
+clear:
ret = keyring_clear(key_ref_to_ptr(keyring_ref));
-
+error_put:
key_ref_put(keyring_ref);
error:
return ret;
*/
long keyctl_set_timeout(key_serial_t id, unsigned timeout)
{
- struct timespec now;
struct key *key, *instkey;
key_ref_t key_ref;
- time_t expiry;
long ret;
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
okay:
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;
- key_schedule_gc(key->expiry + key_gc_delay);
-
- up_write(&key->sem);
+ key_set_timeout(key, timeout);
key_put(key);
ret = 0;