Merge tag 'trace-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Jul 2019 18:51:00 +0000 (11:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Jul 2019 18:51:00 +0000 (11:51 -0700)
Pull tracing updates from Steven Rostedt:
 "The main changes in this release include:

   - Add user space specific memory reading for kprobes

   - Allow kprobes to be executed earlier in boot

  The rest are mostly just various clean ups and small fixes"

* tag 'trace-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (33 commits)
  tracing: Make trace_get_fields() global
  tracing: Let filter_assign_type() detect FILTER_PTR_STRING
  tracing: Pass type into tracing_generic_entry_update()
  ftrace/selftest: Test if set_event/ftrace_pid exists before writing
  ftrace/selftests: Return the skip code when tracing directory not configured in kernel
  tracing/kprobe: Check registered state using kprobe
  tracing/probe: Add trace_event_call accesses APIs
  tracing/probe: Add probe event name and group name accesses APIs
  tracing/probe: Add trace flag access APIs for trace_probe
  tracing/probe: Add trace_event_file access APIs for trace_probe
  tracing/probe: Add trace_event_call register API for trace_probe
  tracing/probe: Add trace_probe init and free functions
  tracing/uprobe: Set print format when parsing command
  tracing/kprobe: Set print format right after parsed command
  kprobes: Fix to init kprobes in subsys_initcall
  tracepoint: Use struct_size() in kmalloc()
  ring-buffer: Remove HAVE_64BIT_ALIGNED_ACCESS
  ftrace: Enable trampoline when rec count returns back to one
  tracing/kprobe: Do not run kprobe boot tests if kprobe_event is on cmdline
  tracing: Make a separate config for trace event self tests
  ...

17 files changed:
1  2 
Documentation/admin-guide/kernel-parameters.txt
Documentation/trace/kprobetrace.rst
Documentation/trace/uprobetracer.rst
arch/Kconfig
arch/x86/kernel/ftrace.c
kernel/kprobes.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_uprobe.c
kernel/tracepoint.c
mm/maccess.c
tools/perf/util/probe-event.c
tools/perf/util/probe-file.c
tools/perf/util/probe-finder.c
tools/testing/selftests/ftrace/ftracetest

@@@ -13,7 -13,7 +13,7 @@@
                        For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
                        are available
  
 -                      See also Documentation/power/runtime_pm.txt, pci=noacpi
 +                      See also Documentation/power/runtime_pm.rst, pci=noacpi
  
        acpi_apic_instance=     [ACPI, IOAPIC]
                        Format: <int>
