Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'probes-fixes-v6.5-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull probe fixes from Masami Hiramatsu:

- fprobe: Add a comment why fprobe will be skipped if another kprobe is
running in fprobe_kprobe_handler().

- probe-events: Fix some issues related to fetch-arguments:

- Fix double counting of the string length for user-string and
symstr. This will require longer buffer in the array case.

- Fix not to count error code (minus value) for the total used
length in array argument. This makes the total used length
shorter.

- Fix to update dynamic used data size counter only if fetcharg uses
the dynamic size data. This may mis-count the used dynamic data
size and corrupt data.

- Revert "tracing: Add "(fault)" name injection to kernel probes"
because that did not work correctly with a bug, and we agreed the
current '(fault)' output (instead of '"(fault)"' like a string)
explains what happened more clearly.

- Fix to record 0-length (means fault access) data_loc data in fetch
function itself, instead of store_trace_args(). If we record an
array of string, this will fix to save fault access data on each
entry of the array correctly.

* tag 'probes-fixes-v6.5-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails
Revert "tracing: Add "(fault)" name injection to kernel probes"
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
tracing/probes: Fix not to count error code to total length
tracing/probes: Fix to avoid double count of the string length on the array
fprobes: Add a comment why fprobe_kprobe_handler exits if kprobe is running

+24 -29
+6
kernel/trace/fprobe.c
··· 100 100 return; 101 101 } 102 102 103 + /* 104 + * This user handler is shared with other kprobes and is not expected to be 105 + * called recursively. So if any other kprobe handler is running, this will 106 + * exit as kprobe does. See the section 'Share the callbacks with kprobes' 107 + * in Documentation/trace/fprobe.rst for more information. 108 + */ 103 109 if (unlikely(kprobe_running())) { 104 110 fp->nmissed++; 105 111 goto recursion_unlock;
+2
kernel/trace/trace.h
··· 113 113 #define MEM_FAIL(condition, fmt, ...) \ 114 114 DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) 115 115 116 + #define FAULT_STRING "(fault)" 117 + 116 118 #define HIST_STACKTRACE_DEPTH 16 117 119 #define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) 118 120 #define HIST_STACKTRACE_SKIP 5
+1 -1
kernel/trace/trace_probe.c
··· 67 67 int len = *(u32 *)data >> 16; 68 68 69 69 if (!len) 70 - trace_seq_puts(s, "(fault)"); 70 + trace_seq_puts(s, FAULT_STRING); 71 71 else 72 72 trace_seq_printf(s, "\"%s\"", 73 73 (const char *)get_loc_data(data, ent));
+8 -22
kernel/trace/trace_probe_kernel.h
··· 2 2 #ifndef __TRACE_PROBE_KERNEL_H_ 3 3 #define __TRACE_PROBE_KERNEL_H_ 4 4 5 - #define FAULT_STRING "(fault)" 6 - 7 5 /* 8 6 * This depends on trace_probe.h, but can not include it due to 9 7 * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c. ··· 13 15 fetch_store_strlen_user(unsigned long addr) 14 16 { 15 17 const void __user *uaddr = (__force const void __user *)addr; 16 - int ret; 17 18 18 - ret = strnlen_user_nofault(uaddr, MAX_STRING_SIZE); 19 - /* 20 - * strnlen_user_nofault returns zero on fault, insert the 21 - * FAULT_STRING when that occurs. 22 - */ 23 - if (ret <= 0) 24 - return strlen(FAULT_STRING) + 1; 25 - return ret; 19 + return strnlen_user_nofault(uaddr, MAX_STRING_SIZE); 26 20 } 27 21 28 22 /* Return the length of string -- including null terminal byte */ ··· 34 44 len++; 35 45 } while (c && ret == 0 && len < MAX_STRING_SIZE); 36 46 37 - /* For faults, return enough to hold the FAULT_STRING */ 38 - return (ret < 0) ? strlen(FAULT_STRING) + 1 : len; 47 + return (ret < 0) ? ret : len; 39 48 } 40 49 41 - static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) 50 + static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base) 42 51 { 43 - if (ret >= 0) { 44 - *(u32 *)dest = make_data_loc(ret, __dest - base); 45 - } else { 46 - strscpy(__dest, FAULT_STRING, len); 47 - ret = strlen(__dest) + 1; 48 - } 52 + if (ret < 0) 53 + ret = 0; 54 + *(u32 *)dest = make_data_loc(ret, __dest - base); 49 55 } 50 56 51 57 /* ··· 62 76 __dest = get_loc_data(dest, base); 63 77 64 78 ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); 65 - set_data_loc(ret, dest, __dest, base, maxlen); 79 + set_data_loc(ret, dest, __dest, base); 66 80 67 81 return ret; 68 82 } ··· 93 107 * probing. 94 108 */ 95 109 ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); 96 - set_data_loc(ret, dest, __dest, base, maxlen); 110 + set_data_loc(ret, dest, __dest, base); 97 111 98 112 return ret; 99 113 }
+5 -5
kernel/trace/trace_probe_tmpl.h
··· 156 156 code++; 157 157 goto array; 158 158 case FETCH_OP_ST_USTRING: 159 - ret += fetch_store_strlen_user(val + code->offset); 159 + ret = fetch_store_strlen_user(val + code->offset); 160 160 code++; 161 161 goto array; 162 162 case FETCH_OP_ST_SYMSTR: 163 - ret += fetch_store_symstrlen(val + code->offset); 163 + ret = fetch_store_symstrlen(val + code->offset); 164 164 code++; 165 165 goto array; 166 166 default: ··· 204 204 array: 205 205 /* the last stage: Loop on array */ 206 206 if (code->op == FETCH_OP_LP_ARRAY) { 207 + if (ret < 0) 208 + ret = 0; 207 209 total += ret; 208 210 if (++i < code->param) { 209 211 code = s3; ··· 267 265 if (unlikely(arg->dynamic)) 268 266 *dl = make_data_loc(maxlen, dyndata - base); 269 267 ret = process_fetch_insn(arg->code, rec, dl, base); 270 - if (unlikely(ret < 0 && arg->dynamic)) { 271 - *dl = make_data_loc(0, dyndata - base); 272 - } else { 268 + if (arg->dynamic && likely(ret > 0)) { 273 269 dyndata += ret; 274 270 maxlen -= ret; 275 271 }
+2 -1
kernel/trace/trace_uprobe.c
··· 170 170 */ 171 171 ret++; 172 172 *(u32 *)dest = make_data_loc(ret, (void *)dst - base); 173 - } 173 + } else 174 + *(u32 *)dest = make_data_loc(0, (void *)dst - base); 174 175 175 176 return ret; 176 177 }