aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-04-29 04:01:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:16 -0400
commit70a5bb72b55e82fbfbf1e22cae6975fac58a1e2d (patch)
tree8e6dcaf5630388d81b23845f293789f2d6a3596b /security
parent4a38e122e2cc6294779021ff4ccc784a3997059e (diff)
keys: add keyctl function to get a security label
Add a keyctl() function to get the security label of a key. The following is added to Documentation/keys.txt: (*) Get the LSM security context attached to a key. long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer, size_t buflen) This function returns a string that represents the LSM security context attached to a key in the buffer provided. Unless there's an error, it always returns the amount of data it could produce, even if that's too big for the buffer, but it won't copy more than requested to userspace. If the buffer pointer is NULL then no copy will take place. A NUL character is included at the end of the string if the buffer is sufficiently big. This is included in the returned count. If no LSM is in force then an empty string will be returned. A process must have view permission on the key for this function to be successful. [akpm@linux-foundation.org: declare keyctl_get_security()] Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Cc: Paul Moore <paul.moore@hp.com> Cc: Chris Wright <chrisw@sous-sol.org> Cc: James Morris <jmorris@namei.org> Cc: Kevin Coffman <kwc@citi.umich.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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