Commit 70a5bb72b55e82fbfbf1e22cae6975fac58a1e2d

Authored by David Howells
Committed by Linus Torvalds
1 parent 4a38e122e2

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>

Showing 9 changed files with 140 additions and 2 deletions Side-by-side Diff

Documentation/keys.txt
... ... @@ -711,6 +711,27 @@
711 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 ===============
715 736 KERNEL SERVICES
716 737 ===============
include/linux/keyctl.h
... ... @@ -49,6 +49,7 @@
49 49 #define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
50 50 #define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
51 51 #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
  52 +#define KEYCTL_GET_SECURITY 17 /* get key security label */
52 53  
53 54 #endif /* _LINUX_KEYCTL_H */
include/linux/security.h
... ... @@ -1009,6 +1009,17 @@
1009 1009 * @perm describes the combination of permissions required of this key.
1010 1010 * Return 1 if permission granted, 0 if permission denied and -ve it the
1011 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 1024 * Security hooks affecting all System V IPC operations.
1014 1025 *
... ... @@ -1538,7 +1549,7 @@
1538 1549 int (*key_permission) (key_ref_t key_ref,
1539 1550 struct task_struct *context,
1540 1551 key_perm_t perm);
1541   -
  1552 + int (*key_getsecurity)(struct key *key, char **_buffer);
1542 1553 #endif /* CONFIG_KEYS */
1543 1554  
1544 1555 #ifdef CONFIG_AUDIT
... ... @@ -2732,6 +2743,7 @@
2732 2743 void security_key_free(struct key *key);
2733 2744 int security_key_permission(key_ref_t key_ref,
2734 2745 struct task_struct *context, key_perm_t perm);
  2746 +int security_key_getsecurity(struct key *key, char **_buffer);
2735 2747  
2736 2748 #else
2737 2749  
... ... @@ -2750,6 +2762,12 @@
2750 2762 struct task_struct *context,
2751 2763 key_perm_t perm)
2752 2764 {
  2765 + return 0;
  2766 +}
  2767 +
  2768 +static inline int security_key_getsecurity(struct key *key, char **_buffer)
  2769 +{
  2770 + *_buffer = NULL;
2753 2771 return 0;
2754 2772 }
2755 2773  
... ... @@ -994,6 +994,13 @@
994 994 {
995 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 1004 #endif /* CONFIG_KEYS */
998 1005  
999 1006 #ifdef CONFIG_AUDIT
... ... @@ -1210,6 +1217,7 @@
1210 1217 set_to_dummy_if_null(ops, key_alloc);
1211 1218 set_to_dummy_if_null(ops, key_free);
1212 1219 set_to_dummy_if_null(ops, key_permission);
  1220 + set_to_dummy_if_null(ops, key_getsecurity);
1213 1221 #endif /* CONFIG_KEYS */
1214 1222 #ifdef CONFIG_AUDIT
1215 1223 set_to_dummy_if_null(ops, audit_rule_init);
security/keys/compat.c
... ... @@ -79,6 +79,9 @@
79 79 case KEYCTL_ASSUME_AUTHORITY:
80 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 85 default:
83 86 return -EOPNOTSUPP;
84 87 }
security/keys/internal.h
... ... @@ -155,7 +155,8 @@
155 155 extern long keyctl_set_reqkey_keyring(int);
156 156 extern long keyctl_set_timeout(key_serial_t, unsigned);
157 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 162 * debugging key validation
security/keys/keyctl.c
... ... @@ -20,6 +20,7 @@
20 20 #include <linux/string.h>
21 21 #include <linux/err.h>
22 22 #include <linux/vmalloc.h>
  23 +#include <linux/security.h>
23 24 #include <asm/uaccess.h>
24 25 #include "internal.h"
25 26  
... ... @@ -1080,6 +1081,66 @@
1080 1081  
1081 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 1146 * the key control system call
... ... @@ -1159,6 +1220,11 @@
1159 1220  
1160 1221 case KEYCTL_ASSUME_AUTHORITY:
1161 1222 return keyctl_assume_authority((key_serial_t) arg2);
  1223 +
  1224 + case KEYCTL_GET_SECURITY:
  1225 + return keyctl_get_security((key_serial_t) arg2,
  1226 + (char *) arg3,
  1227 + (size_t) arg4);
1162 1228  
1163 1229 default:
1164 1230 return -EOPNOTSUPP;
... ... @@ -1156,6 +1156,11 @@
1156 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 1164 #endif /* CONFIG_KEYS */
1160 1165  
1161 1166 #ifdef CONFIG_AUDIT
security/selinux/hooks.c
... ... @@ -5300,6 +5300,20 @@
5300 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 5317 #endif
5304 5318  
5305 5319 static struct security_operations selinux_ops = {
... ... @@ -5488,6 +5502,7 @@
5488 5502 .key_alloc = selinux_key_alloc,
5489 5503 .key_free = selinux_key_free,
5490 5504 .key_permission = selinux_key_permission,
  5505 + .key_getsecurity = selinux_key_getsecurity,
5491 5506 #endif
5492 5507  
5493 5508 #ifdef CONFIG_AUDIT