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.
Unified · Split
| @@ -402,8 +402,8 @@ extern struct ctl_table key_sysctls[]; · 401 unmodified lines | |||
| 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); · 8 unmodified lines | |||
| 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 */ |
| @@ -455,9 +455,9 @@ int commit_creds(struct cred *new) · 454 unmodified lines | |||
| 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 |
| @@ -293,28 +293,26 @@ static int install_session_keyring(struct key *keyring) · 292 unmodified lines | |||
| 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 | ||