@@@ -53,7 -53,7 +53,7 @@@
                        ACPI_DEBUG_PRINT statements, e.g.,
                            ACPI_DEBUG_PRINT((ACPI_DB_INFO, ...
                        The debug_level mask defaults to "info".  See
 -                      Documentation/acpi/debug.txt for more information about
 +                      Documentation/firmware-guide/acpi/debug.rst for more information about
                        debug layers and levels.
  
                        Enable processor driver info messages:
        acpi_sleep=     [HW,ACPI] Sleep options
                        Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
                                  old_ordering, nonvs, sci_force_enable, nobl }
 -                      See Documentation/power/video.txt for information on
 +                      See Documentation/power/video.rst for information on
                        s3_bios and s3_mode.
                        s3_beep is for debugging; it makes the PC's speaker beep
                        as soon as the kernel's real-mode entry point is called.
  
        blkdevparts=    Manual partition parsing of block device(s) for
                        embedded devices based on command line input.
 -                      See Documentation/block/cmdline-partition.txt
 +                      See Documentation/block/cmdline-partition.rst
  
        boot_delay=     Milliseconds to delay each printk during boot.
                        Values larger than 10 seconds (10000) are changed to
                        others).
  
        ccw_timeout_log [S390]
 -                      See Documentation/s390/CommonIO for details.
 +                      See Documentation/s390/common_io.rst for details.
  
        cgroup_disable= [KNL] Disable a particular controller
                        Format: {name of the controller(s) to disable}
                                /selinux/checkreqprot.
  
        cio_ignore=     [S390]
 -                      See Documentation/s390/CommonIO for details.
 +                      See Documentation/s390/common_io.rst for details.
        clk_ignore_unused
                        [CLK]
                        Prevents the clock framework from automatically gating
                        [KNL, x86_64] select a region under 4G first, and
                        fall back to reserve region above 4G when '@offset'
                        hasn't been specified.
 -                      See Documentation/kdump/kdump.txt for further details.
 +                      See Documentation/admin-guide/kdump/kdump.rst for further details.
  
        crashkernel=range1:size1[,range2:size2,...][@offset]
                        [KNL] Same as above, but depends on the memory
                        in the running system. The syntax of range is
                        start-[end] where start and end are both
                        a memory unit (amount[KMG]). See also
 -                      Documentation/kdump/kdump.txt for an example.
 +                      Documentation/admin-guide/kdump/kdump.rst for an example.
  
        crashkernel=size[KMG],high
                        [KNL, x86_64] range could be above 4G. Allow kernel
                        tracking down these problems.
  
        debug_pagealloc=
 -                      [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
 -                      parameter enables the feature at boot time. In
 -                      default, it is disabled. We can avoid allocating huge
 -                      chunk of memory for debug pagealloc if we don't enable
 -                      it at boot time and the system will work mostly same
 -                      with the kernel built without CONFIG_DEBUG_PAGEALLOC.
 +                      [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this parameter
 +                      enables the feature at boot time. By default, it is
 +                      disabled and the system will work mostly the same as a
 +                      kernel built without CONFIG_DEBUG_PAGEALLOC.
                        on: enable the feature
  
        debugpat        [X86] Enable PAT debugging
                        edid/1680x1050.bin, or edid/1920x1080.bin is given
                        and no file with the same name exists. Details and
                        instructions how to build your own EDID data are
 -                      available in Documentation/EDID/HOWTO.txt. An EDID
 +                      available in Documentation/driver-api/edid.rst. An EDID
                        data set will only be used for a particular connector,
                        if its name and a colon are prepended to the EDID
                        name. Each connector may use a unique EDID data
                        for details.
  
        nompx           [X86] Disables Intel Memory Protection Extensions.
 -                      See Documentation/x86/intel_mpx.txt for more
 +                      See Documentation/x86/intel_mpx.rst for more
                        information about the feature.
  
        nopku           [X86] Disable Memory Protection Keys CPU feature found
                        that is to be dynamically loaded by Linux. If there are
                        multiple variables with the same name but with different
                        vendor GUIDs, all of them will be loaded. See
 -                      Documentation/acpi/ssdt-overlays.txt for details.
 +                      Documentation/admin-guide/acpi/ssdt-overlays.rst for details.
  
  
        eisa_irq_edge=  [PARISC,HW]
  
        elevator=       [IOSCHED]
                        Format: { "mq-deadline" | "kyber" | "bfq" }
 -                      See Documentation/block/deadline-iosched.txt,
 -                      Documentation/block/kyber-iosched.txt and
 -                      Documentation/block/bfq-iosched.txt for details.
 +                      See Documentation/block/deadline-iosched.rst,
 +                      Documentation/block/kyber-iosched.rst and
 +                      Documentation/block/bfq-iosched.rst for details.
  
        elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
                        Specifies physical address of start of kernel core
                        image elf header and optionally the size. Generally
                        kexec loader will pass this option to capture kernel.
 -                      See Documentation/kdump/kdump.txt for details.
 +                      See Documentation/admin-guide/kdump/kdump.rst for details.
  
        enable_mtrr_cleanup [X86]
                        The kernel tries to adjust MTRR layout from continuous
                        See also Documentation/fault-injection/.
  
        floppy=         [HW]
 -                      See Documentation/blockdev/floppy.txt.
 +                      See Documentation/admin-guide/blockdev/floppy.rst.
  
        force_pal_cache_flush
                        [IA-64] Avoid check_sal_cache_flush which may hang on
                        Valid parameters: "on", "off"
                        Default: "on"
  
 -      hisax=          [HW,ISDN]
 -                      See Documentation/isdn/README.HiSax.
 -
        hlt             [BUGS=ARM,SH]
  
        hpet=           [X86-32,HPET] option to control HPET usage
                        Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
                        .vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr
                        .cdrom .chs .ignore_cable are additional options
 -                      See Documentation/ide/ide.txt.
 +                      See Documentation/ide/ide.rst.
  
        ide-generic.probe-mask= [HW] (E)IDE subsystem
                        Format: <int>
  
        initrd=         [BOOT] Specify the location of the initial ramdisk
  
 +      init_on_alloc=  [MM] Fill newly allocated pages and heap objects with
 +                      zeroes.
 +                      Format: 0 | 1
 +                      Default set by CONFIG_INIT_ON_ALLOC_DEFAULT_ON.
 +
 +      init_on_free=   [MM] Fill freed pages and heap objects with zeroes.
 +                      Format: 0 | 1
 +                      Default set by CONFIG_INIT_ON_FREE_DEFAULT_ON.
 +
        init_pkru=      [x86] Specify the default memory protection keys rights
                        register contents for all processes.  0x55555554 by
                        default (disallow access to all but pkey 0).  Can
                        Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
                        the default is off.
  
+       kprobe_event=[probe-list]
+                       [FTRACE] Add kprobe events and enable at boot time.
+                       The probe-list is a semicolon delimited list of probe
+                       definitions. Each definition is same as kprobe_events
+                       interface, but the parameters are comma delimited.
+                       For example, to add a kprobe event on vfs_read with
+                       arg1 and arg2, add to the command line;
+                             kprobe_event=p,vfs_read,$arg1,$arg2
+                       See also Documentation/trace/kprobetrace.rst "Kernel
+                       Boot Parameter" section.
        kpti=           [ARM64] Control page table isolation of user
                        and kernel address spaces.
                        Default: enabled on cores which need mitigation.
        memblock=debug  [KNL] Enable memblock debug messages.
  
        load_ramdisk=   [RAM] List of ramdisks to load from floppy
 -                      See Documentation/blockdev/ramdisk.txt.
 +                      See Documentation/admin-guide/blockdev/ramdisk.rst.
  
        lockd.nlm_grace_period=P  [NFS] Assign grace period.
                        Format: <integer>
  
        mce             [X86-32] Machine Check Exception
  
 -      mce=option      [X86-64] See Documentation/x86/x86_64/boot-options.txt
 +      mce=option      [X86-64] See Documentation/x86/x86_64/boot-options.rst
  
        md=             [HW] RAID subsystems devices and level
                        See Documentation/admin-guide/md.rst.
                        set according to the
                        CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
                        option.
 -                      See Documentation/memory-hotplug.txt.
 +                      See Documentation/admin-guide/mm/memory-hotplug.rst.
  
        memmap=exactmap [KNL,X86] Enable setting of an exact
                        E820 memory map, as specified by the user.
                        mem_encrypt=on:         Activate SME
                        mem_encrypt=off:        Do not activate SME
  
 -                      Refer to Documentation/x86/amd-memory-encryption.txt
 +                      Refer to Documentation/virtual/kvm/amd-memory-encryption.rst
                        for details on when memory encryption can be activated.
  
        mem_sleep_default=      [SUSPEND] Default system suspend mode:
                        0 - turn hardlockup detector in nmi_watchdog off
                        1 - turn hardlockup detector in nmi_watchdog on
                        When panic is specified, panic when an NMI watchdog
 -                      timeout occurs (or 'nopanic' to override the opposite
 -                      default). To disable both hard and soft lockup detectors,
 +                      timeout occurs (or 'nopanic' to not panic on an NMI
 +                      watchdog, if CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is set)
 +                      To disable both hard and soft lockup detectors,
                        please see 'nowatchdog'.
                        This is useful when you use a panic=... timeout and
                        need the box quickly up again.
                        /sys/module/printk/parameters/console_suspend) to
                        turn on/off it dynamically.
  
 +      novmcoredd      [KNL,KDUMP]
 +                      Disable device dump. Device dump allows drivers to
 +                      append dump data to vmcore so you can collect driver
 +                      specified debug info.  Drivers can append the data
 +                      without any limit and this data is stored in memory,
 +                      so this may cause significant memory stress.  Disabling
 +                      device dump can help save memory but the driver debug
 +                      data will be no longer available.  This parameter
 +                      is only available when CONFIG_PROC_VMCORE_DEVICE_DUMP
 +                      is set.
 +
        noaliencache    [MM, NUMA, SLAB] Disables the allocation of alien
                        caches in the slab allocator.  Saves per-node memory,
                        but will impact performance.
                        register save and restore. The kernel will only save
                        legacy floating-point registers on task switch.
  
 -      nohugeiomap     [KNL,x86] Disable kernel huge I/O mappings.
 +      nohugeiomap     [KNL,x86,PPC] Disable kernel huge I/O mappings.
  
        nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
                        Equivalent to smt=1.
        numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
                        'node', 'default' can be specified
                        This can be set from sysctl after boot.
 -                      See Documentation/sysctl/vm.txt for details.
 +                      See Documentation/admin-guide/sysctl/vm.rst for details.
  
        ohci1394_dma=early      [HW] enable debugging via the ohci1394 driver.
                        See Documentation/debugging-via-ohci1394.txt for more
  
        pcd.            [PARIDE]
                        See header of drivers/block/paride/pcd.c.
 -                      See also Documentation/blockdev/paride.txt.
 +                      See also Documentation/admin-guide/blockdev/paride.rst.
  
        pci=option[,option...]  [PCI] various PCI subsystem options.
  
                        needed on a platform with proper driver support.
  
        pd.             [PARIDE]
 -                      See Documentation/blockdev/paride.txt.
 +                      See Documentation/admin-guide/blockdev/paride.rst.
  
        pdcchassis=     [PARISC,HW] Disable/Enable PDC Chassis Status codes at
                        boot time.
                        and performance comparison.
  
        pf.             [PARIDE]
 -                      See Documentation/blockdev/paride.txt.
 +                      See Documentation/admin-guide/blockdev/paride.rst.
  
        pg.             [PARIDE]
 -                      See Documentation/blockdev/paride.txt.
 +                      See Documentation/admin-guide/blockdev/paride.rst.
  
        pirq=           [SMP,APIC] Manual mp-table setup
 -                      See Documentation/x86/i386/IO-APIC.txt.
 +                      See Documentation/x86/i386/IO-APIC.rst.
  
        plip=           [PPT,NET] Parallel port network link
                        Format: { parport<nr> | timid | 0 }
  
        prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
                        before loading.
 -                      See Documentation/blockdev/ramdisk.txt.
 +                      See Documentation/admin-guide/blockdev/ramdisk.rst.
  
        psi=            [KNL] Enable or disable pressure stall information
                        tracking.
        pstore.backend= Specify the name of the pstore backend to use
  
        pt.             [PARIDE]
 -                      See Documentation/blockdev/paride.txt.
 +                      See Documentation/admin-guide/blockdev/paride.rst.
  
        pti=            [X86_64] Control Page Table Isolation of user and
                        kernel address spaces.  Disabling this feature
                        See Documentation/admin-guide/md.rst.
  
        ramdisk_size=   [RAM] Sizes of RAM disks in kilobytes
 -                      See Documentation/blockdev/ramdisk.txt.
 +                      See Documentation/admin-guide/blockdev/ramdisk.rst.
  
        random.trust_cpu={on,off}
                        [KNL] Enable or disable trusting the use of the
                        the propagation of recent CPU-hotplug changes up
                        the rcu_node combining tree.
  
 +      rcutree.use_softirq=    [KNL]
 +                      If set to zero, move all RCU_SOFTIRQ processing to
 +                      per-CPU rcuc kthreads.  Defaults to a non-zero
 +                      value, meaning that RCU_SOFTIRQ is used by default.
 +                      Specify rcutree.use_softirq=0 to use rcuc kthreads.
 +
        rcutree.rcu_fanout_exact= [KNL]
                        Disable autobalancing of the rcu_node combining
                        tree.  This is used by rcutorture, and might
  
        relax_domain_level=
                        [KNL, SMP] Set scheduler's default relax_domain_level.
 -                      See Documentation/cgroup-v1/cpusets.txt.
 +                      See Documentation/admin-guide/cgroup-v1/cpusets.rst.
  
        reserve=        [KNL,BUGS] Force kernel to ignore I/O ports or memory
                        Format: <base1>,<size1>[,<base2>,<size2>,...]
                        Specify the offset from the beginning of the partition
                        given by "resume=" at which the swap header is located,
                        in <PAGE_SIZE> units (needed only for swap files).
 -                      See  Documentation/power/swsusp-and-swap-files.txt
 +                      See  Documentation/power/swsusp-and-swap-files.rst
  
        resumedelay=    [HIBERNATION] Delay (in seconds) to pause before attempting to
                        read the resume files
                        Format: <integer>
  
        sonypi.*=       [HW] Sony Programmable I/O Control Device driver
 -                      See Documentation/laptops/sonypi.txt
 +                      See Documentation/admin-guide/laptops/sonypi.rst
  
        spectre_v2=     [X86] Control mitigation of Spectre variant 2
                        (indirect branch speculation) vulnerability.
        swapaccount=[0|1]
                        [KNL] Enable accounting of swap in memory resource
                        controller if no parameter or 1 is given or disable
 -                      it if 0 is given (See Documentation/cgroup-v1/memory.txt)
 +                      it if 0 is given (See Documentation/admin-guide/cgroup-v1/memory.rst)
  
        swiotlb=        [ARM,IA-64,PPC,MIPS,X86]
                        Format: { <int> | force | noforce }
                        vector=percpu: enable percpu vector domain
  
        video=          [FB] Frame buffer configuration
 -                      See Documentation/fb/modedb.txt.
 +                      See Documentation/fb/modedb.rst.
  
        video.brightness_switch_enabled= [0,1]
                        If set to 1, on receiving an ACPI notify event
                        Can be used multiple times for multiple devices.
  
        vga=            [BOOT,X86-32] Select a particular video mode
 -                      See Documentation/x86/boot.txt and
 -                      Documentation/svga.txt.
 +                      See Documentation/x86/boot.rst and
 +                      Documentation/admin-guide/svga.rst.
                        Use vga=ask for menu.
                        This is actually a boot loader parameter; the value is
                        passed to the kernel using a special protocol.
                        targets for exploits that can control RIP.
  
                        emulate     [default] Vsyscalls turn into traps and are
 -                                  emulated reasonably safely.
 +                                  emulated reasonably safely.  The vsyscall
 +                                  page is readable.
  
 -                      native      Vsyscalls are native syscall instructions.
 -                                  This is a little bit faster than trapping
 -                                  and makes a few dynamic recompilers work
 -                                  better than they would in emulation mode.
 -                                  It also makes exploits much easier to write.
 +                      xonly       Vsyscalls turn into traps and are
 +                                  emulated reasonably safely.  The vsyscall
 +                                  page is not readable.
  
                        none        Vsyscalls don't work at all.  This makes
                                    them quite hard to use for exploits but
                        Default: 3 = cyan.
  
        watchdog timers [HW,WDT] For information on watchdog timers,
 -                      see Documentation/watchdog/watchdog-parameters.txt
 +                      see Documentation/watchdog/watchdog-parameters.rst
                        or other driver-specific files in the
                        Documentation/watchdog/ directory.
  
                        Format:
                        <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
  
 +      xive=           [PPC]
 +                      By default on POWER9 and above, the kernel will
 +                      natively use the XIVE interrupt controller. This option
 +                      allows the fallback firmware mode to be used:
 +
 +                      off       Fallback to firmware control of XIVE interrupt
 +                                controller on both pseries and powernv
 +                                platforms. Only useful on POWER9 and above.
 +
        xhci-hcd.quirks         [USB,KNL]
                        A hex value specifying bitmask with supplemental xhci
                        host controller quirks. Meaning of each bit can be
@@@ -51,15 -51,17 +51,17 @@@ Synopsis of kprobe_event
    $argN               : Fetch the Nth function argument. (N >= 1) (\*1)
    $retval     : Fetch return value.(\*2)
    $comm               : Fetch current task comm.
-   +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(\*3)
+   +|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*3)(\*4)
    NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
    FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
                  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
