diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/dummy.c | 8 | ||||
| -rw-r--r-- | security/keys/compat.c | 3 | ||||
| -rw-r--r-- | security/keys/internal.h | 3 | ||||
| -rw-r--r-- | security/keys/keyctl.c | 66 | ||||
| -rw-r--r-- | security/security.c | 5 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 15 |
6 files changed, 99 insertions, 1 deletions
diff --git a/security/dummy.c b/security/dummy.c index 26ee06ef0e93..48cf30226e16 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
| @@ -994,6 +994,13 @@ static inline int dummy_key_permission(key_ref_t key_ref, | |||
| 994 | { | 994 | { |
| 995 | return 0; | 995 | return 0; |
| 996 | } | 996 | } |
| 997 | |||
| 998 | static int dummy_key_getsecurity(struct key *key, char **_buffer) | ||
| 999 | { | ||
| 1000 | *_buffer = NULL; | ||
| 1001 | return 0; | ||
| 1002 | } | ||
| 1003 | |||
| 997 | #endif /* CONFIG_KEYS */ | 1004 | #endif /* CONFIG_KEYS */ |
| 998 | 1005 | ||
| 999 | #ifdef CONFIG_AUDIT | 1006 | #ifdef CONFIG_AUDIT |
| @@ -1210,6 +1217,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
| 1210 | set_to_dummy_if_null(ops, key_alloc); | 1217 | set_to_dummy_if_null(ops, key_alloc); |
| 1211 | set_to_dummy_if_null(ops, key_free); | 1218 | set_to_dummy_if_null(ops, key_free); |
| 1212 | set_to_dummy_if_null(ops, key_permission); | 1219 | set_to_dummy_if_null(ops, key_permission); |
| 1220 | set_to_dummy_if_null(ops, key_getsecurity); | ||
| 1213 | #endif /* CONFIG_KEYS */ | 1221 | #endif /* CONFIG_KEYS */ |
| 1214 | #ifdef CONFIG_AUDIT | 1222 | #ifdef CONFIG_AUDIT |
| 1215 | set_to_dummy_if_null(ops, audit_rule_init); | 1223 | set_to_dummy_if_null(ops, audit_rule_init); |
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 | } |
diff --git a/security/security.c b/security/security.c index a809035441ab..8e64a29dc55d 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -1156,6 +1156,11 @@ int security_key_permission(key_ref_t key_ref, | |||
| 1156 | return security_ops->key_permission(key_ref, context, perm); | 1156 | return security_ops->key_permission(key_ref, context, perm); |
| 1157 | } | 1157 | } |
| 1158 | 1158 | ||
| 1159 | int security_key_getsecurity(struct key *key, char **_buffer) | ||
| 1160 | { | ||
| 1161 | return security_ops->key_getsecurity(key, _buffer); | ||
| 1162 | } | ||
| 1163 | |||
| 1159 | #endif /* CONFIG_KEYS */ | 1164 | #endif /* CONFIG_KEYS */ |
| 1160 | 1165 | ||
| 1161 | #ifdef CONFIG_AUDIT | 1166 | #ifdef CONFIG_AUDIT |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 047365ac9faa..838d1e5e63a1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -5300,6 +5300,20 @@ static int selinux_key_permission(key_ref_t key_ref, | |||
| 5300 | SECCLASS_KEY, perm, NULL); | 5300 | SECCLASS_KEY, perm, NULL); |
| 5301 | } | 5301 | } |
| 5302 | 5302 | ||
| 5303 | static int selinux_key_getsecurity(struct key *key, char **_buffer) | ||
| 5304 | { | ||
| 5305 | struct key_security_struct *ksec = key->security; | ||
| 5306 | char *context = NULL; | ||
| 5307 | unsigned len; | ||
| 5308 | int rc; | ||
| 5309 | |||
| 5310 | rc = security_sid_to_context(ksec->sid, &context, &len); | ||
| 5311 | if (!rc) | ||
| 5312 | rc = len; | ||
| 5313 | *_buffer = context; | ||
| 5314 | return rc; | ||
| 5315 | } | ||
| 5316 | |||
| 5303 | #endif | 5317 | #endif |
| 5304 | 5318 | ||
| 5305 | static struct security_operations selinux_ops = { | 5319 | static struct security_operations selinux_ops = { |
| @@ -5488,6 +5502,7 @@ static struct security_operations selinux_ops = { | |||
| 5488 | .key_alloc = selinux_key_alloc, | 5502 | .key_alloc = selinux_key_alloc, |
| 5489 | .key_free = selinux_key_free, | 5503 | .key_free = selinux_key_free, |
| 5490 | .key_permission = selinux_key_permission, | 5504 | .key_permission = selinux_key_permission, |
| 5505 | .key_getsecurity = selinux_key_getsecurity, | ||
| 5491 | #endif | 5506 | #endif |
| 5492 | 5507 | ||
| 5493 | #ifdef CONFIG_AUDIT | 5508 | #ifdef CONFIG_AUDIT |
