Skip to content

Commit 2b6aa41

Browse files
committed
KEYS: Use structure to capture key restriction function and data
Replace struct key's restrict_link function pointer with a pointer to the new struct key_restriction. The structure contains pointers to the restriction function as well as relevant data for evaluating the restriction. The garbage collector checks restrict_link->keytype when key types are unregistered. Restrictions involving a removed key type are converted to use restrict_link_reject so that restrictions cannot be removed by unregistering key types. Signed-off-by: Mat Martineau <[email protected]>
1 parent e9cc0f6 commit 2b6aa41

File tree

9 files changed

+144
-30
lines changed

9 files changed

+144
-30
lines changed

Documentation/security/keys.txt

+12-9
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ payload contents" for more information.
10321032
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
10331033
const struct cred *cred,
10341034
key_perm_t perm,
1035-
key_restrict_link_func_t restrict_link,
1035+
struct key_restriction *restrict_link,
10361036
unsigned long flags,
10371037
struct key *dest);
10381038

@@ -1044,14 +1044,17 @@ payload contents" for more information.
10441044
KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
10451045
towards the user's quota). Error ENOMEM can also be returned.
10461046

1047-
If restrict_link not NULL, it should point to a function that will be
1048-
called each time an attempt is made to link a key into the new keyring.
1049-
This function is called to check whether a key may be added into the keying
1050-
or not. Callers of key_create_or_update() within the kernel can pass
1051-
KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using
1052-
this is to manage rings of cryptographic keys that are set up when the
1053-
kernel boots where userspace is also permitted to add keys - provided they
1054-
can be verified by a key the kernel already has.
1047+
If restrict_link is not NULL, it should point to a structure that contains
1048+
the function that will be called each time an attempt is made to link a
1049+
key into the new keyring. The structure may also contain a key pointer
1050+
and an associated key type. The function is called to check whether a key
1051+
may be added into the keyring or not. The key type is used by the garbage
1052+
collector to clean up function or data pointers in this structure if the
1053+
given key type is unregistered. Callers of key_create_or_update() within
1054+
the kernel can pass KEY_ALLOC_BYPASS_RESTRICTION to suppress the check.
1055+
An example of using this is to manage rings of cryptographic keys that are
1056+
set up when the kernel boots where userspace is also permitted to add keys
1057+
- provided they can be verified by a key the kernel already has.
10551058

10561059
When called, the restriction function will be passed the keyring being
10571060
added to, the key type, the payload of the key being added, and data to be

certs/system_keyring.c

+20-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/sched.h>
1515
#include <linux/cred.h>
1616
#include <linux/err.h>
17+
#include <linux/slab.h>
1718
#include <keys/asymmetric-type.h>
1819
#include <keys/system_keyring.h>
1920
#include <crypto/pkcs7.h>
@@ -68,6 +69,24 @@ int restrict_link_by_builtin_and_secondary_trusted(
6869
return restrict_link_by_signature(dest_keyring, type, payload,
6970
secondary_trusted_keys);
7071
}
72+
73+
/**
74+
* Allocate a struct key_restriction for the "builtin and secondary trust"
75+
* keyring. Only for use in system_trusted_keyring_init().
76+
*/
77+
static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
78+
{
79+
struct key_restriction *restriction;
80+
81+
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
82+
83+
if (!restriction)
84+
panic("Can't allocate secondary trusted keyring restriction\n");
85+
86+
restriction->check = restrict_link_by_builtin_and_secondary_trusted;
87+
88+
return restriction;
89+
}
7190
#endif
7291

