Skip to content

Commit 69664cf

Browse files
dhowellstorvalds
authored andcommitted
keys: don't generate user and user session keyrings unless they're accessed
Don't generate the per-UID user and user session keyrings unless they're explicitly accessed. This solves a problem during a login process whereby set*uid() is called before the SELinux PAM module, resulting in the per-UID keyrings having the wrong security labels. This also cures the problem of multiple per-UID keyrings sometimes appearing due to PAM modules (including pam_keyinit) setuiding and causing user_structs to come into and go out of existence whilst the session keyring pins the user keyring. This is achieved by first searching for extant per-UID keyrings before inventing new ones. The serial bound argument is also dropped from find_keyring_by_name() as it's not currently made use of (setting it to 0 disables the feature). Signed-off-by: David Howells <dhowells@redhat.com> Cc: <kwc@citi.umich.edu> Cc: <arunsr@cse.iitk.ac.in> Cc: <dwalsh@redhat.com> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Chris Wright <chrisw@sous-sol.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 6b79ccb commit 69664cf

File tree

7 files changed

+96
-145
lines changed

7 files changed

+96
-145
lines changed

include/linux/key.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,6 @@ extern struct key *key_lookup(key_serial_t id);
268268
/*
269269
* the userspace interface
270270
*/
271-
extern struct key root_user_keyring, root_session_keyring;
272-
extern int alloc_uid_keyring(struct user_struct *user,
273-
struct task_struct *ctx);
274271
extern void switch_uid_keyring(struct user_struct *new_user);
275272
extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
276273
extern int copy_thread_group_keys(struct task_struct *tsk);
@@ -299,7 +296,6 @@ extern void key_init(void);
299296
#define make_key_ref(k, p) ({ NULL; })
300297
#define key_ref_to_ptr(k) ({ NULL; })
301298
#define is_key_possessed(k) 0
302-
#define alloc_uid_keyring(u,c) 0
303299
#define switch_uid_keyring(u) do { } while(0)
304300
#define __install_session_keyring(t, k) ({ NULL; })
305301
#define copy_keys(f,t) 0
@@ -312,10 +308,6 @@ extern void key_init(void);
312308
#define key_fsgid_changed(t) do { } while(0)
313309
#define key_init() do { } while(0)
314310

315-
/* Initial keyrings */
316-
extern struct key root_user_keyring;
317-
extern struct key root_session_keyring;
318-
319311
#endif /* CONFIG_KEYS */
320312
#endif /* __KERNEL__ */
321313
#endif /* _LINUX_KEY_H */

kernel/user.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ struct user_struct root_user = {
5353
.files = ATOMIC_INIT(0),
5454
.sigpending = ATOMIC_INIT(0),
5555
.locked_shm = 0,
56-
#ifdef CONFIG_KEYS
57-
.uid_keyring = &root_user_keyring,
58-
.session_keyring = &root_session_keyring,
59-
#endif
6056
#ifdef CONFIG_USER_SCHED
6157
.tg = &init_task_group,
6258
#endif
@@ -420,12 +416,12 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
420416
new->mq_bytes = 0;
421417
#endif
422418
new->locked_shm = 0;
423-
424-
if (alloc_uid_keyring(new, current) < 0)
425-
goto out_free_user;
419+
#ifdef CONFIG_KEYS
420+
new->uid_keyring = new->session_keyring = NULL;
421+
#endif
426422

427423
if (sched_create_user(new) < 0)
428-
goto out_put_keys;
424+
goto out_free_user;
429425

430426
if (uids_user_create(new))
431427
goto out_destoy_sched;
@@ -459,9 +455,6 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
459455

460456
out_destoy_sched:
461457
sched_destroy_user(new);
462-
out_put_keys:
463-
key_put(new->uid_keyring);
464-
key_put(new->session_keyring);
465458
out_free_user:
466459
kmem_cache_free(uid_cachep, new);
467460
out_unlock:

security/keys/internal.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ extern struct mutex key_construction_mutex;
7777
extern wait_queue_head_t request_key_conswq;
7878

7979

80-
extern void keyring_publish_name(struct key *keyring);
81-
8280
extern int __key_link(struct key *keyring, struct key *key);
8381

8482
extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
@@ -102,7 +100,7 @@ extern key_ref_t search_process_keyrings(struct key_type *type,
102100
key_match_func_t match,
103101
struct task_struct *tsk);
104102

105-
extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
103+
extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
106104

107105
extern int install_thread_keyring(struct task_struct *tsk);
108106
extern int install_process_keyring(struct task_struct *tsk);

security/keys/key.c

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Basic authentication token and access key management
22
*
3-
* Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
3+
* Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved.
44
* Written by David Howells (dhowells@redhat.com)
55
*
66
* This program is free software; you can redistribute it and/or
@@ -137,36 +137,6 @@ void key_user_put(struct key_user *user)
137137

138138
} /* end key_user_put() */
139139

