Skip to content

Commit 7216ce8

Browse files
CsomeProgregkh
authored andcommitted
keys: Pin request_key_auth payload in instantiate paths
commit fd15b45 upstream. A: request_key() B: KEYCTL_INSTANTIATE_IOV ================ ========================= create auth key store rka in auth key wait for helper get auth key load rka from auth key copy user payload sleep on #PF helper completed detach and free rka destroy auth key wake up use rka->target_key **USE-AFTER-FREE** Give request_key_auth payloads a refcount. Take a payload reference while authkey->sem stabilizes the payload and revocation state. Hold that reference across the instantiate and reject paths. Drop the auth key owning reference from revoke and destroy. [jarkko: Replaced the first two paragraphs of text with an actual concurrency scenario.] Cc: stable@vger.kernel.org # v5.10+ Fixes: b5f545c ("[PATCH] keys: Permit running process to instantiate keys") Reported-by: Shaomin Chen <eeesssooo020@gmail.com> Closes: https://lore.kernel.org/r/20260519144403.436694-1-eeesssooo020@gmail.com Signed-off-by: Shaomin Chen <eeesssooo020@gmail.com> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b11c1fa commit 7216ce8

4 files changed

Lines changed: 53 additions & 8 deletions

File tree

include/keys/request_key_auth-type.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
#define _KEYS_REQUEST_KEY_AUTH_TYPE_H
1010

1111
#include <linux/key.h>
12+
#include <linux/refcount.h>
1213

1314
/*
1415
* Authorisation record for request_key().
1516
*/
1617
struct request_key_auth {
1718
struct rcu_head rcu;
19+
refcount_t usage;
1820
struct key *target_key;
1921
struct key *dest_keyring;
2022
const struct cred *cred;

security/keys/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ extern struct key *request_key_auth_new(struct key *target,
208208
const void *callout_info,
209209
size_t callout_len,
210210
struct key *dest_keyring);
211+
struct request_key_auth *request_key_auth_get(struct key *authkey);
212+
void request_key_auth_put(struct request_key_auth *rka);
211213

212214
extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
213215

security/keys/keyctl.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,9 +1197,13 @@ static long keyctl_instantiate_key_common(key_serial_t id,
11971197
if (!instkey)
11981198
goto error;
11991199

1200-
rka = instkey->payload.data[0];
1201-
if (rka->target_key->serial != id)
1200+
rka = request_key_auth_get(instkey);
1201+
if (!rka) {
1202+
ret = -EKEYREVOKED;
12021203
goto error;
1204+
}
1205+
if (rka->target_key->serial != id)
1206+
goto error_put_rka;
12031207

12041208
/* pull the payload in if one was supplied */
12051209
payload = NULL;
@@ -1208,7 +1212,7 @@ static long keyctl_instantiate_key_common(key_serial_t id,
12081212
ret = -ENOMEM;
12091213
payload = kvmalloc(plen, GFP_KERNEL);
12101214
if (!payload)
1211-
goto error;
1215+
goto error_put_rka;
12121216

12131217
ret = -EFAULT;
12141218
if (!copy_from_iter_full(payload, plen, from))
@@ -1234,6 +1238,8 @@ static long keyctl_instantiate_key_common(key_serial_t id,
12341238

12351239
error2:
12361240
kvfree_sensitive(payload, plen);
1241+
error_put_rka:
1242+
request_key_auth_put(rka);
12371243
error:
12381244
return ret;
12391245
}
@@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
13581364
if (!instkey)
13591365
goto error;
13601366

1361-
rka = instkey->payload.data[0];
1362-
if (rka->target_key->serial != id)
1367+
rka = request_key_auth_get(instkey);
1368+
if (!rka) {
1369+
ret = -EKEYREVOKED;
13631370
goto error;
1371+
}
1372+
if (rka->target_key->serial != id)
1373+
goto error_put_rka;
13641374

13651375
/* find the destination keyring if present (which must also be
13661376
* writable) */
13671377
ret = get_instantiation_keyring(ringid, rka, &dest_keyring);
13681378
if (ret < 0)
1369-
goto error;
1379+
goto error_put_rka;
13701380

13711381
/* instantiate the key and link it into a keyring */
13721382
ret = key_reject_and_link(rka->target_key, timeout, error,
@@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
13791389
if (ret == 0)
13801390
keyctl_change_reqkey_auth(NULL);
13811391

1392+
error_put_rka:
1393+
request_key_auth_put(rka);
13821394
error:
13831395
return ret;
13841396
}

security/keys/request_key_auth.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static void request_key_auth_describe(const struct key *, struct seq_file *);
2323
static void request_key_auth_revoke(struct key *);
2424
static void request_key_auth_destroy(struct key *);
2525
static long request_key_auth_read(const struct key *, char *, size_t);
26+
static void request_key_auth_rcu_disposal(struct rcu_head *);
2627

2728
/*
2829
* The request-key authorisation key type definition.
@@ -115,6 +116,31 @@ static void free_request_key_auth(struct request_key_auth *rka)
115116
kfree(rka);
116117
}
117118

119+
/*
120+
* Take a reference to the request-key authorisation payload so callers can
121+
* drop authkey->sem before doing operations that may sleep.
122+
*/
123+
struct request_key_auth *request_key_auth_get(struct key *authkey)
124+
{
125+
struct request_key_auth *rka;
126+
127+
down_read(&authkey->sem);
128+
rka = dereference_key_locked(authkey);
129+
if (rka && !test_bit(KEY_FLAG_REVOKED, &authkey->flags))
130+
refcount_inc(&rka->usage);
131+
else
132+
rka = NULL;
133+
up_read(&authkey->sem);
134+
135+
return rka;
136+
}
137+
138+
void request_key_auth_put(struct request_key_auth *rka)
139+
{
140+
if (rka && refcount_dec_and_test(&rka->usage))
141+
call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
142+
}
143+
118144
/*
119145
* Dispose of the request_key_auth record under RCU conditions
120146
*/
@@ -136,8 +162,10 @@ static void request_key_auth_revoke(struct key *key)
136162
struct request_key_auth *rka = dereference_key_locked(key);
137163

138164
kenter("{%d}", key->serial);
165+
if (!rka)
166+
return;
139167
rcu_assign_keypointer(key, NULL);
140-
call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
168+
request_key_auth_put(rka);
141169
}
142170

143171
/*
@@ -150,7 +178,7 @@ static void request_key_auth_destroy(struct key *key)
150178
kenter("{%d}", key->serial);
151179
if (rka) {
152180
rcu_assign_keypointer(key, NULL);
153-
call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
181+
request_key_auth_put(rka);
154182
}
155183
}
156184

@@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct key *target, const char *op,
174202
rka = kzalloc(sizeof(*rka), GFP_KERNEL);
175203
if (!rka)
176204
goto error;
205+
refcount_set(&rka->usage, 1);
177206
rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL);
178207
if (!rka->callout_info)
179208
goto error_free_rka;

0 commit comments

Comments
 (0)