diff options
author | David Howells <dhowells@redhat.com> | 2019-06-26 16:02:32 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-06-26 16:02:32 -0400 |
commit | 218e6424e711ceee31eeba93212fed8ee92d6a11 (patch) | |
tree | 62358ec392304d17294f73779a1a13591468de7b | |
parent | 3b6e4de05e9ee2e2f94e4a3fe14d945e2418d9a8 (diff) |
keys: Garbage collect keys for which the domain has been removed
If a key operation domain (such as a network namespace) has been removed
then attempt to garbage collect all the keys that use it.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | include/linux/key.h | 2 | ||||
-rw-r--r-- | security/keys/internal.h | 3 | ||||
-rw-r--r-- | security/keys/keyring.c | 15 |
3 files changed, 19 insertions, 1 deletions
diff --git a/include/linux/key.h b/include/linux/key.h index abc68555bac3..60c076c6e47f 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -278,6 +278,7 @@ extern void key_revoke(struct key *key); | |||
278 | extern void key_invalidate(struct key *key); | 278 | extern void key_invalidate(struct key *key); |
279 | extern void key_put(struct key *key); | 279 | extern void key_put(struct key *key); |
280 | extern bool key_put_tag(struct key_tag *tag); | 280 | extern bool key_put_tag(struct key_tag *tag); |
281 | extern void key_remove_domain(struct key_tag *domain_tag); | ||
281 | 282 | ||
282 | static inline struct key *__key_get(struct key *key) | 283 | static inline struct key *__key_get(struct key *key) |
283 | { | 284 | { |
@@ -446,6 +447,7 @@ extern void key_init(void); | |||
446 | #define key_fsgid_changed(c) do { } while(0) | 447 | #define key_fsgid_changed(c) do { } while(0) |
447 | #define key_init() do { } while(0) | 448 | #define key_init() do { } while(0) |
448 | #define key_free_user_ns(ns) do { } while(0) | 449 | #define key_free_user_ns(ns) do { } while(0) |
450 | #define key_remove_domain(d) do { } while(0) | ||
449 | 451 | ||
450 | #endif /* CONFIG_KEYS */ | 452 | #endif /* CONFIG_KEYS */ |
451 | #endif /* __KERNEL__ */ | 453 | #endif /* __KERNEL__ */ |
diff --git a/security/keys/internal.h b/security/keys/internal.h index d3a9439e2386..5a561f5f199e 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -209,7 +209,8 @@ static inline bool key_is_dead(const struct key *key, time64_t limit) | |||
209 | return | 209 | return |
210 | key->flags & ((1 << KEY_FLAG_DEAD) | | 210 | key->flags & ((1 << KEY_FLAG_DEAD) | |
211 | (1 << KEY_FLAG_INVALIDATED)) || | 211 | (1 << KEY_FLAG_INVALIDATED)) || |
212 | (key->expiry > 0 && key->expiry <= limit); | 212 | (key->expiry > 0 && key->expiry <= limit) || |
213 | key->domain_tag->removed; | ||
213 | } | 214 | } |
214 | 215 | ||
215 | /* | 216 | /* |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 0da8fa282d56..d3c86fda1510 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -241,6 +241,21 @@ bool key_put_tag(struct key_tag *tag) | |||
241 | return false; | 241 | return false; |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | ||
245 | * key_remove_domain - Kill off a key domain and gc its keys | ||
246 | * @domain_tag: The domain tag to release. | ||
247 | * | ||
248 | * This marks a domain tag as being dead and releases a ref on it. If that | ||
249 | * wasn't the last reference, the garbage collector is poked to try and delete | ||
250 | * all keys that were in the domain. | ||
251 | */ | ||
252 | void key_remove_domain(struct key_tag *domain_tag) | ||
253 | { | ||
254 | domain_tag->removed = true; | ||
255 | if (!key_put_tag(domain_tag)) | ||
256 | key_schedule_gc_links(); | ||
257 | } | ||
258 | |||
244 | /* | 259 | /* |
245 | * Build the next index key chunk. | 260 | * Build the next index key chunk. |
246 | * | 261 | * |