|
@@ -965,6 +965,46 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
|
|
|
|
|
|
} /* end keyctl_set_reqkey_keyring() */
|
|
} /* end keyctl_set_reqkey_keyring() */
|
|
|
|
|
|
|
|
+/*****************************************************************************/
|
|
|
|
+/*
|
|
|
|
+ * 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
|
|
* the key control system call
|
|
@@ -1038,6 +1078,10 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
|
|
case KEYCTL_SET_REQKEY_KEYRING:
|
|
case KEYCTL_SET_REQKEY_KEYRING:
|
|
return keyctl_set_reqkey_keyring(arg2);
|
|
return keyctl_set_reqkey_keyring(arg2);
|
|
|
|
|
|
|
|
+ case KEYCTL_SET_TIMEOUT:
|
|
|
|
+ return keyctl_set_timeout((key_serial_t) arg2,
|
|
|
|
+ (unsigned) arg3);
|
|
|
|
+
|
|
default:
|
|
default:
|
|
return -EOPNOTSUPP;
|
|
return -EOPNOTSUPP;
|
|
}
|
|
}
|