Skip to content

Commit aa41478

Browse files
committed
Merge tag 'trace-v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing fixes from Steven Rostedt: - Found that the synthetic events were using strlen/strscpy() on values that could have come from userspace, and that is bad. Consolidate the string logic of kprobe and eprobe and extend it to the synthetic events to safely process string addresses. - Clean up content of text dump in ftrace_bug() where the output does not make char reads into signed and sign extending the byte output. - Fix some kernel docs in the ring buffer code. * tag 'trace-v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing: Fix reading strings from synthetic events tracing: Add "(fault)" name injection to kernel probes tracing: Move duplicate code of trace_kprobe/eprobe.c into header ring-buffer: Fix kernel-doc ftrace: Fix char print issue in print_ip_ins()
2 parents 3d33e6d + 0934ae9 commit aa41478

File tree

6 files changed

+146
-123
lines changed

6 files changed

+146
-123
lines changed

kernel/trace/ftrace.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,17 +2028,14 @@ static int ftrace_hash_ipmodify_update(struct ftrace_ops *ops,
20282028
static void print_ip_ins(const char *fmt, const unsigned char *p)
20292029
{
20302030
char ins[MCOUNT_INSN_SIZE];
2031-
int i;
20322031

20332032
if (copy_from_kernel_nofault(ins, p, MCOUNT_INSN_SIZE)) {
20342033
printk(KERN_CONT "%s[FAULT] %px\n", fmt, p);
20352034
return;
20362035
}
20372036

20382037
printk(KERN_CONT "%s", fmt);
2039-
2040-
for (i = 0; i < MCOUNT_INSN_SIZE; i++)
2041-
printk(KERN_CONT "%s%02x", i ? ":" : "", ins[i]);
2038+
pr_cont("%*phC", MCOUNT_INSN_SIZE, ins);
20422039
}
20432040

20442041
enum ftrace_bug_type ftrace_bug_type;

kernel/trace/ring_buffer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ size_t ring_buffer_nr_pages(struct trace_buffer *buffer, int cpu)
885885
}
886886

887887
/**
888-
* ring_buffer_nr_pages_dirty - get the number of used pages in the ring buffer
888+
* ring_buffer_nr_dirty_pages - get the number of used pages in the ring buffer
889889
* @buffer: The ring_buffer to get the number of pages from
890890
* @cpu: The cpu of the ring_buffer to get the number of pages from
891891
*
@@ -5305,7 +5305,7 @@ void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu)
53055305
EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
53065306

53075307
/**
5308-
* ring_buffer_reset_cpu - reset a ring buffer per CPU buffer
5308+
* ring_buffer_reset_online_cpus - reset a ring buffer per CPU buffer
53095309
* @buffer: The ring buffer to reset a per cpu buffer of
53105310
* @cpu: The CPU buffer to be reset
53115311
*/
@@ -5375,7 +5375,7 @@ void ring_buffer_reset(struct trace_buffer *buffer)
53755375
EXPORT_SYMBOL_GPL(ring_buffer_reset);
53765376

53775377
/**
5378-
* rind_buffer_empty - is the ring buffer empty?
5378+
* ring_buffer_empty - is the ring buffer empty?
53795379
* @buffer: The ring buffer to test
53805380
*/
53815381
bool ring_buffer_empty(struct trace_buffer *buffer)

kernel/trace/trace_eprobe.c

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "trace_dynevent.h"
1717
#include "trace_probe.h"
1818
#include "trace_probe_tmpl.h"
19+
#include "trace_probe_kernel.h"
1920

2021
#define EPROBE_EVENT_SYSTEM "eprobes"
2122

@@ -456,29 +457,14 @@ NOKPROBE_SYMBOL(process_fetch_insn)
456457
static nokprobe_inline int
457458
fetch_store_strlen_user(unsigned long addr)
458459
{
459-
const void __user *uaddr = (__force const void __user *)addr;
460-
461-
return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
460+
return kern_fetch_store_strlen_user(addr);
462461
}
463462

