diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 8dc5cf85cef4..d69452a0f2fa 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/uuid.h> | 33 | #include <linux/uuid.h> |
34 | #include <linux/of.h> | 34 | #include <linux/of.h> |
35 | #include <net/addrconf.h> | 35 | #include <net/addrconf.h> |
36 | #include <linux/siphash.h> | ||
37 | #include <linux/compiler.h> | ||
36 | #ifdef CONFIG_BLOCK | 38 | #ifdef CONFIG_BLOCK |
37 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
38 | #endif | 40 | #endif |
@@ -1644,6 +1646,73 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1644 | return widen_string(buf, buf - buf_start, end, spec); | 1646 | return widen_string(buf, buf - buf_start, end, spec); |
1645 | } | 1647 | } |
1646 | 1648 | ||
1649 | static bool have_filled_random_ptr_key __read_mostly; | ||
1650 | static siphash_key_t ptr_key __read_mostly; | ||
1651 | |||
1652 | static void fill_random_ptr_key(struct random_ready_callback *unused) | ||
1653 | { | ||
1654 | get_random_bytes(&ptr_key, sizeof(ptr_key)); | ||
1655 | /* | ||
1656 | * have_filled_random_ptr_key==true is dependent on get_random_bytes(). | ||
1657 | * ptr_to_id() needs to see have_filled_random_ptr_key==true | ||
1658 | * after get_random_bytes() returns. | ||
1659 | */ | ||
1660 | smp_mb(); | ||
1661 | WRITE_ONCE(have_filled_random_ptr_key, true); | ||
1662 | } | ||
1663 | |||
1664 | static struct random_ready_callback random_ready = { | ||
1665 | .func = fill_random_ptr_key | ||
1666 | }; | ||
1667 | |||
1668 | static int __init initialize_ptr_random(void) | ||
1669 | { | ||
1670 | int ret = add_random_ready_callback(&random_ready); | ||
1671 | |||
1672 | if (!ret) { | ||
1673 | return 0; | ||
1674 | } else if (ret == -EALREADY) { | ||
1675 | fill_random_ptr_key(&random_ready); | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | return ret; | ||
1680 | } | ||
1681 | early_initcall(initialize_ptr_random); | ||
1682 | |||
1683 | /* Maps a pointer to a 32 bit unique identifier. */ | ||
1684 | static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) | ||
1685 | { | ||
1686 | unsigned long hashval; | ||
1687 | const int default_width = 2 * sizeof(ptr); | ||
1688 | |||
1689 | if (unlikely(!have_filled_random_ptr_key)) { | ||
1690 | spec.field_width = default_width; | ||
1691 | /* string length must be less than default_width */ | ||
1692 | return string(buf, end, "(ptrval)", spec); | ||
1693 | } | ||
1694 | |||
1695 | #ifdef CONFIG_64BIT | ||
1696 | hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key); | ||
1697 | /* | ||
1698 | * Mask off the first 32 bits, this makes explicit that we have | ||
1699 | * modified the address (and 32 bits is plenty for a unique ID). | ||
1700 | */ | ||
1701 | hashval = hashval & 0xffffffff; | ||
1702 | #else | ||
1703 | hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); | ||
1704 | #endif | ||
1705 | |||
1706 | spec.flags |= SMALL; | ||
1707 | if (spec.field_width == -1) { | ||
1708 | spec.field_width = default_width; | ||
1709 | spec.flags |= ZEROPAD; | ||
1710 | } | ||
1711 | spec.base = 16; | ||
1712 | |||
1713 | return number(buf, end, hashval, spec); | ||
1714 | } | ||
1715 | |||
1647 | /* | 1716 | /* |
1648 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 1717 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
1649 | * by an extra set of alphanumeric characters that are extended format | 1718 | * by an extra set of alphanumeric characters that are extended format |
@@ -1754,6 +1823,9 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1754 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 1823 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
1755 | * function pointers are really function descriptors, which contain a | 1824 | * function pointers are really function descriptors, which contain a |
1756 | * pointer to the real address. | 1825 | * pointer to the real address. |
1826 | * | ||
1827 | * Note: The default behaviour (unadorned %p) is to hash the address, | ||
1828 | * rendering it useful as a unique identifier. | ||
1757 | */ | 1829 | */ |
1758 | static noinline_for_stack | 1830 | static noinline_for_stack |
1759 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 1831 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
@@ -1869,14 +1941,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1869 | return device_node_string(buf, end, ptr, spec, fmt + 1); | 1941 | return device_node_string(buf, end, ptr, spec, fmt + 1); |
1870 | } | 1942 | } |
1871 | } | 1943 | } |
1872 | spec.flags |= SMALL; | ||
1873 | if (spec.field_width == -1) { | ||
1874 | spec.field_width = default_width; | ||
1875 | spec.flags |= ZEROPAD; | ||
1876 | } | ||
1877 | spec.base = 16; | ||
1878 | 1944 | ||
1879 | return number(buf, end, (unsigned long) ptr, spec); | 1945 | /* default is to _not_ leak addresses, hash before printing */ |
1946 | return ptr_to_id(buf, end, ptr, spec); | ||
1880 | } | 1947 | } |
1881 | 1948 | ||
1882 | /* | 1949 | /* |