Skip to content

Commit 5ac7eac

Browse files
committed
KEYS: Add a facility to restrict new links into a keyring
Add a facility whereby proposed new links to be added to a keyring can be vetted, permitting them to be rejected if necessary. This can be used to block public keys from which the signature cannot be verified or for which the signature verification fails. It could also be used to provide blacklisting. This affects operations like add_key(), KEYCTL_LINK and KEYCTL_INSTANTIATE. To this end: (1) A function pointer is added to the key struct that, if set, points to the vetting function. This is called as: int (*restrict_link)(struct key *keyring, const struct key_type *key_type, unsigned long key_flags, const union key_payload *key_payload), where 'keyring' will be the keyring being added to, key_type and key_payload will describe the key being added and key_flags[*] can be AND'ed with KEY_FLAG_TRUSTED. [*] This parameter will be removed in a later patch when KEY_FLAG_TRUSTED is removed. The function should return 0 to allow the link to take place or an error (typically -ENOKEY, -ENOPKG or -EKEYREJECTED) to reject the link. The pointer should not be set directly, but rather should be set through keyring_alloc(). Note that if called during add_key(), preparse is called before this method, but a key isn't actually allocated until after this function is called. (2) KEY_ALLOC_BYPASS_RESTRICTION is added. This can be passed to key_create_or_update() or key_instantiate_and_link() to bypass the restriction check. (3) KEY_FLAG_TRUSTED_ONLY is removed. The entire contents of a keyring with this restriction emplaced can be considered 'trustworthy' by virtue of being in the keyring when that keyring is consulted. (4) key_alloc() and keyring_alloc() take an extra argument that will be used to set restrict_link in the new key. This ensures that the pointer is set before the key is published, thus preventing a window of unrestrictedness. Normally this argument will be NULL. (5) As a temporary affair, keyring_restrict_trusted_only() is added. It should be passed to keyring_alloc() as the extra argument instead of setting KEY_FLAG_TRUSTED_ONLY on a keyring. This will be replaced in a later patch with functions that look in the appropriate places for authoritative keys. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
1 parent bda850c commit 5ac7eac

File tree

15 files changed

+198
-52
lines changed

15 files changed

+198
-52
lines changed

Documentation/security/keys.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,10 @@ payload contents" for more information.
999999
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
10001000
const struct cred *cred,
10011001
key_perm_t perm,
1002+
int (*restrict_link)(struct key *,
1003+
const struct key_type *,
1004+
unsigned long,
1005+
const union key_payload *),
10021006
unsigned long flags,
10031007
struct key *dest);
10041008

@@ -1010,6 +1014,24 @@ payload contents" for more information.
10101014
KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
10111015
towards the user's quota). Error ENOMEM can also be returned.
10121016

1017+
If restrict_link not NULL, it should point to a function that will be
1018+
called each time an attempt is made to link a key into the new keyring.
1019+
This function is called to check whether a key may be added into the keying
1020+
or not. Callers of key_create_or_update() within the kernel can pass
1021+
KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using
1022+
this is to manage rings of cryptographic keys that are set up when the
1023+
kernel boots where userspace is also permitted to add keys - provided they
1024+
can be verified by a key the kernel already has.
1025+
1026+
When called, the restriction function will be passed the keyring being
1027+
added to, the key flags value and the type and payload of the key being
1028+
added. Note that when a new key is being created, this is called between
1029+
payload preparsing and actual key creation. The function should return 0
1030+
to allow the link or an error to reject it.
1031+
1032+
A convenience function, restrict_link_reject, exists to always return
1033+
-EPERM to in this case.
1034+
10131035

10141036
(*) To check the validity of a key, this function can be called:
10151037

certs/system_keyring.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,10 @@ static __init int system_trusted_keyring_init(void)
3636
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
3737
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
3838
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
39-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
39+
KEY_ALLOC_NOT_IN_QUOTA,
40+
keyring_restrict_trusted_only, NULL);
4041
if (IS_ERR(system_trusted_keyring))
4142
panic("Can't allocate system trusted keyring\n");
42-
43-
set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
4443
return 0;
4544
}
4645

@@ -85,7 +84,8 @@ static __init int load_system_certificate_list(void)
8584
KEY_USR_VIEW | KEY_USR_READ),
8685
KEY_ALLOC_NOT_IN_QUOTA |
8786
KEY_ALLOC_TRUSTED |
88-
KEY_ALLOC_BUILT_IN);
87+
KEY_ALLOC_BUILT_IN |
88+
KEY_ALLOC_BYPASS_RESTRICTION);
8989
if (IS_ERR(key)) {
9090
pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
9191
PTR_ERR(key));

