aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-09-09 10:00:28 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-09-14 11:42:30 -0400
commit4aeb69672d011fac5c8df671f3ca89f7987c104e (patch)
treed2a96af23b9d6ac742725bb17aafe3d4b377cb6a /kernel/trace/ftrace.c
parent2bccfffd1538f3523847583213567e2f7ce00926 (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.c67
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
1370struct ftrace_iterator { 1370struct 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
1379static void * 1381static void *
1380t_hash_next(struct seq_file *m, void *v, loff_t *pos) 1382t_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
1415static void *t_hash_start(struct seq_file *m, loff_t *pos) 1424static 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
1438static int t_hash_show(struct seq_file *m, void *v) 1450static int
1451t_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
1501static void *t_start(struct seq_file *m, loff_t *pos) 1520static 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
1539static void t_stop(struct seq_file *m, void *p) 1562static void t_stop(struct seq_file *m, void *p)
@@ -1544,16 +1567,18 @@ static void t_stop(struct seq_file *m, void *p)
1544static int t_show(struct seq_file *m, void *v) 1567static 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