7392
/*
@@ -95,7 +114,7 @@ static __init int system_trusted_keyring_init(void)
95114
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
96115
KEY_USR_WRITE),
97116
KEY_ALLOC_NOT_IN_QUOTA,
98-
restrict_link_by_builtin_and_secondary_trusted,
117+
get_builtin_and_secondary_restriction(),
99118
NULL);
100119
if (IS_ERR(secondary_trusted_keys))
101120
panic("Can't allocate secondary trusted keyring\n");

include/linux/key.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ struct key {
217217
};
218218

219219
/* This is set on a keyring to restrict the addition of a link to a key
220-
* to it. If this method isn't provided then it is assumed that the
220+
* to it. If this structure isn't provided then it is assumed that the
221221
* keyring is open to any addition. It is ignored for non-keyring
222222
* keys.
223223
*
@@ -226,7 +226,7 @@ struct key {
226226
* overrides this, allowing the kernel to add extra keys without
227227
* restriction.
228228
*/
229-
key_restrict_link_func_t restrict_link;
229+
struct key_restriction *restrict_link;
230230
};
231231

232232
extern struct key *key_alloc(struct key_type *type,
@@ -235,7 +235,7 @@ extern struct key *key_alloc(struct key_type *type,
235235
const struct cred *cred,
236236
key_perm_t perm,
237237
unsigned long flags,
238-
key_restrict_link_func_t restrict_link);
238+
struct key_restriction *restrict_link);
239239

240240

241241
#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
@@ -311,7 +311,7 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid
311311
const struct cred *cred,
312312
key_perm_t perm,
313313
unsigned long flags,
314-
key_restrict_link_func_t restrict_link,
314+
struct key_restriction *restrict_link,
315315
struct key *dest);
316316

317317
extern int restrict_link_reject(struct key *keyring,

security/integrity/digsig.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
8181
int __init integrity_init_keyring(const unsigned int id)
8282
{
8383
const struct cred *cred = current_cred();
84+
struct key_restriction *restriction;
8485
int err = 0;
8586

8687
if (!init_keyring)
8788
return 0;
8889

90+
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
91+
if (!restriction)
92+
return -ENOMEM;
93+
94+
restriction->check = restrict_link_to_ima;
95+
8996
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
9097
KGIDT_INIT(0), cred,
9198
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
9299
KEY_USR_VIEW | KEY_USR_READ |
93100
KEY_USR_WRITE | KEY_USR_SEARCH),
94101
KEY_ALLOC_NOT_IN_QUOTA,
95-
restrict_link_to_ima, NULL);
102+
restriction, NULL);
96103
if (IS_ERR(keyring[id])) {
97104
err = PTR_ERR(keyring[id]);
98105
pr_info("Can't allocate %s keyring (%d)\n",

security/integrity/ima/ima_mok.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/cred.h>
1818
#include <linux/err.h>
1919
#include <linux/init.h>
20+
#include <linux/slab.h>
2021
#include <keys/system_keyring.h>
2122

2223

@@ -27,15 +28,23 @@ struct key *ima_blacklist_keyring;
2728
*/
2829
__init int ima_mok_init(void)
2930
{
31+
struct key_restriction *restriction;
32+
3033
pr_notice("Allocating IMA blacklist keyring.\n");
3134

35+
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
36+
if (!restriction)
37+
panic("Can't allocate IMA blacklist restriction.");
38+
39+
restriction->check = restrict_link_by_builtin_trusted;
40+
3241
ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
3342
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
3443
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
3544
KEY_USR_VIEW | KEY_USR_READ |
3645
KEY_USR_WRITE | KEY_USR_SEARCH,
3746
KEY_ALLOC_NOT_IN_QUOTA,
38-
restrict_link_by_builtin_trusted, NULL);
47+
restriction, NULL);
3948

4049
if (IS_ERR(ima_blacklist_keyring))
4150
panic("Can't allocate IMA blacklist keyring.");

security/keys/gc.c

+11
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ static void key_garbage_collector(struct work_struct *work)
229229
set_bit(KEY_FLAG_DEAD, &key->flags);
230230
key->perm = 0;
231231
goto skip_dead_key;
232+
} else if (key->type == &key_type_keyring &&
233+
key->restrict_link) {
234+
goto found_restricted_keyring;
232235
}
233236
}
234237

@@ -334,6 +337,14 @@ static void key_garbage_collector(struct work_struct *work)
334337
gc_state |= KEY_GC_REAP_AGAIN;
335338
goto maybe_resched;
336339

