Skip to content

Commit 4bdf0bc

Browse files
committed
KEYS: Introduce a search context structure
Search functions pass around a bunch of arguments, each of which gets copied with each call. Introduce a search context structure to hold these. Whilst we're at it, create a search flag that indicates whether the search should be directly to the description or whether it should iterate through all keys looking for a non-description match. This will be useful when keyrings use a generic data struct with generic routines to manage their content as the search terms can just be passed through to the iterator callback function. Also, for future use, the data to be supplied to the match function is separated from the description pointer in the search context. This makes it clear which is being supplied. Signed-off-by: David Howells <dhowells@redhat.com>
1 parent 16feef4 commit 4bdf0bc

File tree

8 files changed

+179
-158
lines changed

8 files changed

+179
-158
lines changed

include/linux/key-type.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ struct key_type {
6363
*/
6464
size_t def_datalen;
6565

66+
/* Default key search algorithm. */
67+
unsigned def_lookup_type;
68+
#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */
69+
#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */
70+
6671
/* vet a description */
6772
int (*vet_description)(const char *description);
6873

security/keys/internal.h

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,23 +107,31 @@ extern struct key *keyring_search_instkey(struct key *keyring,
107107

108108
typedef int (*key_match_func_t)(const struct key *, const void *);
109109

110+
struct keyring_search_context {
111+
struct keyring_index_key index_key;
112+
const struct cred *cred;
113+
key_match_func_t match;
114+
const void *match_data;
115+
unsigned flags;
116+
#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */
117+
#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */
118+
#define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */
119+
#define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */
120+
#define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */
121+
#define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */
122+
123+
/* Internal stuff */
124+
int skipped_ret;
125+
bool possessed;
126+
key_ref_t result;
127+
struct timespec now;
128+
};
129+
110130
extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
111-
const struct cred *cred,
112-
struct key_type *type,
113-
const void *description,
114-
key_match_func_t match,
115-
bool no_state_check);
116-
117-
extern key_ref_t search_my_process_keyrings(struct key_type *type,
118-
const void *description,
119-
key_match_func_t match,
120-
bool no_state_check,
121-
const struct cred *cred);
122-
extern key_ref_t search_process_keyrings(struct key_type *type,
123-
const void *description,
124-
key_match_func_t match,
125-
bool no_state_check,
126-
const struct cred *cred);
131+
struct keyring_search_context *ctx);
132+
133+
extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
134+
extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
127135

128136
extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
129137

security/keys/keyring.c

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,7 @@ EXPORT_SYMBOL(keyring_alloc);
280280
/**
281281
* keyring_search_aux - Search a keyring tree for a key matching some criteria
282282
* @keyring_ref: A pointer to the keyring with possession indicator.
283-
* @cred: The credentials to use for permissions checks.
284-
* @type: The type of key to search for.
285-
* @description: Parameter for @match.
286-
* @match: Function to rule on whether or not a key is the one required.
287-
* @no_state_check: Don't check if a matching key is bad
283+
* @ctx: The keyring search context.
288284
*
289285
* Search the supplied keyring tree for a key that matches the criteria given.
290286
* The root keyring and any linked keyrings must grant Search permission to the
@@ -314,11 +310,7 @@ EXPORT_SYMBOL(keyring_alloc);
314310
* @keyring_ref is propagated to the returned key reference.
315311
*/
316312
key_ref_t keyring_search_aux(key_ref_t keyring_ref,
317-
const struct cred *cred,
318-
struct key_type *type,
319-
const void *description,
320-
key_match_func_t match,
321-
bool no_state_check)
313+
struct keyring_search_context *ctx)
322314
{
323315
struct {
324316
/* Need a separate keylist pointer for RCU purposes */
@@ -328,20 +320,18 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
328320
} stack[KEYRING_SEARCH_MAX_DEPTH];
329321

330322
struct keyring_list *keylist;
331-
struct timespec now;
332323
unsigned long kflags;
333324
struct key *keyring, *key;
334325
key_ref_t key_ref;
335-
bool possessed;
336326
long err;
337327
int sp, nkeys, kix;
338328

339329
keyring = key_ref_to_ptr(keyring_ref);
340-
possessed = is_key_possessed(keyring_ref);
330+
ctx->possessed = is_key_possessed(keyring_ref);
341331
key_check(keyring);
342332

343333
/* top keyring must have search permission to begin the search */
344-
err = key_task_permission(keyring_ref, cred, KEY_SEARCH);
334+
err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
345335
if (err < 0) {
346336
key_ref = ERR_PTR(err);
347337
goto error;
@@ -353,24 +343,25 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
353343

354344
rcu_read_lock();
355345

356-
now = current_kernel_time();
346+
ctx->now = current_kernel_time();
357347
err = -EAGAIN;
358348
sp = 0;
359349

360350
/* firstly we should check to see if this top-level keyring is what we
361351
* are looking for */
362352
key_ref = ERR_PTR(-EAGAIN);
363353
kflags = keyring->flags;
364-
if (keyring->type == type && match(keyring, description)) {
354+
if (keyring->type == ctx->index_key.type &&
355+
ctx->match(keyring, ctx->match_data)) {
365356
key = keyring;
366-
if (no_state_check)
357+
if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
367358
goto found;
368359

369360
/* check it isn't negative and hasn't expired or been
370361
* revoked */
371362
if (kflags & (1 << KEY_FLAG_REVOKED))
372363
goto error_2;
373-
if (key->expiry && now.tv_sec >= key->expiry)
364+
if (key->expiry && ctx->now.tv_sec >= key->expiry)
374365
goto error_2;
375366
key_ref = ERR_PTR(key->type_data.reject_error);
376367
if (kflags & (1 << KEY_FLAG_NEGATIVE))
@@ -384,7 +375,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
384375
if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
385376
(1 << KEY_FLAG_REVOKED) |
386377
(1 << KEY_FLAG_NEGATIVE)) ||
387-
(keyring->expiry && now.tv_sec >= keyring->expiry))
378+
(keyring->expiry && ctx->now.tv_sec >= keyring->expiry))
388379
goto error_2;
389380

390381
/* start processing a new keyring */
@@ -406,29 +397,29 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
406397
kflags = key->flags;
407398

408399
/* ignore keys not of this type */
409-
if (key->type != type)
400+
if (key->type != ctx->index_key.type)
410401
continue;
411402

412403
/* skip invalidated, revoked and expired keys */
413-
if (!no_state_check) {
404+
if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) {
414405
if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
415406
(1 << KEY_FLAG_REVOKED)))
416407
continue;
417408

