aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c8
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/internal.h3
-rw-r--r--security/keys/keyctl.c66
-rw-r--r--security/security.c5
-rw-r--r--security/selinux/hooks.c15
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
998static 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);
155extern long keyctl_set_reqkey_keyring(int); 155extern long keyctl_set_reqkey_keyring(int);
156extern long keyctl_set_timeout(key_serial_t, unsigned); 156extern long keyctl_set_timeout(key_serial_t, unsigned);
157extern long keyctl_assume_authority(key_serial_t); 157extern long keyctl_assume_authority(key_serial_t);
158 158extern 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 */
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 }
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
1159int 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
5303static 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
5305static struct security_operations selinux_ops = { 5319static 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