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>
This commit is contained in:
David Howells 2019-05-22 14:06:51 +01:00
parent a188339ca5
commit 2e21865faf
3 changed files with 16 additions and 18 deletions

View File

@ -402,8 +402,8 @@ extern struct ctl_table key_sysctls[];
* the userspace interface
*/
extern int install_thread_keyring_to_cred(struct cred *cred);
extern void key_fsuid_changed(struct task_struct *tsk);
extern void key_fsgid_changed(struct task_struct *tsk);
extern void key_fsuid_changed(struct cred *new_cred);
extern void key_fsgid_changed(struct cred *new_cred);
extern void key_init(void);
#else /* CONFIG_KEYS */
@ -418,8 +418,8 @@ extern void key_init(void);
#define make_key_ref(k, p) NULL
#define key_ref_to_ptr(k) NULL
#define is_key_possessed(k) 0
#define key_fsuid_changed(t) do { } while(0)
#define key_fsgid_changed(t) do { } while(0)
#define key_fsuid_changed(c) do { } while(0)
#define key_fsgid_changed(c) do { } while(0)
#define key_init() do { } while(0)
#endif /* CONFIG_KEYS */

View File

@ -455,9 +455,9 @@ int commit_creds(struct cred *new)
/* alter the thread keyring */
if (!uid_eq(new->fsuid, old->fsuid))
key_fsuid_changed(task);
key_fsuid_changed(new);
if (!gid_eq(new->fsgid, old->fsgid))
key_fsgid_changed(task);
key_fsgid_changed(new);
/* do it
* RLIMIT_NPROC limits on user->processes have already been checked

View File

@ -293,28 +293,26 @@ static int install_session_keyring(struct key *keyring)
/*
* Handle the fsuid changing.
*/
void key_fsuid_changed(struct task_struct *tsk)
void key_fsuid_changed(struct cred *new_cred)
{
/* update the ownership of the thread keyring */
BUG_ON(!tsk->cred);
if (tsk->cred->thread_keyring) {
down_write(&tsk->cred->thread_keyring->sem);
tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
up_write(&tsk->cred->thread_keyring->sem);
if (new_cred->thread_keyring) {
down_write(&new_cred->thread_keyring->sem);
new_cred->thread_keyring->uid = new_cred->fsuid;
up_write(&new_cred->thread_keyring->sem);
}
}
/*
* Handle the fsgid changing.
*/
void key_fsgid_changed(struct task_struct *tsk)
void key_fsgid_changed(struct cred *new_cred)
{
/* update the ownership of the thread keyring */
BUG_ON(!tsk->cred);
if (tsk->cred->thread_keyring) {
down_write(&tsk->cred->thread_keyring->sem);
tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
up_write(&tsk->cred->thread_keyring->sem);
if (new_cred->thread_keyring) {
down_write(&new_cred->thread_keyring->sem);
new_cred->thread_keyring->gid = new_cred->fsgid;
up_write(&new_cred->thread_keyring->sem);
}
}