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 | 402 | * the userspace interface |
| 403 | 403 | */ |
| 404 | 404 | extern int install_thread_keyring_to_cred(struct cred *cred); |
| 405 | −extern void key_fsuid_changed(struct task_struct *tsk); | |
| 406 | −extern void key_fsgid_changed(struct task_struct *tsk); | |
| 405 | +extern void key_fsuid_changed(struct cred *new_cred); | |
| 406 | +extern void key_fsgid_changed(struct cred *new_cred); | |
| 407 | 407 | extern void key_init(void); |
| 408 | 408 | |
| 409 | 409 | #else /* CONFIG_KEYS */ |
| @@ -418,8 +418,8 @@ extern void key_init(void); · 8 unmodified lines | ||
| 418 | 418 | #define make_key_ref(k, p) NULL |
| 419 | 419 | #define key_ref_to_ptr(k) NULL |
| 420 | 420 | #define is_key_possessed(k) 0 |
| 421 | −#define key_fsuid_changed(t) do { } while(0) | |
| 422 | −#define key_fsgid_changed(t) do { } while(0) | |
| 421 | +#define key_fsuid_changed(c) do { } while(0) | |
| 422 | +#define key_fsgid_changed(c) do { } while(0) | |
| 423 | 423 | #define key_init() do { } while(0) |
| 424 | 424 | |
| 425 | 425 | #endif /* CONFIG_KEYS */ |
| @@ -455,9 +455,9 @@ int commit_creds(struct cred *new) · 454 unmodified lines | ||
| 455 | 455 | |
| 456 | 456 | /* alter the thread keyring */ |
| 457 | 457 | if (!uid_eq(new->fsuid, old->fsuid)) |
| 458 | − key_fsuid_changed(task); | |
| 458 | + key_fsuid_changed(new); | |
| 459 | 459 | if (!gid_eq(new->fsgid, old->fsgid)) |
| 460 | − key_fsgid_changed(task); | |
| 460 | + key_fsgid_changed(new); | |
| 461 | 461 | |
| 462 | 462 | /* do it |
| 463 | 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 | 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 | 298 | /* update the ownership of the thread keyring */ |
| 299 | − BUG_ON(!tsk->cred); | |
| 300 | − if (tsk->cred->thread_keyring) { | |
| 301 | − down_write(&tsk->cred->thread_keyring->sem); | |
| 302 | − tsk->cred->thread_keyring->uid = tsk->cred->fsuid; | |
| 303 | − up_write(&tsk->cred->thread_keyring->sem); | |
| 299 | + if (new_cred->thread_keyring) { | |
| 300 | + down_write(&new_cred->thread_keyring->sem); | |
| 301 | + new_cred->thread_keyring->uid = new_cred->fsuid; | |
| 302 | + up_write(&new_cred->thread_keyring->sem); | |
| 304 | 303 | } |
| 305 | 304 | } |
| 306 | 305 | |
| 307 | 306 | /* |
| 308 | 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 | 311 | /* update the ownership of the thread keyring */ |
| 313 | − BUG_ON(!tsk->cred); | |
| 314 | − if (tsk->cred->thread_keyring) { | |
| 315 | − down_write(&tsk->cred->thread_keyring->sem); | |
| 316 | − tsk->cred->thread_keyring->gid = tsk->cred->fsgid; | |
| 317 | − up_write(&tsk->cred->thread_keyring->sem); | |
| 312 | + if (new_cred->thread_keyring) { | |
| 313 | + down_write(&new_cred->thread_keyring->sem); | |
| 314 | + new_cred->thread_keyring->gid = new_cred->fsgid; | |
| 315 | + up_write(&new_cred->thread_keyring->sem); | |
| 318 | 316 | } |
| 319 | 317 | } |
| 320 | 318 | |