Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: allow UTF-8 literals in bpf_bprintf_prepare()

bpf_bprintf_prepare() only needs ASCII parsing for conversion
specifiers. Plain text can safely carry bytes >= 0x80, so allow
UTF-8 literals outside '%' sequences while keeping ASCII control
bytes rejected and format specifiers ASCII-only.

This keeps existing parsing rules for format directives unchanged,
while allowing helpers such as bpf_trace_printk() to emit UTF-8
literal text.

Update test_snprintf_negative() in the same commit so selftests keep
matching the new plain-text vs format-specifier split during bisection.

Fixes: 48cac3f4a96d ("bpf: Implement formatted output helpers with bstr_printf")
Signed-off-by: Yihan Ding <dingyihan@uniontech.com>
Acked-by: Paul Chaignon <paul.chaignon@gmail.com>
Link: https://lore.kernel.org/r/20260416120142.1420646-2-dingyihan@uniontech.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yihan Ding and committed by
Alexei Starovoitov
b960430e 766bf026

+18 -2
+16 -1
kernel/bpf/helpers.c
··· 845 845 data->buf = buffers->buf; 846 846 847 847 for (i = 0; i < fmt_size; i++) { 848 - if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i])) { 848 + unsigned char c = fmt[i]; 849 + 850 + /* 851 + * Permit bytes >= 0x80 in plain text so UTF-8 literals can pass 852 + * through unchanged, while still rejecting ASCII control bytes. 853 + */ 854 + if (isascii(c) && !isprint(c) && !isspace(c)) { 849 855 err = -EINVAL; 850 856 goto out; 851 857 } ··· 873 867 * always access fmt[i + 1], in the worst case it will be a 0 874 868 */ 875 869 i++; 870 + c = fmt[i]; 871 + /* 872 + * The format parser below only understands ASCII conversion 873 + * specifiers and modifiers, so reject non-ASCII after '%'. 874 + */ 875 + if (!isascii(c)) { 876 + err = -EINVAL; 877 + goto out; 878 + } 876 879 877 880 /* skip optional "[0 +-][num]" width formatting field */ 878 881 while (fmt[i] == '0' || fmt[i] == '+' || fmt[i] == '-' ||
+2 -1
tools/testing/selftests/bpf/prog_tests/snprintf.c
··· 114 114 ASSERT_ERR(load_single_snprintf("%--------"), "invalid specifier 5"); 115 115 ASSERT_ERR(load_single_snprintf("%lc"), "invalid specifier 6"); 116 116 ASSERT_ERR(load_single_snprintf("%llc"), "invalid specifier 7"); 117 - ASSERT_ERR(load_single_snprintf("\x80"), "non ascii character"); 117 + ASSERT_OK(load_single_snprintf("\x80"), "non ascii plain text"); 118 + ASSERT_ERR(load_single_snprintf("%\x80"), "non ascii in specifier"); 118 119 ASSERT_ERR(load_single_snprintf("\x1"), "non printable character"); 119 120 ASSERT_ERR(load_single_snprintf("%p%"), "invalid specifier 8"); 120 121 ASSERT_ERR(load_single_snprintf("%s%"), "invalid specifier 9");