2022-01-28 20:08:31

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 0/7] tracing: Misc bugfixes

Hi Steve,

This is an assorted bunch of bugfixes addressing a bugzilla bug,
smatch warnings, and related things I found while fixing those. In
particular, when looking at the bugzilla bug,
https://bugzilla.kernel.org/show_bug.cgi?id=215513, I noticed that the
err_log output looked truncated and looking further into it found that
it was, because the hist trigger command was very long, exceeding the
256 character limit.

Obviously that's too short, and the final 3 patches remove that
limitation.

Tom

The following changes since commit 4798f3784b1208138e06ab2de65666c19d51ab4d:

tools/tracing: Update Makefile to build rtla (2022-01-27 11:47:17 -0500)

are available in the Git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git ftrace/misc-bugfixes-v1

Tom Zanussi (7):
tracing: Fix smatch warning for null glob in
event_hist_trigger_parse()
tracing: Fix smatch warning for do while check in
event_hist_trigger_parse()
tracing: Propagate is_signed to expression
tracing: Don't inc err_log entry count if entry allocation fails
tracing: Remove size restriction on tracing_log_err cmd strings
tracing: Remove size restriction on hist trigger cmd error logging
tracing: Remove size restriction on synthetic event cmd error logging

kernel/trace/trace.c | 56 ++++++++++++++++++++++++-------
kernel/trace/trace.h | 2 +-
kernel/trace/trace_events_hist.c | 39 ++++++++++++++++-----
kernel/trace/trace_events_synth.c | 17 ++++++++--
4 files changed, 88 insertions(+), 26 deletions(-)

--
2.17.1


2022-01-28 20:08:59

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 1/7] tracing: Fix smatch warning for null glob in event_hist_trigger_parse()

The recent rename of event_hist_trigger_parse() caused smatch
re-evaluation of trace_events_hist.c and as a result an old warning
was found:

kernel/trace/trace_events_hist.c:6174 event_hist_trigger_parse()
error: we previously assumed 'glob' could be null (see line 6166)

glob should never be null (and apparently smatch can also figure that
out and skip the warning when using the cross-function DB (but which
can't be used with a 0day build as it takes too much time to
generate)).

Nonetheless for clarity, remove the test but add a WARN_ON() in case
the code ever changes.

Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace_events_hist.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index cd9610688ddc..e0860146dd39 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -6164,7 +6164,9 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,

lockdep_assert_held(&event_mutex);

- if (glob && strlen(glob)) {
+ WARN_ON(!glob);
+
+ if (strlen(glob)) {
hist_err_clear();
last_cmd_set(file, param);
}
--
2.17.1

2022-01-28 20:09:00

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 2/7] tracing: Fix smatch warning for do while check in event_hist_trigger_parse()

The patch ec5ce0987541: "tracing: Allow whitespace to surround hist
trigger filter" from Jan 15, 2018, leads to the following Smatch
static checker warning:

kernel/trace/trace_events_hist.c:6199 event_hist_trigger_parse()
warn: 'p' can't be NULL.

Since p is always checked for a NULL value at the top of loop and
nothing in the rest of the loop will set it to NULL, the warning
is correct and might as well be 1 to silence the warning.

Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace_events_hist.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index e0860146dd39..b894d68082ea 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -6199,7 +6199,7 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
continue;
}
break;
- } while (p);
+ } while (1);

if (!p)
param = NULL;
--
2.17.1

2022-01-28 20:09:01

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 3/7] tracing: Propagate is_signed to expression

During expression parsing, a new expression field is created which
should inherit the properties of the operands, such as size and
is_signed.

is_signed propagation was missing, causing spurious errors with signed
operands. Add it in parse_expr() and parse_unary() to fix the problem.

