summaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c81
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
1649static bool have_filled_random_ptr_key __read_mostly;
1650static siphash_key_t ptr_key __read_mostly;
1651
1652static 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
1664static struct random_ready_callback random_ready = {
1665 .func = fill_random_ptr_key
1666};
1667
1668static 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}
1681early_initcall(initialize_ptr_random);
1682
1683/* Maps a pointer to a 32 bit unique identifier. */
1684static 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 */
1758static noinline_for_stack 1830static noinline_for_stack
1759char *pointer(const char *fmt, char *buf, char *end, void *ptr, 1831char *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/*