浏览代码

[PATCH] keys: Permit key expiry time to be set

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 <dhowells@redhat.com>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: Alexander Zangerl <az@bond.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
David Howells 19 年之前
父节点
当前提交
017679c4d4
共有 5 个文件被更改,包括 63 次插入1 次删除
  1. 14 1
      Documentation/keys.txt
  2. 1 0
      include/linux/keyctl.h
  3. 3 0
      security/keys/compat.c
  4. 1 0
      security/keys/internal.h
  5. 44 0
      security/keys/keyctl.c

+ 14 - 1
Documentation/keys.txt

@@ -498,7 +498,7 @@ The keyctl syscall functions are:
      keyring is full, error ENFILE will result.
      keyring is full, error ENFILE will result.
 
 
      The link procedure checks the nesting of the keyrings, returning ELOOP if
      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:
  (*) 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.
      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
 KERNEL SERVICES
 ===============
 ===============

+ 1 - 0
include/linux/keyctl.h

@@ -46,5 +46,6 @@
 #define KEYCTL_INSTANTIATE		12	/* instantiate a partially constructed key */
 #define KEYCTL_INSTANTIATE		12	/* instantiate a partially constructed key */
 #define KEYCTL_NEGATE			13	/* negate 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_REQKEY_KEYRING	14	/* set default request-key keyring */
+#define KEYCTL_SET_TIMEOUT		15	/* set key timeout */
 
 
 #endif /*  _LINUX_KEYCTL_H */
 #endif /*  _LINUX_KEYCTL_H */

+ 3 - 0
security/keys/compat.c

@@ -74,6 +74,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
 	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(arg2, arg3);
+
 	default:
 	default:
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 	}
 	}

+ 1 - 0
security/keys/internal.h

@@ -136,6 +136,7 @@ extern long keyctl_instantiate_key(key_serial_t, const void __user *,
 				   size_t, key_serial_t);
 				   size_t, key_serial_t);
 extern long keyctl_negate_key(key_serial_t, unsigned, 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_reqkey_keyring(int);
+extern long keyctl_set_timeout(key_serial_t, unsigned);
 
 
 
 
 /*
 /*

+ 44 - 0
security/keys/keyctl.c

@@ -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;
 	}
 	}