Bug 205857 - tracing broken for kernels with CONFIG_GCC_PLUGIN_STRUCTLEAK=y due __attribute__ leak to tracefs formats
Summary: tracing broken for kernels with CONFIG_GCC_PLUGIN_STRUCTLEAK=y due __attribut...
Status: NEEDINFO
Alias: None
Product: Tools
Classification: Unclassified
Component: Trace-cmd/Kernelshark (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Steven Rostedt
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-12-14 15:34 UTC by Ivan Prisyazhnyy
Modified: 2020-01-31 19:18 UTC (History)
2 users (show)

See Also:
Kernel Version: 5.x
Tree: Mainline
Regression: No


Attachments
tools lib traceevent: Handle gcc __attribute__(()) in fields (3.01 KB, patch)
2020-01-30 23:56 UTC, Steven Rostedt
Details | Diff

Description Ivan Prisyazhnyy 2019-12-14 15:34:57 UTC
### What

1. `tools/lib/traceevent` can't parse formats with `__attribute__`:

    $ sudo perf record -e syscalls:sys_enter_io_submit -aR
    libtraceevent: No such file or directory
      Error: expected type 4 but read 5

`trace-cmd` fails the same way while reporting.

2. `__attribute__` leaks into syscalls metadata at include/linux/syscalls.h:

    #define SYSCALL_METADATA(sname, nb, ...)

that leads to the leak of the attributes to the `tracefs`
trace events formats.

    $ cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_io_submit/format
    name: sys_enter_io_submit
    ID: 897
    format:
    field:unsigned short common_type; offset:0; size:2; signed:0;
    ...
    field:struct iocb __attribute__((user)) * __attribute__((user)) * iocbpp; offset:32; size:8; signed:0;
                      ^^^                     ^^^
.

### Where

I am a user of Arch Linux. Arch kernels come with `CONFIG_GCC_PLUGIN_STRUCTLEAK=y`. 
This defines `__user __attribute__((user))` that exists already for at least 2 years.

I suppose all kernels since this was introduced and with enabled STRUCTLEAK 
plugin have broken tracing for the syscalls with `__user` arguments.

### Why
 
In kernels built with `CONFIG_GCC_PLUGIN_STRUCTLEAK=y`
definition of macros `__user` differs from the usual one:

If `__CHECKER__` is false at `include/linux/compiler_types.h:28`:

    # ifdef STRUCTLEAK_PLUGIN
    #  define __user __attribute__((user))
    # else
    #  define __user
    # endif

It seems that this fact leads the syscalls metadata macros at
`include/linux/syscalls.h`

    214:#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
    198:#define SYSCALL_METADATA(sname, nb, ...)

to include GGC attributes extensions (`__attribute__`) into the
syscalls metadata that is then delivered to the `tracefs/syscalls/format`.

This gets syscalls formats to have `__attribute__` inside:

    $ cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_io_submit/format
    name: sys_enter_io_submit
    ID: 897
    format:
    field:unsigned short common_type; offset:0; size:2; signed:0;
    ...
    field:struct iocb __attribute__((user)) * __attribute__((user)) * iocbpp; offset:32; size:8; signed:0;
    ...

traceevent library does not support fields format that contains
GCC `__attribute__`, like in the example above.

This in its turn makes it impossible to use tracing for those syscalls:

    $ sudo perf record -e syscalls:sys_enter_io_submit -aR
    libtraceevent: No such file or directory
      Error: expected type 4 but read 5

Thus, tracing does not work for some syscalls in Arch Linux kernels.
And I suppose for all kernels that built with structleak plugin support.

### Test

https://github.com/sitano/traceevent_attribute
Comment 1 Steven Rostedt 2020-01-30 23:56:21 UTC
Created attachment 287037 [details]
tools lib traceevent: Handle gcc __attribute__(()) in fields

Does this patch fix it for you?

Note You need to log in before you can comment on or make changes to this bug.