340+
/* We found a restricted keyring and need to update the restriction if
341+
* it is associated with the dead key type.
342+
*/
343+
found_restricted_keyring:
344+
spin_unlock(&key_serial_lock);
345+
keyring_restriction_gc(key, key_gc_dead_keytype);
346+
goto maybe_resched;
347+
337348
/* We found a keyring and we need to check the payload for links to
338349
* dead or expired keys. We don't flag another reap immediately as we
339350
* have to wait for the old payload to be destroyed by RCU before we

security/keys/internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ extern void key_change_session_keyring(struct callback_head *twork);
168168
extern struct work_struct key_gc_work;
169169
extern unsigned key_gc_delay;
170170
extern void keyring_gc(struct key *keyring, time_t limit);
171+
extern void keyring_restriction_gc(struct key *keyring,
172+
struct key_type *dead_type);
171173
extern void key_schedule_gc(time_t gc_at);
172174
extern void key_schedule_gc_links(void);
173175
extern void key_gc_keytype(struct key_type *ktype);

security/keys/key.c

+14-9
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,15 @@ static inline void key_alloc_serial(struct key *key)
201201
* @cred: The credentials specifying UID namespace.
202202
* @perm: The permissions mask of the new key.
203203
* @flags: Flags specifying quota properties.
204-
* @restrict_link: Optional link restriction method for new keyrings.
204+
* @restrict_link: Optional link restriction for new keyrings.
205205
*
206206
* Allocate a key of the specified type with the attributes given. The key is
207207
* returned in an uninstantiated state and the caller needs to instantiate the
208208
* key before returning.
209209
*
210+
* The restrict_link structure (if not NULL) will be freed when the
211+
* keyring is destroyed, so it must be dynamically allocated.
212+
*
210213
* The user's key count quota is updated to reflect the creation of the key and
211214
* the user's key data quota has the default for the key type reserved. The
212215
* instantiation function should amend this as necessary. If insufficient
@@ -225,7 +228,7 @@ static inline void key_alloc_serial(struct key *key)
225228
struct key *key_alloc(struct key_type *type, const char *desc,
226229
kuid_t uid, kgid_t gid, const struct cred *cred,
227230
key_perm_t perm, unsigned long flags,
228-
key_restrict_link_func_t restrict_link)
231+
struct key_restriction *restrict_link)
229232
{
230233
struct key_user *user = NULL;
231234
struct key *key;
@@ -497,9 +500,11 @@ int key_instantiate_and_link(struct key *key,
497500
}
498501

499502
if (keyring) {
500-
if (keyring->restrict_link) {
501-
ret = keyring->restrict_link(keyring, key->type,
502-
&prep.payload, NULL);
503+
if (keyring->restrict_link && keyring->restrict_link->check) {
504+
struct key_restriction *keyres = keyring->restrict_link;
505+
506+
ret = keyres->check(keyring, key->type, &prep.payload,
507+
keyres->key);
503508
if (ret < 0)
504509
goto error;
505510
}
@@ -804,7 +809,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
804809
struct key *keyring, *key = NULL;
805810
key_ref_t key_ref;
806811
int ret;
807-
key_restrict_link_func_t restrict_link = NULL;
812+
struct key_restriction *restrict_link = NULL;
808813

809814
/* look up the key type to see if it's one of the registered kernel
810815
* types */
@@ -850,9 +855,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
850855
}
851856
index_key.desc_len = strlen(index_key.description);
852857

853-
if (restrict_link) {
854-
ret = restrict_link(keyring, index_key.type, &prep.payload,
855-
NULL);
858+
if (restrict_link && restrict_link->check) {
859+
ret = restrict_link->check(keyring, index_key.type,
860+
&prep.payload, restrict_link->key);
856861
if (ret < 0) {
857862
key_ref = ERR_PTR(ret);
858863
goto error_free_prep;

security/keys/keyring.c

+63-5
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,13 @@ static void keyring_destroy(struct key *keyring)
394394
write_unlock(&keyring_name_lock);
395395
}
396396

397+
if (keyring->restrict_link) {
398+
struct key_restriction *keyres = keyring->restrict_link;
399+
400+
key_put(keyres->key);
401+
kfree(keyres);
402+
}
403+
397404
assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);
398405
}
399406

