summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-06-26 16:02:32 -0400
committerDavid Howells <dhowells@redhat.com>2019-06-26 16:02:32 -0400
commit218e6424e711ceee31eeba93212fed8ee92d6a11 (patch)
tree62358ec392304d17294f73779a1a13591468de7b
parent3b6e4de05e9ee2e2f94e4a3fe14d945e2418d9a8 (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.h2
-rw-r--r--security/keys/internal.h3
-rw-r--r--security/keys/keyring.c15
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);
278extern void key_invalidate(struct key *key); 278extern void key_invalidate(struct key *key);
279extern void key_put(struct key *key); 279extern void key_put(struct key *key);
280extern bool key_put_tag(struct key_tag *tag); 280extern bool key_put_tag(struct key_tag *tag);
281extern void key_remove_domain(struct key_tag *domain_tag);
281 282
282static inline struct key *__key_get(struct key *key) 283static 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 */
252void 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 *