aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-09-14 12:26:13 -0400
committerJames Morris <jmorris@namei.org>2009-09-14 19:11:02 -0400
commitc08ef808ef24df32e25fbd949fe5310172f3c408 (patch)
tree12bae6fd48e1cdcc1b792c221376c727d9472cc6 /security/keys/keyring.c
parent5c84342a3e147a23752276650340801c237d0e56 (diff)
KEYS: Fix garbage collector
Fix a number of problems with the new key garbage collector: (1) A rogue semicolon in keyring_gc() was causing the initial count of dead keys to be miscalculated. (2) A missing return in keyring_gc() meant that under certain circumstances, the keyring semaphore would be unlocked twice. (3) The key serial tree iterator (key_garbage_collector()) part of the garbage collector has been modified to: (a) Complete each scan of the keyrings before setting the new timer. (b) Only set the new timer for keys that have yet to expire. This means that the new timer is now calculated correctly, and the gc doesn't get into a loop continually scanning for keys that have expired, and preventing other things from happening, like RCU cleaning up the old keyring contents. (c) Perform an extra scan if any keys were garbage collected in this one as a key might become garbage during a scan, and (b) could mean we don't set the timer again. (4) Made key_schedule_gc() take the time at which to do a collection run, rather than the time at which the key expires. This means the collection of dead keys (key type unregistered) can happen immediately. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index ac977f661a79..8ec02746ca99 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1019,18 +1019,18 @@ void keyring_gc(struct key *keyring, time_t limit)
1019 struct key *key; 1019 struct key *key;
1020 int loop, keep, max; 1020 int loop, keep, max;
1021 1021
1022 kenter("%x", key_serial(keyring)); 1022 kenter("{%x,%s}", key_serial(keyring), keyring->description);
1023 1023
1024 down_write(&keyring->sem); 1024 down_write(&keyring->sem);
1025 1025
1026 klist = keyring->payload.subscriptions; 1026 klist = keyring->payload.subscriptions;
1027 if (!klist) 1027 if (!klist)
1028 goto just_return; 1028 goto no_klist;
1029 1029
1030 /* work out how many subscriptions we're keeping */ 1030 /* work out how many subscriptions we're keeping */
1031 keep = 0; 1031 keep = 0;
1032 for (loop = klist->nkeys - 1; loop >= 0; loop--) 1032 for (loop = klist->nkeys - 1; loop >= 0; loop--)
1033 if (!key_is_dead(klist->keys[loop], limit)); 1033 if (!key_is_dead(klist->keys[loop], limit))
1034 keep++; 1034 keep++;
1035 1035
1036 if (keep == klist->nkeys) 1036 if (keep == klist->nkeys)
@@ -1041,7 +1041,7 @@ void keyring_gc(struct key *keyring, time_t limit)
1041 new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *), 1041 new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *),
1042 GFP_KERNEL); 1042 GFP_KERNEL);
1043 if (!new) 1043 if (!new)
1044 goto just_return; 1044 goto nomem;
1045 new->maxkeys = max; 1045 new->maxkeys = max;
1046 new->nkeys = 0; 1046 new->nkeys = 0;
1047 new->delkey = 0; 1047 new->delkey = 0;
@@ -1081,7 +1081,21 @@ void keyring_gc(struct key *keyring, time_t limit)
1081discard_new: 1081discard_new:
1082 new->nkeys = keep; 1082 new->nkeys = keep;
1083 keyring_clear_rcu_disposal(&new->rcu); 1083 keyring_clear_rcu_disposal(&new->rcu);
1084 up_write(&keyring->sem);
1085 kleave(" [discard]");
1086 return;
1087
1084just_return: 1088just_return:
1085 up_write(&keyring->sem); 1089 up_write(&keyring->sem);
1086 kleave(" [no]"); 1090 kleave(" [no dead]");
1091 return;
1092
1093no_klist:
1094 up_write(&keyring->sem);
1095 kleave(" [no_klist]");
1096 return;
1097
1098nomem:
1099 up_write(&keyring->sem);
1100 kleave(" [oom]");
1087} 1101}