Skip to content

Commit 4f40988

Browse files
committed
keys: Hoist locking out of __key_link_begin()
jira LE-1907 Rebuild_History Non-Buildable kernel-4.18.0-553.5.1.el8_10 commit-author David Howells <[email protected]> commit df593ee Hoist the locking of out of __key_link_begin() and into its callers. This is necessary to allow the upcoming key_move() operation to correctly order taking of the source keyring semaphore, the destination keyring semaphore and the keyring serialisation lock. Signed-off-by: David Howells <[email protected]> (cherry picked from commit df593ee) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 0a5646c commit 4f40988

File tree

4 files changed

+76
-38
lines changed

4 files changed

+76
-38
lines changed

security/keys/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ extern wait_queue_head_t request_key_conswq;
9595
extern struct key_type *key_type_lookup(const char *type);
9696
extern void key_type_put(struct key_type *ktype);
9797

98+
extern int __key_link_lock(struct key *keyring,
99+
const struct keyring_index_key *index_key);
98100
extern int __key_link_begin(struct key *keyring,
99101
const struct keyring_index_key *index_key,
100102
struct assoc_array_edit **_edit);

security/keys/key.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ int key_instantiate_and_link(struct key *key,
501501
struct key *authkey)
502502
{
503503
struct key_preparsed_payload prep;
504-
struct assoc_array_edit *edit;
504+
struct assoc_array_edit *edit = NULL;
505505
int ret;
506506

507507
memset(&prep, 0, sizeof(prep));
@@ -516,10 +516,14 @@ int key_instantiate_and_link(struct key *key,
516516
}
517517

518518
if (keyring) {
519-
ret = __key_link_begin(keyring, &key->index_key, &edit);
519+
ret = __key_link_lock(keyring, &key->index_key);
520520
if (ret < 0)
521521
goto error;
522522

523+
ret = __key_link_begin(keyring, &key->index_key, &edit);
524+
if (ret < 0)
525+
goto error_link_end;
526+
523527
if (keyring->restrict_link && keyring->restrict_link->check) {
524528
struct key_restriction *keyres = keyring->restrict_link;
525529

@@ -571,7 +575,7 @@ int key_reject_and_link(struct key *key,
571575
struct key *keyring,
572576
struct key *authkey)
573577
{
574-
struct assoc_array_edit *edit;
578+
struct assoc_array_edit *edit = NULL;
575579
int ret, awaken, link_ret = 0;
576580

577581
key_check(key);
@@ -584,7 +588,12 @@ int key_reject_and_link(struct key *key,
584588
if (keyring->restrict_link)
585589
return -EPERM;
586590

587-
link_ret = __key_link_begin(keyring, &key->index_key, &edit);
591+
link_ret = __key_link_lock(keyring, &key->index_key);
592+
if (link_ret == 0) {
593+
link_ret = __key_link_begin(keyring, &key->index_key, &edit);
594+
if (link_ret < 0)
595+
__key_link_end(keyring, &key->index_key, edit);
596+
}
588597
}
589598

590599
mutex_lock(&key_construction_mutex);
@@ -811,7 +820,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
811820
.description = description,
812821
};
813822
struct key_preparsed_payload prep;
814-
struct assoc_array_edit *edit;
823+
struct assoc_array_edit *edit = NULL;
815824
const struct cred *cred = current_cred();
816825
struct key *keyring, *key = NULL;
817826
key_ref_t key_ref;
@@ -861,12 +870,18 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
861870
}
862871
index_key.desc_len = strlen(index_key.description);
863872

864-
ret = __key_link_begin(keyring, &index_key, &edit);
873+
ret = __key_link_lock(keyring, &index_key);
865874
if (ret < 0) {
866875
key_ref = ERR_PTR(ret);
867876
goto error_free_prep;
868877
}
869878

879+
ret = __key_link_begin(keyring, &index_key, &edit);
880+
if (ret < 0) {
881+
key_ref = ERR_PTR(ret);
882+
goto error_link_end;
883+
}
884+
870885
if (restrict_link && restrict_link->check) {
871886
ret = restrict_link->check(keyring, index_key.type,
872887
&prep.payload, restrict_link->key);

security/keys/keyring.c

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,14 +1192,34 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
11921192
return PTR_ERR(ctx.result) == -EAGAIN ? 0 : PTR_ERR(ctx.result);
11931193
}
11941194

1195+
/*
1196+
* Lock keyring for link.
1197+
*/
1198+
int __key_link_lock(struct key *keyring,
1199+
const struct keyring_index_key *index_key)
1200+
__acquires(&keyring->sem)
1201+
__acquires(&keyring_serialise_link_lock)
1202+
{
1203+
if (keyring->type != &key_type_keyring)
1204+
return -ENOTDIR;
1205+
1206+
down_write(&keyring->sem);
1207+
1208+
/* Serialise link/link calls to prevent parallel calls causing a cycle
1209+
* when linking two keyring in opposite orders.
1210+
*/
1211+
if (index_key->type == &key_type_keyring)
1212+
mutex_lock(&keyring_serialise_link_lock);
1213+
1214+
return 0;
1215+
}
1216+
11951217
/*
11961218
* Preallocate memory so that a key can be linked into to a keyring.
11971219
*/
11981220
int __key_link_begin(struct key *keyring,
11991221
const struct keyring_index_key *index_key,
12001222
struct assoc_array_edit **_edit)
1201-
__acquires(&keyring->sem)
1202-
__acquires(&keyring_serialise_link_lock)
12031223
{
12041224
struct assoc_array_edit *edit;
12051225
int ret;
@@ -1208,20 +1228,13 @@ int __key_link_begin(struct key *keyring,
12081228
keyring->serial, index_key->type->name, index_key->description);
12091229

12101230
BUG_ON(index_key->desc_len == 0);
1231+
BUG_ON(*_edit != NULL);
12111232

1212-
if (keyring->type != &key_type_keyring)
1213-
return -ENOTDIR;
1214-
1215-
down_write(&keyring->sem);
1233+
*_edit = NULL;
12161234

12171235
ret = -EKEYREVOKED;
12181236
if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
1219-
goto error_krsem;
1220-
1221-
/* serialise link/link calls to prevent parallel calls causing a cycle
1222-
* when linking two keyring in opposite orders */
1223-
if (index_key->type == &key_type_keyring)
1224-
mutex_lock(&keyring_serialise_link_lock);
1237+
goto error;
12251238

12261239
/* Create an edit script that will insert/replace the key in the
12271240
* keyring tree.
@@ -1232,7 +1245,7 @@ int __key_link_begin(struct key *keyring,
12321245
NULL);
12331246
if (IS_ERR(edit)) {
12341247
ret = PTR_ERR(edit);
1235-
goto error_sem;
1248+
goto error;
12361249
}
12371250

12381251
/* If we're not replacing a link in-place then we're going to need some
@@ -1251,11 +1264,7 @@ int __key_link_begin(struct key *keyring,
12511264

12521265
error_cancel:
12531266
assoc_array_cancel_edit(edit);
1254-
error_sem:
1255-
if (index_key->type == &key_type_keyring)
1256-
mutex_unlock(&keyring_serialise_link_lock);
1257-
error_krsem:
1258-
up_write(&keyring->sem);
1267+
error:
12591268
kleave(" = %d", ret);
12601269
return ret;
12611270
}
@@ -1305,9 +1314,6 @@ void __key_link_end(struct key *keyring,
13051314
BUG_ON(index_key->type == NULL);
13061315
kenter("%d,%s,", keyring->serial, index_key->type->name);
13071316

1308-
if (index_key->type == &key_type_keyring)
1309-
mutex_unlock(&keyring_serialise_link_lock);
1310-
13111317
if (edit) {
13121318
if (!edit->dead_leaf) {
13131319
key_payload_reserve(keyring,
@@ -1316,6 +1322,9 @@ void __key_link_end(struct key *keyring,
13161322
assoc_array_cancel_edit(edit);
13171323
}
13181324
up_write(&keyring->sem);
1325+
1326+
if (index_key->type == &key_type_keyring)
1327+
mutex_unlock(&keyring_serialise_link_lock);
13191328
}
13201329

13211330
/*
@@ -1351,25 +1360,32 @@ static int __key_link_check_restriction(struct key *keyring, struct key *key)
13511360
*/
13521361
int key_link(struct key *keyring, struct key *key)
13531362
{
1354-
struct assoc_array_edit *edit;
1363+
struct assoc_array_edit *edit = NULL;
13551364
int ret;
13561365

13571366
kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage));
13581367

13591368
key_check(keyring);
13601369
key_check(key);
13611370

1371+
ret = __key_link_lock(keyring, &key->index_key);
1372+
if (ret < 0)
1373+
goto error;
1374+
13621375
ret = __key_link_begin(keyring, &key->index_key, &edit);
1363-
if (ret == 0) {
1364-
kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage));
1365-
ret = __key_link_check_restriction(keyring, key);
1366-
if (ret == 0)
1367-
ret = __key_link_check_live_key(keyring, key);
1368-
if (ret == 0)
1369-
__key_link(key, &edit);
1370-
__key_link_end(keyring, &key->index_key, edit);
1371-
}
1376+
if (ret < 0)
1377+
goto error_end;
1378+
1379+
kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage));
1380+
ret = __key_link_check_restriction(keyring, key);
1381+
if (ret == 0)
1382+
ret = __key_link_check_live_key(keyring, key);
1383+
if (ret == 0)
1384+
__key_link(key, &edit);
13721385

1386+
error_end:
1387+
__key_link_end(keyring, &key->index_key, edit);
1388+
error:
13731389
kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage));
13741390
return ret;
13751391
}

security/keys/request_key.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
357357
struct key_user *user,
358358
struct key **_key)
359359
{
360-
struct assoc_array_edit *edit;
360+
struct assoc_array_edit *edit = NULL;
361361
struct key *key;
362362
key_perm_t perm;
363363
key_ref_t key_ref;
@@ -386,6 +386,9 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
386386
set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
387387

388388
if (dest_keyring) {
389+
ret = __key_link_lock(dest_keyring, &ctx->index_key);
390+
if (ret < 0)
391+
goto link_lock_failed;
389392
ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit);
390393
if (ret < 0)
391394
goto link_prealloc_failed;
@@ -437,6 +440,8 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
437440
return ret;
438441

439442
link_prealloc_failed:
443+
__key_link_end(dest_keyring, &ctx->index_key, edit);
444+
link_lock_failed:
440445
mutex_unlock(&user->cons_lock);
441446
key_put(key);
442447
kleave(" = %d [prelink]", ret);

0 commit comments

Comments
 (0)