Skip to content

Commit fff2929

Browse files
ereshetovaJames Morris
authored andcommitted
security, keys: convert key.usage from atomic_t to refcount_t
refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: David Windsor <dwindsor@gmail.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <james.l.morris@oracle.com>
1 parent 8291798 commit fff2929

File tree

6 files changed

+13
-12
lines changed

6 files changed

+13
-12
lines changed

include/linux/key.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/rwsem.h>
2424
#include <linux/atomic.h>
2525
#include <linux/assoc_array.h>
26+
#include <linux/refcount.h>
2627

2728
#ifdef __KERNEL__
2829
#include <linux/uidgid.h>
@@ -135,7 +136,7 @@ static inline bool is_key_possessed(const key_ref_t key_ref)
135136
* - Kerberos TGTs and tickets
136137
*/
137138
struct key {
138-
atomic_t usage; /* number of references */
139+
refcount_t usage; /* number of references */
139140
key_serial_t serial; /* key serial number */
140141
union {
141142
struct list_head graveyard_link;
@@ -242,7 +243,7 @@ extern void key_put(struct key *key);
242243

243244
static inline struct key *__key_get(struct key *key)
244245
{
245-
atomic_inc(&key->usage);
246+
refcount_inc(&key->usage);
246247
return key;
247248
}
248249

security/keys/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static void key_garbage_collector(struct work_struct *work)
220220
key = rb_entry(cursor, struct key, serial_node);
221221
cursor = rb_next(cursor);
222222

223-
if (atomic_read(&key->usage) == 0)
223+
if (refcount_read(&key->usage) == 0)
224224
goto found_unreferenced_key;
225225

226226
if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) {

security/keys/key.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
285285
if (!key->index_key.description)
286286
goto no_memory_3;
287287

288-
atomic_set(&key->usage, 1);
288+
refcount_set(&key->usage, 1);
289289
init_rwsem(&key->sem);
290290
lockdep_set_class(&key->sem, &type->lock_class);
291291
key->index_key.type = type;
@@ -621,7 +621,7 @@ void key_put(struct key *key)
621621
if (key) {
622622
key_check(key);
623623

624-
if (atomic_dec_and_test(&key->usage))
624+
if (refcount_dec_and_test(&key->usage))
625625
schedule_work(&key_gc_work);
626626
}
627627
}
@@ -656,7 +656,7 @@ struct key *key_lookup(key_serial_t id)
656656

657657
found:
658658
/* pretend it doesn't exist if it is awaiting deletion */
659-
if (atomic_read(&key->usage) == 0)
659+
if (refcount_read(&key->usage) == 0)
660660
goto not_found;
661661

662662
/* this races with key_put(), but that doesn't matter since key_put()

security/keys/keyring.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
10331033
/* we've got a match but we might end up racing with
10341034
* key_cleanup() if the keyring is currently 'dead'
10351035
* (ie. it has a zero usage count) */
1036-
if (!atomic_inc_not_zero(&keyring->usage))
1036+
if (!refcount_inc_not_zero(&keyring->usage))
10371037
continue;
10381038
keyring->last_used_at = current_kernel_time().tv_sec;
10391039
goto out;
@@ -1250,14 +1250,14 @@ int key_link(struct key *keyring, struct key *key)
12501250
struct assoc_array_edit *edit;
12511251
int ret;
12521252

1253-
kenter("{%d,%d}", keyring->serial, atomic_read(&keyring->usage));
1253+
kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage));
12541254

12551255
key_check(keyring);
12561256
key_check(key);
12571257

12581258
ret = __key_link_begin(keyring, &key->index_key, &edit);
12591259
if (ret == 0) {
1260-
kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage));
1260+
kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage));
12611261
ret = __key_link_check_restriction(keyring, key);
12621262
if (ret == 0)
12631263
ret = __key_link_check_live_key(keyring, key);
@@ -1266,7 +1266,7 @@ int key_link(struct key *keyring, struct key *key)
12661266
__key_link_end(keyring, &key->index_key, edit);
12671267
}
12681268

1269-
kleave(" = %d {%d,%d}", ret, keyring->serial, atomic_read(&keyring->usage));
1269+
kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage));
12701270
return ret;
12711271
}
12721272
EXPORT_SYMBOL(key_link);

security/keys/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
252252
showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
253253
showflag(key, 'N', KEY_FLAG_NEGATIVE),
254254
showflag(key, 'i', KEY_FLAG_INVALIDATED),
255-
atomic_read(&key->usage),
255+
refcount_read(&key->usage),
256256
xbuf,
257257
key->perm,
258258
from_kuid_munged(seq_user_ns(m), key->uid),

security/keys/request_key_auth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
213213
if (ret < 0)
214214
goto error_inst;
215215

216-
kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
216+
kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage));
217217
return authkey;
218218

219219
auth_key_revoked:

0 commit comments

Comments
 (0)