aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/keys.txt21
-rw-r--r--include/linux/keyctl.h1
-rw-r--r--include/linux/security.h20
-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
9 files changed, 140 insertions, 2 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index b82d38de8b89..be424b02437d 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -711,6 +711,27 @@ The keyctl syscall functions are:
711 The assumed authoritative key is inherited across fork and exec. 711 The assumed authoritative key is inherited across fork and exec.
712 712
713 713
714 (*) Get the LSM security context attached to a key.
715
716 long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
717 size_t buflen)
718
719 This function returns a string that represents the LSM security context
720 attached to a key in the buffer provided.
721
722 Unless there's an error, it always returns the amount of data it could
723 produce, even if that's too big for the buffer, but it won't copy more
724 than requested to userspace. If the buffer pointer is NULL then no copy
725 will take place.
726
727 A NUL character is included at the end of the string if the buffer is
728 sufficiently big. This is included in the returned count. If no LSM is
729 in force then an empty string will be returned.
730
731 A process must have view permission on the key for this function to be
732 successful.
733
734
714=============== 735===============
715KERNEL SERVICES 736KERNEL SERVICES
716=============== 737===============
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 3365945640c9..656ee6b77a4a 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -49,5 +49,6 @@
49#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */ 49#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
50#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */ 50#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
51#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ 51#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
52#define KEYCTL_GET_SECURITY 17 /* get key security label */
52 53
53#endif /* _LINUX_KEYCTL_H */ 54#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 3ebcdd00b17d..adb09d893ae0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1009,6 +1009,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1009 * @perm describes the combination of permissions required of this key. 1009 * @perm describes the combination of permissions required of this key.
1010 * Return 1 if permission granted, 0 if permission denied and -ve it the 1010 * Return 1 if permission granted, 0 if permission denied and -ve it the
1011 * normal permissions model should be effected. 1011 * normal permissions model should be effected.
1012 * @key_getsecurity:
1013 * Get a textual representation of the security context attached to a key
1014 * for the purposes of honouring KEYCTL_GETSECURITY. This function
1015 * allocates the storage for the NUL-terminated string and the caller
1016 * should free it.
1017 * @key points to the key to be queried.
1018 * @_buffer points to a pointer that should be set to point to the
1019 * resulting string (if no label or an error occurs).
1020 * Return the length of the string (including terminating NUL) or -ve if
1021 * an error.
1022 * May also return 0 (and a NULL buffer pointer) if there is no label.
1012 * 1023 *
1013 * Security hooks affecting all System V IPC operations. 1024 * Security hooks affecting all System V IPC operations.
1014 * 1025 *
@@ -1538,7 +1549,7 @@ struct security_operations {
1538 int (*key_permission) (key_ref_t key_ref, 1549 int (*key_permission) (key_ref_t key_ref,
1539 struct task_struct *context, 1550 struct task_struct *context,
1540 key_perm_t perm); 1551 key_perm_t perm);
1541 1552 int (*key_getsecurity)(struct key *key, char **_buffer);
1542#endif /* CONFIG_KEYS */ 1553#endif /* CONFIG_KEYS */
1543 1554
1544#ifdef CONFIG_AUDIT 1555#ifdef CONFIG_AUDIT
@@ -2732,6 +2743,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long f
2732void security_key_free(struct key *key); 2743void security_key_free(struct key *key);
2733int security_key_permission(key_ref_t key_ref, 2744int security_key_permission(key_ref_t key_ref,
2734 struct task_struct *context, key_perm_t perm); 2745 struct task_struct *context, key_perm_t perm);
2746int security_key_getsecurity(struct key *key, char **_buffer);
2735 2747
2736#else 2748#else
2737 2749
@@ -2753,6 +2765,12 @@ static inline int security_key_permission(key_ref_t key_ref,
2753 return 0; 2765 return 0;
2754} 2766}
2755 2767
2768static inline int security_key_getsecurity(struct key *key, char **_buffer)
2769{
2770 *_buffer = NULL;
2771 return 0;
2772}
2773
2756#endif 2774#endif
2757#endif /* CONFIG_KEYS */ 2775#endif /* CONFIG_KEYS */
2758 2776
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