aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2015-06-15 17:50:25 -0400
committerSteven Rostedt <rostedt@goodmis.org>2015-06-17 07:13:30 -0400
commit2cf30dc180cea808077f003c5116388183e54f9e (patch)
tree056fceae0c35d8fed52f7e8344a79524beba30f4
parent108029323910c5dd1ef8fa2d10da1ce5fbce6e12 (diff)
tracing: Have filter check for balanced ops
When the following filter is used it causes a warning to trigger: # cd /sys/kernel/debug/tracing # echo "((dev==1)blocks==2)" > events/ext4/ext4_truncate_exit/filter -bash: echo: write error: Invalid argument # cat events/ext4/ext4_truncate_exit/filter ((dev==1)blocks==2) ^ parse_error: No error ------------[ cut here ]------------ WARNING: CPU: 2 PID: 1223 at kernel/trace/trace_events_filter.c:1640 replace_preds+0x3c5/0x990() Modules linked in: bnep lockd grace bluetooth ... CPU: 3 PID: 1223 Comm: bash Tainted: G W 4.1.0-rc3-test+ #450 Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v02.05 05/07/2012 0000000000000668 ffff8800c106bc98 ffffffff816ed4f9 ffff88011ead0cf0 0000000000000000 ffff8800c106bcd8 ffffffff8107fb07 ffffffff8136b46c ffff8800c7d81d48 ffff8800d4c2bc00 ffff8800d4d4f920 00000000ffffffea Call Trace: [<ffffffff816ed4f9>] dump_stack+0x4c/0x6e [<ffffffff8107fb07>] warn_slowpath_common+0x97/0xe0 [<ffffffff8136b46c>] ? _kstrtoull+0x2c/0x80 [<ffffffff8107fb6a>] warn_slowpath_null+0x1a/0x20 [<ffffffff81159065>] replace_preds+0x3c5/0x990 [<ffffffff811596b2>] create_filter+0x82/0xb0 [<ffffffff81159944>] apply_event_filter+0xd4/0x180 [<ffffffff81152bbf>] event_filter_write+0x8f/0x120 [<ffffffff811db2a8>] __vfs_write+0x28/0xe0 [<ffffffff811dda43>] ? __sb_start_write+0x53/0xf0 [<ffffffff812e51e0>] ? security_file_permission+0x30/0xc0 [<ffffffff811dc408>] vfs_write+0xb8/0x1b0 [<ffffffff811dc72f>] SyS_write+0x4f/0xb0 [<ffffffff816f5217>] system_call_fastpath+0x12/0x6a ---[ end trace e11028bd95818dcd ]--- Worse yet, reading the error message (the filter again) it says that there was no error, when there clearly was. The issue is that the code that checks the input does not check for balanced ops. That is, having an op between a closed parenthesis and the next token. This would only cause a warning, and fail out before doing any real harm, but it should still not caues a warning, and the error reported should work: # cd /sys/kernel/debug/tracing # echo "((dev==1)blocks==2)" > events/ext4/ext4_truncate_exit/filter -bash: echo: write error: Invalid argument # cat events/ext4/ext4_truncate_exit/filter ((dev==1)blocks==2) ^ parse_error: Meaningless filter expression And give no kernel warning. Link: http://lkml.kernel.org/r/20150615175025.7e809215@gandalf.local.home Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Ingo Molnar <mingo@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: stable@vger.kernel.org # 2.6.31+ Reported-by: Vince Weaver <vincent.weaver@maine.edu> Tested-by: Vince Weaver <vincent.weaver@maine.edu> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--kernel/trace/trace_events_filter.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index ced69da0ff55..7f2e97ce71a7 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1369,19 +1369,26 @@ static int check_preds(struct filter_parse_state *ps)
1369{ 1369{
1370 int n_normal_preds = 0, n_logical_preds = 0; 1370 int n_normal_preds = 0, n_logical_preds = 0;
1371 struct postfix_elt *elt; 1371 struct postfix_elt *elt;
1372 int cnt = 0;
1372 1373
1373 list_for_each_entry(elt, &ps->postfix, list) { 1374 list_for_each_entry(elt, &ps->postfix, list) {
1374 if (elt->op == OP_NONE) 1375 if (elt->op == OP_NONE) {
1376 cnt++;
1375 continue; 1377 continue;
1378 }
1376 1379
1377 if (elt->op == OP_AND || elt->op == OP_OR) { 1380 if (elt->op == OP_AND || elt->op == OP_OR) {
1378 n_logical_preds++; 1381 n_logical_preds++;
1382 cnt--;
1379 continue; 1383 continue;
1380 } 1384 }
1385 if (elt->op != OP_NOT)
1386 cnt--;
1381 n_normal_preds++; 1387 n_normal_preds++;
1388 WARN_ON_ONCE(cnt < 0);
1382 } 1389 }
1383 1390
1384 if (!n_normal_preds || n_logical_preds >= n_normal_preds) { 1391 if (cnt != 1 || !n_normal_preds || n_logical_preds >= n_normal_preds) {
1385 parse_error(ps, FILT_ERR_INVALID_FILTER, 0); 1392 parse_error(ps, FILT_ERR_INVALID_FILTER, 0);
1386 return -EINVAL; 1393 return -EINVAL;
1387 } 1394 }