464463
/* Return the length of string -- including null terminal byte */
465464
static nokprobe_inline int
466465
fetch_store_strlen(unsigned long addr)
467466
{
468-
int ret, len = 0;
469-
u8 c;
470-
471-
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
472-
if (addr < TASK_SIZE)
473-
return fetch_store_strlen_user(addr);
474-
#endif
475-
476-
do {
477-
ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
478-
len++;
479-
} while (c && ret == 0 && len < MAX_STRING_SIZE);
480-
481-
return (ret < 0) ? ret : len;
467+
return kern_fetch_store_strlen(addr);
482468
}
483469

484470
/*
@@ -488,21 +474,7 @@ fetch_store_strlen(unsigned long addr)
488474
static nokprobe_inline int
489475
fetch_store_string_user(unsigned long addr, void *dest, void *base)
490476
{
491-
const void __user *uaddr = (__force const void __user *)addr;
492-
int maxlen = get_loc_len(*(u32 *)dest);
493-
void *__dest;
494-
long ret;
495-
496-
if (unlikely(!maxlen))
497-
return -ENOMEM;
498-
499-
__dest = get_loc_data(dest, base);
500-
501-
ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
502-
if (ret >= 0)
503-
*(u32 *)dest = make_data_loc(ret, __dest - base);
504-
505-
return ret;
477+
return kern_fetch_store_string_user(addr, dest, base);
506478
}
507479

508480
/*
@@ -512,29 +484,7 @@ fetch_store_string_user(unsigned long addr, void *dest, void *base)
512484
static nokprobe_inline int
513485
fetch_store_string(unsigned long addr, void *dest, void *base)
514486
{
515-
int maxlen = get_loc_len(*(u32 *)dest);
516-
void *__dest;
517-
long ret;
518-
519-
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
520-
if ((unsigned long)addr < TASK_SIZE)
521-
return fetch_store_string_user(addr, dest, base);
522-
#endif
523-
524-
if (unlikely(!maxlen))
525-
return -ENOMEM;
526-
527-
__dest = get_loc_data(dest, base);
528-
529-
/*
530-
* Try to get string again, since the string can be changed while
531-
* probing.
532-
*/
533-
ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
534-
if (ret >= 0)
535-
*(u32 *)dest = make_data_loc(ret, __dest - base);
536-
537-
return ret;
487+
return kern_fetch_store_string(addr, dest, base);
538488
}
539489

540490
static nokprobe_inline int

kernel/trace/trace_events_synth.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
/* for gfp flag names */
1818
#include <linux/trace_events.h>
1919
#include <trace/events/mmflags.h>
20+
#include "trace_probe.h"
21+
#include "trace_probe_kernel.h"
2022

2123
#include "trace_synth.h"
2224