-                 (x8/x16/x32/x64), "string" and bitfield are supported.
+                 (x8/x16/x32/x64), "string", "ustring" and bitfield
+                 are supported.
  
    (\*1) only for the probe on function entry (offs == 0).
    (\*2) only for return probe.
    (\*3) this is useful for fetching a field of data structures.
+   (\*4) "u" means user-space dereference. See :ref:`user_mem_access`.
  
  Types
  -----
@@@ -77,7 -79,8 +79,8 @@@ apply it to registers/stack-entries etc
  wrong, but '+8($stack):x8[8]' is OK.)
  String type is a special type, which fetches a "null-terminated" string from
  kernel space. This means it will fail and store NULL if the string container
- has been paged out.
+ has been paged out. "ustring" type is an alternative of string for user-space.
+ See :ref:`user_mem_access` for more info..
  The string array type is a bit different from other types. For other base
  types, <base-type>[1] is equal to <base-type> (e.g. +0(%di):x32[1] is same
  as +0(%di):x32.) But string[1] is not equal to string. The string type itself
@@@ -92,6 -95,25 +95,25 @@@ Symbol type('symbol') is an alias of u3
  which shows given pointer in "symbol+offset" style.
  For $comm, the default type is "string"; any other type is invalid.
  
+ .. _user_mem_access:
+ User Memory Access
+ ------------------
+ Kprobe events supports user-space memory access. For that purpose, you can use
+ either user-space dereference syntax or 'ustring' type.
+ The user-space dereference syntax allows you to access a field of a data
+ structure in user-space. This is done by adding the "u" prefix to the
+ dereference syntax. For example, +u4(%si) means it will read memory from the
+ address in the register %si offset by 4, and the memory is expected to be in
+ user-space. You can use this for strings too, e.g. +u0(%si):string will read
+ a string from the address in the register %si that is expected to be in user-
+ space. 'ustring' is a shortcut way of performing the same task. That is,
+ +0(%si):ustring is equivalent to +u0(%si):string.
+ Note that kprobe-event provides the user-memory access syntax but it doesn't
+ use it transparently. This means if you use normal dereference or string type
+ for user memory, it might fail, and may always fail on some archs. The user
+ has to carefully check if the target data is in kernel or user space.
  
  Per-Probe Event Filtering
  -------------------------
@@@ -124,6 -146,20 +146,20 @@@ You can check the total number of prob
  The first column is event name, the second is the number of probe hits,
  the third is the number of probe miss-hits.
  
+ Kernel Boot Parameter
+ ---------------------
+ You can add and enable new kprobe events when booting up the kernel by
+ "kprobe_event=" parameter. The parameter accepts a semicolon-delimited
+ kprobe events, which format is similar to the kprobe_events.
+ The difference is that the probe definition parameters are comma-delimited
+ instead of space. For example, adding myprobe event on do_sys_open like below
+   p:myprobe do_sys_open dfd=%ax filename=%dx flags=%cx mode=+4($stack)
+ should be below for kernel boot parameter (just replace spaces with comma)
+   p:myprobe,do_sys_open,dfd=%ax,filename=%dx,flags=%cx,mode=+4($stack)
  
  Usage examples
  --------------
@@@ -189,13 -225,6 +225,13 @@@ events, you need to enable it
    echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
    echo 1 > /sys/kernel/debug/tracing/events/kprobes/myretprobe/enable
  
 +Use the following command to start tracing in an interval.
 +::
 +
 +    # echo 1 > tracing_on
 +    Open something...
 +    # echo 0 > tracing_on
 +
  And you can see the traced information via /sys/kernel/debug/tracing/trace.
  ::
  
@@@ -42,16 -42,18 +42,18 @@@ Synopsis of uprobe_trace
     @+OFFSET   : Fetch memory at OFFSET (OFFSET from same file as PATH)
     $stackN    : Fetch Nth entry of stack (N >= 0)
     $stack     : Fetch stack address.
-    $retval    : Fetch return value.(*)
+    $retval    : Fetch return value.(\*1)
     $comm      : Fetch current task comm.
-    +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
+    +|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*2)(\*3)
     NAME=FETCHARG     : Set NAME as the argument name of FETCHARG.
     FETCHARG:TYPE     : Set TYPE as the type of FETCHARG. Currently, basic types
                       (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
                       (x8/x16/x32/x64), "string" and bitfield are supported.
  
-   (*) only for return probe.
-   (**) this is useful for fetching a field of data structures.
+   (\*1) only for return probe.
+   (\*2) this is useful for fetching a field of data structures.
+   (\*3) Unlike kprobe event, "u" prefix will just be ignored, becuse uprobe
+         events can access only user-space memory.
  
  Types
  -----
@@@ -152,15 -154,10 +154,15 @@@ events, you need to enable it by:
  
      # echo 1 > events/uprobes/enable
  
 -Lets disable the event after sleeping for some time.
 +Lets start tracing, sleep for some time and stop tracing.
  ::
  
 +    # echo 1 > tracing_on
      # sleep 20
 +    # echo 0 > tracing_on
 +
 +Also, you can disable the event by::
 +
      # echo 0 > events/uprobes/enable
  
  And you can see the traced information via /sys/kernel/debug/tracing/trace.
diff --combined arch/Kconfig
@@@ -128,22 -128,6 +128,6 @@@ config UPROBE
            managed by the kernel and kept transparent to the probed
            application. )
  
- config HAVE_64BIT_ALIGNED_ACCESS
-       def_bool 64BIT && !HAVE_EFFICIENT_UNALIGNED_ACCESS
-       help
-         Some architectures require 64 bit accesses to be 64 bit
-         aligned, which also requires structs containing 64 bit values
-         to be 64 bit aligned too. This includes some 32 bit
-         architectures which can do 64 bit accesses, as well as 64 bit
-         architectures without unaligned access.
-         This symbol should be selected by an architecture if 64 bit
-         accesses are required to be 64 bit aligned in this way even
-         though it is not a 64 bit architecture.
-         See Documentation/unaligned-memory-access.txt for more
-         information on the topic of unaligned memory accesses.
  config HAVE_EFFICIENT_UNALIGNED_ACCESS
        bool
        help
@@@ -260,14 -244,6 +244,14 @@@ config ARCH_HAS_SET_MEMOR
  config ARCH_HAS_SET_DIRECT_MAP
        bool
  
 +#
 +# Select if arch has an uncached kernel segment and provides the
 +# uncached_kernel_address / cached_kernel_address symbols to use it
 +#
 +config ARCH_HAS_UNCACHED_SEGMENT
 +      select ARCH_HAS_DMA_PREP_COHERENT
 +      bool
 +
  # Select if arch init_task must go in the __init_task_data section
  config ARCH_TASK_STRUCT_ON_STACK
         bool
diff --combined arch/x86/kernel/ftrace.c
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/init.h>
  #include <linux/list.h>
  #include <linux/module.h>
 +#include <linux/memory.h>
  
  #include <trace/syscall.h>
  
  #ifdef CONFIG_DYNAMIC_FTRACE
  
  int ftrace_arch_code_modify_prepare(void)
 +    __acquires(&text_mutex)
  {
 +      /*
 +       * Need to grab text_mutex to prevent a race from module loading
 +       * and live kernel patching from changing the text permissions while
 +       * ftrace has it set to "read/write".
 +       */
 +      mutex_lock(&text_mutex);
        set_kernel_text_rw();
        set_all_modules_text_rw();
        return 0;
  }
  
  int ftrace_arch_code_modify_post_process(void)
 +    __releases(&text_mutex)
  {
        set_all_modules_text_ro();
        set_kernel_text_ro();
 +      mutex_unlock(&text_mutex);
        return 0;
  }
  
@@@ -310,6 -300,7 +310,6 @@@ int ftrace_int3_handler(struct pt_regs 
  
        ip = regs->ip - INT3_INSN_SIZE;
  
 -#ifdef CONFIG_X86_64
        if (ftrace_location(ip)) {
                int3_emulate_call(regs, (unsigned long)ftrace_regs_caller);
                return 1;
                int3_emulate_call(regs, ftrace_update_func_call);
                return 1;
        }
 -#else
 -      if (ftrace_location(ip) || is_ftrace_caller(ip)) {
 -              int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);
 -              return 1;
 -      }
 -#endif
  
        return 0;
  }
@@@ -373,7 -370,7 +373,7 @@@ static int add_brk_on_nop(struct dyn_ft
        return add_break(rec->ip, old);
  }
  
