Re: [PATCH] cred: mark the copy in prepare_creds() as a data race
From: Bradley Morgan
Date: Sat Oct 31 2026 - 22:25:35 EST
On 30 October 2026 03:33:08 GMT, Babanpreet Singh <bbnpreetsingh@xxxxxxxxx>
wrote:
Well! Okay then. Nearly missed this (sigh)
>prepare_creds() copies the old cred while other tasks may be changing
>its refcount. Mark as data race.
It's not the ref count,
Both reports show a 4 byte write 168 bytes into the object:
write to 0xffff888103d7fbe8 of 4 bytes
read to 0xffff888103d7fb40 of 184 bytes
0xfbe8 - 0xfb40 = 0xa8. usage is an atomic_long_t at offset 0, so a hit
there would be 8 bytes at the very start of the struct. What actually
raced is this line of get_cred_many(),
nonconst_cred->non_rcu = 0;
a plain write to a published cred. The atomic_long_add() under it never
shows up, iirc KCSAN models the atomic fine. So non_rcu in the subject
and the description, thats what the fix is about.
>
>Reported-by: syzbot+ee58b040032d8bed63d9@xxxxxxxxxxxxxxxxxxxxxxxxx
>Closes: https://syzkaller.appspot.com/bug?extid=ee58b040032d8bed63d9
>Reported-by: syzbot+557fdc985d6ac3831e14@xxxxxxxxxxxxxxxxxxxxxxxxx
>Closes: https://syzkaller.appspot.com/bug?extid=557fdc985d6ac3831e14
>Assisted-by: Claude:claude-opus-5-5
>Signed-off-by: Babanpreet Singh <bbnpreetsingh@xxxxxxxxx>
>---
>Compile tested with gcc and clang; the KCSAN instrumentation of
>kernel/cred.o was checked before and after.
Sooo? What was the after? Could you have said something like "This bug
isn't reproduced any longer, tested by soandso"
> kernel/cred.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/kernel/cred.c b/kernel/cred.c
>index d01df40a9a386..d212db445c138 100644
>--- a/kernel/cred.c
>+++ b/kernel/cred.c
>@@ -189,7 +189,7 @@ struct cred *prepare_creds(void)
> kdebug("prepare_creds() alloc %p", new);
>
> old = task->cred;
>- memcpy(new, old, sizeof(struct cred));
>+ data_race(memcpy(new, old, sizeof(struct cred)));
Hmmm. Comment..?
WARNING: data_race without comment
#12: FILE: kernel/cred.c:192:
+ data_race(memcpy(new, old, sizeof(struct cred)));
The docs says it plain: "Applications of
data_race() should have a comment so as to document the reasoning behind
why it was deemed safe."
I suggest
/*
* The only fields a published cred can still change are non_rcu and
* usage, and both get set fresh just below. Keeping a copied non_rcu
* would be wrong anyway, __put_cred() then skips the grace period.
*/
data_race(memcpy(new, old, sizeof(struct cred)));
Feel free to bikeshed
prepare_kernel_cred() ALSO does the same copy further down the same file,
*new = *old, off get_task_cred(daemon). Same race, untouched. Did you mean
to leave it out, or has syzbot just not hit it yet?
>
> new->non_rcu = 0;
> atomic_long_set(&new->usage, 1);
>
>base-commit: 881f19c2ffbc73f351b257e09c71e6059939b770
>
--- Thanks!