diff options
author | David Howells <dhowells@redhat.com> | 2019-05-22 09:06:51 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-22 09:06:51 -0400 |
commit | 2e21865faf4fd7ca99eb2ace072c6d618059e342 (patch) | |
tree | cb05e816e95bc4785b7c601b2f33d3ad6396e1fc | |
parent | a188339ca5a396acc588e5851ed7e19f66b0ebd9 (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.h | 8 | ||||
-rw-r--r-- | kernel/cred.c | 4 | ||||
-rw-r--r-- | security/keys/process_keys.c | 22 |
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 | */ |
404 | extern int install_thread_keyring_to_cred(struct cred *cred); | 404 | extern int install_thread_keyring_to_cred(struct cred *cred); |
405 | extern void key_fsuid_changed(struct task_struct *tsk); | 405 | extern void key_fsuid_changed(struct cred *new_cred); |
406 | extern void key_fsgid_changed(struct task_struct *tsk); | 406 | extern void key_fsgid_changed(struct cred *new_cred); |
407 | extern void key_init(void); | 407 | extern 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 | */ |
296 | void key_fsuid_changed(struct task_struct *tsk) | 296 | void 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 | */ |
310 | void key_fsgid_changed(struct task_struct *tsk) | 309 | void 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 | ||