Reported-by: Yordan Karadzhov <[email protected]>
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215513
Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace_events_hist.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index b894d68082ea..ada87bfb5bb8 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2503,6 +2503,8 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
(HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
expr->fn = hist_field_unary_minus;
expr->operands[0] = operand1;
+ expr->size = operand1->size;
+ expr->is_signed = operand1->is_signed;
expr->operator = FIELD_OP_UNARY_MINUS;
expr->name = expr_str(expr, 0);
expr->type = kstrdup_const(operand1->type, GFP_KERNEL);
@@ -2719,6 +2721,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,

/* The operand sizes should be the same, so just pick one */
expr->size = operand1->size;
+ expr->is_signed = operand1->is_signed;

expr->operator = field_op;
expr->type = kstrdup_const(operand1->type, GFP_KERNEL);
--
2.17.1

2022-01-28 20:09:20

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 4/7] tracing: Don't inc err_log entry count if entry allocation fails

tr->n_err_log_entries should only be increased if entry allocation
succeeds.

Doing it when it fails won't cause any problems other than wasting an
entry, but should be fixed anyway.

Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index a73d78dcda2c..addd8297874e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7740,7 +7740,8 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
err = kzalloc(sizeof(*err), GFP_KERNEL);
if (!err)
err = ERR_PTR(-ENOMEM);
- tr->n_err_log_entries++;
+ else
+ tr->n_err_log_entries++;

return err;
}
--
2.17.1

2022-01-28 20:09:27

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 6/7] tracing: Remove size restriction on hist trigger cmd error logging

Currently, hist trigger command error strings are restricted to a
length of MAX_FILTER_STR_VAL (256), which is too short for some
commands already seen in the wild (with cmd strings longer than that
showing up truncated in err_log).

Remove the restriction so that no hist trigger command error string is
ever truncated.

Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace_events_hist.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index ada87bfb5bb8..be4a001a607f 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -727,11 +727,16 @@ static struct track_data *track_data_alloc(unsigned int key_len,
return data;
}

-static char last_cmd[MAX_FILTER_STR_VAL];
+#define HIST_PREFIX "hist:"
+
+static char *last_cmd;
static char last_cmd_loc[MAX_FILTER_STR_VAL];

static int errpos(char *str)
{
+ if (!str || !last_cmd)
+ return 0;
+
return err_pos(last_cmd, str);
}

@@ -739,12 +744,19 @@ static void last_cmd_set(struct trace_event_file *file, char *str)
{
const char *system = NULL, *name = NULL;
struct trace_event_call *call;
+ int len = 0;

if (!str)
return;

- strcpy(last_cmd, "hist:");
- strncat(last_cmd, str, MAX_FILTER_STR_VAL - 1 - sizeof("hist:"));
+ len += sizeof(HIST_PREFIX) + strlen(str) + 1;
+ kfree(last_cmd);
+ last_cmd = kzalloc(len, GFP_KERNEL);
+ if (!last_cmd)
+ return;
+
+ strcpy(last_cmd, HIST_PREFIX);
+ strncat(last_cmd, str, len - 1 - sizeof(HIST_PREFIX));

if (file) {
call = file->event_call;
@@ -757,18 +769,22 @@ static void last_cmd_set(struct trace_event_file *file, char *str)
}

if (system)
- snprintf(last_cmd_loc, MAX_FILTER_STR_VAL, "hist:%s:%s", system, name);
+ snprintf(last_cmd_loc, MAX_FILTER_STR_VAL, HIST_PREFIX "%s:%s", system, name);
}

-static void hist_err(struct trace_array *tr, u8 err_type, u8 err_pos)
+static void hist_err(struct trace_array *tr, u8 err_type, u16 err_pos)
{
+ if (!last_cmd)
+ return;
+
tracing_log_err(tr, last_cmd_loc, last_cmd, err_text,
err_type, err_pos);
}

static void hist_err_clear(void)
{
- last_cmd[0] = '\0';
+ if (last_cmd)
+ last_cmd[0] = '\0';
last_cmd_loc[0] = '\0';
}

@@ -5610,7 +5626,7 @@ static int event_hist_trigger_print(struct seq_file *m,
bool have_var = false;
unsigned int i;

- seq_puts(m, "hist:");
+ seq_puts(m, HIST_PREFIX);

if (data->name)
seq_printf(m, "%s:", data->name);
--
2.17.1

2022-01-28 20:09:29

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 5/7] tracing: Remove size restriction on tracing_log_err cmd strings

Currently, tracing_log_err.cmd strings are restricted to a length of
MAX_FILTER_STR_VAL (256), which is too short for some commands already
seen in the wild (with cmd strings longer than that showing up
truncated).