fs/cifs/cifsacl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ init_cifs_idmap(void)
360360
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
361361
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
362362
KEY_USR_VIEW | KEY_USR_READ,
363-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
363+
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
364364
if (IS_ERR(keyring)) {
365365
ret = PTR_ERR(keyring);
366366
goto failed_put_cred;

fs/nfs/nfs4idmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ int nfs_idmap_init(void)
201201
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
202202
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
203203
KEY_USR_VIEW | KEY_USR_READ,
204-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
204+
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
205205
if (IS_ERR(keyring)) {
206206
ret = PTR_ERR(keyring);
207207
goto failed_put_cred;

include/linux/key.h

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,9 @@ struct key {
174174
#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
175175
#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
176176
#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */
177-
#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */
178-
#define KEY_FLAG_BUILTIN 10 /* set if key is builtin */
179-
#define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */
180-
#define KEY_FLAG_KEEP 12 /* set if key should not be removed */
177+
#define KEY_FLAG_BUILTIN 9 /* set if key is built in to the kernel */
178+
#define KEY_FLAG_ROOT_CAN_INVAL 10 /* set if key can be invalidated by root without permission */
179+
#define KEY_FLAG_KEEP 11 /* set if key should not be removed */
181180

182181
/* the key type and key description string
183182
* - the desc is used to match a key against search criteria
@@ -205,21 +204,41 @@ struct key {
205204
};
206205
int reject_error;
207206
};
207+
208+
/* This is set on a keyring to restrict the addition of a link to a key
209+
* to it. If this method isn't provided then it is assumed that the
210+
* keyring is open to any addition. It is ignored for non-keyring
211+
* keys.
212+
*
213+
* This is intended for use with rings of trusted keys whereby addition
214+
* to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION
215+
* overrides this, allowing the kernel to add extra keys without
216+
* restriction.
217+
*/
218+
int (*restrict_link)(struct key *keyring,
219+
const struct key_type *type,
220+
unsigned long flags,
221+
const union key_payload *payload);
208222
};
209223

210224
extern struct key *key_alloc(struct key_type *type,
211225
const char *desc,
212226
kuid_t uid, kgid_t gid,
213227
const struct cred *cred,
214228
key_perm_t perm,
215-
unsigned long flags);
229+
unsigned long flags,
230+
int (*restrict_link)(struct key *,
231+
const struct key_type *,
232+
unsigned long,
233+
const union key_payload *));
216234

217235

218-
#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
219-
#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
220-
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
221-
#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
222-
#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
236+
#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
237+
#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
238+
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
239+
#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
240+
#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
241+
#define KEY_ALLOC_BYPASS_RESTRICTION 0x0010 /* Override the check on restricted keyrings */
223242

224243
extern void key_revoke(struct key *key);
225244
extern void key_invalidate(struct key *key);
@@ -288,8 +307,22 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid
288307
const struct cred *cred,
289308
key_perm_t perm,
290309
unsigned long flags,
310+
int (*restrict_link)(struct key *,
311+
const struct key_type *,
312+
unsigned long,
313+
const union key_payload *),
291314
struct key *dest);
292315

316+
extern int keyring_restrict_trusted_only(struct key *keyring,
317+
const struct key_type *type,
318+
unsigned long,
319+
const union key_payload *payload);
320+
321+
extern int restrict_link_reject(struct key *keyring,
322+
const struct key_type *type,
323+
unsigned long flags,
324+
const union key_payload *payload);
325+
293326
extern int keyring_clear(struct key *keyring);
294327

295328
extern key_ref_t keyring_search(key_ref_t keyring,

net/dns_resolver/dns_key.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ static int __init init_dns_resolver(void)
281281
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
282282
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
283283
KEY_USR_VIEW | KEY_USR_READ,
284-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
284+
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
285285
if (IS_ERR(keyring)) {
286286
ret = PTR_ERR(keyring);
287287
goto failed_put_cred;

net/rxrpc/ar-key.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
965965

966966
key = key_alloc(&key_type_rxrpc, "x",
967967
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
968-
KEY_ALLOC_NOT_IN_QUOTA);
968+
KEY_ALLOC_NOT_IN_QUOTA, NULL);
969969
if (IS_ERR(key)) {
970970
_leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
971971
return -ENOMEM;
@@ -1012,7 +1012,7 @@ struct key *rxrpc_get_null_key(const char *keyname)
10121012

10131013
key = key_alloc(&key_type_rxrpc, keyname,
10141014
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
1015-
KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
1015+
KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
10161016
if (IS_ERR(key))
10171017
return key;
10181018

security/integrity/digsig.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,9 @@ int __init integrity_init_keyring(const unsigned int id)
8383
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
8484
KEY_USR_VIEW | KEY_USR_READ |
8585
KEY_USR_WRITE | KEY_USR_SEARCH),
86-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
87-
if (!IS_ERR(keyring[id]))
88-
set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
89-
else {
86+
KEY_ALLOC_NOT_IN_QUOTA,
87+
NULL, NULL);
88+
if (IS_ERR(keyring[id])) {
9089
err = PTR_ERR(keyring[id]);
9190
pr_info("Can't allocate %s keyring (%d)\n",
9291
keyring_name[id], err);

security/integrity/ima/ima_mok.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@ __init int ima_mok_init(void)
3535
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
3636
KEY_USR_VIEW | KEY_USR_READ |
3737
KEY_USR_WRITE | KEY_USR_SEARCH,
38-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
38+
KEY_ALLOC_NOT_IN_QUOTA,
39+
keyring_restrict_trusted_only, NULL);
3940

4041
ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
4142
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
4243
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
4344
KEY_USR_VIEW | KEY_USR_READ |
4445
KEY_USR_WRITE | KEY_USR_SEARCH,
45-
KEY_ALLOC_NOT_IN_QUOTA, NULL);
46+
KEY_ALLOC_NOT_IN_QUOTA,
47+
keyring_restrict_trusted_only, NULL);
4648

