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 |