Remove the restriction so that no command string is ever truncated.

Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace.c | 55 +++++++++++++++++++++++++++++++++-----------
kernel/trace/trace.h | 2 +-
2 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index addd8297874e..ba62607f9957 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7719,7 +7719,7 @@ const struct file_operations trace_min_max_fops = {
struct err_info {
const char **errs; /* ptr to loc-specific array of err strings */
u8 type; /* index into errs -> specific err string */
- u8 pos; /* MAX_FILTER_STR_VAL = 256 */
+ u16 pos; /* caret position */
u64 ts;
};

@@ -7727,26 +7727,52 @@ struct tracing_log_err {
struct list_head list;
struct err_info info;
char loc[TRACING_LOG_LOC_MAX]; /* err location */
- char cmd[MAX_FILTER_STR_VAL]; /* what caused err */
+ char *cmd; /* what caused err */
};

static DEFINE_MUTEX(tracing_err_log_lock);

-static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
+static struct tracing_log_err *alloc_tracing_log_err(int len)
+{
+ struct tracing_log_err *err;
+
+ err = kzalloc(sizeof(*err), GFP_KERNEL);
+ if (!err)
+ return ERR_PTR(-ENOMEM);
+
+ err->cmd = kzalloc(len, GFP_KERNEL);
+ if (!err->cmd) {
+ kfree(err);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return err;
+}
+
+static void free_tracing_log_err(struct tracing_log_err *err)
+{
+ kfree(err->cmd);
+ kfree(err);
+}
+
+static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr,
+ int len)
{
struct tracing_log_err *err;

if (tr->n_err_log_entries < TRACING_LOG_ERRS_MAX) {
- err = kzalloc(sizeof(*err), GFP_KERNEL);
- if (!err)
- err = ERR_PTR(-ENOMEM);
- else
+ err = alloc_tracing_log_err(len);
+ if (PTR_ERR(err) != -ENOMEM)
tr->n_err_log_entries++;

return err;
}

err = list_first_entry(&tr->err_log, struct tracing_log_err, list);
+ kfree(err->cmd);
+ err->cmd = kzalloc(len, GFP_KERNEL);
+ if (!err->cmd)
+ return ERR_PTR(-ENOMEM);
list_del(&err->list);

return err;
@@ -7807,22 +7833,25 @@ unsigned int err_pos(char *cmd, const char *str)
*/
void tracing_log_err(struct trace_array *tr,
const char *loc, const char *cmd,
- const char **errs, u8 type, u8 pos)
+ const char **errs, u8 type, u16 pos)
{
struct tracing_log_err *err;
+ int len = 0;

if (!tr)
tr = &global_trace;

+ len += sizeof(CMD_PREFIX) + 2 * sizeof("\n") + strlen(cmd) + 1;
+
mutex_lock(&tracing_err_log_lock);
- err = get_tracing_log_err(tr);
+ err = get_tracing_log_err(tr, len);
if (PTR_ERR(err) == -ENOMEM) {
mutex_unlock(&tracing_err_log_lock);
return;
}

snprintf(err->loc, TRACING_LOG_LOC_MAX, "%s: error: ", loc);
- snprintf(err->cmd, MAX_FILTER_STR_VAL,"\n" CMD_PREFIX "%s\n", cmd);
+ snprintf(err->cmd, len, "\n" CMD_PREFIX "%s\n", cmd);

err->info.errs = errs;
err->info.type = type;
@@ -7840,7 +7869,7 @@ static void clear_tracing_err_log(struct trace_array *tr)
mutex_lock(&tracing_err_log_lock);
list_for_each_entry_safe(err, next, &tr->err_log, list) {
list_del(&err->list);
- kfree(err);
+ free_tracing_log_err(err);
}

tr->n_err_log_entries = 0;
@@ -7868,9 +7897,9 @@ static void tracing_err_log_seq_stop(struct seq_file *m, void *v)
mutex_unlock(&tracing_err_log_lock);
}

-static void tracing_err_log_show_pos(struct seq_file *m, u8 pos)
+static void tracing_err_log_show_pos(struct seq_file *m, u16 pos)
{
- u8 i;
+ u16 i;

for (i = 0; i < sizeof(CMD_PREFIX) - 1; i++)
seq_putc(m, ' ');
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index d038ddbf1bea..0f5e22238cd2 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1878,7 +1878,7 @@ extern ssize_t trace_parse_run_command(struct file *file,
extern unsigned int err_pos(char *cmd, const char *str);
extern void tracing_log_err(struct trace_array *tr,
const char *loc, const char *cmd,
- const char **errs, u8 type, u8 pos);
+ const char **errs, u8 type, u16 pos);

/*
* Normal trace_printk() and friends allocates special buffers
--
2.17.1

2022-01-28 20:11:12

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 7/7] tracing: Remove size restriction on synthetic event cmd error logging

Currently, synthetic event command error strings are restricted to a
length of MAX_FILTER_STR_VAL (256), which is too short for some
commands already seen in the wild (with cmd strings longer than that
showing up truncated in err_log).

Remove the restriction so that no synthetic event command error string
is ever truncated.

Signed-off-by: Tom Zanussi <[email protected]>
---
kernel/trace/trace_events_synth.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 149011e34ad9..7d50b4251c60 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -42,10 +42,13 @@ enum { ERRORS };

static const char *err_text[] = { ERRORS };

-static char last_cmd[MAX_FILTER_STR_VAL];
+static char *last_cmd;

static int errpos(const char *str)
{
+ if (!str || !last_cmd)
+ return 0;
+
return err_pos(last_cmd, str);
}

@@ -54,11 +57,19 @@ static void last_cmd_set(const char *str)
if (!str)
return;

- strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);
+ kfree(last_cmd);
+ last_cmd = kzalloc(strlen(str) + 1, GFP_KERNEL);
+ if (!last_cmd)
+ return;
+
+ strncpy(last_cmd, str, strlen(str));
}

-static void synth_err(u8 err_type, u8 err_pos)
+static void synth_err(u8 err_type, u16 err_pos)
{
+ if (!last_cmd)
+ return;
+
tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
err_type, err_pos);
}
--
2.17.1

2022-01-28 22:22:27

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH 0/7] tracing: Misc bugfixes

On Thu, 27 Jan 2022 15:44:14 -0600
Tom Zanussi <[email protected]> wrote:

> Hi Steve,
>
> This is an assorted bunch of bugfixes addressing a bugzilla bug,
> smatch warnings, and related things I found while fixing those. In
> particular, when looking at the bugzilla bug,
> https://bugzilla.kernel.org/show_bug.cgi?id=215513, I noticed that the
> err_log output looked truncated and looking further into it found that
> it was, because the hist trigger command was very long, exceeding the
> 256 character limit.
>
> Obviously that's too short, and the final 3 patches remove that
> limitation.

Thanks Tom,

I'm going to run all of them through my tests, but I'm only going to push
the first 4 to Linus for rc, and the limitation limit can wait till the
merge window.

-- Steve

2022-01-28 22:36:53

by Tom Zanussi

[permalink] [raw]
Subject: Re: [PATCH 0/7] tracing: Misc bugfixes

On Thu, 2022-01-27 at 18:26 -0500, Steven Rostedt wrote:
> On Thu, 27 Jan 2022 15:44:14 -0600
> Tom Zanussi <[email protected]> wrote:
>
> > Hi Steve,
> >
> > This is an assorted bunch of bugfixes addressing a bugzilla bug,
> > smatch warnings, and related things I found while fixing those. In
> > particular, when looking at the bugzilla bug,
> > https://bugzilla.kernel.org/show_bug.cgi?id=215513, I noticed that
> > the
> > err_log output looked truncated and looking further into it found
> > that
> > it was, because the hist trigger command was very long, exceeding
> > the
> > 256 character limit.
> >
> > Obviously that's too short, and the final 3 patches remove that
> > limitation.
>
> Thanks Tom,
>
> I'm going to run all of them through my tests, but I'm only going to
> push
> the first 4 to Linus for rc, and the limitation limit can wait till
> the
> merge window.
>

OK, sounds good, thanks.

Tom

> -- Steve