4749
if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring))
4850
panic("Can't allocate IMA MOK or blacklist keyrings.");
49-
set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_mok_keyring->flags);
5051

51-
set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_blacklist_keyring->flags);
5252
set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags);
5353
return 0;
5454
}

security/keys/key.c

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ 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.
204205
*
205206
* Allocate a key of the specified type with the attributes given. The key is
206207
* returned in an uninstantiated state and the caller needs to instantiate the
@@ -223,7 +224,11 @@ static inline void key_alloc_serial(struct key *key)
223224
*/
224225
struct key *key_alloc(struct key_type *type, const char *desc,
225226
kuid_t uid, kgid_t gid, const struct cred *cred,
226-
key_perm_t perm, unsigned long flags)
227+
key_perm_t perm, unsigned long flags,
228+
int (*restrict_link)(struct key *,
229+
const struct key_type *,
230+
unsigned long,
231+
const union key_payload *))
227232
{
228233
struct key_user *user = NULL;
229234
struct key *key;
@@ -291,6 +296,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
291296
key->uid = uid;
292297
key->gid = gid;
293298
key->perm = perm;
299+
key->restrict_link = restrict_link;
294300

295301
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
296302
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
@@ -496,6 +502,12 @@ int key_instantiate_and_link(struct key *key,
496502
}
497503

498504
if (keyring) {
505+
if (keyring->restrict_link) {
506+
ret = keyring->restrict_link(keyring, key->type,
507+
key->flags, &prep.payload);
508+
if (ret < 0)
509+
goto error;
510+
}
499511
ret = __key_link_begin(keyring, &key->index_key, &edit);
500512
if (ret < 0)
501513
goto error;
@@ -551,8 +563,12 @@ int key_reject_and_link(struct key *key,
551563
awaken = 0;
552564
ret = -EBUSY;
553565

554-
if (keyring)
566+
if (keyring) {
567+
if (keyring->restrict_link)
568+
return -EPERM;
569+
555570
link_ret = __key_link_begin(keyring, &key->index_key, &edit);
571+
}
556572

557573
mutex_lock(&key_construction_mutex);
558574

@@ -793,6 +809,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
793809
struct key *keyring, *key = NULL;
794810
key_ref_t key_ref;
795811
int ret;
812+
int (*restrict_link)(struct key *,
813+
const struct key_type *,
814+
unsigned long,
815+
const union key_payload *) = NULL;
796816

797817
/* look up the key type to see if it's one of the registered kernel
798818
* types */
@@ -811,6 +831,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
811831

812832
key_check(keyring);
813833

834+
key_ref = ERR_PTR(-EPERM);
835+
if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION))
836+
restrict_link = keyring->restrict_link;
837+
814838
key_ref = ERR_PTR(-ENOTDIR);
815839
if (keyring->type != &key_type_keyring)
816840
goto error_put_type;
@@ -835,10 +859,15 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
835859
}
836860
index_key.desc_len = strlen(index_key.description);
837861

838-
key_ref = ERR_PTR(-EPERM);
839-
if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags))
840-
goto error_free_prep;
841-
flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0;
862+
if (restrict_link) {
863+
unsigned long kflags = prep.trusted ? KEY_FLAG_TRUSTED : 0;
864+
ret = restrict_link(keyring,
865+
index_key.type, kflags, &prep.payload);
866+
if (ret < 0) {
867+
key_ref = ERR_PTR(ret);
868+
goto error_free_prep;
869+
}
870+
}
842871

843872
ret = __key_link_begin(keyring, &index_key, &edit);
844873
if (ret < 0) {
@@ -879,7 +908,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
879908

880909
/* allocate a new key */
881910
key = key_alloc(index_key.type, index_key.description,
882-
cred->fsuid, cred->fsgid, cred, perm, flags);
911+
cred->fsuid, cred->fsgid, cred, perm, flags, NULL);
883912
if (IS_ERR(key)) {
884913
key_ref = ERR_CAST(key);
885914
goto error_link_end;

0 commit comments

Comments
 (0)