printk changes for 7.2

-----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEESH4wyp42V4tXvYsjUqAMR0iAlPIFAmoyRfwbFIAAAAAABAAO
 bWFudTIsMi41KzEuMTIsMiwyAAoJEFKgDEdIgJTycTcP/iiyiE+mkR5ruuPNwPsb
 3JH6xKVmwcdC+EeyoNLDcR5aNAiY3GSuwXWo9oVX9HAbA9fC68od7ITuPmQn2j6l
 Rbl9ITtx+mmfhDFrYNIhUXjLlhddojRBPPzfNG68lOzlG7JG75DiIAt30BRuXlbJ
 njn+eeOuRsL2Y5JJn8Vvv9GnV7NyGb5lvrJzAeOv5zc7qngcu3RSUjt6NryfauRn
 ZDBqrhQcDpFJ8cZoLq1D9p83tDStzjHBn9VkpXX7Y4dl5fTowI85CWCgFiXLg1KQ
 KGPq0XXDI1Yw4UNABCxffhxa8nyQyaA35DAllpUNB6hY9QlMZLOGxZjmTtqxeQtP
 SA01c3RpxQAvyiuja1zzvso+Km3o9doHk7gLDq6z++YfO0u0wjh2wS4IVOKfvyIk
 LpK6vNQb0gjNqQmn1EYvBPpinnypSeffGGdkmkEZosr4ACAwEE+wg84422NS4gji
 1erRecvHnlYIF5wIjCkzLeqGwQLSn4TblHf9/4ImaZrjf8uWaxSsBZam5OfjJpsU
 LP3//oeIbEnwBNgPE8bIRw5s4L+cenTeAmS8vl7qR5InshSo1FmtYWFbrmw3/Gfy
 ajV/f67J807XN03p220aRFm1x48aA5eye3VGI7wYnWVwRLIPjEh8nISEa/pV3jxW
 4b/N7+xze8zYV9zTPPRGh1u5
 =yXoT
 -----END PGP SIGNATURE-----

Merge tag 'printk-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux

Pull printk updates from Petr Mladek:

 - Add upper case flavor for printing MAC addresses (%p[mM][U]) and use
   it in the nintendo driver

 - Fix matching of hash_pointers= parameter modes

 - Fix size check of vsprintf() field_width and precision values

 - Add check of size returned by vsprintf()

 - Add KUnit test for restricted pointer printing (%pK)

 - Some code cleanup

* tag 'printk-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  HID: nintendo: Use %pM format specifier for MAC addresses
  vsprintf: Add upper case flavour to %p[mM]
  lib/vsprintf: replace min_t/max_t with min/max
  printk: fix typos in comments
  lib/vsprintf: Require exact hash_pointers mode matches
  vsprintf: Add test for restricted kernel pointers
  vsprintf: Only export no_hash_pointers to test module
  lib/vsprintf: Limit the returning size to INT_MAX
  lib/vsprintf: Fix to check field_width and precision
This commit is contained in:
Linus Torvalds 2026-06-17 12:05:20 -07:00
commit 0db1496dcb
6 changed files with 85 additions and 52 deletions

View File

@ -322,6 +322,7 @@ MAC/FDDI addresses
%pMF 00-01-02-03-04-05
%pm 000102030405
%pmR 050403020100
%p[mM][FR][U]
For printing 6-byte MAC/FDDI addresses in hex notation. The ``M`` and ``m``
specifiers result in a printed address with (M) or without (m) byte
@ -335,6 +336,8 @@ For Bluetooth addresses the ``R`` specifier shall be used after the ``M``
specifier to use reversed byte order suitable for visual interpretation
of Bluetooth addresses which are in the little endian order.
When ``U`` is passed, the result is printed in the upper case.
Passed by reference.
IPv4 addresses

View File

