diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-09-09 10:00:28 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-09-14 11:42:30 -0400 |
commit | 4aeb69672d011fac5c8df671f3ca89f7987c104e (patch) | |
tree | d2a96af23b9d6ac742725bb17aafe3d4b377cb6a /kernel/trace/ftrace.c | |
parent | 2bccfffd1538f3523847583213567e2f7ce00926 (diff) |
tracing: Replace typecasted void pointer in set_ftrace_filter code
The set_ftrace_filter uses seq_file and reads from two lists. The
pointer returned by t_next() can either be of type struct dyn_ftrace
or struct ftrace_func_probe. If there is a bug (there was one)
the wrong pointer may be used and the reference can cause an oops.
This patch makes t_next() and friends only return the iterator structure
which now has a pointer of type struct dyn_ftrace and struct
ftrace_func_probe. The t_show() can now test if the pointer is NULL or
not and if the pointer exists, it is guaranteed to be of the correct type.
Now if there's a bug, only wrong data will be shown but not an oops.
Cc: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 585ea27025b1..c8db0dbb984e 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -1368,25 +1368,29 @@ enum { | |||
1368 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ | 1368 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ |
1369 | 1369 | ||
1370 | struct ftrace_iterator { | 1370 | struct ftrace_iterator { |
1371 | loff_t func_pos; | 1371 | loff_t func_pos; |
1372 | struct ftrace_page *pg; | 1372 | struct ftrace_page *pg; |
1373 | int hidx; | 1373 | struct dyn_ftrace *func; |
1374 | int idx; | 1374 | struct ftrace_func_probe *probe; |
1375 | unsigned flags; | 1375 | struct trace_parser parser; |
1376 | struct trace_parser parser; | 1376 | int hidx; |
1377 | int idx; | ||
1378 | unsigned flags; | ||
1377 | }; | 1379 | }; |
1378 | 1380 | ||
1379 | static void * | 1381 | static void * |
1380 | t_hash_next(struct seq_file *m, void *v, loff_t *pos) | 1382 | t_hash_next(struct seq_file *m, loff_t *pos) |
1381 | { | 1383 | { |
1382 | struct ftrace_iterator *iter = m->private; | 1384 | struct ftrace_iterator *iter = m->private; |
1383 | struct hlist_node *hnd = v; | 1385 | struct hlist_node *hnd = NULL; |
1384 | struct hlist_head *hhd; | 1386 | struct hlist_head *hhd; |
1385 | 1387 | ||
1386 | WARN_ON(!(iter->flags & FTRACE_ITER_HASH)); | 1388 | WARN_ON(!(iter->flags & FTRACE_ITER_HASH)); |
1387 | 1389 | ||
1388 | (*pos)++; | 1390 | (*pos)++; |
1389 | 1391 | ||
1392 | if (iter->probe) | ||
1393 | hnd = &iter->probe->node; | ||
1390 | retry: | 1394 | retry: |
1391 | if (iter->hidx >= FTRACE_FUNC_HASHSIZE) | 1395 | if (iter->hidx >= FTRACE_FUNC_HASHSIZE) |
1392 | return NULL; | 1396 | return NULL; |
@@ -1409,7 +1413,12 @@ t_hash_next(struct seq_file *m, void *v, loff_t *pos) | |||
1409 | } | 1413 | } |
1410 | } | 1414 | } |
1411 | 1415 | ||
1412 | return hnd; | 1416 | if (WARN_ON_ONCE(!hnd)) |
1417 | return NULL; | ||
1418 | |||
1419 | iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node); | ||
1420 | |||
1421 | return iter; | ||
1413 | } | 1422 | } |
1414 | 1423 | ||
1415 | static void *t_hash_start(struct seq_file *m, loff_t *pos) | 1424 | static void *t_hash_start(struct seq_file *m, loff_t *pos) |
@@ -1428,19 +1437,24 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos) | |||
1428 | 1437 | ||
1429 | iter->hidx = 0; | 1438 | iter->hidx = 0; |
1430 | for (l = 0; l <= (*pos - iter->func_pos); ) { | 1439 | for (l = 0; l <= (*pos - iter->func_pos); ) { |
1431 | p = t_hash_next(m, p, &l); | 1440 | p = t_hash_next(m, &l); |
1432 | if (!p) | 1441 | if (!p) |
1433 | break; | 1442 | break; |
1434 | } | 1443 | } |
1435 | return p; | 1444 | if (!p) |
1445 | return NULL; | ||
1446 | |||
1447 | return iter; | ||
1436 | } | 1448 | } |
1437 | 1449 | ||
1438 | static int t_hash_show(struct seq_file *m, void *v) | 1450 | static int |
1451 | t_hash_show(struct seq_file *m, struct ftrace_iterator *iter) | ||
1439 | { | 1452 | { |
1440 | struct ftrace_func_probe *rec; | 1453 | struct ftrace_func_probe *rec; |
1441 | struct hlist_node *hnd = v; | ||
1442 | 1454 | ||
1443 | rec = hlist_entry(hnd, struct ftrace_func_probe, node); | 1455 | rec = iter->probe; |
1456 | if (WARN_ON_ONCE(!rec)) | ||
1457 | return -EIO; | ||
1444 | 1458 | ||
1445 | if (rec->ops->print) | 1459 | if (rec->ops->print) |
1446 | return rec->ops->print(m, rec->ip, rec->ops, rec->data); | 1460 | return rec->ops->print(m, rec->ip, rec->ops, rec->data); |
@@ -1461,7 +1475,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
1461 | struct dyn_ftrace *rec = NULL; | 1475 | struct dyn_ftrace *rec = NULL; |
1462 | 1476 | ||
1463 | if (iter->flags & FTRACE_ITER_HASH) | 1477 | if (iter->flags & FTRACE_ITER_HASH) |
1464 | return t_hash_next(m, v, pos); | 1478 | return t_hash_next(m, pos); |
1465 | 1479 | ||
1466 | (*pos)++; | 1480 | (*pos)++; |
1467 | 1481 | ||
@@ -1495,7 +1509,12 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
1495 | } | 1509 | } |
1496 | } | 1510 | } |
1497 | 1511 | ||
1498 | return rec; | 1512 | if (!rec) |
1513 | return NULL; | ||
1514 | |||
1515 | iter->func = rec; | ||
1516 | |||
1517 | return iter; | ||
1499 | } | 1518 | } |
1500 | 1519 | ||
1501 | static void *t_start(struct seq_file *m, loff_t *pos) | 1520 | static void *t_start(struct seq_file *m, loff_t *pos) |
@@ -1530,10 +1549,14 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
1530 | break; | 1549 | break; |
1531 | } | 1550 | } |
1532 | 1551 | ||
1533 | if (!p && iter->flags & FTRACE_ITER_FILTER) | 1552 | if (!p) { |
1534 | return t_hash_start(m, pos); | 1553 | if (iter->flags & FTRACE_ITER_FILTER) |
1554 | return t_hash_start(m, pos); | ||
1535 | 1555 | ||
1536 | return p; | 1556 | return NULL; |
1557 | } | ||
1558 | |||
1559 | return iter; | ||
1537 | } | 1560 | } |
1538 | 1561 | ||
1539 | static void t_stop(struct seq_file *m, void *p) | 1562 | static void t_stop(struct seq_file *m, void *p) |
@@ -1544,16 +1567,18 @@ static void t_stop(struct seq_file *m, void *p) | |||
1544 | static int t_show(struct seq_file *m, void *v) | 1567 | static int t_show(struct seq_file *m, void *v) |
1545 | { | 1568 | { |
1546 | struct ftrace_iterator *iter = m->private; | 1569 | struct ftrace_iterator *iter = m->private; |
1547 | struct dyn_ftrace *rec = v; | 1570 | struct dyn_ftrace *rec; |
1548 | 1571 | ||
1549 | if (iter->flags & FTRACE_ITER_HASH) | 1572 | if (iter->flags & FTRACE_ITER_HASH) |
1550 | return t_hash_show(m, v); | 1573 | return t_hash_show(m, iter); |
1551 | 1574 | ||
1552 | if (iter->flags & FTRACE_ITER_PRINTALL) { | 1575 | if (iter->flags & FTRACE_ITER_PRINTALL) { |
1553 | seq_printf(m, "#### all functions enabled ####\n"); | 1576 | seq_printf(m, "#### all functions enabled ####\n"); |
1554 | return 0; | 1577 | return 0; |
1555 | } | 1578 | } |
1556 | 1579 | ||
1580 | rec = iter->func; | ||
1581 | |||
1557 | if (!rec) | 1582 | if (!rec) |
1558 | return 0; | 1583 | return 0; |
1559 | 1584 | ||