aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMat Martineau <mathew.j.martineau@linux.intel.com>2017-03-01 19:44:09 -0500
committerMat Martineau <mathew.j.martineau@linux.intel.com>2017-04-04 17:10:12 -0400
commit6563c91fd645556c7801748f15bc727c77fcd311 (patch)
tree714a6be7606cb6646c7b182bae136ef26bc9692e
parent4a420896f12d2d043602f134ae18ad6be5b9d9dd (diff)
KEYS: Add KEYCTL_RESTRICT_KEYRING
Keyrings recently gained restrict_link capabilities that allow individual keys to be validated prior to linking. This functionality was only available using internal kernel APIs. With the KEYCTL_RESTRICT_KEYRING command existing keyrings can be configured to check the content of keys before they are linked, and then allow or disallow linkage of that key to the keyring. To restrict a keyring, call: keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring, const char *type, const char *restriction) where 'type' is the name of a registered key type and 'restriction' is a string describing how key linkage is to be restricted. The restriction option syntax is specific to each key type. Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
-rw-r--r--Documentation/security/keys.txt25
-rw-r--r--include/linux/key.h6
-rw-r--r--include/uapi/linux/keyctl.h1
-rw-r--r--security/keys/compat.c4
-rw-r--r--security/keys/internal.h3
-rw-r--r--security/keys/keyctl.c58
-rw-r--r--security/keys/keyring.c105
7 files changed, 201 insertions, 1 deletions
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 5fe04a7cc03d..5f554aab8751 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -857,6 +857,31 @@ The keyctl syscall functions are:
857 supported, error ENOKEY if the key could not be found, or error 857 supported, error ENOKEY if the key could not be found, or error
858 EACCES if the key is not readable by the caller. 858 EACCES if the key is not readable by the caller.
859 859
860 (*) Restrict keyring linkage
861
862 long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring,
863 const char *type, const char *restriction);
864
865 An existing keyring can restrict linkage of additional keys by evaluating
866 the contents of the key according to a restriction scheme.
867
868 "keyring" is the key ID for an existing keyring to apply a restriction
869 to. It may be empty or may already have keys linked. Existing linked keys
870 will remain in the keyring even if the new restriction would reject them.
871
872 "type" is a registered key type.
873
874 "restriction" is a string describing how key linkage is to be restricted.
875 The format varies depending on the key type, and the string is passed to
876 the lookup_restriction() function for the requested type. It may specify
877 a method and relevant data for the restriction such as signature
878 verification or constraints on key payload. If the requested key type is
879 later unregistered, no keys may be added to the keyring after the key type
880 is removed.
881
882 To apply a keyring restriction the process must have Set Attribute
883 permission and the keyring must not be previously restricted.
884
860=============== 885===============
861KERNEL SERVICES 886KERNEL SERVICES
862=============== 887===============
diff --git a/include/linux/key.h b/include/linux/key.h
index d2916363689c..0c9b93b0d1f7 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -219,7 +219,8 @@ struct key {
219 /* This is set on a keyring to restrict the addition of a link to a key 219 /* This is set on a keyring to restrict the addition of a link to a key
220 * to it. If this structure isn't provided then it is assumed that the 220 * to it. If this structure isn't provided then it is assumed that the
221 * keyring is open to any addition. It is ignored for non-keyring 221 * keyring is open to any addition. It is ignored for non-keyring
222 * keys. 222 * keys. Only set this value using keyring_restrict(), keyring_alloc(),
223 * or key_alloc().
223 * 224 *
224 * This is intended for use with rings of trusted keys whereby addition 225 * This is intended for use with rings of trusted keys whereby addition
225 * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION 226 * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION
@@ -328,6 +329,9 @@ extern key_ref_t keyring_search(key_ref_t keyring,
328extern int keyring_add_key(struct key *keyring, 329extern int keyring_add_key(struct key *keyring,
329 struct key *key); 330 struct key *key);
330 331
332extern int keyring_restrict(key_ref_t keyring, const char *type,
333 const char *restriction);
334
331extern struct key *key_lookup(key_serial_t id); 335extern struct key *key_lookup(key_serial_t id);
332 336
333static inline key_serial_t key_serial(const struct key *key) 337static inline key_serial_t key_serial(const struct key *key)
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
index 86eddd6241f3..ff79c44e49a3 100644
--- a/include/uapi/linux/keyctl.h
+++ b/include/uapi/linux/keyctl.h
@@ -60,6 +60,7 @@
60#define KEYCTL_INVALIDATE 21 /* invalidate a key */ 60#define KEYCTL_INVALIDATE 21 /* invalidate a key */
61#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ 61#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */
62#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */ 62#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */
63#define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */
63 64
64/* keyctl structures */ 65/* keyctl structures */
65struct keyctl_dh_params { 66struct keyctl_dh_params {
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 36c80bf5b89c..bb98f2b8dd7d 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -136,6 +136,10 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
136 return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3), 136 return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3),
137 arg4, compat_ptr(arg5)); 137 arg4, compat_ptr(arg5));
138 138
139 case KEYCTL_RESTRICT_KEYRING:
140 return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
141 compat_ptr(arg4));
142
139 default: 143 default:
140 return -EOPNOTSUPP; 144 return -EOPNOTSUPP;
141 } 145 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 24762ae9a198..6ce016314897 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -252,6 +252,9 @@ struct iov_iter;
252extern long keyctl_instantiate_key_common(key_serial_t, 252extern long keyctl_instantiate_key_common(key_serial_t,
253 struct iov_iter *, 253 struct iov_iter *,
254 key_serial_t); 254 key_serial_t);
255extern long keyctl_restrict_keyring(key_serial_t id,
256 const char __user *_type,
257 const char __user *_restriction);
255#ifdef CONFIG_PERSISTENT_KEYRINGS 258#ifdef CONFIG_PERSISTENT_KEYRINGS
256extern long keyctl_get_persistent(uid_t, key_serial_t); 259extern long keyctl_get_persistent(uid_t, key_serial_t);
257extern unsigned persistent_keyring_expiry; 260extern unsigned persistent_keyring_expiry;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 52c34532c785..6ee2826a2d06 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1583,6 +1583,59 @@ error_keyring:
1583} 1583}
1584 1584
1585/* 1585/*
1586 * Apply a restriction to a given keyring.
1587 *
1588 * The caller must have Setattr permission to change keyring restrictions.
1589 *
1590 * The requested type name may be a NULL pointer to reject all attempts
1591 * to link to the keyring. If _type is non-NULL, _restriction can be
1592 * NULL or a pointer to a string describing the restriction. If _type is
1593 * NULL, _restriction must also be NULL.
1594 *
1595 * Returns 0 if successful.
1596 */
1597long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
1598 const char __user *_restriction)
1599{
1600 key_ref_t key_ref;
1601 bool link_reject = !_type;
1602 char type[32];
1603 char *restriction = NULL;
1604 long ret;
1605
1606 key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR);
1607 if (IS_ERR(key_ref))
1608 return PTR_ERR(key_ref);
1609
1610 if (_type) {
1611 ret = key_get_type_from_user(type, _type, sizeof(type));
1612 if (ret < 0)
1613 goto error;
1614 }
1615
1616 if (_restriction) {
1617 if (!_type) {
1618 ret = -EINVAL;
1619 goto error;
1620 }
1621
1622 restriction = strndup_user(_restriction, PAGE_SIZE);
1623 if (IS_ERR(restriction)) {
1624 ret = PTR_ERR(restriction);
1625 goto error;
1626 }
1627 }
1628
1629 ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction);
1630 kfree(restriction);
1631
1632error:
1633 key_ref_put(key_ref);
1634
1635 return ret;
1636}
1637
1638/*
1586 * The key control system call 1639 * The key control system call
1587 */ 1640 */
1588SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, 1641SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
@@ -1693,6 +1746,11 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
1693 (char __user *) arg3, (size_t) arg4, 1746 (char __user *) arg3, (size_t) arg4,
1694 (void __user *) arg5); 1747 (void __user *) arg5);
1695 1748
1749 case KEYCTL_RESTRICT_KEYRING:
1750 return keyctl_restrict_keyring((key_serial_t) arg2,
1751 (const char __user *) arg3,
1752 (const char __user *) arg4);
1753
1696 default: 1754 default:
1697 return -EOPNOTSUPP; 1755 return -EOPNOTSUPP;
1698 } 1756 }
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 838334fec6ce..4d1678e4586f 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -947,6 +947,111 @@ key_ref_t keyring_search(key_ref_t keyring,
947} 947}
948EXPORT_SYMBOL(keyring_search); 948EXPORT_SYMBOL(keyring_search);
949 949
950static struct key_restriction *keyring_restriction_alloc(
951 key_restrict_link_func_t check)
952{
953 struct key_restriction *keyres =
954 kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
955
956 if (!keyres)
957 return ERR_PTR(-ENOMEM);
958
959 keyres->check = check;
960
961 return keyres;
962}
963
964/*
965 * Semaphore to serialise restriction setup to prevent reference count
966 * cycles through restriction key pointers.
967 */
968static DECLARE_RWSEM(keyring_serialise_restrict_sem);
969
970/*
971 * Check for restriction cycles that would prevent keyring garbage collection.
972 * keyring_serialise_restrict_sem must be held.
973 */
974static bool keyring_detect_restriction_cycle(const struct key *dest_keyring,
975 struct key_restriction *keyres)
976{
977 while (keyres && keyres->key &&
978 keyres->key->type == &key_type_keyring) {
979 if (keyres->key == dest_keyring)
980 return true;
981
982 keyres = keyres->key->restrict_link;
983 }
984
985 return false;
986}
987
988/**
989 * keyring_restrict - Look up and apply a restriction to a keyring
990 *
991 * @keyring: The keyring to be restricted
992 * @restriction: The restriction options to apply to the keyring
993 */
994int keyring_restrict(key_ref_t keyring_ref, const char *type,
995 const char *restriction)
996{
997 struct key *keyring;
998 struct key_type *restrict_type = NULL;
999 struct key_restriction *restrict_link;
1000 int ret = 0;
1001
1002 keyring = key_ref_to_ptr(keyring_ref);
1003 key_check(keyring);
1004
1005 if (keyring->type != &key_type_keyring)
1006 return -ENOTDIR;
1007
1008 if (!type) {
1009 restrict_link = keyring_restriction_alloc(restrict_link_reject);
1010 } else {
1011 restrict_type = key_type_lookup(type);
1012
1013 if (IS_ERR(restrict_type))
1014 return PTR_ERR(restrict_type);
1015
1016 if (!restrict_type->lookup_restriction) {
1017 ret = -ENOENT;
1018 goto error;
1019 }
1020
1021 restrict_link = restrict_type->lookup_restriction(restriction);
1022 }
1023
1024 if (IS_ERR(restrict_link)) {
1025 ret = PTR_ERR(restrict_link);
1026 goto error;
1027 }
1028
1029 down_write(&keyring->sem);
1030 down_write(&keyring_serialise_restrict_sem);
1031
1032 if (keyring->restrict_link)
1033 ret = -EEXIST;
1034 else if (keyring_detect_restriction_cycle(keyring, restrict_link))
1035 ret = -EDEADLK;
1036 else
1037 keyring->restrict_link = restrict_link;
1038
1039 up_write(&keyring_serialise_restrict_sem);
1040 up_write(&keyring->sem);
1041
1042 if (ret < 0) {
1043 key_put(restrict_link->key);
1044 kfree(restrict_link);
1045 }
1046
1047error:
1048 if (restrict_type)
1049 key_type_put(restrict_type);
1050
1051 return ret;
1052}
1053EXPORT_SYMBOL(keyring_restrict);
1054
950/* 1055/*
951 * Search the given keyring for a key that might be updated. 1056 * Search the given keyring for a key that might be updated.
952 * 1057 *