[for-next][PATCH 17/18] tracing: Fix 64-bit and signed histogram fields on 32-bit kernels
From: Steven Rostedt
Date: Fri Oct 16 2026 - 10:34:43 EST
From: Donggeun Yoo <donggeunyoo.kernel@xxxxxxxxx>
DEFINE_HIST_FIELD_FN() reads a trace event field and widens it to the u64
the histogram uses as a key or a value:
type *addr = (type *)(event + hist_field->field->offset);
return (u64)(unsigned long)*addr;
unsigned long is 32 bits on a 32-bit kernel, so the intermediate cast
discards the upper half of a 64-bit field, and widens a signed field by
zero extension from 32 bits rather than sign extension from its own
width. Five of the eight instantiations are wrong there: s64, u64, s32,
s16 and s8.
The cast came in with commit 79e577cbce4c ("tracing: Support string type
key properly"), which also added hist_field_dynstring() and
hist_field_pstring(). Those convert a char * to u64 and do warn without
an unsigned long in between on 32-bit. DEFINE_HIST_FIELD_FN() converts an
integer and never a pointer, so it gains nothing from the cast and only
loses information.
Drop the intermediate cast and let the usual arithmetic conversions widen
*addr according to its own type. unsigned long is 64 bits on LP64, so the
two forms are identical there and 64-bit kernels are unaffected.
Cc: stable@xxxxxxxxxxxxxxx
Link: https://patch.msgid.link/20260917015532.103081-1-donggeunyoo.kernel@xxxxxxxxx
Fixes: 79e577cbce4c ("tracing: Support string type key properly")
Reported-by: sashiko-bot@xxxxxxxxxx
Closes: https://lore.kernel.org/all/20260914054614.82A9B1F000FF@xxxxxxxxxxxxxxx/
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@xxxxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
kernel/trace/trace_events_hist.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index c150e1130a5f..7d3bb7da4dd1 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -466,7 +466,7 @@ static u64 hist_field_unary_minus(struct hist_field *hist_field,
{ \
type *addr = (type *)(event + hist_field->field->offset); \
\
- return (u64)(unsigned long)*addr; \
+ return (u64)*addr; \
}
DEFINE_HIST_FIELD_FN(s64);
--
2.53.0