diff options
author | Masami Hiramatsu (Google) <mhiramat@kernel.org> | 2023-06-29 09:58:39 +0900 |
---|---|---|
committer | Masami Hiramatsu (Google) <mhiramat@kernel.org> | 2023-06-29 10:00:02 +0900 |
commit | c8be1ba8b966d8fa1f95ec45773b0e3cfc8981f7 (patch) | |
tree | 715989a56f4a0bc22afca268d1a1f59a8c722437 | |
parent | fc739a50dc8625466a38da0d40fdbf725e4ea60b (diff) | |
download | linux-topic/fix-probe-template.tar.gz |
tracing/probes: Fix return value when "(fault)" is injectedtopic/fix-probe-template
When the "(fault)" is injected, the return value of fetch_store_string*()
must be the length of the "(fault)", but it returns error code.
Fix it to return correct length, and cleanup the variable name to be more
readable.
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://lore.kernel.org/all/8819b154-2ba1-43c3-98a2-cbde20892023@moroto.mountain/
Fixes: 2e9906f84fc7 ("tracing: Add "(fault)" name injection to kernel probes")
Cc: stable@vger.kernel.org
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
-rw-r--r-- | kernel/trace/trace_probe_kernel.h | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h index c4e1d4c03a85f..bc05e145351a7 100644 --- a/kernel/trace/trace_probe_kernel.h +++ b/kernel/trace/trace_probe_kernel.h @@ -48,14 +48,18 @@ fetch_store_strlen(unsigned long addr) return (ret < 0) ? strlen(FAULT_STRING) + 1 : len; } -static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) +static nokprobe_inline int set_data_loc(int ret, + void *dest_entry, + void *dest_data, + void *base, int len) { - if (ret >= 0) { - *(u32 *)dest = make_data_loc(ret, __dest - base); - } else { - strscpy(__dest, FAULT_STRING, len); - ret = strlen(__dest) + 1; + if (ret < 0) { + strscpy(dest_data, FAULT_STRING, len); + ret = strlen(dest_data) + 1; } + *(u32 *)dest_entry = make_data_loc(ret, dest_data - base); + + return ret; } /* @@ -63,22 +67,21 @@ static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void * with max length and relative data location. */ static nokprobe_inline int -fetch_store_string_user(unsigned long addr, void *dest, void *base) +fetch_store_string_user(unsigned long addr, void *dest_entry, void *base) { const void __user *uaddr = (__force const void __user *)addr; - int maxlen = get_loc_len(*(u32 *)dest); - void *__dest; + int maxlen = get_loc_len(*(u32 *)dest_entry); + void *dest_data; long ret; if (unlikely(!maxlen)) return -ENOMEM; - __dest = get_loc_data(dest, base); + dest_data = get_loc_data(dest_entry, base); - ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); - set_data_loc(ret, dest, __dest, base, maxlen); + ret = strncpy_from_user_nofault(dest_data, uaddr, maxlen); - return ret; + return set_data_loc(ret, dest_entry, dest_data, base, maxlen); } /* @@ -86,30 +89,29 @@ fetch_store_string_user(unsigned long addr, void *dest, void *base) * length and relative data location. */ static nokprobe_inline int -fetch_store_string(unsigned long addr, void *dest, void *base) +fetch_store_string(unsigned long addr, void *dest_entry, void *base) { - int maxlen = get_loc_len(*(u32 *)dest); - void *__dest; + int maxlen = get_loc_len(*(u32 *)dest_entry); + void *dest_data; long ret; #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if ((unsigned long)addr < TASK_SIZE) - return fetch_store_string_user(addr, dest, base); + return fetch_store_string_user(addr, dest_entry, base); #endif if (unlikely(!maxlen)) return -ENOMEM; - __dest = get_loc_data(dest, base); + dest_data = get_loc_data(dest_entry, base); /* * Try to get string again, since the string can be changed while * probing. */ - ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); - set_data_loc(ret, dest, __dest, base, maxlen); + ret = strncpy_from_kernel_nofault(dest_data, (void *)addr, maxlen); - return ret; + return set_data_loc(ret, dest_entry, dest_data, base, maxlen); } static nokprobe_inline int |