418-
if (key->expiry && now.tv_sec >= key->expiry)
409+
if (key->expiry && ctx->now.tv_sec >= key->expiry)
419410
continue;
420411
}
421412

422413
/* keys that don't match */
423-
if (!match(key, description))
414+
if (!ctx->match(key, ctx->match_data))
424415
continue;
425416

426417
/* key must have search permissions */
427-
if (key_task_permission(make_key_ref(key, possessed),
428-
cred, KEY_SEARCH) < 0)
418+
if (key_task_permission(make_key_ref(key, ctx->possessed),
419+
ctx->cred, KEY_SEARCH) < 0)
429420
continue;
430421

431-
if (no_state_check)
422+
if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
432423
goto found;
433424

434425
/* we set a different error code if we pass a negative key */
@@ -456,8 +447,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
456447
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
457448
continue;
458449

459-
if (key_task_permission(make_key_ref(key, possessed),
460-
cred, KEY_SEARCH) < 0)
450+
if (key_task_permission(make_key_ref(key, ctx->possessed),
451+
ctx->cred, KEY_SEARCH) < 0)
461452
continue;
462453

463454
/* stack the current position */
@@ -489,12 +480,12 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
489480
/* we found a viable match */
490481
found:
491482
atomic_inc(&key->usage);
492-
key->last_used_at = now.tv_sec;
493-
keyring->last_used_at = now.tv_sec;
483+
key->last_used_at = ctx->now.tv_sec;
484+
keyring->last_used_at = ctx->now.tv_sec;
494485
while (sp > 0)
495-
stack[--sp].keyring->last_used_at = now.tv_sec;
486+
stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
496487
key_check(key);
497-
key_ref = make_key_ref(key, possessed);
488+
key_ref = make_key_ref(key, ctx->possessed);
498489
error_2:
499490
rcu_read_unlock();
500491
error:
@@ -514,11 +505,20 @@ key_ref_t keyring_search(key_ref_t keyring,
514505
struct key_type *type,
515506
const char *description)
516507
{
517-
if (!type->match)
508+
struct keyring_search_context ctx = {
509+
.index_key.type = type,
510+
.index_key.description = description,
511+
.cred = current_cred(),
512+
.match = type->match,
513+
.match_data = description,
514+
.flags = (type->def_lookup_type |
515+
KEYRING_SEARCH_DO_STATE_CHECK),
516+
};
517+
518+
if (!ctx.match)
518519
return ERR_PTR(-ENOKEY);
519520

520-
return keyring_search_aux(keyring, current->cred,
521-
type, description, type->match, false);
521+
return keyring_search_aux(keyring, &ctx);
522522
}
523523
EXPORT_SYMBOL(keyring_search);
524524

security/keys/proc.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ static void proc_keys_stop(struct seq_file *p, void *v)
182182

183183
static int proc_keys_show(struct seq_file *m, void *v)
184184
{
185-
const struct cred *cred = current_cred();
186185
struct rb_node *_p = v;
187186
struct key *key = rb_entry(_p, struct key, serial_node);
188187
struct timespec now;
@@ -191,15 +190,23 @@ static int proc_keys_show(struct seq_file *m, void *v)
191190
char xbuf[12];
192191
int rc;
193192

193+
struct keyring_search_context ctx = {
194+
.index_key.type = key->type,
195+
.index_key.description = key->description,
196+
.cred = current_cred(),
197+
.match = lookup_user_key_possessed,
198+
.match_data = key,
199+
.flags = (KEYRING_SEARCH_NO_STATE_CHECK |
200+
KEYRING_SEARCH_LOOKUP_DIRECT),
201+
};
202+
194203
key_ref = make_key_ref(key, 0);
195204

196205
/* determine if the key is possessed by this process (a test we can
197206
* skip if the key does not indicate the possessor can view it
198207
*/
199208
if (key->perm & KEY_POS_VIEW) {
200-
skey_ref = search_my_process_keyrings(key->type, key,
201-
lookup_user_key_possessed,
202-
true, cred);
209+
skey_ref = search_my_process_keyrings(&ctx);
203210
if (!IS_ERR(skey_ref)) {
204211
key_ref_put(skey_ref);
205212
key_ref = make_key_ref(key, 1);
@@ -211,7 +218,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
211218
* - the caller holds a spinlock, and thus the RCU read lock, making our
212219
* access to __current_cred() safe
213220
*/
214-
rc = key_task_permission(key_ref, cred, KEY_VIEW);
221+
rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW);
215222
if (rc < 0)
216223
return 0;
217224

0 commit comments

Comments
 (0)