2022-07-31 19:22:26

by Steven Rostedt

[permalink] [raw]
Subject: [for-next][PATCH 21/21] tracing: Use a struct alignof to determine trace event field alignment

From: "Steven Rostedt (Google)" <[email protected]>

alignof() gives an alignment of types as they would be as standalone
variables. But alignment in structures might be different, and when
building the fields of events, the alignment must be the actual
alignment otherwise the field offsets may not match what they actually
are.

This caused trace-cmd to crash, as libtraceevent did not check if the
field offset was bigger than the event. The write_msr and read_msr
events on 32 bit had their fields incorrect, because it had a u64 field
between two ints. alignof(u64) would give 8, but the u64 field was at a
4 byte alignment.

Define a macro as:

ALIGN_STRUCTFIELD(type) ((int)(offsetof(struct {char a; type b;}, b)))

which gives the actual alignment of types in a structure.

Link: https://lkml.kernel.org/r/[email protected]

Cc: Ingo Molnar <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: [email protected]
Fixes: 04ae87a52074e ("ftrace: Rework event_create_dir()")
Signed-off-by: Steven Rostedt (Google) <[email protected]>
---
include/trace/stages/stage4_event_fields.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/trace/stages/stage4_event_fields.h b/include/trace/stages/stage4_event_fields.h
index c3790ec7a453..80d34f396555 100644
--- a/include/trace/stages/stage4_event_fields.h
+++ b/include/trace/stages/stage4_event_fields.h
@@ -2,16 +2,18 @@

/* Stage 4 definitions for creating trace events */

+#define ALIGN_STRUCTFIELD(type) ((int)(offsetof(struct {char a; type b;}, b)))
+
#undef __field_ext
#define __field_ext(_type, _item, _filter_type) { \
.type = #_type, .name = #_item, \
- .size = sizeof(_type), .align = __alignof__(_type), \
+ .size = sizeof(_type), .align = ALIGN_STRUCTFIELD(_type), \
.is_signed = is_signed_type(_type), .filter_type = _filter_type },

#undef __field_struct_ext
#define __field_struct_ext(_type, _item, _filter_type) { \
.type = #_type, .name = #_item, \
- .size = sizeof(_type), .align = __alignof__(_type), \
+ .size = sizeof(_type), .align = ALIGN_STRUCTFIELD(_type), \
0, .filter_type = _filter_type },

#undef __field
@@ -23,7 +25,7 @@
#undef __array
#define __array(_type, _item, _len) { \
.type = #_type"["__stringify(_len)"]", .name = #_item, \
- .size = sizeof(_type[_len]), .align = __alignof__(_type), \
+ .size = sizeof(_type[_len]), .align = ALIGN_STRUCTFIELD(_type), \
.is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER },

#undef __dynamic_array
--
2.35.1


2022-08-01 08:05:14

by David Laight

[permalink] [raw]
Subject: RE: [for-next][PATCH 21/21] tracing: Use a struct alignof to determine trace event field alignment

From: Steven Rostedt
> Sent: 31 July 2022 20:04
>
> alignof() gives an alignment of types as they would be as standalone
> variables. But alignment in structures might be different, and when
> building the fields of events, the alignment must be the actual
> alignment otherwise the field offsets may not match what they actually
> are.
>
> This caused trace-cmd to crash, as libtraceevent did not check if the
> field offset was bigger than the event. The write_msr and read_msr
> events on 32 bit had their fields incorrect, because it had a u64 field
> between two ints. alignof(u64) would give 8, but the u64 field was at a
> 4 byte alignment.
>
> Define a macro as:
>
> ALIGN_STRUCTFIELD(type) ((int)(offsetof(struct {char a; type b;}, b)))
>
> which gives the actual alignment of types in a structure.

The simpler:
__alignof__(struct {type b;})
also works.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

2022-08-01 21:17:57

by Steven Rostedt

[permalink] [raw]
Subject: Re: [for-next][PATCH 21/21] tracing: Use a struct alignof to determine trace event field alignment

On Mon, 1 Aug 2022 07:46:22 +0000
David Laight <[email protected]> wrote:

> > Define a macro as:
> >
> > ALIGN_STRUCTFIELD(type) ((int)(offsetof(struct {char a; type b;}, b)))
> >
> > which gives the actual alignment of types in a structure.
>
> The simpler:
> __alignof__(struct {type b;})
> also works.

I'll have to try that out.

For now, as the previous version made it through all my tests, I may be
pushing it, but change it to this for simplicity if that also works and
passes all my test.

Thanks,

-- Steve