keys, dns: Allow key types (eg. DNS) to be reclaimed immediately on expiry
[platform/kernel/linux-starfive.git] / security / keys / gc.c
index 3c90807..eaddace 100644 (file)
@@ -67,6 +67,19 @@ void key_schedule_gc(time64_t gc_at)
 }
 
 /*
+ * Set the expiration time on a key.
+ */
+void key_set_expiry(struct key *key, time64_t expiry)
+{
+       key->expiry = expiry;
+       if (expiry != TIME64_MAX) {
+               if (!(key->type->flags & KEY_TYPE_INSTANT_REAP))
+                       expiry += key_gc_delay;
+               key_schedule_gc(expiry);
+       }
+}
+
+/*
  * Schedule a dead links collection run.
  */
 void key_schedule_gc_links(void)
@@ -176,7 +189,6 @@ static void key_garbage_collector(struct work_struct *work)
        static u8 gc_state;             /* Internal persistent state */
 #define KEY_GC_REAP_AGAIN      0x01    /* - Need another cycle */
 #define KEY_GC_REAPING_LINKS   0x02    /* - We need to reap links */
-#define KEY_GC_SET_TIMER       0x04    /* - We need to restart the timer */
 #define KEY_GC_REAPING_DEAD_1  0x10    /* - We need to mark dead keys */
 #define KEY_GC_REAPING_DEAD_2  0x20    /* - We need to reap dead key links */
 #define KEY_GC_REAPING_DEAD_3  0x40    /* - We need to reap dead keys */
@@ -184,21 +196,17 @@ static void key_garbage_collector(struct work_struct *work)
 
        struct rb_node *cursor;
        struct key *key;
-       time64_t new_timer, limit;
+       time64_t new_timer, limit, expiry;
 
        kenter("[%lx,%x]", key_gc_flags, gc_state);
 
        limit = ktime_get_real_seconds();
-       if (limit > key_gc_delay)
-               limit -= key_gc_delay;
-       else
-               limit = key_gc_delay;
 
        /* Work out what we're going to be doing in this pass */
        gc_state &= KEY_GC_REAPING_DEAD_1 | KEY_GC_REAPING_DEAD_2;
        gc_state <<= 1;
        if (test_and_clear_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags))
-               gc_state |= KEY_GC_REAPING_LINKS | KEY_GC_SET_TIMER;
+               gc_state |= KEY_GC_REAPING_LINKS;
 
        if (test_and_clear_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags))
                gc_state |= KEY_GC_REAPING_DEAD_1;
@@ -233,8 +241,11 @@ continue_scanning:
                        }
                }
 
-               if (gc_state & KEY_GC_SET_TIMER) {
-                       if (key->expiry > limit && key->expiry < new_timer) {
+               expiry = key->expiry;
+               if (expiry != TIME64_MAX) {
+                       if (!(key->type->flags & KEY_TYPE_INSTANT_REAP))
+                               expiry += key_gc_delay;
+                       if (expiry > limit && expiry < new_timer) {
                                kdebug("will expire %x in %lld",
                                       key_serial(key), key->expiry - limit);
                                new_timer = key->expiry;
@@ -276,7 +287,7 @@ maybe_resched:
         */
        kdebug("pass complete");
 
-       if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)TIME64_MAX) {
+       if (new_timer != TIME64_MAX) {
                new_timer += key_gc_delay;
                key_schedule_gc(new_timer);
        }