diff options
-rw-r--r-- | Documentation/security/keys.txt | 22 | ||||
-rw-r--r-- | certs/system_keyring.c | 8 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4idmap.c | 2 | ||||
-rw-r--r-- | include/linux/key.h | 53 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 2 | ||||
-rw-r--r-- | net/rxrpc/ar-key.c | 4 | ||||
-rw-r--r-- | security/integrity/digsig.c | 7 | ||||
-rw-r--r-- | security/integrity/ima/ima_mok.c | 8 | ||||
-rw-r--r-- | security/keys/key.c | 43 | ||||
-rw-r--r-- | security/keys/keyring.c | 73 | ||||
-rw-r--r-- | security/keys/persistent.c | 4 | ||||
-rw-r--r-- | security/keys/process_keys.c | 16 | ||||
-rw-r--r-- | security/keys/request_key.c | 4 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 2 |
15 files changed, 198 insertions, 52 deletions
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 8c183873b2b7..a6a50b359025 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -999,6 +999,10 @@ payload contents" for more information. | |||
999 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 999 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
1000 | const struct cred *cred, | 1000 | const struct cred *cred, |
1001 | key_perm_t perm, | 1001 | key_perm_t perm, |
1002 | int (*restrict_link)(struct key *, | ||
1003 | const struct key_type *, | ||
1004 | unsigned long, | ||
1005 | const union key_payload *), | ||
1002 | unsigned long flags, | 1006 | unsigned long flags, |
1003 | struct key *dest); | 1007 | struct key *dest); |
1004 | 1008 | ||
@@ -1010,6 +1014,24 @@ payload contents" for more information. | |||
1010 | KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted | 1014 | KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted |
1011 | towards the user's quota). Error ENOMEM can also be returned. | 1015 | towards the user's quota). Error ENOMEM can also be returned. |
1012 | 1016 | ||
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 | |||
1013 | 1035 | ||
1014 | (*) To check the validity of a key, this function can be called: | 1036 | (*) To check the validity of a key, this function can be called: |
1015 | 1037 | ||
diff --git a/certs/system_keyring.c b/certs/system_keyring.c index dc18869ff680..417d65882870 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c | |||
@@ -36,11 +36,10 @@ static __init int system_trusted_keyring_init(void) | |||
36 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), | 36 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), |
37 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 37 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
38 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), | 38 | 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); | ||
40 | if (IS_ERR(system_trusted_keyring)) | 41 | if (IS_ERR(system_trusted_keyring)) |
41 | panic("Can't allocate system trusted keyring\n"); | 42 | panic("Can't allocate system trusted keyring\n"); |
42 | |||
43 | set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); | ||
44 | return 0; | 43 | return 0; |
45 | } | 44 | } |
46 | 45 | ||
@@ -85,7 +84,8 @@ static __init int load_system_certificate_list(void) | |||
85 | KEY_USR_VIEW | KEY_USR_READ), | 84 | KEY_USR_VIEW | KEY_USR_READ), |
86 | KEY_ALLOC_NOT_IN_QUOTA | | 85 | KEY_ALLOC_NOT_IN_QUOTA | |
87 | KEY_ALLOC_TRUSTED | | 86 | KEY_ALLOC_TRUSTED | |
88 | KEY_ALLOC_BUILT_IN); | 87 | KEY_ALLOC_BUILT_IN | |
88 | KEY_ALLOC_BYPASS_RESTRICTION); | ||
89 | if (IS_ERR(key)) { | 89 | if (IS_ERR(key)) { |
90 | pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", | 90 | pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", |
91 | PTR_ERR(key)); | 91 | PTR_ERR(key)); |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 3f93125916bf..71e8a56e9479 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -360,7 +360,7 @@ init_cifs_idmap(void) | |||
360 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, | 360 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, |
361 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 361 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
362 | KEY_USR_VIEW | KEY_USR_READ, | 362 | KEY_USR_VIEW | KEY_USR_READ, |
363 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | 363 | KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); |
364 | if (IS_ERR(keyring)) { | 364 | if (IS_ERR(keyring)) { |
365 | ret = PTR_ERR(keyring); | 365 | ret = PTR_ERR(keyring); |
366 | goto failed_put_cred; | 366 | goto failed_put_cred; |
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 5ba22c6b0ffa..c444285bb1b1 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c | |||
@@ -201,7 +201,7 @@ int nfs_idmap_init(void) | |||
201 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, | 201 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, |
202 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 202 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
203 | KEY_USR_VIEW | KEY_USR_READ, | 203 | KEY_USR_VIEW | KEY_USR_READ, |
204 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | 204 | KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); |
205 | if (IS_ERR(keyring)) { | 205 | if (IS_ERR(keyring)) { |
206 | ret = PTR_ERR(keyring); | 206 | ret = PTR_ERR(keyring); |
207 | goto failed_put_cred; | 207 | goto failed_put_cred; |
diff --git a/include/linux/key.h b/include/linux/key.h index 5f5b1129dc92..83b603639d2e 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -174,10 +174,9 @@ struct key { | |||
174 | #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ | 174 | #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ |
175 | #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ | 175 | #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ |
176 | #define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ | 176 | #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 */ | 177 | #define KEY_FLAG_BUILTIN 9 /* set if key is built in to the kernel */ |
178 | #define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ | 178 | #define KEY_FLAG_ROOT_CAN_INVAL 10 /* set if key can be invalidated by root without permission */ |
179 | #define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ | 179 | #define KEY_FLAG_KEEP 11 /* set if key should not be removed */ |
180 | #define KEY_FLAG_KEEP 12 /* set if key should not be removed */ | ||
181 | 180 | ||
182 | /* the key type and key description string | 181 | /* the key type and key description string |
183 | * - the desc is used to match a key against search criteria | 182 | * - the desc is used to match a key against search criteria |
@@ -205,6 +204,21 @@ struct key { | |||
205 | }; | 204 | }; |
206 | int reject_error; | 205 | int reject_error; |
207 | }; | 206 | }; |
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); | ||
208 | }; | 222 | }; |
209 | 223 | ||
210 | extern struct key *key_alloc(struct key_type *type, | 224 | extern struct key *key_alloc(struct key_type *type, |
@@ -212,14 +226,19 @@ extern struct key *key_alloc(struct key_type *type, | |||
212 | kuid_t uid, kgid_t gid, | 226 | kuid_t uid, kgid_t gid, |
213 | const struct cred *cred, | 227 | const struct cred *cred, |
214 | key_perm_t perm, | 228 | 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 *)); | ||
216 | 234 | ||
217 | 235 | ||
218 | #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ | 236 | #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 */ | 237 | #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ |
220 | #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ | 238 | #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ |
221 | #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ | 239 | #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ |
222 | #define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */ | 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 */ | ||
223 | 242 | ||
224 | extern void key_revoke(struct key *key); | 243 | extern void key_revoke(struct key *key); |
225 | extern void key_invalidate(struct key *key); | 244 | 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 | |||
288 | const struct cred *cred, | 307 | const struct cred *cred, |
289 | key_perm_t perm, | 308 | key_perm_t perm, |
290 | unsigned long flags, | 309 | unsigned long flags, |
310 | int (*restrict_link)(struct key *, | ||
311 | const struct key_type *, | ||
312 | unsigned long, | ||
313 | const union key_payload *), | ||
291 | struct key *dest); | 314 | struct key *dest); |
292 | 315 | ||
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 | |||
293 | extern int keyring_clear(struct key *keyring); | 326 | extern int keyring_clear(struct key *keyring); |
294 | 327 | ||
295 | extern key_ref_t keyring_search(key_ref_t keyring, | 328 | extern key_ref_t keyring_search(key_ref_t keyring, |
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index c79b85eb4d4c..8737412c7b27 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -281,7 +281,7 @@ static int __init init_dns_resolver(void) | |||
281 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, | 281 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, |
282 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 282 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
283 | KEY_USR_VIEW | KEY_USR_READ, | 283 | KEY_USR_VIEW | KEY_USR_READ, |
284 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | 284 | KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); |
285 | if (IS_ERR(keyring)) { | 285 | if (IS_ERR(keyring)) { |
286 | ret = PTR_ERR(keyring); | 286 | ret = PTR_ERR(keyring); |
287 | goto failed_put_cred; | 287 | goto failed_put_cred; |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 3fb492eedeb9..1021b4c0bdd2 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -965,7 +965,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn, | |||
965 | 965 | ||
966 | key = key_alloc(&key_type_rxrpc, "x", | 966 | key = key_alloc(&key_type_rxrpc, "x", |
967 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0, | 967 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0, |
968 | KEY_ALLOC_NOT_IN_QUOTA); | 968 | KEY_ALLOC_NOT_IN_QUOTA, NULL); |
969 | if (IS_ERR(key)) { | 969 | if (IS_ERR(key)) { |
970 | _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key)); | 970 | _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key)); |
971 | return -ENOMEM; | 971 | return -ENOMEM; |
@@ -1012,7 +1012,7 @@ struct key *rxrpc_get_null_key(const char *keyname) | |||
1012 | 1012 | ||
1013 | key = key_alloc(&key_type_rxrpc, keyname, | 1013 | key = key_alloc(&key_type_rxrpc, keyname, |
1014 | GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, | 1014 | 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); |
1016 | if (IS_ERR(key)) | 1016 | if (IS_ERR(key)) |
1017 | return key; | 1017 | return key; |
1018 | 1018 | ||
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 8ef15118cc78..659566c2200b 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -83,10 +83,9 @@ int __init integrity_init_keyring(const unsigned int id) | |||
83 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 83 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
84 | KEY_USR_VIEW | KEY_USR_READ | | 84 | KEY_USR_VIEW | KEY_USR_READ | |
85 | KEY_USR_WRITE | KEY_USR_SEARCH), | 85 | KEY_USR_WRITE | KEY_USR_SEARCH), |
86 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | 86 | KEY_ALLOC_NOT_IN_QUOTA, |
87 | if (!IS_ERR(keyring[id])) | 87 | NULL, NULL); |
88 | set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); | 88 | if (IS_ERR(keyring[id])) { |
89 | else { | ||
90 | err = PTR_ERR(keyring[id]); | 89 | err = PTR_ERR(keyring[id]); |
91 | pr_info("Can't allocate %s keyring (%d)\n", | 90 | pr_info("Can't allocate %s keyring (%d)\n", |
92 | keyring_name[id], err); | 91 | keyring_name[id], err); |
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 676885e4320e..ef91248cb934 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c | |||
@@ -35,20 +35,20 @@ __init int ima_mok_init(void) | |||
35 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 35 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
36 | KEY_USR_VIEW | KEY_USR_READ | | 36 | KEY_USR_VIEW | KEY_USR_READ | |
37 | KEY_USR_WRITE | KEY_USR_SEARCH, | 37 | 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); | ||
39 | 40 | ||
40 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", | 41 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", |
41 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), | 42 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), |
42 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 43 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
43 | KEY_USR_VIEW | KEY_USR_READ | | 44 | KEY_USR_VIEW | KEY_USR_READ | |
44 | KEY_USR_WRITE | KEY_USR_SEARCH, | 45 | 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); | ||
46 | 48 | ||
47 | if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) | 49 | if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) |
48 | panic("Can't allocate IMA MOK or blacklist keyrings."); | 50 | panic("Can't allocate IMA MOK or blacklist keyrings."); |
49 | set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_mok_keyring->flags); | ||
50 | 51 | ||
51 | set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_blacklist_keyring->flags); | ||
52 | set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); | 52 | set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); |
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
diff --git a/security/keys/key.c b/security/keys/key.c index b28755131687..deb881754e03 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -201,6 +201,7 @@ serial_exists: | |||
201 | * @cred: The credentials specifying UID namespace. | 201 | * @cred: The credentials specifying UID namespace. |
202 | * @perm: The permissions mask of the new key. | 202 | * @perm: The permissions mask of the new key. |
203 | * @flags: Flags specifying quota properties. | 203 | * @flags: Flags specifying quota properties. |
204 | * @restrict_link: Optional link restriction method for new keyrings. | ||
204 | * | 205 | * |
205 | * Allocate a key of the specified type with the attributes given. The key is | 206 | * Allocate a key of the specified type with the attributes given. The key is |
206 | * returned in an uninstantiated state and the caller needs to instantiate the | 207 | * returned in an uninstantiated state and the caller needs to instantiate the |
@@ -223,7 +224,11 @@ serial_exists: | |||
223 | */ | 224 | */ |
224 | struct key *key_alloc(struct key_type *type, const char *desc, | 225 | struct key *key_alloc(struct key_type *type, const char *desc, |
225 | kuid_t uid, kgid_t gid, const struct cred *cred, | 226 | 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 *)) | ||
227 | { | 232 | { |
228 | struct key_user *user = NULL; | 233 | struct key_user *user = NULL; |
229 | struct key *key; | 234 | struct key *key; |
@@ -291,6 +296,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
291 | key->uid = uid; | 296 | key->uid = uid; |
292 | key->gid = gid; | 297 | key->gid = gid; |
293 | key->perm = perm; | 298 | key->perm = perm; |
299 | key->restrict_link = restrict_link; | ||
294 | 300 | ||
295 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) | 301 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) |
296 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; | 302 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
@@ -496,6 +502,12 @@ int key_instantiate_and_link(struct key *key, | |||
496 | } | 502 | } |
497 | 503 | ||
498 | if (keyring) { | 504 | 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 | } | ||
499 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 511 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
500 | if (ret < 0) | 512 | if (ret < 0) |
501 | goto error; | 513 | goto error; |
@@ -551,8 +563,12 @@ int key_reject_and_link(struct key *key, | |||
551 | awaken = 0; | 563 | awaken = 0; |
552 | ret = -EBUSY; | 564 | ret = -EBUSY; |
553 | 565 | ||
554 | if (keyring) | 566 | if (keyring) { |
567 | if (keyring->restrict_link) | ||
568 | return -EPERM; | ||
569 | |||
555 | link_ret = __key_link_begin(keyring, &key->index_key, &edit); | 570 | link_ret = __key_link_begin(keyring, &key->index_key, &edit); |
571 | } | ||
556 | 572 | ||
557 | mutex_lock(&key_construction_mutex); | 573 | mutex_lock(&key_construction_mutex); |
558 | 574 | ||
@@ -793,6 +809,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
793 | struct key *keyring, *key = NULL; | 809 | struct key *keyring, *key = NULL; |
794 | key_ref_t key_ref; | 810 | key_ref_t key_ref; |
795 | int ret; | 811 | int ret; |
812 | int (*restrict_link)(struct key *, | ||
813 | const struct key_type *, | ||
814 | unsigned long, | ||
815 | const union key_payload *) = NULL; | ||
796 | 816 | ||
797 | /* look up the key type to see if it's one of the registered kernel | 817 | /* look up the key type to see if it's one of the registered kernel |
798 | * types */ | 818 | * types */ |
@@ -811,6 +831,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
811 | 831 | ||
812 | key_check(keyring); | 832 | key_check(keyring); |
813 | 833 | ||
834 | key_ref = ERR_PTR(-EPERM); | ||
835 | if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION)) | ||
836 | restrict_link = keyring->restrict_link; | ||
837 | |||
814 | key_ref = ERR_PTR(-ENOTDIR); | 838 | key_ref = ERR_PTR(-ENOTDIR); |
815 | if (keyring->type != &key_type_keyring) | 839 | if (keyring->type != &key_type_keyring) |
816 | goto error_put_type; | 840 | goto error_put_type; |
@@ -835,10 +859,15 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
835 | } | 859 | } |
836 | index_key.desc_len = strlen(index_key.description); | 860 | index_key.desc_len = strlen(index_key.description); |
837 | 861 | ||
838 | key_ref = ERR_PTR(-EPERM); | 862 | if (restrict_link) { |
839 | if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) | 863 | unsigned long kflags = prep.trusted ? KEY_FLAG_TRUSTED : 0; |
840 | goto error_free_prep; | 864 | ret = restrict_link(keyring, |
841 | flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; | 865 | index_key.type, kflags, &prep.payload); |
866 | if (ret < 0) { | ||
867 | key_ref = ERR_PTR(ret); | ||
868 | goto error_free_prep; | ||
869 | } | ||
870 | } | ||
842 | 871 | ||
843 | ret = __key_link_begin(keyring, &index_key, &edit); | 872 | ret = __key_link_begin(keyring, &index_key, &edit); |
844 | if (ret < 0) { | 873 | if (ret < 0) { |
@@ -879,7 +908,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
879 | 908 | ||
880 | /* allocate a new key */ | 909 | /* allocate a new key */ |
881 | key = key_alloc(index_key.type, index_key.description, | 910 | 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); |
883 | if (IS_ERR(key)) { | 912 | if (IS_ERR(key)) { |
884 | key_ref = ERR_CAST(key); | 913 | key_ref = ERR_CAST(key); |
885 | goto error_link_end; | 914 | goto error_link_end; |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f931ccfeefb0..d2d1f3378008 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -491,13 +491,18 @@ static long keyring_read(const struct key *keyring, | |||
491 | */ | 491 | */ |
492 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | 492 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, |
493 | const struct cred *cred, key_perm_t perm, | 493 | const struct cred *cred, key_perm_t perm, |
494 | unsigned long flags, struct key *dest) | 494 | unsigned long flags, |
495 | int (*restrict_link)(struct key *, | ||
496 | const struct key_type *, | ||
497 | unsigned long, | ||
498 | const union key_payload *), | ||
499 | struct key *dest) | ||
495 | { | 500 | { |
496 | struct key *keyring; | 501 | struct key *keyring; |
497 | int ret; | 502 | int ret; |
498 | 503 | ||
499 | keyring = key_alloc(&key_type_keyring, description, | 504 | keyring = key_alloc(&key_type_keyring, description, |
500 | uid, gid, cred, perm, flags); | 505 | uid, gid, cred, perm, flags, restrict_link); |
501 | if (!IS_ERR(keyring)) { | 506 | if (!IS_ERR(keyring)) { |
502 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 507 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
503 | if (ret < 0) { | 508 | if (ret < 0) { |
@@ -510,6 +515,51 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
510 | } | 515 | } |
511 | EXPORT_SYMBOL(keyring_alloc); | 516 | EXPORT_SYMBOL(keyring_alloc); |
512 | 517 | ||
518 | /** | ||
519 | * keyring_restrict_trusted_only - Restrict additions to a keyring to trusted keys only | ||
520 | * @keyring: The keyring being added to. | ||
521 | * @type: The type of key being added. | ||
522 | * @flags: The key flags. | ||
523 | * @payload: The payload of the key intended to be added. | ||
524 | * | ||
525 | * Reject the addition of any links to a keyring that point to keys that aren't | ||
526 | * marked as being trusted. It can be overridden by passing | ||
527 | * KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when adding a key | ||
528 | * to a keyring. | ||
529 | * | ||
530 | * This is meant to be passed as the restrict_link parameter to | ||
531 | * keyring_alloc(). | ||
532 | */ | ||
533 | int keyring_restrict_trusted_only(struct key *keyring, | ||
534 | const struct key_type *type, | ||
535 | unsigned long flags, | ||
536 | const union key_payload *payload) | ||
537 | { | ||
538 | return flags & KEY_FLAG_TRUSTED ? 0 : -EPERM; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * restrict_link_reject - Give -EPERM to restrict link | ||
543 | * @keyring: The keyring being added to. | ||
544 | * @type: The type of key being added. | ||
545 | * @flags: The key flags. | ||
546 | * @payload: The payload of the key intended to be added. | ||
547 | * | ||
548 | * Reject the addition of any links to a keyring. It can be overridden by | ||
549 | * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when | ||
550 | * adding a key to a keyring. | ||
551 | * | ||
552 | * This is meant to be passed as the restrict_link parameter to | ||
553 | * keyring_alloc(). | ||
554 | */ | ||
555 | int restrict_link_reject(struct key *keyring, | ||
556 | const struct key_type *type, | ||
557 | unsigned long flags, | ||
558 | const union key_payload *payload) | ||
559 | { | ||
560 | return -EPERM; | ||
561 | } | ||
562 | |||
513 | /* | 563 | /* |
514 | * By default, we keys found by getting an exact match on their descriptions. | 564 | * By default, we keys found by getting an exact match on their descriptions. |
515 | */ | 565 | */ |
@@ -1191,6 +1241,17 @@ void __key_link_end(struct key *keyring, | |||
1191 | up_write(&keyring->sem); | 1241 | up_write(&keyring->sem); |
1192 | } | 1242 | } |
1193 | 1243 | ||
1244 | /* | ||
1245 | * Check addition of keys to restricted keyrings. | ||
1246 | */ | ||
1247 | static int __key_link_check_restriction(struct key *keyring, struct key *key) | ||
1248 | { | ||
1249 | if (!keyring->restrict_link) | ||
1250 | return 0; | ||
1251 | return keyring->restrict_link(keyring, | ||
1252 | key->type, key->flags, &key->payload); | ||
1253 | } | ||
1254 | |||
1194 | /** | 1255 | /** |
1195 | * key_link - Link a key to a keyring | 1256 | * key_link - Link a key to a keyring |
1196 | * @keyring: The keyring to make the link in. | 1257 | * @keyring: The keyring to make the link in. |
@@ -1221,14 +1282,12 @@ int key_link(struct key *keyring, struct key *key) | |||
1221 | key_check(keyring); | 1282 | key_check(keyring); |
1222 | key_check(key); | 1283 | key_check(key); |
1223 | 1284 | ||
1224 | if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && | ||
1225 | !test_bit(KEY_FLAG_TRUSTED, &key->flags)) | ||
1226 | return -EPERM; | ||
1227 | |||
1228 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 1285 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
1229 | if (ret == 0) { | 1286 | if (ret == 0) { |
1230 | kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); | 1287 | kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); |
1231 | ret = __key_link_check_live_key(keyring, key); | 1288 | ret = __key_link_check_restriction(keyring, key); |
1289 | if (ret == 0) | ||
1290 | ret = __key_link_check_live_key(keyring, key); | ||
1232 | if (ret == 0) | 1291 | if (ret == 0) |
1233 | __key_link(key, &edit); | 1292 | __key_link(key, &edit); |
1234 | __key_link_end(keyring, &key->index_key, edit); | 1293 | __key_link_end(keyring, &key->index_key, edit); |
diff --git a/security/keys/persistent.c b/security/keys/persistent.c index c9fae5ea89fe..2ef45b319dd9 100644 --- a/security/keys/persistent.c +++ b/security/keys/persistent.c | |||
@@ -26,7 +26,7 @@ static int key_create_persistent_register(struct user_namespace *ns) | |||
26 | current_cred(), | 26 | current_cred(), |
27 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 27 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
28 | KEY_USR_VIEW | KEY_USR_READ), | 28 | KEY_USR_VIEW | KEY_USR_READ), |
29 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | 29 | KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); |
30 | if (IS_ERR(reg)) | 30 | if (IS_ERR(reg)) |
31 | return PTR_ERR(reg); | 31 | return PTR_ERR(reg); |
32 | 32 | ||
@@ -60,7 +60,7 @@ static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid, | |||
60 | uid, INVALID_GID, current_cred(), | 60 | uid, INVALID_GID, current_cred(), |
61 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 61 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
62 | KEY_USR_VIEW | KEY_USR_READ), | 62 | KEY_USR_VIEW | KEY_USR_READ), |
63 | KEY_ALLOC_NOT_IN_QUOTA, | 63 | KEY_ALLOC_NOT_IN_QUOTA, NULL, |
64 | ns->persistent_keyring_register); | 64 | ns->persistent_keyring_register); |
65 | if (IS_ERR(persistent)) | 65 | if (IS_ERR(persistent)) |
66 | return ERR_CAST(persistent); | 66 | return ERR_CAST(persistent); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e6d50172872f..40a885239782 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -76,7 +76,8 @@ int install_user_keyrings(void) | |||
76 | if (IS_ERR(uid_keyring)) { | 76 | if (IS_ERR(uid_keyring)) { |
77 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, | 77 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, |
78 | cred, user_keyring_perm, | 78 | cred, user_keyring_perm, |
79 | KEY_ALLOC_IN_QUOTA, NULL); | 79 | KEY_ALLOC_IN_QUOTA, |
80 | NULL, NULL); | ||
80 | if (IS_ERR(uid_keyring)) { | 81 | if (IS_ERR(uid_keyring)) { |
81 | ret = PTR_ERR(uid_keyring); | 82 | ret = PTR_ERR(uid_keyring); |
82 | goto error; | 83 | goto error; |
@@ -92,7 +93,8 @@ int install_user_keyrings(void) | |||
92 | session_keyring = | 93 | session_keyring = |
93 | keyring_alloc(buf, user->uid, INVALID_GID, | 94 | keyring_alloc(buf, user->uid, INVALID_GID, |
94 | cred, user_keyring_perm, | 95 | cred, user_keyring_perm, |
95 | KEY_ALLOC_IN_QUOTA, NULL); | 96 | KEY_ALLOC_IN_QUOTA, |
97 | NULL, NULL); | ||
96 | if (IS_ERR(session_keyring)) { | 98 | if (IS_ERR(session_keyring)) { |
97 | ret = PTR_ERR(session_keyring); | 99 | ret = PTR_ERR(session_keyring); |
98 | goto error_release; | 100 | goto error_release; |
@@ -134,7 +136,8 @@ int install_thread_keyring_to_cred(struct cred *new) | |||
134 | 136 | ||
135 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, | 137 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
136 | KEY_POS_ALL | KEY_USR_VIEW, | 138 | KEY_POS_ALL | KEY_USR_VIEW, |
137 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 139 | KEY_ALLOC_QUOTA_OVERRUN, |
140 | NULL, NULL); | ||
138 | if (IS_ERR(keyring)) | 141 | if (IS_ERR(keyring)) |
139 | return PTR_ERR(keyring); | 142 | return PTR_ERR(keyring); |
140 | 143 | ||
@@ -180,7 +183,8 @@ int install_process_keyring_to_cred(struct cred *new) | |||
180 | 183 | ||
181 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, | 184 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, |
182 | KEY_POS_ALL | KEY_USR_VIEW, | 185 | KEY_POS_ALL | KEY_USR_VIEW, |
183 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 186 | KEY_ALLOC_QUOTA_OVERRUN, |
187 | NULL, NULL); | ||
184 | if (IS_ERR(keyring)) | 188 | if (IS_ERR(keyring)) |
185 | return PTR_ERR(keyring); | 189 | return PTR_ERR(keyring); |
186 | 190 | ||
@@ -231,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
231 | 235 | ||
232 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, | 236 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, |
233 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | 237 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, |
234 | flags, NULL); | 238 | flags, NULL, NULL); |
235 | if (IS_ERR(keyring)) | 239 | if (IS_ERR(keyring)) |
236 | return PTR_ERR(keyring); | 240 | return PTR_ERR(keyring); |
237 | } else { | 241 | } else { |
@@ -785,7 +789,7 @@ long join_session_keyring(const char *name) | |||
785 | keyring = keyring_alloc( | 789 | keyring = keyring_alloc( |
786 | name, old->uid, old->gid, old, | 790 | name, old->uid, old->gid, old, |
787 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, | 791 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, |
788 | KEY_ALLOC_IN_QUOTA, NULL); | 792 | KEY_ALLOC_IN_QUOTA, NULL, NULL); |
789 | if (IS_ERR(keyring)) { | 793 | if (IS_ERR(keyring)) { |
790 | ret = PTR_ERR(keyring); | 794 | ret = PTR_ERR(keyring); |
791 | goto error2; | 795 | goto error2; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index c7a117c9a8f3..a29e3554751e 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -116,7 +116,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
116 | cred = get_current_cred(); | 116 | cred = get_current_cred(); |
117 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | 117 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, |
118 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | 118 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, |
119 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 119 | KEY_ALLOC_QUOTA_OVERRUN, NULL, NULL); |
120 | put_cred(cred); | 120 | put_cred(cred); |
121 | if (IS_ERR(keyring)) { | 121 | if (IS_ERR(keyring)) { |
122 | ret = PTR_ERR(keyring); | 122 | ret = PTR_ERR(keyring); |
@@ -355,7 +355,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx, | |||
355 | 355 | ||
356 | key = key_alloc(ctx->index_key.type, ctx->index_key.description, | 356 | key = key_alloc(ctx->index_key.type, ctx->index_key.description, |
357 | ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred, | 357 | ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred, |
358 | perm, flags); | 358 | perm, flags, NULL); |
359 | if (IS_ERR(key)) | 359 | if (IS_ERR(key)) |
360 | goto alloc_failed; | 360 | goto alloc_failed; |
361 | 361 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 4f0f112fe276..9db8b4a82787 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -202,7 +202,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
202 | authkey = key_alloc(&key_type_request_key_auth, desc, | 202 | authkey = key_alloc(&key_type_request_key_auth, desc, |
203 | cred->fsuid, cred->fsgid, cred, | 203 | cred->fsuid, cred->fsgid, cred, |
204 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 204 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
205 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); | 205 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL); |
206 | if (IS_ERR(authkey)) { | 206 | if (IS_ERR(authkey)) { |
207 | ret = PTR_ERR(authkey); | 207 | ret = PTR_ERR(authkey); |
208 | goto error_alloc; | 208 | goto error_alloc; |