@@ -409,6 +411,7 @@ static unsigned int trace_string(struct synth_trace_event *entry,
409411
{
410412
unsigned int len = 0;
411413
char *str_field;
414+
int ret;
412415

413416
if (is_dynamic) {
414417
u32 data_offset;
@@ -417,19 +420,27 @@ static unsigned int trace_string(struct synth_trace_event *entry,
417420
data_offset += event->n_u64 * sizeof(u64);
418421
data_offset += data_size;
419422

420-
str_field = (char *)entry + data_offset;
421-
422-
len = strlen(str_val) + 1;
423-
strscpy(str_field, str_val, len);
423+
len = kern_fetch_store_strlen((unsigned long)str_val);
424424

425425
data_offset |= len << 16;
426426
*(u32 *)&entry->fields[*n_u64] = data_offset;
427427

428+
ret = kern_fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry);
429+
428430
(*n_u64)++;
429431
} else {
430432
str_field = (char *)&entry->fields[*n_u64];
431433

432-
strscpy(str_field, str_val, STR_VAR_LEN_MAX);
434+
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
435+
if ((unsigned long)str_val < TASK_SIZE)
436+
ret = strncpy_from_user_nofault(str_field, str_val, STR_VAR_LEN_MAX);
437+
else
438+
#endif
439+
ret = strncpy_from_kernel_nofault(str_field, str_val, STR_VAR_LEN_MAX);
440+
441+
if (ret < 0)
442+
strcpy(str_field, FAULT_STRING);
443+
433444
(*n_u64) += STR_VAR_LEN_MAX / sizeof(u64);
434445
}
435446

@@ -462,7 +473,7 @@ static notrace void trace_event_raw_event_synth(void *__data,
462473
val_idx = var_ref_idx[field_pos];
463474
str_val = (char *)(long)var_ref_vals[val_idx];
464475

465-
len = strlen(str_val) + 1;
476+
len = kern_fetch_store_strlen((unsigned long)str_val);
466477

467478
fields_size += len;
468479
}

kernel/trace/trace_kprobe.c

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "trace_kprobe_selftest.h"
2121
#include "trace_probe.h"
2222
#include "trace_probe_tmpl.h"
23+
#include "trace_probe_kernel.h"
2324

2425
#define KPROBE_EVENT_SYSTEM "kprobes"
2526
#define KRETPROBE_MAXACTIVE_MAX 4096
@@ -1223,29 +1224,14 @@ static const struct file_operations kprobe_profile_ops = {
12231224
static nokprobe_inline int
12241225
fetch_store_strlen_user(unsigned long addr)
12251226
{
1226-
const void __user *uaddr = (__force const void __user *)addr;
1227-
1228-
return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
1227+
return kern_fetch_store_strlen_user(addr);
12291228
}
12301229

12311230
/* Return the length of string -- including null terminal byte */
12321231
static nokprobe_inline int
12331232
fetch_store_strlen(unsigned long addr)
12341233
{
1235-
int ret, len = 0;
1236-
u8 c;
1237-
1238-
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
1239-
if (addr < TASK_SIZE)
1240-
return fetch_store_strlen_user(addr);
1241-
#endif
1242-
1243-
do {
1244-
ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
1245-
len++;
1246-
} while (c && ret == 0 && len < MAX_STRING_SIZE);
1247-
1248-
return (ret < 0) ? ret : len;
1234+
return kern_fetch_store_strlen(addr);
12491235
}
12501236

12511237
/*
@@ -1255,21 +1241,7 @@ fetch_store_strlen(unsigned long addr)
12551241
static nokprobe_inline int
12561242
fetch_store_string_user(unsigned long addr, void *dest, void *base)
12571243
{
1258-
const void __user *uaddr = (__force const void __user *)addr;
1259-
int maxlen = get_loc_len(*(u32 *)dest);
1260-
void *__dest;
1261-
long ret;
1262-
1263-
if (unlikely(!maxlen))
1264-
return -ENOMEM;
1265-
1266-
__dest = get_loc_data(dest, base);
1267-
1268-
ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
1269-
if (ret >= 0)
1270-
*(u32 *)dest = make_data_loc(ret, __dest - base);
1271-
1272-
return ret;
1244+
return kern_fetch_store_string_user(addr, dest, base);
12731245
}
12741246

12751247
/*
@@ -1279,29 +1251,7 @@ fetch_store_string_user(unsigned long addr, void *dest, void *base)
12791251
static nokprobe_inline int
12801252
fetch_store_string(unsigned long addr, void *dest, void *base)
12811253
{
1282-
int maxlen = get_loc_len(*(u32 *)dest);
1283-
void *__dest;
1284-
long ret;
1285-
1286-
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
1287-
if ((unsigned long)addr < TASK_SIZE)
1288-
return fetch_store_string_user(addr, dest, base);
1289-
#endif
1290-
1291-
if (unlikely(!maxlen))
1292-
return -ENOMEM;
1293-
1294-
__dest = get_loc_data(dest, base);
1295-
1296-
/*
1297-
* Try to get string again, since the string can be changed while
1298-
* probing.
1299-
*/
1300-
ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
1301-
if (ret >= 0)
1302-
*(u32 *)dest = make_data_loc(ret, __dest - base);
1303-
1304-
return ret;
1254+
return kern_fetch_store_string(addr, dest, base);
13051255
}
13061256

13071257
static nokprobe_inline int

0 commit comments

Comments
 (0)