lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 115/530] tracing: Move duplicate code of trace_kprobe/eprobe.c into header
    Date
    From: Steven Rostedt (Google) <rostedt@goodmis.org>

    commit f1d3cbfaafc10464550c6d3a125f4fc802bbaed5 upstream.

    The functions:

    fetch_store_strlen_user()
    fetch_store_strlen()
    fetch_store_string_user()
    fetch_store_string()

    are identical in both trace_kprobe.c and trace_eprobe.c. Move them into
    a new header file trace_probe_kernel.h to share it. This code will later
    be used by the synthetic events as well.

    Marked for stable as a fix for a crash in synthetic events requires it.

    Link: https://lkml.kernel.org/r/20221012104534.467668078@goodmis.org

    Cc: stable@vger.kernel.org
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Tom Zanussi <zanussi@kernel.org>
    Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
    Reviewed-by: Tom Zanussi <zanussi@kernel.org>
    Fixes: bd82631d7ccdc ("tracing: Add support for dynamic strings to synthetic events")
    Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    kernel/trace/trace_eprobe.c | 60 +----------------------
    kernel/trace/trace_kprobe.c | 60 +----------------------
    kernel/trace/trace_probe_kernel.h | 96 ++++++++++++++++++++++++++++++++++++++
    3 files changed, 106 insertions(+), 110 deletions(-)
    create mode 100644 kernel/trace/trace_probe_kernel.h

    --- a/kernel/trace/trace_eprobe.c
    +++ b/kernel/trace/trace_eprobe.c
    @@ -16,6 +16,7 @@
    #include "trace_dynevent.h"
    #include "trace_probe.h"
    #include "trace_probe_tmpl.h"
    +#include "trace_probe_kernel.h"

    #define EPROBE_EVENT_SYSTEM "eprobes"

    @@ -447,29 +448,14 @@ NOKPROBE_SYMBOL(process_fetch_insn)
    static nokprobe_inline int
    fetch_store_strlen_user(unsigned long addr)
    {
    - const void __user *uaddr = (__force const void __user *)addr;
    -
    - return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
    + return kern_fetch_store_strlen_user(addr);
    }

    /* Return the length of string -- including null terminal byte */
    static nokprobe_inline int
    fetch_store_strlen(unsigned long addr)
    {
    - int ret, len = 0;
    - u8 c;
    -
    -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    - if (addr < TASK_SIZE)
    - return fetch_store_strlen_user(addr);
    -#endif
    -
    - do {
    - ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
    - len++;
    - } while (c && ret == 0 && len < MAX_STRING_SIZE);
    -
    - return (ret < 0) ? ret : len;
    + return kern_fetch_store_strlen(addr);
    }

    /*
    @@ -479,21 +465,7 @@ fetch_store_strlen(unsigned long addr)
    static nokprobe_inline int
    fetch_store_string_user(unsigned long addr, void *dest, void *base)
    {
    - const void __user *uaddr = (__force const void __user *)addr;
    - int maxlen = get_loc_len(*(u32 *)dest);
    - void *__dest;
    - long ret;
    -
    - if (unlikely(!maxlen))
    - return -ENOMEM;
    -
    - __dest = get_loc_data(dest, base);
    -
    - ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
    - if (ret >= 0)
    - *(u32 *)dest = make_data_loc(ret, __dest - base);
    -
    - return ret;
    + return kern_fetch_store_string_user(addr, dest, base);
    }

    /*
    @@ -503,29 +475,7 @@ fetch_store_string_user(unsigned long ad
    static nokprobe_inline int
    fetch_store_string(unsigned long addr, void *dest, void *base)
    {
    - int maxlen = get_loc_len(*(u32 *)dest);
    - void *__dest;
    - long ret;
    -
    -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    - if ((unsigned long)addr < TASK_SIZE)
    - return fetch_store_string_user(addr, dest, base);
    -#endif
    -
    - if (unlikely(!maxlen))
    - return -ENOMEM;
    -
    - __dest = get_loc_data(dest, base);
    -
    - /*
    - * Try to get string again, since the string can be changed while
    - * probing.
    - */
    - ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
    - if (ret >= 0)
    - *(u32 *)dest = make_data_loc(ret, __dest - base);
    -
    - return ret;
    + return kern_fetch_store_string(addr, dest, base);
    }

    static nokprobe_inline int
    --- a/kernel/trace/trace_kprobe.c
    +++ b/kernel/trace/trace_kprobe.c
    @@ -19,6 +19,7 @@
    #include "trace_kprobe_selftest.h"
    #include "trace_probe.h"
    #include "trace_probe_tmpl.h"
    +#include "trace_probe_kernel.h"

    #define KPROBE_EVENT_SYSTEM "kprobes"
    #define KRETPROBE_MAXACTIVE_MAX 4096
    @@ -1223,29 +1224,14 @@ static const struct file_operations kpro
    static nokprobe_inline int
    fetch_store_strlen_user(unsigned long addr)
    {
    - const void __user *uaddr = (__force const void __user *)addr;
    -
    - return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
    + return kern_fetch_store_strlen_user(addr);
    }

    /* Return the length of string -- including null terminal byte */
    static nokprobe_inline int
    fetch_store_strlen(unsigned long addr)
    {
    - int ret, len = 0;
    - u8 c;
    -
    -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    - if (addr < TASK_SIZE)
    - return fetch_store_strlen_user(addr);
    -#endif
    -
    - do {
    - ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
    - len++;
    - } while (c && ret == 0 && len < MAX_STRING_SIZE);
    -
    - return (ret < 0) ? ret : len;
    + return kern_fetch_store_strlen(addr);
    }

    /*
    @@ -1255,21 +1241,7 @@ fetch_store_strlen(unsigned long addr)
    static nokprobe_inline int
    fetch_store_string_user(unsigned long addr, void *dest, void *base)
    {
    - const void __user *uaddr = (__force const void __user *)addr;
    - int maxlen = get_loc_len(*(u32 *)dest);
    - void *__dest;
    - long ret;
    -
    - if (unlikely(!maxlen))
    - return -ENOMEM;
    -
    - __dest = get_loc_data(dest, base);
    -
    - ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
    - if (ret >= 0)
    - *(u32 *)dest = make_data_loc(ret, __dest - base);
    -
    - return ret;
    + return kern_fetch_store_string_user(addr, dest, base);
    }

    /*
    @@ -1279,29 +1251,7 @@ fetch_store_string_user(unsigned long ad
    static nokprobe_inline int
    fetch_store_string(unsigned long addr, void *dest, void *base)
    {
    - int maxlen = get_loc_len(*(u32 *)dest);
    - void *__dest;
    - long ret;
    -
    -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    - if ((unsigned long)addr < TASK_SIZE)
    - return fetch_store_string_user(addr, dest, base);
    -#endif
    -
    - if (unlikely(!maxlen))
    - return -ENOMEM;
    -
    - __dest = get_loc_data(dest, base);
    -
    - /*
    - * Try to get string again, since the string can be changed while
    - * probing.
    - */
    - ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
    - if (ret >= 0)
    - *(u32 *)dest = make_data_loc(ret, __dest - base);
    -
    - return ret;
    + return kern_fetch_store_string(addr, dest, base);
    }

    static nokprobe_inline int
    --- /dev/null
    +++ b/kernel/trace/trace_probe_kernel.h
    @@ -0,0 +1,96 @@
    +/* SPDX-License-Identifier: GPL-2.0 */
    +#ifndef __TRACE_PROBE_KERNEL_H_
    +#define __TRACE_PROBE_KERNEL_H_
    +
    +/*
    + * This depends on trace_probe.h, but can not include it due to
    + * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
    + * Which means that any other user must include trace_probe.h before including
    + * this file.
    + */
    +/* Return the length of string -- including null terminal byte */
    +static nokprobe_inline int
    +kern_fetch_store_strlen_user(unsigned long addr)
    +{
    + const void __user *uaddr = (__force const void __user *)addr;
    +
    + return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
    +}
    +
    +/* Return the length of string -- including null terminal byte */
    +static nokprobe_inline int
    +kern_fetch_store_strlen(unsigned long addr)
    +{
    + int ret, len = 0;
    + u8 c;
    +
    +#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    + if (addr < TASK_SIZE)
    + return kern_fetch_store_strlen_user(addr);
    +#endif
    +
    + do {
    + ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
    + len++;
    + } while (c && ret == 0 && len < MAX_STRING_SIZE);
    +
    + return (ret < 0) ? ret : len;
    +}
    +
    +/*
    + * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf
    + * with max length and relative data location.
    + */
    +static nokprobe_inline int
    +kern_fetch_store_string_user(unsigned long addr, void *dest, void *base)
    +{
    + const void __user *uaddr = (__force const void __user *)addr;
    + int maxlen = get_loc_len(*(u32 *)dest);
    + void *__dest;
    + long ret;
    +
    + if (unlikely(!maxlen))
    + return -ENOMEM;
    +
    + __dest = get_loc_data(dest, base);
    +
    + ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
    + if (ret >= 0)
    + *(u32 *)dest = make_data_loc(ret, __dest - base);
    +
    + return ret;
    +}
    +
    +/*
    + * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max
    + * length and relative data location.
    + */
    +static nokprobe_inline int
    +kern_fetch_store_string(unsigned long addr, void *dest, void *base)
    +{
    + int maxlen = get_loc_len(*(u32 *)dest);
    + void *__dest;
    + long ret;
    +
    +#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
    + if ((unsigned long)addr < TASK_SIZE)
    + return kern_fetch_store_string_user(addr, dest, base);
    +#endif
    +
    + if (unlikely(!maxlen))
    + return -ENOMEM;
    +
    + __dest = get_loc_data(dest, base);
    +
    + /*
    + * Try to get string again, since the string can be changed while
    + * probing.
    + */
    + ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
    + if (ret >= 0)
    + *(u32 *)dest = make_data_loc(ret, __dest - base);
    +
    + return ret;
    +}
    +
    +#endif /* __TRACE_PROBE_KERNEL_H_ */

    \
     
     \ /
      Last update: 2022-10-24 15:47    [W:3.316 / U:0.968 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site