aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/cred.h
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-10-02 14:24:29 -0400
committerDavid Howells <dhowells@redhat.com>2012-10-02 14:24:29 -0400
commit3a50597de8635cd05133bd12c95681c82fe7b878 (patch)
treed81c3e46dcef80fbaf84fdf1e8f43676625bab8e /include/linux/cred.h
parenta84a921978b7d56e0e4b87ffaca6367429b4d8ff (diff)
KEYS: Make the session and process keyrings per-thread
Make the session keyring per-thread rather than per-process, but still inherited from the parent thread to solve a problem with PAM and gdm. The problem is that join_session_keyring() will reject attempts to change the session keyring of a multithreaded program but gdm is now multithreaded before it gets to the point of starting PAM and running pam_keyinit to create the session keyring. See: https://bugs.freedesktop.org/show_bug.cgi?id=49211 The reason that join_session_keyring() will only change the session keyring under a single-threaded environment is that it's hard to alter the other thread's credentials to effect the change in a multi-threaded program. The problems are such as: (1) How to prevent two threads both running join_session_keyring() from racing. (2) Another thread's credentials may not be modified directly by this process. (3) The number of threads is uncertain whilst we're not holding the appropriate spinlock, making preallocation slightly tricky. (4) We could use TIF_NOTIFY_RESUME and key_replace_session_keyring() to get another thread to replace its keyring, but that means preallocating for each thread. A reasonable way around this is to make the session keyring per-thread rather than per-process and just document that if you want a common session keyring, you must get it before you spawn any threads - which is the current situation anyway. Whilst we're at it, we can the process keyring behave in the same way. This means we can clean up some of the ickyness in the creds code. Basically, after this patch, the session, process and thread keyrings are about inheritance rules only and not about sharing changes of keyring. Reported-by: Mantas M. <grawity@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Ray Strode <rstrode@redhat.com>
Diffstat (limited to 'include/linux/cred.h')
-rw-r--r--include/linux/cred.h17
1 files changed, 2 insertions, 15 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ebbed2ce6637..0142aacb70b7 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -77,21 +77,6 @@ extern int in_group_p(kgid_t);
77extern int in_egroup_p(kgid_t); 77extern int in_egroup_p(kgid_t);
78 78
79/* 79/*
80 * The common credentials for a thread group
81 * - shared by CLONE_THREAD
82 */
83#ifdef CONFIG_KEYS
84struct thread_group_cred {
85 atomic_t usage;
86 pid_t tgid; /* thread group process ID */
87 spinlock_t lock;
88 struct key __rcu *session_keyring; /* keyring inherited over fork */
89 struct key *process_keyring; /* keyring private to this process */
90 struct rcu_head rcu; /* RCU deletion hook */
91};
92#endif
93
94/*
95 * The security context of a task 80 * The security context of a task
96 * 81 *
97 * The parts of the context break down into two categories: 82 * The parts of the context break down into two categories:
@@ -139,6 +124,8 @@ struct cred {
139#ifdef CONFIG_KEYS 124#ifdef CONFIG_KEYS
140 unsigned char jit_keyring; /* default keyring to attach requested 125 unsigned char jit_keyring; /* default keyring to attach requested
141 * keys to */ 126 * keys to */
127 struct key __rcu *session_keyring; /* keyring inherited over fork */
128 struct key *process_keyring; /* keyring private to this process */
142 struct key *thread_keyring; /* keyring private to this thread */ 129 struct key *thread_keyring; /* keyring private to this thread */
143 struct key *request_key_auth; /* assumed request_key authority */ 130 struct key *request_key_auth; /* assumed request_key authority */
144 struct thread_group_cred *tgcred; /* thread-group shared credentials */ 131 struct thread_group_cred *tgcred; /* thread-group shared credentials */