diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/compat.c | 3 | ||||
-rw-r--r-- | security/keys/internal.h | 3 | ||||
-rw-r--r-- | security/keys/keyctl.c | 66 |
3 files changed, 71 insertions, 1 deletions
diff --git a/security/keys/compat.c b/security/keys/compat.c index e10ec995f275..c766c68a63bc 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
79 | case KEYCTL_ASSUME_AUTHORITY: | 79 | case KEYCTL_ASSUME_AUTHORITY: |
80 | return keyctl_assume_authority(arg2); | 80 | return keyctl_assume_authority(arg2); |
81 | 81 | ||
82 | case KEYCTL_GET_SECURITY: | ||
83 | return keyctl_get_security(arg2, compat_ptr(arg3), arg4); | ||
84 | |||
82 | default: | 85 | default: |
83 | return -EOPNOTSUPP; | 86 | return -EOPNOTSUPP; |
84 | } | 87 | } |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 3cc04c2afe1c..6361d3736dbc 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -155,7 +155,8 @@ extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); | |||
155 | extern long keyctl_set_reqkey_keyring(int); | 155 | extern long keyctl_set_reqkey_keyring(int); |
156 | extern long keyctl_set_timeout(key_serial_t, unsigned); | 156 | extern long keyctl_set_timeout(key_serial_t, unsigned); |
157 | extern long keyctl_assume_authority(key_serial_t); | 157 | extern long keyctl_assume_authority(key_serial_t); |
158 | 158 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, | |
159 | size_t buflen); | ||
159 | 160 | ||
160 | /* | 161 | /* |
161 | * debugging key validation | 162 | * debugging key validation |
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 | } |