diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2008-10-01 10:52:51 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-14 04:39:07 -0400 |
commit | 7104f300c5a69b46dda00d898034dd05c9f21739 (patch) | |
tree | a8c885bd61fb1e269f277837b2e521179faf8739 /kernel/trace/trace.c | |
parent | 797d3712a9dd75c720558612be05f42c031a7bb5 (diff) |
ftrace: type cast filter+verifier
The mmiotrace map had a bug that would typecast the entry from
the trace to the wrong type. That is a known danger of C typecasts,
there's absolutely zero checking done on them.
Help that problem a bit by using a GCC extension to implement a
type filter that restricts the types that a trace record can be
cast into, and by adding a dynamic check (in debug mode) to verify
the type of the entry.
This patch adds a macro to assign all entries of ftrace using the type
of the variable and checking the entry id. The typecasts are now done
in the macro for only those types that it knows about, which should
be all the types that are allowed to be read from the tracer.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c1634068adfa..948f7d821c62 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1350 | } | 1350 | } |
1351 | switch (entry->type) { | 1351 | switch (entry->type) { |
1352 | case TRACE_FN: { | 1352 | case TRACE_FN: { |
1353 | struct ftrace_entry *field = (struct ftrace_entry *)entry; | 1353 | struct ftrace_entry *field; |
1354 | |||
1355 | trace_assign_type(field, entry); | ||
1354 | 1356 | ||
1355 | seq_print_ip_sym(s, field->ip, sym_flags); | 1357 | seq_print_ip_sym(s, field->ip, sym_flags); |
1356 | trace_seq_puts(s, " ("); | 1358 | trace_seq_puts(s, " ("); |
@@ -1363,8 +1365,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1363 | } | 1365 | } |
1364 | case TRACE_CTX: | 1366 | case TRACE_CTX: |
1365 | case TRACE_WAKE: { | 1367 | case TRACE_WAKE: { |
1366 | struct ctx_switch_entry *field = | 1368 | struct ctx_switch_entry *field; |
1367 | (struct ctx_switch_entry *)entry; | 1369 | |
1370 | trace_assign_type(field, entry); | ||
1368 | 1371 | ||
1369 | T = field->next_state < sizeof(state_to_char) ? | 1372 | T = field->next_state < sizeof(state_to_char) ? |
1370 | state_to_char[field->next_state] : 'X'; | 1373 | state_to_char[field->next_state] : 'X'; |
@@ -1384,7 +1387,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1384 | break; | 1387 | break; |
1385 | } | 1388 | } |
1386 | case TRACE_SPECIAL: { | 1389 | case TRACE_SPECIAL: { |
1387 | struct special_entry *field = (struct special_entry *)entry; | 1390 | struct special_entry *field; |
1391 | |||
1392 | trace_assign_type(field, entry); | ||
1388 | 1393 | ||
1389 | trace_seq_printf(s, "# %ld %ld %ld\n", | 1394 | trace_seq_printf(s, "# %ld %ld %ld\n", |
1390 | field->arg1, | 1395 | field->arg1, |
@@ -1393,7 +1398,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1393 | break; | 1398 | break; |
1394 | } | 1399 | } |
1395 | case TRACE_STACK: { | 1400 | case TRACE_STACK: { |
1396 | struct stack_entry *field = (struct stack_entry *)entry; | 1401 | struct stack_entry *field; |
1402 | |||
1403 | trace_assign_type(field, entry); | ||
1397 | 1404 | ||
1398 | for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { | 1405 | for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { |
1399 | if (i) | 1406 | if (i) |
@@ -1404,7 +1411,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1404 | break; | 1411 | break; |
1405 | } | 1412 | } |
1406 | case TRACE_PRINT: { | 1413 | case TRACE_PRINT: { |
1407 | struct print_entry *field = (struct print_entry *)entry; | 1414 | struct print_entry *field; |
1415 | |||
1416 | trace_assign_type(field, entry); | ||
1408 | 1417 | ||
1409 | seq_print_ip_sym(s, field->ip, sym_flags); | 1418 | seq_print_ip_sym(s, field->ip, sym_flags); |
1410 | trace_seq_printf(s, ": %s", field->buf); | 1419 | trace_seq_printf(s, ": %s", field->buf); |
@@ -1454,7 +1463,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1454 | 1463 | ||
1455 | switch (entry->type) { | 1464 | switch (entry->type) { |
1456 | case TRACE_FN: { | 1465 | case TRACE_FN: { |
1457 | struct ftrace_entry *field = (struct ftrace_entry *)entry; | 1466 | struct ftrace_entry *field; |
1467 | |||
1468 | trace_assign_type(field, entry); | ||
1458 | 1469 | ||
1459 | ret = seq_print_ip_sym(s, field->ip, sym_flags); | 1470 | ret = seq_print_ip_sym(s, field->ip, sym_flags); |
1460 | if (!ret) | 1471 | if (!ret) |
@@ -1480,8 +1491,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1480 | } | 1491 | } |
1481 | case TRACE_CTX: | 1492 | case TRACE_CTX: |
1482 | case TRACE_WAKE: { | 1493 | case TRACE_WAKE: { |
1483 | struct ctx_switch_entry *field = | 1494 | struct ctx_switch_entry *field; |
1484 | (struct ctx_switch_entry *)entry; | 1495 | |
1496 | trace_assign_type(field, entry); | ||
1485 | 1497 | ||
1486 | S = field->prev_state < sizeof(state_to_char) ? | 1498 | S = field->prev_state < sizeof(state_to_char) ? |
1487 | state_to_char[field->prev_state] : 'X'; | 1499 | state_to_char[field->prev_state] : 'X'; |
@@ -1501,7 +1513,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1501 | break; | 1513 | break; |
1502 | } | 1514 | } |
1503 | case TRACE_SPECIAL: { | 1515 | case TRACE_SPECIAL: { |
1504 | struct special_entry *field = (struct special_entry *)entry; | 1516 | struct special_entry *field; |
1517 | |||
1518 | trace_assign_type(field, entry); | ||
1505 | 1519 | ||
1506 | ret = trace_seq_printf(s, "# %ld %ld %ld\n", | 1520 | ret = trace_seq_printf(s, "# %ld %ld %ld\n", |
1507 | field->arg1, | 1521 | field->arg1, |
@@ -1512,7 +1526,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1512 | break; | 1526 | break; |
1513 | } | 1527 | } |
1514 | case TRACE_STACK: { | 1528 | case TRACE_STACK: { |
1515 | struct stack_entry *field = (struct stack_entry *)entry; | 1529 | struct stack_entry *field; |
1530 | |||
1531 | trace_assign_type(field, entry); | ||
1516 | 1532 | ||
1517 | for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { | 1533 | for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { |
1518 | if (i) { | 1534 | if (i) { |
@@ -1531,7 +1547,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1531 | break; | 1547 | break; |
1532 | } | 1548 | } |
1533 | case TRACE_PRINT: { | 1549 | case TRACE_PRINT: { |
1534 | struct print_entry *field = (struct print_entry *)entry; | 1550 | struct print_entry *field; |
1551 | |||
1552 | trace_assign_type(field, entry); | ||
1535 | 1553 | ||
1536 | seq_print_ip_sym(s, field->ip, sym_flags); | 1554 | seq_print_ip_sym(s, field->ip, sym_flags); |
1537 | trace_seq_printf(s, ": %s", field->buf); | 1555 | trace_seq_printf(s, ": %s", field->buf); |
@@ -1562,7 +1580,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
1562 | 1580 | ||
1563 | switch (entry->type) { | 1581 | switch (entry->type) { |
1564 | case TRACE_FN: { | 1582 | case TRACE_FN: { |
1565 | struct ftrace_entry *field = (struct ftrace_entry *)entry; | 1583 | struct ftrace_entry *field; |
1584 | |||
1585 | trace_assign_type(field, entry); | ||
1566 | 1586 | ||
1567 | ret = trace_seq_printf(s, "%x %x\n", | 1587 | ret = trace_seq_printf(s, "%x %x\n", |
1568 | field->ip, | 1588 | field->ip, |
@@ -1573,8 +1593,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
1573 | } | 1593 | } |
1574 | case TRACE_CTX: | 1594 | case TRACE_CTX: |
1575 | case TRACE_WAKE: { | 1595 | case TRACE_WAKE: { |
1576 | struct ctx_switch_entry *field = | 1596 | struct ctx_switch_entry *field; |
1577 | (struct ctx_switch_entry *)entry; | 1597 | |
1598 | trace_assign_type(field, entry); | ||
1578 | 1599 | ||
1579 | S = field->prev_state < sizeof(state_to_char) ? | 1600 | S = field->prev_state < sizeof(state_to_char) ? |
1580 | state_to_char[field->prev_state] : 'X'; | 1601 | state_to_char[field->prev_state] : 'X'; |
@@ -1596,7 +1617,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
1596 | } | 1617 | } |
1597 | case TRACE_SPECIAL: | 1618 | case TRACE_SPECIAL: |
1598 | case TRACE_STACK: { | 1619 | case TRACE_STACK: { |
1599 | struct special_entry *field = (struct special_entry *)entry; | 1620 | struct special_entry *field; |
1621 | |||
1622 | trace_assign_type(field, entry); | ||
1600 | 1623 | ||
1601 | ret = trace_seq_printf(s, "# %ld %ld %ld\n", | 1624 | ret = trace_seq_printf(s, "# %ld %ld %ld\n", |
1602 | field->arg1, | 1625 | field->arg1, |
@@ -1607,7 +1630,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
1607 | break; | 1630 | break; |
1608 | } | 1631 | } |
1609 | case TRACE_PRINT: { | 1632 | case TRACE_PRINT: { |
1610 | struct print_entry *field = (struct print_entry *)entry; | 1633 | struct print_entry *field; |
1634 | |||
1635 | trace_assign_type(field, entry); | ||
1611 | 1636 | ||
1612 | trace_seq_printf(s, "# %lx %s", field->ip, field->buf); | 1637 | trace_seq_printf(s, "# %lx %s", field->ip, field->buf); |
1613 | if (entry->flags & TRACE_FLAG_CONT) | 1638 | if (entry->flags & TRACE_FLAG_CONT) |
@@ -1648,7 +1673,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
1648 | 1673 | ||
1649 | switch (entry->type) { | 1674 | switch (entry->type) { |
1650 | case TRACE_FN: { | 1675 | case TRACE_FN: { |
1651 | struct ftrace_entry *field = (struct ftrace_entry *)entry; | 1676 | struct ftrace_entry *field; |
1677 | |||
1678 | trace_assign_type(field, entry); | ||
1652 | 1679 | ||
1653 | SEQ_PUT_HEX_FIELD_RET(s, field->ip); | 1680 | SEQ_PUT_HEX_FIELD_RET(s, field->ip); |
1654 | SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip); | 1681 | SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip); |
@@ -1656,8 +1683,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
1656 | } | 1683 | } |
1657 | case TRACE_CTX: | 1684 | case TRACE_CTX: |
1658 | case TRACE_WAKE: { | 1685 | case TRACE_WAKE: { |
1659 | struct ctx_switch_entry *field = | 1686 | struct ctx_switch_entry *field; |
1660 | (struct ctx_switch_entry *)entry; | 1687 | |
1688 | trace_assign_type(field, entry); | ||
1661 | 1689 | ||
1662 | S = field->prev_state < sizeof(state_to_char) ? | 1690 | S = field->prev_state < sizeof(state_to_char) ? |
1663 | state_to_char[field->prev_state] : 'X'; | 1691 | state_to_char[field->prev_state] : 'X'; |
@@ -1676,7 +1704,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
1676 | } | 1704 | } |
1677 | case TRACE_SPECIAL: | 1705 | case TRACE_SPECIAL: |
1678 | case TRACE_STACK: { | 1706 | case TRACE_STACK: { |
1679 | struct special_entry *field = (struct special_entry *)entry; | 1707 | struct special_entry *field; |
1708 | |||
1709 | trace_assign_type(field, entry); | ||
1680 | 1710 | ||
1681 | SEQ_PUT_HEX_FIELD_RET(s, field->arg1); | 1711 | SEQ_PUT_HEX_FIELD_RET(s, field->arg1); |
1682 | SEQ_PUT_HEX_FIELD_RET(s, field->arg2); | 1712 | SEQ_PUT_HEX_FIELD_RET(s, field->arg2); |
@@ -1705,15 +1735,18 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
1705 | 1735 | ||
1706 | switch (entry->type) { | 1736 | switch (entry->type) { |
1707 | case TRACE_FN: { | 1737 | case TRACE_FN: { |
1708 | struct ftrace_entry *field = (struct ftrace_entry *)entry; | 1738 | struct ftrace_entry *field; |
1739 | |||
1740 | trace_assign_type(field, entry); | ||
1709 | 1741 | ||
1710 | SEQ_PUT_FIELD_RET(s, field->ip); | 1742 | SEQ_PUT_FIELD_RET(s, field->ip); |
1711 | SEQ_PUT_FIELD_RET(s, field->parent_ip); | 1743 | SEQ_PUT_FIELD_RET(s, field->parent_ip); |
1712 | break; | 1744 | break; |
1713 | } | 1745 | } |
1714 | case TRACE_CTX: { | 1746 | case TRACE_CTX: { |
1715 | struct ctx_switch_entry *field = | 1747 | struct ctx_switch_entry *field; |
1716 | (struct ctx_switch_entry *)entry; | 1748 | |
1749 | trace_assign_type(field, entry); | ||
1717 | 1750 | ||
1718 | SEQ_PUT_FIELD_RET(s, field->prev_pid); | 1751 | SEQ_PUT_FIELD_RET(s, field->prev_pid); |
1719 | SEQ_PUT_FIELD_RET(s, field->prev_prio); | 1752 | SEQ_PUT_FIELD_RET(s, field->prev_prio); |
@@ -1725,7 +1758,9 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
1725 | } | 1758 | } |
1726 | case TRACE_SPECIAL: | 1759 | case TRACE_SPECIAL: |
1727 | case TRACE_STACK: { | 1760 | case TRACE_STACK: { |
1728 | struct special_entry *field = (struct special_entry *)entry; | 1761 | struct special_entry *field; |
1762 | |||
1763 | trace_assign_type(field, entry); | ||
1729 | 1764 | ||
1730 | SEQ_PUT_FIELD_RET(s, field->arg1); | 1765 | SEQ_PUT_FIELD_RET(s, field->arg1); |
1731 | SEQ_PUT_FIELD_RET(s, field->arg2); | 1766 | SEQ_PUT_FIELD_RET(s, field->arg2); |