summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-22 09:06:51 -0400
committerDavid Howells <dhowells@redhat.com>2019-05-22 09:06:51 -0400
commit2e21865faf4fd7ca99eb2ace072c6d618059e342 (patch)
treecb05e816e95bc4785b7c601b2f33d3ad6396e1fc
parenta188339ca5a396acc588e5851ed7e19f66b0ebd9 (diff)
keys: sparse: Fix key_fs[ug]id_changed()
Sparse warnings are incurred by key_fs[ug]id_changed() due to unprotected accesses of tsk->cred, which is marked __rcu. Fix this by passing the new cred struct to these functions from commit_creds() rather than the task pointer. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <jamorris@linux.microsoft.com>
-rw-r--r--include/linux/key.h8
-rw-r--r--kernel/cred.c4
-rw-r--r--security/keys/process_keys.c22
3 files changed, 16 insertions, 18 deletions
diff --git a/include/linux/key.h b/include/linux/key.h
index 7099985e35a9..1f09aad1c98c 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -402,8 +402,8 @@ extern struct ctl_table key_sysctls[];
402 * the userspace interface 402 * the userspace interface
403 */ 403 */
404extern int install_thread_keyring_to_cred(struct cred *cred); 404extern int install_thread_keyring_to_cred(struct cred *cred);
405extern void key_fsuid_changed(struct task_struct *tsk); 405extern void key_fsuid_changed(struct cred *new_cred);
406extern void key_fsgid_changed(struct task_struct *tsk); 406extern void key_fsgid_changed(struct cred *new_cred);
407extern void key_init(void); 407extern void key_init(void);
408 408
409#else /* CONFIG_KEYS */ 409#else /* CONFIG_KEYS */
@@ -418,8 +418,8 @@ extern void key_init(void);
418#define make_key_ref(k, p) NULL 418#define make_key_ref(k, p) NULL
419#define key_ref_to_ptr(k) NULL 419#define key_ref_to_ptr(k) NULL
420#define is_key_possessed(k) 0 420#define is_key_possessed(k) 0
421#define key_fsuid_changed(t) do { } while(0) 421#define key_fsuid_changed(c) do { } while(0)
422#define key_fsgid_changed(t) do { } while(0) 422#define key_fsgid_changed(c) do { } while(0)
423#define key_init() do { } while(0) 423#define key_init() do { } while(0)
424 424
425#endif /* CONFIG_KEYS */ 425#endif /* CONFIG_KEYS */
diff --git a/kernel/cred.c b/kernel/cred.c
index 45d77284aed0..3bd40de9e192 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -455,9 +455,9 @@ int commit_creds(struct cred *new)
455 455
456 /* alter the thread keyring */ 456 /* alter the thread keyring */
457 if (!uid_eq(new->fsuid, old->fsuid)) 457 if (!uid_eq(new->fsuid, old->fsuid))
458 key_fsuid_changed(task); 458 key_fsuid_changed(new);
459 if (!gid_eq(new->fsgid, old->fsgid)) 459 if (!gid_eq(new->fsgid, old->fsgid))
460 key_fsgid_changed(task); 460 key_fsgid_changed(new);
461 461
462 /* do it 462 /* do it
463 * RLIMIT_NPROC limits on user->processes have already been checked 463 * RLIMIT_NPROC limits on user->processes have already been checked
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index f05f7125a7d5..ba5d3172cafe 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -293,28 +293,26 @@ static int install_session_keyring(struct key *keyring)
293/* 293/*
294 * Handle the fsuid changing. 294 * Handle the fsuid changing.
295 */ 295 */
296void key_fsuid_changed(struct task_struct *tsk) 296void key_fsuid_changed(struct cred *new_cred)
297{ 297{
298 /* update the ownership of the thread keyring */ 298 /* update the ownership of the thread keyring */
299 BUG_ON(!tsk->cred); 299 if (new_cred->thread_keyring) {
300 if (tsk->cred->thread_keyring) { 300 down_write(&new_cred->thread_keyring->sem);
301 down_write(&tsk->cred->thread_keyring->sem); 301 new_cred->thread_keyring->uid = new_cred->fsuid;
302 tsk->cred->thread_keyring->uid = tsk->cred->fsuid; 302 up_write(&new_cred->thread_keyring->sem);
303 up_write(&tsk->cred->thread_keyring->sem);
304 } 303 }
305} 304}
306 305
307/* 306/*
308 * Handle the fsgid changing. 307 * Handle the fsgid changing.
309 */ 308 */
310void key_fsgid_changed(struct task_struct *tsk) 309void key_fsgid_changed(struct cred *new_cred)
311{ 310{
312 /* update the ownership of the thread keyring */ 311 /* update the ownership of the thread keyring */
313 BUG_ON(!tsk->cred); 312 if (new_cred->thread_keyring) {
314 if (tsk->cred->thread_keyring) { 313 down_write(&new_cred->thread_keyring->sem);
315 down_write(&tsk->cred->thread_keyring->sem); 314 new_cred->thread_keyring->gid = new_cred->fsgid;
316 tsk->cred->thread_keyring->gid = tsk->cred->fsgid; 315 up_write(&new_cred->thread_keyring->sem);
317 up_write(&tsk->cred->thread_keyring->sem);
318 } 316 }
319} 317}
320 318