- static int add_breakpoints(struct dyn_ftrace *rec, int enable)
+ static int add_breakpoints(struct dyn_ftrace *rec, bool enable)
  {
        unsigned long ftrace_addr;
        int ret;
@@@ -481,7 -478,7 +481,7 @@@ static int add_update_nop(struct dyn_ft
        return add_update_code(ip, new);
  }
  
- static int add_update(struct dyn_ftrace *rec, int enable)
+ static int add_update(struct dyn_ftrace *rec, bool enable)
  {
        unsigned long ftrace_addr;
        int ret;
@@@ -527,7 -524,7 +527,7 @@@ static int finish_update_nop(struct dyn
        return ftrace_write(ip, new, 1);
  }
  
- static int finish_update(struct dyn_ftrace *rec, int enable)
+ static int finish_update(struct dyn_ftrace *rec, bool enable)
  {
        unsigned long ftrace_addr;
        int ret;
diff --combined kernel/kprobes.c
@@@ -1,8 -1,21 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   *  Kernel Probes (KProbes)
   *  kernel/kprobes.c
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - *
   * Copyright (C) IBM Corporation, 2002, 2004
   *
   * 2002-Oct   Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
@@@ -2276,6 -2289,7 +2276,7 @@@ static int __init init_kprobes(void
                init_test_probes();
        return err;
  }
+ subsys_initcall(init_kprobes);
  
  #ifdef CONFIG_DEBUG_FS
  static void report_probe(struct seq_file *pi, struct kprobe *p,
@@@ -2570,23 -2584,34 +2571,21 @@@ static const struct file_operations fop
  
  static int __init debugfs_kprobe_init(void)
  {
 -      struct dentry *dir, *file;
 +      struct dentry *dir;
        unsigned int value = 1;
  
        dir = debugfs_create_dir("kprobes", NULL);
 -      if (!dir)
 -              return -ENOMEM;
  
 -      file = debugfs_create_file("list", 0400, dir, NULL,
 -                              &debugfs_kprobes_operations);
 -      if (!file)
 -              goto error;
 +      debugfs_create_file("list", 0400, dir, NULL,
 +                          &debugfs_kprobes_operations);
  
 -      file = debugfs_create_file("enabled", 0600, dir,
 -                                      &value, &fops_kp);
 -      if (!file)
 -              goto error;
 +      debugfs_create_file("enabled", 0600, dir, &value, &fops_kp);
  
 -      file = debugfs_create_file("blacklist", 0400, dir, NULL,
 -                              &debugfs_kprobe_blacklist_ops);
 -      if (!file)
 -              goto error;
 +      debugfs_create_file("blacklist", 0400, dir, NULL,
 +                          &debugfs_kprobe_blacklist_ops);
  
        return 0;
 -
 -error:
 -      debugfs_remove(dir);
 -      return -ENOMEM;
  }
  
  late_initcall(debugfs_kprobe_init);
  #endif /* CONFIG_DEBUG_FS */
- module_init(init_kprobes);
diff --combined kernel/trace/Kconfig
@@@ -1,4 -1,3 +1,4 @@@
 +# SPDX-License-Identifier: GPL-2.0-only
  #
  # Architectures that offer an FUNCTION_TRACER implementation should
  #  select HAVE_FUNCTION_TRACER:
@@@ -597,9 -596,19 +597,19 @@@ config FTRACE_STARTUP_TES
          functioning properly. It will do tests on all the configured
          tracers of ftrace.
  
+ config EVENT_TRACE_STARTUP_TEST
+       bool "Run selftest on trace events"
+       depends on FTRACE_STARTUP_TEST
+       default y
+       help
+         This option performs a test on all trace events in the system.
+         It basically just enables each event and runs some code that
+         will trigger events (not necessarily the event it enables)
+         This may take some time run as there are a lot of events.
  config EVENT_TRACE_TEST_SYSCALLS
        bool "Run selftest on syscall events"
-       depends on FTRACE_STARTUP_TEST
+       depends on EVENT_TRACE_STARTUP_TEST
        help
         This option will also enable testing every syscall event.
         It only enables the event and disables it and runs various loads
diff --combined kernel/trace/ftrace.c
@@@ -1622,6 -1622,11 +1622,11 @@@ static bool test_rec_ops_needs_regs(str
        return  keep_regs;
  }
  
+ static struct ftrace_ops *
+ ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
+ static struct ftrace_ops *
+ ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
  static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
                                     int filter_hash,
                                     bool inc)
                        }
  
                        /*
-                        * If the rec had TRAMP enabled, then it needs to
-                        * be cleared. As TRAMP can only be enabled iff
-                        * there is only a single ops attached to it.
-                        * In otherwords, always disable it on decrementing.
-                        * In the future, we may set it if rec count is
-                        * decremented to one, and the ops that is left
-                        * has a trampoline.
+                        * The TRAMP needs to be set only if rec count
+                        * is decremented to one, and the ops that is
+                        * left has a trampoline. As TRAMP can only be
+                        * enabled if there is only a single ops attached
+                        * to it.
                         */
-                       rec->flags &= ~FTRACE_FL_TRAMP;
+                       if (ftrace_rec_count(rec) == 1 &&
+                           ftrace_find_tramp_ops_any(rec))
+                               rec->flags |= FTRACE_FL_TRAMP;
+                       else
+                               rec->flags &= ~FTRACE_FL_TRAMP;
  
                        /*
                         * flags will be cleared in ftrace_check_record()
                count++;
  
                /* Must match FTRACE_UPDATE_CALLS in ftrace_modify_all_code() */
-               update |= ftrace_test_record(rec, 1) != FTRACE_UPDATE_IGNORE;
+               update |= ftrace_test_record(rec, true) != FTRACE_UPDATE_IGNORE;
  
                /* Shortcut, if we handled all records, we are done. */
                if (!all && count == hash->count)
@@@ -1951,11 -1958,6 +1958,6 @@@ static void print_ip_ins(const char *fm
                printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
  }
  
- static struct ftrace_ops *
- ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
- static struct ftrace_ops *
- ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
  enum ftrace_bug_type ftrace_bug_type;
  const void *ftrace_expected;
  
@@@ -2047,7 -2049,7 +2049,7 @@@ void ftrace_bug(int failed, struct dyn_
        }
  }
  
- static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
+ static int ftrace_check_record(struct dyn_ftrace *rec, bool enable, bool update)
  {
        unsigned long flag = 0UL;
  
  /**
   * ftrace_update_record, set a record that now is tracing or not
   * @rec: the record to update
-  * @enable: set to 1 if the record is tracing, zero to force disable
+  * @enable: set to true if the record is tracing, false to force disable
   *
   * The records that represent all functions that can be traced need
   * to be updated when tracing has been enabled.
   */
- int ftrace_update_record(struct dyn_ftrace *rec, int enable)
+ int ftrace_update_record(struct dyn_ftrace *rec, bool enable)
  {
-       return ftrace_check_record(rec, enable, 1);
+       return ftrace_check_record(rec, enable, true);
  }
  
  /**
   * ftrace_test_record, check if the record has been enabled or not
   * @rec: the record to test
-  * @enable: set to 1 to check if enabled, 0 if it is disabled
+  * @enable: set to true to check if enabled, false if it is disabled
   *
   * The arch code may need to test if a record is already set to
   * tracing to determine how to modify the function code that it
   * represents.
   */
- int ftrace_test_record(struct dyn_ftrace *rec, int enable)
+ int ftrace_test_record(struct dyn_ftrace *rec, bool enable)
  {
-       return ftrace_check_record(rec, enable, 0);
+       return ftrace_check_record(rec, enable, false);
  }
  
  static struct ftrace_ops *
@@@ -2356,7 -2358,7 +2358,7 @@@ unsigned long ftrace_get_addr_curr(stru
  }
  
  static int
- __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
+ __ftrace_replace_code(struct dyn_ftrace *rec, bool enable)
  {
        unsigned long ftrace_old_addr;
        unsigned long ftrace_addr;
@@@ -2395,7 -2397,7 +2397,7 @@@ void __weak ftrace_replace_code(int mod
  {
        struct dyn_ftrace *rec;
        struct ftrace_page *pg;
-       int enable = mod_flags & FTRACE_MODIFY_ENABLE_FL;
+       bool enable = mod_flags & FTRACE_MODIFY_ENABLE_FL;
        int schedulable = mod_flags & FTRACE_MODIFY_MAY_SLEEP_FL;
        int failed;
  
@@@ -2935,13 -2937,14 +2937,13 @@@ static int ftrace_update_code(struct mo
                        p = &pg->records[i];
                        p->flags = rec_flags;
  
 -#ifndef CC_USING_NOP_MCOUNT
                        /*
                         * Do the initial record conversion from mcount jump
                         * to the NOP instructions.
                         */
 -                      if (!ftrace_code_disable(mod, p))
 +                      if (!__is_defined(CC_USING_NOP_MCOUNT) &&
 +                          !ftrace_code_disable(mod, p))
                                break;
 -#endif
  
                        update_cnt++;
                }
@@@ -4220,13 -4223,10 +4222,13 @@@ void free_ftrace_func_mapper(struct ftr
        struct ftrace_func_entry *entry;
        struct ftrace_func_map *map;
        struct hlist_head *hhd;
 -      int size = 1 << mapper->hash.size_bits;
 -      int i;
 +      int size, i;
 +
 +      if (!mapper)
 +              return;
  
        if (free_func && mapper->hash.count) {
 +              size = 1 << mapper->hash.size_bits;
                for (i = 0; i < size; i++) {
                        hhd = &mapper->hash.buckets[i];
                        hlist_for_each_entry(entry, hhd, hlist) {
diff --combined kernel/trace/trace.c
@@@ -366,7 -366,7 +366,7 @@@ trace_ignore_this_task(struct trace_pid
  }
  
  /**
-  * trace_pid_filter_add_remove_task - Add or remove a task from a pid_list
+  * trace_filter_add_remove_task - Add or remove a task from a pid_list
   * @pid_list: The list to modify
   * @self: The current task for fork or NULL for exit
   * @task: The task to add or remove
@@@ -743,8 -743,7 +743,7 @@@ trace_event_setup(struct ring_buffer_ev
  {
        struct trace_entry *ent = ring_buffer_event_data(event);
  
-       tracing_generic_entry_update(ent, flags, pc);
-       ent->type = type;
+       tracing_generic_entry_update(ent, type, flags, pc);
  }
  
  static __always_inline struct ring_buffer_event *
@@@ -2312,13 -2311,14 +2311,14 @@@ enum print_line_t trace_handle_return(s
  EXPORT_SYMBOL_GPL(trace_handle_return);
  
  void
- tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
-                            int pc)
+ tracing_generic_entry_update(struct trace_entry *entry, unsigned short type,
+                            unsigned long flags, int pc)
  {
        struct task_struct *tsk = current;
  
        entry->preempt_count            = pc & 0xff;
        entry->pid                      = (tsk) ? tsk->pid : 0;
+       entry->type                     = type;
        entry->flags =
  #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
                (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@@ -4842,12 -4842,13 +4842,13 @@@ static const char readme_msg[] 
        "\t     args: <name>=fetcharg[:type]\n"
        "\t fetcharg: %<register>, @<address>, @<symbol>[+|-<offset>],\n"
  #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
-       "\t           $stack<index>, $stack, $retval, $comm, $arg<N>\n"
+       "\t           $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
  #else
-       "\t           $stack<index>, $stack, $retval, $comm\n"
+       "\t           $stack<index>, $stack, $retval, $comm,\n"
  #endif
+       "\t           +|-[u]<offset>(<fetcharg>)\n"
        "\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
-       "\t           b<bit-width>@<bit-offset>/<container-size>,\n"
+       "\t           b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
        "\t           <type>\\[<array-size>\\]\n"
  #ifdef CONFIG_HIST_TRIGGERS
        "\t    field: <stype> <name>;\n"
@@@ -6719,13 -6720,11 +6720,13 @@@ tracing_snapshot_write(struct file *fil
                        break;
                }
  #endif
 -              if (!tr->allocated_snapshot) {
 +              if (tr->allocated_snapshot)
 +                      ret = resize_buffer_duplicate_size(&tr->max_buffer,
 +                                      &tr->trace_buffer, iter->cpu_file);
 +              else
                        ret = tracing_alloc_snapshot_instance(tr);
 -                      if (ret < 0)
 -                              break;
 -              }
 +              if (ret < 0)
 +                      break;
                local_irq_disable();
                /* Now, we're going to swap */
                if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
@@@ -6925,7 -6924,7 +6926,7 @@@ struct tracing_log_err 
  
  static DEFINE_MUTEX(tracing_err_log_lock);
  
 -struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
 +static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
  {
        struct tracing_log_err *err;
  
@@@ -7128,24 -7127,12 +7129,24 @@@ static ssize_t tracing_err_log_write(st
        return count;
  }
  
 +static int tracing_err_log_release(struct inode *inode, struct file *file)
 +{
 +      struct trace_array *tr = inode->i_private;
 +
 +      trace_array_put(tr);
 +
 +      if (file->f_mode & FMODE_READ)
 +              seq_release(inode, file);
 +
 +      return 0;
 +}
 +
  static const struct file_operations tracing_err_log_fops = {
        .open           = tracing_err_log_open,
        .write          = tracing_err_log_write,
        .read           = seq_read,
        .llseek         = seq_lseek,
 -      .release        = tracing_release_generic_tr,
 +      .release        = tracing_err_log_release,
  };
  
  static int tracing_buffers_open(struct inode *inode, struct file *filp)
@@@ -8206,7 -8193,7 +8207,7 @@@ static const struct file_operations buf
        .llseek         = default_llseek,
  };
  
 -struct dentry *trace_instance_dir;
 +static struct dentry *trace_instance_dir;
  
  static void
  init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer);
@@@ -8618,6 -8605,10 +8619,6 @@@ struct dentry *tracing_init_dentry(void
         */
        tr->dir = debugfs_create_automount("tracing", NULL,
                                           trace_automount, NULL);
 -      if (!tr->dir) {
 -              pr_warn_once("Could not create debugfs directory 'tracing'\n");
 -              return ERR_PTR(-ENOMEM);
 -      }
  
        return NULL;
  }
@@@ -428,7 -428,7 +428,7 @@@ predicate_parse(const char *str, int nr
        op_stack = kmalloc_array(nr_parens, sizeof(*op_stack), GFP_KERNEL);
        if (!op_stack)
                return ERR_PTR(-ENOMEM);
 -      prog_stack = kmalloc_array(nr_preds, sizeof(*prog_stack), GFP_KERNEL);
 +      prog_stack = kcalloc(nr_preds, sizeof(*prog_stack), GFP_KERNEL);
        if (!prog_stack) {
                parse_error(pe, -ENOMEM, 0);
                goto out_free;
  out_free:
        kfree(op_stack);
        kfree(inverts);
 -      kfree(prog_stack);
 +      if (prog_stack) {
 +              for (i = 0; prog_stack[i].pred; i++)
 +                      kfree(prog_stack[i].pred);
 +              kfree(prog_stack);
 +      }
        return ERR_PTR(ret);
  }
  
@@@ -1084,6 -1080,9 +1084,9 @@@ int filter_assign_type(const char *type
        if (strchr(type, '[') && strstr(type, "char"))
                return FILTER_STATIC_STRING;
  
+       if (strcmp(type, "char *") == 0 || strcmp(type, "const char *") == 0)
+               return FILTER_PTR_STRING;
        return FILTER_OTHER;
  }
  
@@@ -140,6 -140,13 +140,13 @@@ probe_mem_read(void *dest, void *src, s
  
        return copy_from_user(dest, vaddr, size) ? -EFAULT : 0;
  }
+ static nokprobe_inline int
+ probe_mem_read_user(void *dest, void *src, size_t size)
+ {
+       return probe_mem_read(dest, src, size);
+ }
  /*
   * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
   * length and relative data location.
@@@ -176,6 -183,12 +183,12 @@@ fetch_store_string(unsigned long addr, 
        return ret;
  }
  
+ static nokprobe_inline int
+ fetch_store_string_user(unsigned long addr, void *dest, void *base)
+ {
+       return fetch_store_string(addr, dest, base);
+ }
  /* Return the length of string -- including null terminal byte */
  static nokprobe_inline int
  fetch_store_strlen(unsigned long addr)
        return (len > MAX_STRING_SIZE) ? 0 : len;
  }
  
+ static nokprobe_inline int
+ fetch_store_strlen_user(unsigned long addr)
+ {
+       return fetch_store_strlen(addr);
+ }
  static unsigned long translate_user_vaddr(unsigned long file_offset)
  {
        unsigned long base_addr;
@@@ -270,8 -289,8 +289,8 @@@ static bool trace_uprobe_match(const ch
  {
        struct trace_uprobe *tu = to_trace_uprobe(ev);
  
-       return strcmp(trace_event_name(&tu->tp.call), event) == 0 &&
-               (!system || strcmp(tu->tp.call.class->system, system) == 0);
+       return strcmp(trace_probe_name(&tu->tp), event) == 0 &&
+           (!system || strcmp(trace_probe_group_name(&tu->tp), system) == 0);
  }
  
  /*
@@@ -281,25 -300,17 +300,17 @@@ static struct trace_uprobe 
  alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
  {
        struct trace_uprobe *tu;
-       if (!event || !group)
-               return ERR_PTR(-EINVAL);
+       int ret;
  
        tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
        if (!tu)
                return ERR_PTR(-ENOMEM);
  
-       tu->tp.call.class = &tu->tp.class;
-       tu->tp.call.name = kstrdup(event, GFP_KERNEL);
-       if (!tu->tp.call.name)
-               goto error;
-       tu->tp.class.system = kstrdup(group, GFP_KERNEL);
-       if (!tu->tp.class.system)
+       ret = trace_probe_init(&tu->tp, event, group);
+       if (ret < 0)
                goto error;
  
        dyn_event_init(&tu->devent, &trace_uprobe_ops);
-       INIT_LIST_HEAD(&tu->tp.files);
        tu->consumer.handler = uprobe_dispatcher;
        if (is_ret)
                tu->consumer.ret_handler = uretprobe_dispatcher;
        return tu;
  
  error:
-       kfree(tu->tp.call.name);
        kfree(tu);
  
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(ret);
  }
  
  static void free_trace_uprobe(struct trace_uprobe *tu)
  {
-       int i;
        if (!tu)
                return;
  
-       for (i = 0; i < tu->tp.nr_args; i++)
-               traceprobe_free_probe_arg(&tu->tp.args[i]);
        path_put(&tu->path);
-       kfree(tu->tp.call.class->system);
-       kfree(tu->tp.call.name);
+       trace_probe_cleanup(&tu->tp);
        kfree(tu->filename);
        kfree(tu);
  }
@@@ -336,8 -340,8 +340,8 @@@ static struct trace_uprobe *find_probe_
        struct trace_uprobe *tu;
  
        for_each_trace_uprobe(tu, pos)
-               if (strcmp(trace_event_name(&tu->tp.call), event) == 0 &&
-                   strcmp(tu->tp.call.class->system, group) == 0)
+               if (strcmp(trace_probe_name(&tu->tp), event) == 0 &&
+                   strcmp(trace_probe_group_name(&tu->tp), group) == 0)
                        return tu;
  
        return NULL;
@@@ -372,8 -376,8 +376,8 @@@ static struct trace_uprobe *find_old_tr
        struct trace_uprobe *tmp, *old = NULL;
        struct inode *new_inode = d_real_inode(new->path.dentry);
  
-       old = find_probe_event(trace_event_name(&new->tp.call),
-                               new->tp.call.class->system);
+       old = find_probe_event(trace_probe_name(&new->tp),
+                               trace_probe_group_name(&new->tp));
  
        for_each_trace_uprobe(tmp, pos) {
                if ((old ? old != tmp : true) &&
@@@ -426,6 -430,8 +430,6 @@@ end
  /*
   * Argument syntax:
   *  - Add uprobe: p|r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS]
 - *
 - *  - Remove uprobe: -:[GRP/]EVENT
   */
  static int trace_uprobe_create(int argc, const char **argv)
  {
        ret = 0;
        ref_ctr_offset = 0;
  
 -      /* argc must be >= 1 */
 -      if (argv[0][0] == 'r')
 +      switch (argv[0][0]) {
 +      case 'r':
                is_return = true;
 -      else if (argv[0][0] != 'p' || argc < 2)
 +              break;
 +      case 'p':
 +              break;
 +      default:
 +              return -ECANCELED;
 +      }
 +
 +      if (argc < 2)
                return -ECANCELED;
  
        if (argv[0][1] == ':')
                        goto error;
        }
  
+       ret = traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu));
+       if (ret < 0)
+               goto error;
        ret = register_trace_uprobe(tu);
        if (!ret)
                goto out;
@@@ -621,8 -624,8 +629,8 @@@ static int trace_uprobe_show(struct seq
        char c = is_ret_probe(tu) ? 'r' : 'p';
        int i;
  
-       seq_printf(m, "%c:%s/%s %s:0x%0*lx", c, tu->tp.call.class->system,
-                       trace_event_name(&tu->tp.call), tu->filename,
+       seq_printf(m, "%c:%s/%s %s:0x%0*lx", c, trace_probe_group_name(&tu->tp),
+                       trace_probe_name(&tu->tp), tu->filename,
                        (int)(sizeof(void *) * 2), tu->offset);
  
        if (tu->ref_ctr_offset)
@@@ -692,7 -695,7 +700,7 @@@ static int probes_profile_seq_show(stru
  
        tu = to_trace_uprobe(ev);
        seq_printf(m, "  %s %-44s %15lu\n", tu->filename,
-                       trace_event_name(&tu->tp.call), tu->nhit);
+                       trace_probe_name(&tu->tp), tu->nhit);
        return 0;
  }
  
@@@ -818,7 -821,7 +826,7 @@@ static void __uprobe_trace_func(struct 
        struct ring_buffer *buffer;
        void *data;
        int size, esize;
-       struct trace_event_call *call = &tu->tp.call;
+       struct trace_event_call *call = trace_probe_event_call(&tu->tp);
  
        WARN_ON(call != trace_file->event_call);
  
@@@ -860,7 -863,7 +868,7 @@@ static int uprobe_trace_func(struct tra
                return 0;
  
        rcu_read_lock();
-       list_for_each_entry_rcu(link, &tu->tp.files, list)
+       trace_probe_for_each_link_rcu(link, &tu->tp)
                __uprobe_trace_func(tu, 0, regs, ucb, dsize, link->file);
        rcu_read_unlock();
  
@@@ -874,7 -877,7 +882,7 @@@ static void uretprobe_trace_func(struc
        struct event_file_link *link;
  
        rcu_read_lock();
-       list_for_each_entry_rcu(link, &tu->tp.files, list)
+       trace_probe_for_each_link_rcu(link, &tu->tp)
                __uprobe_trace_func(tu, func, regs, ucb, dsize, link->file);
        rcu_read_unlock();
  }
@@@ -893,12 -896,12 +901,12 @@@ print_uprobe_event(struct trace_iterato
  
        if (is_ret_probe(tu)) {
                trace_seq_printf(s, "%s: (0x%lx <- 0x%lx)",
-                                trace_event_name(&tu->tp.call),
+                                trace_probe_name(&tu->tp),
                                 entry->vaddr[1], entry->vaddr[0]);
                data = DATAOF_TRACE_ENTRY(entry, true);
        } else {
                trace_seq_printf(s, "%s: (0x%lx)",
-                                trace_event_name(&tu->tp.call),
+                                trace_probe_name(&tu->tp),
                                 entry->vaddr[0]);
                data = DATAOF_TRACE_ENTRY(entry, false);
        }
@@@ -921,26 -924,20 +929,20 @@@ probe_event_enable(struct trace_uprobe 
                   filter_func_t filter)
  {
        bool enabled = trace_probe_is_enabled(&tu->tp);
-       struct event_file_link *link = NULL;
        int ret;
  
        if (file) {
-               if (tu->tp.flags & TP_FLAG_PROFILE)
+               if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
                        return -EINTR;
  
-               link = kmalloc(sizeof(*link), GFP_KERNEL);
-               if (!link)
-                       return -ENOMEM;
-               link->file = file;
-               list_add_tail_rcu(&link->list, &tu->tp.files);
-               tu->tp.flags |= TP_FLAG_TRACE;
+               ret = trace_probe_add_file(&tu->tp, file);
+               if (ret < 0)
+                       return ret;
        } else {
-               if (tu->tp.flags & TP_FLAG_TRACE)
+               if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
                        return -EINTR;
  
-               tu->tp.flags |= TP_FLAG_PROFILE;
+               trace_probe_set_flag(&tu->tp, TP_FLAG_PROFILE);
        }
  
        WARN_ON(!uprobe_filter_is_empty(&tu->filter));
        uprobe_buffer_disable();
  
   err_flags:
-       if (file) {
-               list_del(&link->list);
-               kfree(link);
-               tu->tp.flags &= ~TP_FLAG_TRACE;
-       } else {
-               tu->tp.flags &= ~TP_FLAG_PROFILE;
-       }
+       if (file)
+               trace_probe_remove_file(&tu->tp, file);
+       else
+               trace_probe_clear_flag(&tu->tp, TP_FLAG_PROFILE);
        return ret;
  }
  
@@@ -987,26 -982,18 +987,18 @@@ probe_event_disable(struct trace_uprob
                return;
  
        if (file) {
-               struct event_file_link *link;
-               link = find_event_file_link(&tu->tp, file);
-               if (!link)
+               if (trace_probe_remove_file(&tu->tp, file) < 0)
                        return;
  
-               list_del_rcu(&link->list);
-               /* synchronize with u{,ret}probe_trace_func */
-               synchronize_rcu();
-               kfree(link);
-               if (!list_empty(&tu->tp.files))
+               if (trace_probe_is_enabled(&tu->tp))
                        return;
-       }
+       } else
+               trace_probe_clear_flag(&tu->tp, TP_FLAG_PROFILE);
  
        WARN_ON(!uprobe_filter_is_empty(&tu->filter));
  
        uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
        tu->inode = NULL;
-       tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE;
  
        uprobe_buffer_disable();
  }
@@@ -1126,7 -1113,7 +1118,7 @@@ static void __uprobe_perf_func(struct t
                               unsigned long func, struct pt_regs *regs,
                               struct uprobe_cpu_buffer *ucb, int dsize)
  {
-       struct trace_event_call *call = &tu->tp.call;
+       struct trace_event_call *call = trace_probe_event_call(&tu->tp);
        struct uprobe_trace_entry_head *entry;
        struct hlist_head *head;
        void *data;
@@@ -1279,11 -1266,11 +1271,11 @@@ static int uprobe_dispatcher(struct upr
        ucb = uprobe_buffer_get();
        store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
  
-       if (tu->tp.flags & TP_FLAG_TRACE)
+       if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
                ret |= uprobe_trace_func(tu, regs, ucb, dsize);
  
  #ifdef CONFIG_PERF_EVENTS
-       if (tu->tp.flags & TP_FLAG_PROFILE)
+       if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
                ret |= uprobe_perf_func(tu, regs, ucb, dsize);
  #endif
        uprobe_buffer_put(ucb);
@@@ -1314,11 -1301,11 +1306,11 @@@ static int uretprobe_dispatcher(struct 
        ucb = uprobe_buffer_get();
        store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
  
-       if (tu->tp.flags & TP_FLAG_TRACE)
+       if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
                uretprobe_trace_func(tu, func, regs, ucb, dsize);
  
  #ifdef CONFIG_PERF_EVENTS
-       if (tu->tp.flags & TP_FLAG_PROFILE)
+       if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
                uretprobe_perf_func(tu, func, regs, ucb, dsize);
  #endif
        uprobe_buffer_put(ucb);
@@@ -1329,57 -1316,28 +1321,28 @@@ static struct trace_event_functions upr
        .trace          = print_uprobe_event
  };
  
- static inline void init_trace_event_call(struct trace_uprobe *tu,
-                                        struct trace_event_call *call)
+ static inline void init_trace_event_call(struct trace_uprobe *tu)
  {
-       INIT_LIST_HEAD(&call->class->fields);
+       struct trace_event_call *call = trace_probe_event_call(&tu->tp);
        call->event.funcs = &uprobe_funcs;
        call->class->define_fields = uprobe_event_define_fields;
  
 -      call->flags = TRACE_EVENT_FL_UPROBE;
 +      call->flags = TRACE_EVENT_FL_UPROBE | TRACE_EVENT_FL_CAP_ANY;
        call->class->reg = trace_uprobe_register;
        call->data = tu;
  }
  
  static int register_uprobe_event(struct trace_uprobe *tu)
  {
-       struct trace_event_call *call = &tu->tp.call;
-       int ret = 0;
-       init_trace_event_call(tu, call);
-       if (traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0)
-               return -ENOMEM;
+       init_trace_event_call(tu);
  
-       ret = register_trace_event(&call->event);
-       if (!ret) {
-               kfree(call->print_fmt);
-               return -ENODEV;
-       }
-       ret = trace_add_event_call(call);
-       if (ret) {
-               pr_info("Failed to register uprobe event: %s\n",
-                       trace_event_name(call));
-               kfree(call->print_fmt);
-               unregister_trace_event(&call->event);
-       }
-       return ret;
+       return trace_probe_register_event_call(&tu->tp);
  }
  
  static int unregister_uprobe_event(struct trace_uprobe *tu)
  {
-       int ret;
-       /* tu->event is unregistered in trace_remove_event_call() */
-       ret = trace_remove_event_call(&tu->tp.call);
-       if (ret)
-               return ret;
-       kfree(tu->tp.call.print_fmt);
-       tu->tp.call.print_fmt = NULL;
-       return 0;
+       return trace_probe_unregister_event_call(&tu->tp);
  }
  
  #ifdef CONFIG_PERF_EVENTS
@@@ -1419,14 -1377,14 +1382,14 @@@ create_local_trace_uprobe(char *name, u
        tu->path = path;
        tu->ref_ctr_offset = ref_ctr_offset;
        tu->filename = kstrdup(name, GFP_KERNEL);
-       init_trace_event_call(tu, &tu->tp.call);
+       init_trace_event_call(tu);
  
        if (traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0) {
                ret = -ENOMEM;
                goto error;
        }
  
-       return &tu->tp.call;
+       return trace_probe_event_call(&tu->tp);
  error:
        free_trace_uprobe(tu);
        return ERR_PTR(ret);
@@@ -1438,9 -1396,6 +1401,6 @@@ void destroy_local_trace_uprobe(struct 
  
        tu = container_of(event_call, struct trace_uprobe, tp.call);
  
-       kfree(tu->tp.call.print_fmt);
-       tu->tp.call.print_fmt = NULL;
        free_trace_uprobe(tu);
  }
  #endif /* CONFIG_PERF_EVENTS */
diff --combined kernel/tracepoint.c
@@@ -1,6 -1,19 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2008-2014 Mathieu Desnoyers
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   */
  #include <linux/module.h>
  #include <linux/mutex.h>
@@@ -55,8 -68,8 +55,8 @@@ struct tp_probes 
  
  static inline void *allocate_probes(int count)
  {
-       struct tp_probes *p  = kmalloc(count * sizeof(struct tracepoint_func)
-                       + sizeof(struct tp_probes), GFP_KERNEL);
+       struct tp_probes *p  = kmalloc(struct_size(p, probes, count),
+                                      GFP_KERNEL);
        return p == NULL ? NULL : p->probes;
  }
  
diff --combined mm/maccess.c
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Access kernel memory without faulting.
   */
@@@ -6,8 -5,20 +6,20 @@@
  #include <linux/mm.h>
  #include <linux/uaccess.h>
  
+ static __always_inline long
+ probe_read_common(void *dst, const void __user *src, size_t size)
+ {
+       long ret;
+       pagefault_disable();
+       ret = __copy_from_user_inatomic(dst, src, size);
+       pagefault_enable();
+       return ret ? -EFAULT : 0;
+ }
  /**
-  * probe_kernel_read(): safely attempt to read from a location
+  * probe_kernel_read(): safely attempt to read from a kernel-space location
   * @dst: pointer to the buffer that shall take the data
   * @src: address to read from
   * @size: size of the data chunk
@@@ -30,16 -41,40 +42,40 @@@ long __probe_kernel_read(void *dst, con
        mm_segment_t old_fs = get_fs();
  
        set_fs(KERNEL_DS);
-       pagefault_disable();
-       ret = __copy_from_user_inatomic(dst,
-                       (__force const void __user *)src, size);
-       pagefault_enable();
+       ret = probe_read_common(dst, (__force const void __user *)src, size);
        set_fs(old_fs);
  
-       return ret ? -EFAULT : 0;
+       return ret;
  }
  EXPORT_SYMBOL_GPL(probe_kernel_read);
  
+ /**
+  * probe_user_read(): safely attempt to read from a user-space location
+  * @dst: pointer to the buffer that shall take the data
+  * @src: address to read from. This must be a user address.
+  * @size: size of the data chunk
+  *
+  * Safely read from user address @src to the buffer at @dst. If a kernel fault
+  * happens, handle that and return -EFAULT.
+  */
+ long __weak probe_user_read(void *dst, const void __user *src, size_t size)
+     __attribute__((alias("__probe_user_read")));
+ long __probe_user_read(void *dst, const void __user *src, size_t size)
+ {
+       long ret = -EFAULT;
+       mm_segment_t old_fs = get_fs();
+       set_fs(USER_DS);
+       if (access_ok(src, size))
+               ret = probe_read_common(dst, src, size);
+       set_fs(old_fs);
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(probe_user_read);
  /**
   * probe_kernel_write(): safely attempt to write to a location
   * @dst: address to write to
@@@ -67,6 -102,7 +103,7 @@@ long __probe_kernel_write(void *dst, co
  }
  EXPORT_SYMBOL_GPL(probe_kernel_write);
  
  /**
   * strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
   * @dst:   Destination address, in kernel space.  This buffer must be at
@@@ -106,3 -142,76 +143,76 @@@ long strncpy_from_unsafe(char *dst, con
  
        return ret ? -EFAULT : src - unsafe_addr;
  }
+ /**
+  * strncpy_from_unsafe_user: - Copy a NUL terminated string from unsafe user
+  *                            address.
+  * @dst:   Destination address, in kernel space.  This buffer must be at
+  *         least @count bytes long.
+  * @unsafe_addr: Unsafe user address.
+  * @count: Maximum number of bytes to copy, including the trailing NUL.
+  *
+  * Copies a NUL-terminated string from unsafe user address to kernel buffer.
+  *
+  * On success, returns the length of the string INCLUDING the trailing NUL.
+  *
+  * If access fails, returns -EFAULT (some data may have been copied
+  * and the trailing NUL added).
+  *
+  * If @count is smaller than the length of the string, copies @count-1 bytes,
+  * sets the last byte of @dst buffer to NUL and returns @count.
+  */
+ long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
+                             long count)
+ {
+       mm_segment_t old_fs = get_fs();
+       long ret;
+       if (unlikely(count <= 0))
+               return 0;
+       set_fs(USER_DS);
+       pagefault_disable();
+       ret = strncpy_from_user(dst, unsafe_addr, count);
+       pagefault_enable();
+       set_fs(old_fs);
+       if (ret >= count) {
+               ret = count;
+               dst[ret - 1] = '\0';
+       } else if (ret > 0) {
+               ret++;
+       }
+       return ret;
+ }
+ /**
+  * strnlen_unsafe_user: - Get the size of a user string INCLUDING final NUL.
+  * @unsafe_addr: The string to measure.
+  * @count: Maximum count (including NUL)
+  *
+  * Get the size of a NUL-terminated string in user space without pagefault.
+  *
+  * Returns the size of the string INCLUDING the terminating NUL.
+  *
+  * If the string is too long, returns a number larger than @count. User
+  * has to check the return value against "> count".
+  * On exception (or invalid count), returns 0.
+  *
+  * Unlike strnlen_user, this can be used from IRQ handler etc. because
+  * it disables pagefaults.
+  */
+ long strnlen_unsafe_user(const void __user *unsafe_addr, long count)
+ {
+       mm_segment_t old_fs = get_fs();
+       int ret;
+       set_fs(USER_DS);
+       pagefault_disable();
+       ret = strnlen_user(unsafe_addr, count);
+       pagefault_enable();
+       set_fs(old_fs);
+       return ret;
+ }
@@@ -1,8 -1,22 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * probe-event.c : perf-probe definition to probe_events format converter
   *
   * Written by Masami Hiramatsu <mhiramat@redhat.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - *
   */
  
  #include <inttypes.h>
@@@ -19,6 -33,7 +19,6 @@@
  #include <limits.h>
  #include <elf.h>
  
 -#include "util.h"
  #include "event.h"
  #include "namespaces.h"
  #include "strlist.h"
@@@ -38,8 -53,7 +38,8 @@@
  #include "session.h"
  #include "string2.h"
  
 -#include "sane_ctype.h"
 +#include <linux/ctype.h>
 +#include <linux/zalloc.h>
  
  #define PERFPROBE_GROUP "probe"
  
@@@ -214,9 -228,9 +214,9 @@@ out
  
  static void clear_perf_probe_point(struct perf_probe_point *pp)
  {
 -      free(pp->file);
 -      free(pp->function);
 -      free(pp->lazy_line);
 +      zfree(&pp->file);
 +      zfree(&pp->function);
 +      zfree(&pp->lazy_line);
  }
  
  static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
@@@ -1175,11 -1189,12 +1175,11 @@@ int show_available_vars(struct perf_pro
  
  void line_range__clear(struct line_range *lr)
  {
 -      free(lr->function);
 -      free(lr->file);
 -      free(lr->path);
 -      free(lr->comp_dir);
 +      zfree(&lr->function);
 +      zfree(&lr->file);
 +      zfree(&lr->path);
 +      zfree(&lr->comp_dir);
        intlist__delete(lr->line_list);
 -      memset(lr, 0, sizeof(*lr));
  }
  
  int line_range__init(struct line_range *lr)
@@@ -1562,6 -1577,17 +1562,17 @@@ static int parse_perf_probe_arg(char *s
                str = tmp + 1;
        }
  
+       tmp = strchr(str, '@');
+       if (tmp && tmp != str && strcmp(tmp + 1, "user")) { /* user attr */
+               if (!user_access_is_supported()) {
+                       semantic_error("ftrace does not support user access\n");
+                       return -EINVAL;
+               }
+               *tmp = '\0';
+               arg->user_access = true;
+               pr_debug("user_access ");
+       }
        tmp = strchr(str, ':');
        if (tmp) {      /* Type setting */
                *tmp = '\0';
@@@ -2202,15 -2228,15 +2213,15 @@@ void clear_perf_probe_event(struct perf
        struct perf_probe_arg_field *field, *next;
        int i;
  
 -      free(pev->event);
 -      free(pev->group);
 -      free(pev->target);
 +      zfree(&pev->event);
 +      zfree(&pev->group);
 +      zfree(&pev->target);
        clear_perf_probe_point(&pev->point);
  
        for (i = 0; i < pev->nargs; i++) {
 -              free(pev->args[i].name);
 -              free(pev->args[i].var);
 -              free(pev->args[i].type);
 +              zfree(&pev->args[i].name);
 +              zfree(&pev->args[i].var);
 +              zfree(&pev->args[i].type);
                field = pev->args[i].field;
                while (field) {
                        next = field->next;
                        field = next;
                }
        }
 -      free(pev->args);
 -      memset(pev, 0, sizeof(*pev));
 +      zfree(&pev->args);
  }
  
  #define strdup_or_goto(str, label)    \
@@@ -2300,15 -2327,15 +2311,15 @@@ void clear_probe_trace_event(struct pro
        struct probe_trace_arg_ref *ref, *next;
        int i;
  
 -      free(tev->event);
 -      free(tev->group);
 -      free(tev->point.symbol);
 -      free(tev->point.realname);
 -      free(tev->point.module);
 +      zfree(&tev->event);
 +      zfree(&tev->group);
 +      zfree(&tev->point.symbol);
 +      zfree(&tev->point.realname);
 +      zfree(&tev->point.module);
        for (i = 0; i < tev->nargs; i++) {
 -              free(tev->args[i].name);
 -              free(tev->args[i].value);
 -              free(tev->args[i].type);
 +              zfree(&tev->args[i].name);
 +              zfree(&tev->args[i].value);
 +              zfree(&tev->args[i].type);
                ref = tev->args[i].ref;
                while (ref) {
                        next = ref->next;
                        ref = next;
                }
        }
 -      free(tev->args);
 -      memset(tev, 0, sizeof(*tev));
 +      zfree(&tev->args);
  }
  
  struct kprobe_blacklist_node {
@@@ -2333,8 -2361,8 +2344,8 @@@ static void kprobe_blacklist__delete(st
        while (!list_empty(blacklist)) {
                node = list_first_entry(blacklist,
                                        struct kprobe_blacklist_node, list);
 -              list_del(&node->list);
 -              free(node->symbol);
 +              list_del_init(&node->list);
 +              zfree(&node->symbol);
                free(node);
        }
  }
@@@ -1,8 -1,18 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * probe-file.c : operate ftrace k/uprobe events files
   *
   * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
 - *
   */
  #include <errno.h>
  #include <fcntl.h>
@@@ -10,8 -20,8 +10,8 @@@
  #include <sys/types.h>
  #include <sys/uio.h>
  #include <unistd.h>
 +#include <linux/zalloc.h>
  #include "namespaces.h"
 -#include "util.h"
  #include "event.h"
  #include "strlist.h"
  #include "strfilter.h"
@@@ -1005,6 -1015,7 +1005,7 @@@ enum ftrace_readme 
        FTRACE_README_PROBE_TYPE_X = 0,
        FTRACE_README_KRETPROBE_OFFSET,
        FTRACE_README_UPROBE_REF_CTR,
+       FTRACE_README_USER_ACCESS,
        FTRACE_README_END,
  };
  
@@@ -1017,6 -1028,7 +1018,7 @@@ static struct 
        DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
        DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
        DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
+       DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*[u]<offset>*"),
  };
  
  static bool scan_ftrace_readme(enum ftrace_readme type)
@@@ -1077,3 -1089,8 +1079,8 @@@ bool uprobe_ref_ctr_is_supported(void
  {
        return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR);
  }
+ bool user_access_is_supported(void)
+ {
+       return scan_ftrace_readme(FTRACE_README_USER_ACCESS);
+ }
@@@ -1,8 -1,22 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * probe-finder.c : C expression to kprobe event converter
   *
   * Written by Masami Hiramatsu <mhiramat@redhat.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - *
   */
  
  #include <inttypes.h>
  #include <dwarf-regs.h>
  
  #include <linux/bitops.h>
 +#include <linux/zalloc.h>
  #include "event.h"
  #include "dso.h"
  #include "debug.h"
  #include "intlist.h"
 -#include "util.h"
  #include "strlist.h"
  #include "symbol.h"
  #include "probe-finder.h"
@@@ -280,7 -294,7 +280,7 @@@ static_var
  
  static int convert_variable_type(Dwarf_Die *vr_die,
                                 struct probe_trace_arg *tvar,
-                                const char *cast)
+                                const char *cast, bool user_access)
  {
        struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
        Dwarf_Die type;
        pr_debug("%s type is %s.\n",
                 dwarf_diename(vr_die), dwarf_diename(&type));
  
-       if (cast && strcmp(cast, "string") == 0) {      /* String type */
+       if (cast && (!strcmp(cast, "string") || !strcmp(cast, "ustring"))) {
+               /* String type */
                ret = dwarf_tag(&type);
                if (ret != DW_TAG_pointer_type &&
                    ret != DW_TAG_array_type) {
                                pr_warning("Out of memory error\n");
                                return -ENOMEM;
                        }
+                       (*ref_ptr)->user_access = user_access;
                }
                if (!die_compare_name(&type, "char") &&
                    !die_compare_name(&type, "unsigned char")) {
@@@ -397,7 -413,7 +399,7 @@@ formatted
  static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
                                    struct perf_probe_arg_field *field,
                                    struct probe_trace_arg_ref **ref_ptr,
-                                   Dwarf_Die *die_mem)
+                                   Dwarf_Die *die_mem, bool user_access)
  {
        struct probe_trace_arg_ref *ref = *ref_ptr;
        Dwarf_Die type;
                                *ref_ptr = ref;
                }
                ref->offset += dwarf_bytesize(&type) * field->index;
+               ref->user_access = user_access;
                goto next;
        } else if (tag == DW_TAG_pointer_type) {
                /* Check the pointer and dereference */
                }
        }
        ref->offset += (long)offs;
+       ref->user_access = user_access;
  
        /* If this member is unnamed, we need to reuse this field */
        if (!dwarf_diename(die_mem))
                return convert_variable_fields(die_mem, varname, field,
-                                               &ref, die_mem);
+                                               &ref, die_mem, user_access);
  
  next:
        /* Converting next field */
        if (field->next)
                return convert_variable_fields(die_mem, field->name,
-                                       field->next, &ref, die_mem);
+                               field->next, &ref, die_mem, user_access);
        else
                return 0;
  }
@@@ -541,11 -559,12 +545,12 @@@ static int convert_variable(Dwarf_Die *
        else if (ret == 0 && pf->pvar->field) {
                ret = convert_variable_fields(vr_die, pf->pvar->var,
                                              pf->pvar->field, &pf->tvar->ref,
-                                             &die_mem);
+                                             &die_mem, pf->pvar->user_access);
                vr_die = &die_mem;
        }
        if (ret == 0)
-               ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
+               ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type,
+                                           pf->pvar->user_access);
        /* *expr will be cached in libdw. Don't free it. */
        return ret;
  }
@@@ -1,11 -1,11 +1,11 @@@
  #!/bin/sh
 +# SPDX-License-Identifier: GPL-2.0-only
  
  # ftracetest - Ftrace test shell scripts
  #
  # Copyright (C) Hitachi Ltd., 2014
  #  Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
  #
 -# Released under the terms of the GPL v2.
  
  usage() { # errno [message]
  [ ! -z "$2" ] && echo $2
@@@ -23,9 -23,15 +23,15 @@@ echo "                          If <dir> is -, all 
  exit $1
  }
  
+ # default error
+ err_ret=1
+ # kselftest skip code is 4
+ err_skip=4
  errexit() { # message
    echo "Error: $1" 1>&2
-   exit 1
+   exit $err_ret
  }
  
  # Ensuring user privilege
@@@ -116,11 -122,31 +122,31 @@@ parse_opts() { # opt
  }
  
  # Parameters
- DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
- if [ -z "$DEBUGFS_DIR" ]; then
-     TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
- else
-     TRACING_DIR=$DEBUGFS_DIR/tracing
+ TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
+ if [ -z "$TRACING_DIR" ]; then
+     DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
+     if [ -z "$DEBUGFS_DIR" ]; then
+       # If tracefs exists, then so does /sys/kernel/tracing
+       if [ -d "/sys/kernel/tracing" ]; then
+           mount -t tracefs nodev /sys/kernel/tracing ||
+             errexit "Failed to mount /sys/kernel/tracing"
+           TRACING_DIR="/sys/kernel/tracing"
+       # If debugfs exists, then so does /sys/kernel/debug
+       elif [ -d "/sys/kernel/debug" ]; then
+           mount -t debugfs nodev /sys/kernel/debug ||
+             errexit "Failed to mount /sys/kernel/debug"
+           TRACING_DIR="/sys/kernel/debug/tracing"
+       else
+           err_ret=$err_skip
+           errexit "debugfs and tracefs are not configured in this kernel"
+       fi
+     else
+       TRACING_DIR="$DEBUGFS_DIR/tracing"
+     fi
+ fi
+ if [ ! -d "$TRACING_DIR" ]; then
+     err_ret=$err_skip
+     errexit "ftrace is not configured in this kernel"
  fi
  
  TOP_DIR=`absdir $0`
@@@ -318,7 -344,6 +344,7 @@@ run_test() { # testfil
      local testlog=/proc/self/fd/1
    fi
    export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
 +  export FTRACETEST_ROOT=$TOP_DIR
    echo "execute$INSTANCE: "$1 > $testlog
    SIG_RESULT=0
    if [ $VERBOSE -eq -1 ]; then