NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/60980: rcu_replace_pointer() fails to update the original pointer



>Number:         60980
>Category:       kern
>Synopsis:       rcu_replace_pointer() fails to update the original pointer
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Nov 07 09:40:01 +0000 2026
>Originator:     hoshinomori
>Release:        NetBSD 11.0_STABLE
>Organization:
>Environment:
System: NetBSD xps13-7390-2in1.owarisekai.moe 11.0_STABLE NetBSD 11.0_STABLE (GENERIC) #8: Wed Nov 4 20:13:26 CST 2026 root%xps13-7390-2in1.owarisekai.moe@localhost:/usr/obj/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:
The rcu_replace_pointer() macro in src/sys/external/bsd/common/include/linux/rcupdate.h doesn't update the original pointer.
The macro copy PTRP into a local var __rrp_ptrp and then call rcu_assign_pointer on it instead of the original one.
>How-To-Repeat:
cc rcu_replace_pointer_test.c -o test && ./test
expect output:
returned_old=1 updated_caller=0 still_old=1

=== rcu_replace_pointer_test.c ===
#include <stdio.h>
#define WARN_ON(c) ((void)(c))
#define atomic_store_release(p, v) __atomic_store_n((p), (v), __ATOMIC_RELEASE)

#define	rcu_assign_pointer(P,V)	atomic_store_release(&(P), (V))

#define	rcu_dereference_protected(P, C) ({				      \
	WARN_ON(!(C));							      \
	(P);								      \
})

#define	rcu_replace_pointer(PTRP, NEWPTR, C) ({				      \
	__typeof__(PTRP) __rrp_ptrp = (PTRP);				      \
	__typeof__(PTRP) __rrp_oldptr =					      \
		rcu_dereference_protected(__rrp_ptrp, C);		      \
	rcu_assign_pointer(__rrp_ptrp, NEWPTR);				      \
	__rrp_oldptr;							      \
})

int
main(void)
{
	int old_object = 1, new_object = 2;
	struct { int *engines; } ctx = { &old_object };
	int *ret = rcu_replace_pointer(ctx.engines, &new_object, 1);
	printf("returned_old=%d updated_caller=%d still_old=%d\n",
		ret == &old_object, ctx.engines == &new_object,
		ctx.engines == &old_object);
	return !(ret == &old_object && ctx.engines == &new_object);
}
=== EOF ===

>Fix:
Index: rcupdate.h
===================================================================
RCS file: /cvsroot/src/sys/external/bsd/common/include/linux/rcupdate.h,v
retrieving revision 1.8
diff -u -r1.8 rcupdate.h
--- rcupdate.h	19 Dec 2021 11:49:11 -0000	1.8
+++ rcupdate.h	7 Nov 2026 09:16:14 -0000
@@ -54,10 +54,10 @@
 })
 
 #define	rcu_replace_pointer(PTRP, NEWPTR, C) ({				      \
-	__typeof__(PTRP) __rrp_ptrp = (PTRP);				      \
+	__typeof__(&(PTRP)) __rrp_ptrp = &(PTRP);			      \
 	__typeof__(PTRP) __rrp_oldptr =					      \
-		rcu_dereference_protected(__rrp_ptrp, C);		      \
-	rcu_assign_pointer(__rrp_ptrp, NEWPTR);				      \
+		rcu_dereference_protected(*__rrp_ptrp, C);		      \
+	rcu_assign_pointer(*__rrp_ptrp, NEWPTR);			      \
 	__rrp_oldptr;							      \
 })
 




Home | Main Index | Thread Index | Old Index