-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tracing: Move duplicate code of trace_kprobe/eprobe.c into header
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: bd82631 ("tracing: Add support for dynamic strings to synthetic events") Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
- Loading branch information
Steven Rostedt (Google)
committed
Oct 12, 2022
1 parent
b7085b6
commit f1d3cbf
Showing
3 changed files
with
106 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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_ */ |