140-
/*****************************************************************************/
141-
/*
142-
* insert a key with a fixed serial number
143-
*/
144-
static void __init __key_insert_serial(struct key *key)
145-
{
146-
struct rb_node *parent, **p;
147-
struct key *xkey;
148-
149-
parent = NULL;
150-
p = &key_serial_tree.rb_node;
151-
152-
while (*p) {
153-
parent = *p;
154-
xkey = rb_entry(parent, struct key, serial_node);
155-
156-
if (key->serial < xkey->serial)
157-
p = &(*p)->rb_left;
158-
else if (key->serial > xkey->serial)
159-
p = &(*p)->rb_right;
160-
else
161-
BUG();
162-
}
163-
164-
/* we've found a suitable hole - arrange for this key to occupy it */
165-
rb_link_node(&key->serial_node, parent, p);
166-
rb_insert_color(&key->serial_node, &key_serial_tree);
167-
168-
} /* end __key_insert_serial() */
169-
170140
/*****************************************************************************/
171141
/*
172142
* assign a key the next unique serial number
@@ -1020,17 +990,4 @@ void __init key_init(void)
1020990
rb_insert_color(&root_key_user.node,
1021991
&key_user_tree);
1022992

1023-
/* record root's user standard keyrings */
1024-
key_check(&root_user_keyring);
1025-
key_check(&root_session_keyring);
1026-
1027-
__key_insert_serial(&root_user_keyring);
1028-
__key_insert_serial(&root_session_keyring);
1029-
1030-
keyring_publish_name(&root_user_keyring);
1031-
keyring_publish_name(&root_session_keyring);
1032-
1033-
/* link the two root keyrings together */
1034-
key_link(&root_session_keyring, &root_user_keyring);
1035-
1036993
} /* end key_init() */

security/keys/keyring.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* keyring.c: keyring handling
1+
/* Keyring handling
22
*
3-
* Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
3+
* Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
44
* Written by David Howells (dhowells@redhat.com)
55
*
66
* This program is free software; you can redistribute it and/or
@@ -79,7 +79,7 @@ static DECLARE_RWSEM(keyring_serialise_link_sem);
7979
* publish the name of a keyring so that it can be found by name (if it has
8080
* one)
8181
*/
82-
void keyring_publish_name(struct key *keyring)
82+
static void keyring_publish_name(struct key *keyring)
8383
{
8484
int bucket;
8585

@@ -516,10 +516,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
516516
/*
517517
* find a keyring with the specified name
518518
* - all named keyrings are searched
519-
* - only find keyrings with search permission for the process
520-
* - only find keyrings with a serial number greater than the one specified
519+
* - normally only finds keyrings with search permission for the current process
521520
*/
522-
struct key *find_keyring_by_name(const char *name, key_serial_t bound)
521+
struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
523522
{
524523
struct key *keyring;
525524
int bucket;
@@ -545,15 +544,11 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
545544
if (strcmp(keyring->description, name) != 0)
546545
continue;
547546

548-
if (key_permission(make_key_ref(keyring, 0),
547+
if (!skip_perm_check &&
548+
key_permission(make_key_ref(keyring, 0),
549549
KEY_SEARCH) < 0)
550550
continue;
551551

552-
/* found a potential candidate, but we still need to
553-
* check the serial number */
554-
if (keyring->serial <= bound)
555-
continue;
556-
557552
/* we've got a match */
558553
atomic_inc(&keyring->usage);
559554
read_unlock(&keyring_name_lock);

0 commit comments

Comments
 (0)