diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 66 |
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 | */ | ||
1092 | long 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 | } |