@ -2431,14 +2431,8 @@ static int joycon_read_info(struct joycon_ctlr *ctlr)
for (i = 4, j = 0; j < 6; i++, j++)
ctlr->mac_addr[j] = report->subcmd_reply.data[i];
ctlr->mac_addr_str = devm_kasprintf(&ctlr->hdev->dev, GFP_KERNEL,
"%02X:%02X:%02X:%02X:%02X:%02X",
ctlr->mac_addr[0],
ctlr->mac_addr[1],
ctlr->mac_addr[2],
ctlr->mac_addr[3],
ctlr->mac_addr[4],
ctlr->mac_addr[5]);
ctlr->mac_addr_str = devm_kasprintf(&ctlr->hdev->dev, GFP_KERNEL, "%pMU",
ctlr->mac_addr);
if (!ctlr->mac_addr_str)
return -ENOMEM;
hid_info(ctlr->hdev, "controller MAC = %s\n", ctlr->mac_addr_str);

View File

@ -1487,7 +1487,7 @@ bool nbcon_allow_unsafe_takeover(void)
* or write_thread().
*
* When false, the write_thread() callback is used and would be
* called in a preemtible context unless disabled by the
* called in a preemptible context unless disabled by the
* device_lock. The legacy handover is not allowed in this mode.
*
* Context: Any context except NMI.
@ -1868,7 +1868,7 @@ void nbcon_free(struct console *con)
* Return: True if the console was acquired. False otherwise.
*
* Console drivers will usually use their own internal synchronization
* mechasism to synchronize between console printing and non-printing
* mechanism to synchronize between console printing and non-printing
* activities (such as setting baud rates). However, nbcon console drivers
* supporting atomic consoles may also want to mark unsafe sections when
* performing non-printing activities in order to synchronize against their
@ -1954,7 +1954,7 @@ EXPORT_SYMBOL_GPL(nbcon_device_release);
*
* kdb emits messages on consoles registered for printk() without
* storing them into the ring buffer. It has to acquire the console
* ownerhip so that it could call con->write_atomic() callback a safe way.
* ownership so that it could call con->write_atomic() callback a safe way.
*
* This function acquires the nbcon console using priority NBCON_PRIO_EMERGENCY
* and marks it unsafe for handover/takeover.

View File

@ -188,7 +188,7 @@ static int __init control_devkmsg(char *str)
/*
* Sysctl cannot change it anymore. The kernel command line setting of
* this parameter is to force the setting to be permanent throughout the
* runtime of the system. This is a precation measure against userspace
* runtime of the system. This is a precautionary measure against userspace
* trying to be a smarta** and attempting to change it up on us.
*/
devkmsg_log |= DEVKMSG_LOG_MASK_LOCK;
@ -1975,7 +1975,7 @@ int console_lock_spinning_disable_and_check(int cookie)
* the current owner is running and cannot reschedule until it
* is ready to lose the lock.
*
* Return: 1 if we got the lock, 0 othrewise
* Return: 1 if we got the lock, 0 otherwise
*/
static int console_trylock_spinning(void)
{
@ -3285,7 +3285,7 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
continue;
/*
* An usable console made a progress. There might still be
* A usable console made progress. There might still be
* pending messages.
*/
*try_again = true;

View File

@ -319,7 +319,27 @@ symbol_ptr(struct kunit *kunittest)
static void
kernel_ptr(struct kunit *kunittest)
{
/* We can't test this without access to kptr_restrict. */
switch (kptr_restrict) {
case 0:
if (no_hash_pointers) {
test(PTR_STR, "%pK", PTR);
} else {
char buf[PLAIN_BUF_SIZE];
plain_hash_to_buffer(kunittest, PTR, buf, PLAIN_BUF_SIZE);
/* %pK behaves the same as hashing */
test(buf, "%pK", PTR);
}
break;
case 1:
/* The KUnit kthread has all capabilities, including CAP_SYSLOG */
test(PTR_STR, "%pK", PTR);
break;
case 2:
default:
test(ZEROS "00000000", "%pK", PTR);
break;
}
}
static void
@ -415,8 +435,10 @@ mac(struct kunit *kunittest)
test("2d:48:d6:fc:7a:05", "%pM", addr);
test("05:7a:fc:d6:48:2d", "%pMR", addr);
test("05:7A:FC:D6:48:2D", "%pMRU", addr);
test("2d-48-d6-fc-7a-05", "%pMF", addr);
test("2d48d6fc7a05", "%pm", addr);
test("2D48D6FC7A05", "%pmU", addr);
test("057afcd6482d", "%pmR", addr);
}