@@ -492,7 +499,7 @@ static long keyring_read(const struct key *keyring,
492499
struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
493500
const struct cred *cred, key_perm_t perm,
494501
unsigned long flags,
495-
key_restrict_link_func_t restrict_link,
502+
struct key_restriction *restrict_link,
496503
struct key *dest)
497504
{
498505
struct key *keyring;
@@ -523,8 +530,8 @@ EXPORT_SYMBOL(keyring_alloc);
523530
* passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when
524531
* adding a key to a keyring.
525532
*
526-
* This is meant to be passed as the restrict_link parameter to
527-
* keyring_alloc().
533+
* This is meant to be stored in a key_restriction structure which is passed
534+
* in the restrict_link parameter to keyring_alloc().
528535
*/
529536
int restrict_link_reject(struct key *keyring,
530537
const struct key_type *type,
@@ -1220,9 +1227,10 @@ void __key_link_end(struct key *keyring,
12201227
*/
12211228
static int __key_link_check_restriction(struct key *keyring, struct key *key)
12221229
{
1223-
if (!keyring->restrict_link)
1230+
if (!keyring->restrict_link || !keyring->restrict_link->check)
12241231
return 0;
1225-
return keyring->restrict_link(keyring, key->type, &key->payload, NULL);
1232+
return keyring->restrict_link->check(keyring, key->type, &key->payload,
1233+
keyring->restrict_link->key);
12261234
}
12271235

12281236
/**
@@ -1426,3 +1434,53 @@ void keyring_gc(struct key *keyring, time_t limit)
14261434
up_write(&keyring->sem);
14271435
kleave(" [gc]");
14281436
}
1437+
1438+
/*
1439+
* Garbage collect restriction pointers from a keyring.
1440+
*
1441+
* Keyring restrictions are associated with a key type, and must be cleaned
1442+
* up if the key type is unregistered. The restriction is altered to always
1443+
* reject additional keys so a keyring cannot be opened up by unregistering
1444+
* a key type.
1445+
*
1446+
* Not called with any keyring locks held. The keyring's key struct will not
1447+
* be deallocated under us as only our caller may deallocate it.
1448+
*
1449+
* The caller is required to hold key_types_sem and dead_type->sem. This is
1450+
* fulfilled by key_gc_keytype() holding the locks on behalf of
1451+
* key_garbage_collector(), which it invokes on a workqueue.
1452+
*/
1453+
void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type)
1454+
{
1455+
struct key_restriction *keyres;
1456+
1457+
kenter("%x{%s}", keyring->serial, keyring->description ?: "");
1458+
1459+
/*
1460+
* keyring->restrict_link is only assigned at key allocation time
1461+
* or with the key type locked, so the only values that could be
1462+
* concurrently assigned to keyring->restrict_link are for key
1463+
* types other than dead_type. Given this, it's ok to check
1464+
* the key type before acquiring keyring->sem.
1465+
*/
1466+
if (!dead_type || !keyring->restrict_link ||
1467+
keyring->restrict_link->keytype != dead_type) {
1468+
kleave(" [no restriction gc]");
1469+
return;
1470+
}
1471+
1472+
/* Lock the keyring to ensure that a link is not in progress */
1473+
down_write(&keyring->sem);
1474+
1475+
keyres = keyring->restrict_link;
1476+
1477+
keyres->check = restrict_link_reject;
1478+
1479+
key_put(keyres->key);
1480+
keyres->key = NULL;
1481+
keyres->keytype = NULL;
1482+
1483+
up_write(&keyring->sem);
1484+
1485+
kleave(" [restriction gc]");
1486+
}

0 commit comments

Comments
 (0)