Skip to content

Commit 4b4eef5

Browse files
committed
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
2 parents 831fe28 + 797311b commit 4b4eef5

File tree

6 files changed

+24
-29
lines changed

6 files changed

+24
-29
lines changed

kernel/trace/fprobe.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
100100
return;
101101
}
102102

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+
*/
103109
if (unlikely(kprobe_running())) {
104110
fp->nmissed++;
105111
goto recursion_unlock;

kernel/trace/trace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ enum trace_type {
113113
#define MEM_FAIL(condition, fmt, ...) \
114114
DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__)
115115

116+
#define FAULT_STRING "(fault)"
117+
116118
#define HIST_STACKTRACE_DEPTH 16
117119
#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))
118120
#define HIST_STACKTRACE_SKIP 5

kernel/trace/trace_probe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent)
6767
int len = *(u32 *)data >> 16;
6868

6969
if (!len)
70-
trace_seq_puts(s, "(fault)");
70+
trace_seq_puts(s, FAULT_STRING);
7171
else
7272
trace_seq_printf(s, "\"%s\"",
7373
(const char *)get_loc_data(data, ent));

kernel/trace/trace_probe_kernel.h

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
#ifndef __TRACE_PROBE_KERNEL_H_
33
#define __TRACE_PROBE_KERNEL_H_
44

5-
#define FAULT_STRING "(fault)"
6-
75
/*
86
* This depends on trace_probe.h, but can not include it due to
97
* the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
@@ -15,16 +13,8 @@ static nokprobe_inline int
1513
fetch_store_strlen_user(unsigned long addr)
1614
{
1715
const void __user *uaddr = (__force const void __user *)addr;
18-
int ret;
1916

20-
ret = strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
21-
/*
22-
* strnlen_user_nofault returns zero on fault, insert the
23-
* FAULT_STRING when that occurs.
24-
*/
25-
if (ret <= 0)
26-
return strlen(FAULT_STRING) + 1;
27-
return ret;
17+
return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
2818
}
2919

3020
/* Return the length of string -- including null terminal byte */
@@ -44,18 +34,14 @@ fetch_store_strlen(unsigned long addr)
4434
len++;
4535
} while (c && ret == 0 && len < MAX_STRING_SIZE);
4636

47-
/* For faults, return enough to hold the FAULT_STRING */
48-
return (ret < 0) ? strlen(FAULT_STRING) + 1 : len;
37+
return (ret < 0) ? ret : len;
4938
}
5039

51-
static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len)
40+
static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base)
5241
{
53-
if (ret >= 0) {
54-
*(u32 *)dest = make_data_loc(ret, __dest - base);
55-
} else {
56-
strscpy(__dest, FAULT_STRING, len);
57-
ret = strlen(__dest) + 1;
58-
}
42+
if (ret < 0)
43+
ret = 0;
44+
*(u32 *)dest = make_data_loc(ret, __dest - base);
5945
}
6046

6147
/*
@@ -76,7 +62,7 @@ fetch_store_string_user(unsigned long addr, void *dest, void *base)
7662
__dest = get_loc_data(dest, base);
7763

7864
ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
79-
set_data_loc(ret, dest, __dest, base, maxlen);
65+
set_data_loc(ret, dest, __dest, base);
8066

8167
return ret;
8268
}
@@ -107,7 +93,7 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
10793
* probing.
10894
*/
10995
ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
110-
set_data_loc(ret, dest, __dest, base, maxlen);
96+
set_data_loc(ret, dest, __dest, base);
11197

11298
return ret;
11399
}

kernel/trace/trace_probe_tmpl.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,11 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
156156
code++;
157157
goto array;
158158
case FETCH_OP_ST_USTRING:
159-
ret += fetch_store_strlen_user(val + code->offset);
159+
ret = fetch_store_strlen_user(val + code->offset);
160160
code++;
161161
goto array;
162162
case FETCH_OP_ST_SYMSTR:
163-
ret += fetch_store_symstrlen(val + code->offset);
163+
ret = fetch_store_symstrlen(val + code->offset);
164164
code++;
165165
goto array;
166166
default:
@@ -204,6 +204,8 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
204204
array:
205205
/* the last stage: Loop on array */
206206
if (code->op == FETCH_OP_LP_ARRAY) {
207+
if (ret < 0)
208+
ret = 0;
207209
total += ret;
208210
if (++i < code->param) {
209211
code = s3;
@@ -265,9 +267,7 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec,
265267
if (unlikely(arg->dynamic))
266268
*dl = make_data_loc(maxlen, dyndata - base);
267269
ret = process_fetch_insn(arg->code, rec, dl, base);
268-
if (unlikely(ret < 0 && arg->dynamic)) {
269-
*dl = make_data_loc(0, dyndata - base);
270-
} else {
270+
if (arg->dynamic && likely(ret > 0)) {
271271
dyndata += ret;
272272
maxlen -= ret;
273273
}

kernel/trace/trace_uprobe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
170170
*/
171171
ret++;
172172
*(u32 *)dest = make_data_loc(ret, (void *)dst - base);
173-
}
173+
} else
174+
*(u32 *)dest = make_data_loc(0, (void *)dst - base);
174175

175176
return ret;
176177
}

0 commit comments

Comments
 (0)