aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 1698bf90ee84..56e963b700b9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -20,6 +20,7 @@
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <linux/security.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include "internal.h" 25#include "internal.h"
25 26
@@ -1080,6 +1081,66 @@ error:
1080 1081
1081} /* end keyctl_assume_authority() */ 1082} /* end keyctl_assume_authority() */
1082 1083
1084/*
1085 * get the security label of a key
1086 * - the key must grant us view permission
1087 * - if there's a buffer, we place up to buflen bytes of data into it
1088 * - unless there's an error, we return the amount of information available,
1089 * irrespective of how much we may have copied (including the terminal NUL)
1090 * - implements keyctl(KEYCTL_GET_SECURITY)
1091 */
1092long keyctl_get_security(key_serial_t keyid,
1093 char __user *buffer,
1094 size_t buflen)
1095{
1096 struct key *key, *instkey;
1097 key_ref_t key_ref;
1098 char *context;
1099 long ret;
1100
1101 key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
1102 if (IS_ERR(key_ref)) {
1103 if (PTR_ERR(key_ref) != -EACCES)
1104 return PTR_ERR(key_ref);
1105
1106 /* viewing a key under construction is also permitted if we
1107 * have the authorisation token handy */
1108 instkey = key_get_instantiation_authkey(keyid);
1109 if (IS_ERR(instkey))
1110 return PTR_ERR(key_ref);
1111 key_put(instkey);
1112
1113 key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
1114 if (IS_ERR(key_ref))
1115 return PTR_ERR(key_ref);
1116 }
1117
1118 key = key_ref_to_ptr(key_ref);
1119 ret = security_key_getsecurity(key, &context);
1120 if (ret == 0) {
1121 /* if no information was returned, give userspace an empty
1122 * string */
1123 ret = 1;
1124 if (buffer && buflen > 0 &&
1125 copy_to_user(buffer, "", 1) != 0)
1126 ret = -EFAULT;
1127 } else if (ret > 0) {
1128 /* return as much data as there's room for */
1129 if (buffer && buflen > 0) {
1130 if (buflen > ret)
1131 buflen = ret;
1132
1133 if (copy_to_user(buffer, context, buflen) != 0)
1134 ret = -EFAULT;
1135 }
1136
1137 kfree(context);
1138 }
1139
1140 key_ref_put(key_ref);
1141 return ret;
1142}
1143
1083/*****************************************************************************/ 1144/*****************************************************************************/
1084/* 1145/*
1085 * the key control system call 1146 * the key control system call
@@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
1160 case KEYCTL_ASSUME_AUTHORITY: 1221 case KEYCTL_ASSUME_AUTHORITY:
1161 return keyctl_assume_authority((key_serial_t) arg2); 1222 return keyctl_assume_authority((key_serial_t) arg2);
1162 1223
1224 case KEYCTL_GET_SECURITY:
1225 return keyctl_get_security((key_serial_t) arg2,
1226 (char *) arg3,
1227 (size_t) arg4);
1228
1163 default: 1229 default:
1164 return -EOPNOTSUPP; 1230 return -EOPNOTSUPP;
1165 } 1231 }