diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7a708f82559..23920c5ff728 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -336,7 +336,7 @@ char *put_dec(char *buf, unsigned long long n) | |||
| 336 | * | 336 | * |
| 337 | * If speed is not important, use snprintf(). It's easy to read the code. | 337 | * If speed is not important, use snprintf(). It's easy to read the code. |
| 338 | */ | 338 | */ |
| 339 | int num_to_str(char *buf, int size, unsigned long long num) | 339 | int num_to_str(char *buf, int size, unsigned long long num, unsigned int width) |
| 340 | { | 340 | { |
| 341 | /* put_dec requires 2-byte alignment of the buffer. */ | 341 | /* put_dec requires 2-byte alignment of the buffer. */ |
| 342 | char tmp[sizeof(num) * 3] __aligned(2); | 342 | char tmp[sizeof(num) * 3] __aligned(2); |
| @@ -350,11 +350,21 @@ int num_to_str(char *buf, int size, unsigned long long num) | |||
| 350 | len = put_dec(tmp, num) - tmp; | 350 | len = put_dec(tmp, num) - tmp; |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | if (len > size) | 353 | if (len > size || width > size) |
| 354 | return 0; | 354 | return 0; |
| 355 | |||
| 356 | if (width > len) { | ||
| 357 | width = width - len; | ||
| 358 | for (idx = 0; idx < width; idx++) | ||
| 359 | buf[idx] = ' '; | ||
| 360 | } else { | ||
| 361 | width = 0; | ||
| 362 | } | ||
| 363 | |||
| 355 | for (idx = 0; idx < len; ++idx) | 364 | for (idx = 0; idx < len; ++idx) |
| 356 | buf[idx] = tmp[len - idx - 1]; | 365 | buf[idx + width] = tmp[len - idx - 1]; |
| 357 | return len; | 366 | |
| 367 | return len + width; | ||
| 358 | } | 368 | } |
| 359 | 369 | ||
| 360 | #define SIGN 1 /* unsigned/signed, must be 1 */ | 370 | #define SIGN 1 /* unsigned/signed, must be 1 */ |
| @@ -1659,19 +1669,22 @@ char *pointer_string(char *buf, char *end, const void *ptr, | |||
| 1659 | return number(buf, end, (unsigned long int)ptr, spec); | 1669 | return number(buf, end, (unsigned long int)ptr, spec); |
| 1660 | } | 1670 | } |
| 1661 | 1671 | ||
| 1662 | static bool have_filled_random_ptr_key __read_mostly; | 1672 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); |
| 1663 | static siphash_key_t ptr_key __read_mostly; | 1673 | static siphash_key_t ptr_key __read_mostly; |
| 1664 | 1674 | ||
| 1665 | static void fill_random_ptr_key(struct random_ready_callback *unused) | 1675 | static void enable_ptr_key_workfn(struct work_struct *work) |
| 1666 | { | 1676 | { |
| 1667 | get_random_bytes(&ptr_key, sizeof(ptr_key)); | 1677 | get_random_bytes(&ptr_key, sizeof(ptr_key)); |
| 1668 | /* | 1678 | /* Needs to run from preemptible context */ |
| 1669 | * have_filled_random_ptr_key==true is dependent on get_random_bytes(). | 1679 | static_branch_disable(¬_filled_random_ptr_key); |
| 1670 | * ptr_to_id() needs to see have_filled_random_ptr_key==true | 1680 | } |
| 1671 | * after get_random_bytes() returns. | 1681 | |
| 1672 | */ | 1682 | static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn); |
| 1673 | smp_mb(); | 1683 | |
| 1674 | WRITE_ONCE(have_filled_random_ptr_key, true); | 1684 | static void fill_random_ptr_key(struct random_ready_callback *unused) |
| 1685 | { | ||
| 1686 | /* This may be in an interrupt handler. */ | ||
| 1687 | queue_work(system_unbound_wq, &enable_ptr_key_work); | ||
| 1675 | } | 1688 | } |
| 1676 | 1689 | ||
| 1677 | static struct random_ready_callback random_ready = { | 1690 | static struct random_ready_callback random_ready = { |
| @@ -1685,7 +1698,8 @@ static int __init initialize_ptr_random(void) | |||
| 1685 | if (!ret) { | 1698 | if (!ret) { |
| 1686 | return 0; | 1699 | return 0; |
| 1687 | } else if (ret == -EALREADY) { | 1700 | } else if (ret == -EALREADY) { |
| 1688 | fill_random_ptr_key(&random_ready); | 1701 | /* This is in preemptible context */ |
| 1702 | enable_ptr_key_workfn(&enable_ptr_key_work); | ||
| 1689 | return 0; | 1703 | return 0; |
| 1690 | } | 1704 | } |
| 1691 | 1705 | ||
| @@ -1699,7 +1713,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) | |||
| 1699 | unsigned long hashval; | 1713 | unsigned long hashval; |
| 1700 | const int default_width = 2 * sizeof(ptr); | 1714 | const int default_width = 2 * sizeof(ptr); |
| 1701 | 1715 | ||
| 1702 | if (unlikely(!have_filled_random_ptr_key)) { | 1716 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { |
| 1703 | spec.field_width = default_width; | 1717 | spec.field_width = default_width; |
| 1704 | /* string length must be less than default_width */ | 1718 | /* string length must be less than default_width */ |
| 1705 | return string(buf, end, "(ptrval)", spec); | 1719 | return string(buf, end, "(ptrval)", spec); |
| @@ -2591,6 +2605,8 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args) | |||
| 2591 | case 's': | 2605 | case 's': |
| 2592 | case 'F': | 2606 | case 'F': |
| 2593 | case 'f': | 2607 | case 'f': |
| 2608 | case 'x': | ||
| 2609 | case 'K': | ||
| 2594 | save_arg(void *); | 2610 | save_arg(void *); |
| 2595 | break; | 2611 | break; |
| 2596 | default: | 2612 | default: |
| @@ -2765,6 +2781,8 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2765 | case 's': | 2781 | case 's': |
| 2766 | case 'F': | 2782 | case 'F': |
| 2767 | case 'f': | 2783 | case 'f': |
| 2784 | case 'x': | ||
| 2785 | case 'K': | ||
| 2768 | process = true; | 2786 | process = true; |
| 2769 | break; | 2787 | break; |
| 2770 | default: | 2788 | default: |