View File

@ -59,7 +59,7 @@
/* Disable pointer hashing if requested */
bool no_hash_pointers __ro_after_init;
EXPORT_SYMBOL_GPL(no_hash_pointers);
EXPORT_SYMBOL_FOR_MODULES(no_hash_pointers, "printf_kunit");
/*
* Hashed pointers policy selected by "hash_pointers=..." boot param
@ -850,6 +850,7 @@ static char *default_pointer(char *buf, char *end, const void *ptr,
}
int kptr_restrict __read_mostly;
EXPORT_SYMBOL_FOR_MODULES(kptr_restrict, "printf_kunit");
static noinline_for_stack
char *restricted_pointer(char *buf, char *end, const void *ptr,
@ -1201,7 +1202,7 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
}
if (spec.field_width > 0)
len = min_t(int, spec.field_width, 64);
len = min(spec.field_width, 64);
for (i = 0; i < len; ++i) {
if (buf < end)
@ -1226,7 +1227,7 @@ char *bitmap_string(char *buf, char *end, const unsigned long *bitmap,
struct printf_spec spec, const char *fmt)
{
const int CHUNKSZ = 32;
int nr_bits = max_t(int, spec.field_width, 0);
int nr_bits = max(spec.field_width, 0);
int i, chunksz;
bool first = true;
@ -1269,7 +1270,7 @@ static noinline_for_stack
char *bitmap_list_string(char *buf, char *end, const unsigned long *bitmap,
struct printf_spec spec, const char *fmt)
{
int nr_bits = max_t(int, spec.field_width, 0);
int nr_bits = max(spec.field_width, 0);
bool first = true;
int rbot, rtop;
@ -1302,31 +1303,39 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
char *p = mac_addr;
int i;
char separator;
char separator = ':';
bool reversed = false;
bool uc = false;
if (check_pointer(&buf, end, addr, spec))
return buf;
switch (fmt[1]) {
case 'F':
uc = fmt[2] == 'U';
separator = '-';
break;
case 'R':
uc = fmt[2] == 'U';
reversed = true;
fallthrough;
break;
case 'U':
uc = true;
break;
default:
separator = ':';
break;
}
for (i = 0; i < 6; i++) {
if (reversed)
p = hex_byte_pack(p, addr[5 - i]);
u8 byte = reversed ? addr[5 - i] : addr[i];
if (uc)
p = hex_byte_pack_upper(p, byte);
else
p = hex_byte_pack(p, addr[i]);
p = hex_byte_pack(p, byte);
if (fmt[0] == 'M' && i != 5)
*p++ = separator;
@ -2354,13 +2363,13 @@ static int __init hash_pointers_mode_parse(char *str)
if (!str) {
pr_warn("Hash pointers mode empty; falling back to auto.\n");
hash_pointers_mode = HASH_PTR_AUTO;
} else if (strncmp(str, "auto", 4) == 0) {
} else if (strcmp(str, "auto") == 0) {
pr_info("Hash pointers mode set to auto.\n");
hash_pointers_mode = HASH_PTR_AUTO;
} else if (strncmp(str, "never", 5) == 0) {
} else if (strcmp(str, "never") == 0) {
pr_info("Hash pointers mode set to never.\n");
hash_pointers_mode = HASH_PTR_NEVER;
} else if (strncmp(str, "always", 6) == 0) {
} else if (strcmp(str, "always") == 0) {
pr_info("Hash pointers mode set to always.\n");
hash_pointers_mode = HASH_PTR_ALWAYS;
} else {
@ -2409,6 +2418,7 @@ early_param("no_hash_pointers", no_hash_pointers_enable);
* - 'MF' For a 6-byte MAC FDDI address, it prints the address
* with a dash-separated hex notation
* - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
* - '[mM][FR][U]' One of the above in the upper case
* - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
* IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
* IPv6 uses colon separated network-order 16 bit hex with leading 0's
@ -2543,6 +2553,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
case 'm': /* Contiguous: 000102030405 */
/* [mM]F (FDDI) */
/* [mM]R (Reverse order; Bluetooth) */
/* [mM][FR][U] (One of the above in the upper case) */
return mac_address_string(buf, end, ptr, spec, fmt);
case 'I': /* Formatted IP supported
* 4: 1.2.3.4
@ -2633,6 +2644,18 @@ static unsigned char spec_flag(unsigned char c)
return (c < sizeof(spec_flag_array)) ? spec_flag_array[c] : 0;
}
static void set_field_width(struct printf_spec *spec, int width)
{
spec->field_width = clamp(width, -FIELD_WIDTH_MAX, FIELD_WIDTH_MAX);
WARN_ONCE(spec->field_width != width, "field width %d out of range", width);
}
static void set_precision(struct printf_spec *spec, int prec)
{
spec->precision = clamp(prec, 0, PRECISION_MAX);
WARN_ONCE(spec->precision < prec, "precision %d too large", prec);
}
/*
* Helper function to decode printf style format.
* Each call decode a token from the format and return the
@ -2703,7 +2726,7 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
spec->field_width = -1;
if (isdigit(*fmt.str))
spec->field_width = skip_atoi(&fmt.str);
set_field_width(spec, skip_atoi(&fmt.str));
else if (unlikely(*fmt.str == '*')) {
/* it's the next argument */
fmt.state = FORMAT_STATE_WIDTH;
@ -2717,9 +2740,7 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
if (unlikely(*fmt.str == '.')) {
fmt.str++;
if (isdigit(*fmt.str)) {
spec->precision = skip_atoi(&fmt.str);
if (spec->precision < 0)
spec->precision = 0;
set_precision(spec, skip_atoi(&fmt.str));
} else if (*fmt.str == '*') {
/* it's the next argument */
fmt.state = FORMAT_STATE_PRECISION;
@ -2792,24 +2813,6 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
return fmt;
}
static void
set_field_width(struct printf_spec *spec, int width)
{
spec->field_width = width;
if (WARN_ONCE(spec->field_width != width, "field width %d too large", width)) {
spec->field_width = clamp(width, -FIELD_WIDTH_MAX, FIELD_WIDTH_MAX);
}
}
static void
set_precision(struct printf_spec *spec, int prec)
{
spec->precision = prec;
if (WARN_ONCE(spec->precision != prec, "precision %d too large", prec)) {
spec->precision = clamp(prec, 0, PRECISION_MAX);
}
}
/*
* Turn a 1/2/4-byte value into a 64-bit one for printing: truncate
* as necessary and deal with signedness.
@ -2857,6 +2860,7 @@ static unsigned long long convert_num_spec(unsigned int val, int size, struct pr
int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
{
char *str, *end;
size_t ret_size;
struct printf_spec spec = {0};
struct fmt fmt = {
.str = fmt_str,
@ -2976,8 +2980,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
}
/* the trailing null byte doesn't count towards the total */
return str-buf;
ret_size = str - buf;
/* Make sure the return value is within the positive integer range */
if (WARN_ON_ONCE(ret_size > INT_MAX))
ret_size = INT_MAX;
return ret_size;
}
EXPORT_SYMBOL(vsnprintf);
@ -3281,6 +3289,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt_str, const u32 *bin_buf)
struct printf_spec spec = {0};
char *str, *end;
const char *args = (const char *)bin_buf;
size_t ret_size;
if (WARN_ON_ONCE(size > INT_MAX))
return 0;
@ -3429,7 +3438,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt_str, const u32 *bin_buf)
#undef get_arg
/* the trailing null byte doesn't count towards the total */
return str - buf;
ret_size = str - buf;
/* Make sure the return value is within the positive integer range */
if (WARN_ON_ONCE(ret_size > INT_MAX))
ret_size = INT_MAX;
return ret_size;
}
EXPORT_SYMBOL_GPL(bstr_printf);