|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/string.h>
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
+#include <linux/security.h>
|
|
|
#include <asm/uaccess.h>
|
|
|
#include "internal.h"
|
|
|
|
|
@@ -1080,6 +1081,66 @@ error:
|
|
|
|
|
|
} /* end keyctl_assume_authority() */
|
|
|
|
|
|
+/*
|
|
|
+ * get the security label of a key
|
|
|
+ * - the key must grant us view permission
|
|
|
+ * - if there's a buffer, we place up to buflen bytes of data into it
|
|
|
+ * - unless there's an error, we return the amount of information available,
|
|
|
+ * irrespective of how much we may have copied (including the terminal NUL)
|
|
|
+ * - implements keyctl(KEYCTL_GET_SECURITY)
|
|
|
+ */
|
|
|
+long keyctl_get_security(key_serial_t keyid,
|
|
|
+ char __user *buffer,
|
|
|
+ size_t buflen)
|
|
|
+{
|
|
|
+ struct key *key, *instkey;
|
|
|
+ key_ref_t key_ref;
|
|
|
+ char *context;
|
|
|
+ long ret;
|
|
|
+
|
|
|
+ key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
|
|
|
+ if (IS_ERR(key_ref)) {
|
|
|
+ if (PTR_ERR(key_ref) != -EACCES)
|
|
|
+ return PTR_ERR(key_ref);
|
|
|
+
|
|
|
+ /* viewing a key under construction is also permitted if we
|
|
|
+ * have the authorisation token handy */
|
|
|
+ instkey = key_get_instantiation_authkey(keyid);
|
|
|
+ if (IS_ERR(instkey))
|
|
|
+ return PTR_ERR(key_ref);
|
|
|
+ key_put(instkey);
|
|
|
+
|
|
|
+ key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
|
|
|
+ if (IS_ERR(key_ref))
|
|
|
+ return PTR_ERR(key_ref);
|
|
|
+ }
|
|
|
+
|
|
|
+ key = key_ref_to_ptr(key_ref);
|
|
|
+ ret = security_key_getsecurity(key, &context);
|
|
|
+ if (ret == 0) {
|
|
|
+ /* if no information was returned, give userspace an empty
|
|
|
+ * string */
|
|
|
+ ret = 1;
|
|
|
+ if (buffer && buflen > 0 &&
|
|
|
+ copy_to_user(buffer, "", 1) != 0)
|
|
|
+ ret = -EFAULT;
|
|
|
+ } else if (ret > 0) {
|
|
|
+ /* return as much data as there's room for */
|
|
|
+ if (buffer && buflen > 0) {
|
|
|
+ if (buflen > ret)
|
|
|
+ buflen = ret;
|
|
|
+
|
|
|
+ if (copy_to_user(buffer, context, buflen) != 0)
|
|
|
+ ret = -EFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(context);
|
|
|
+ }
|
|
|
+
|
|
|
+ key_ref_put(key_ref);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*****************************************************************************/
|
|
|
/*
|
|
|
* the key control system call
|
|
@@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
|
|
|
case KEYCTL_ASSUME_AUTHORITY:
|
|
|
return keyctl_assume_authority((key_serial_t) arg2);
|
|
|
|
|
|
+ case KEYCTL_GET_SECURITY:
|
|
|
+ return keyctl_get_security((key_serial_t) arg2,
|
|
|
+ (char *) arg3,
|
|
|
+ (size_t) arg4);
|
|
|
+
|
|
|
default:
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|