diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg index fff817efa508..f307506eb54c 100644 --- a/Documentation/ABI/testing/dev-kmsg +++ b/Documentation/ABI/testing/dev-kmsg @@ -12,7 +12,7 @@ Description: The /dev/kmsg character device node provides userspace access The logged line can be prefixed with a syslog prefix, which carries the syslog priority and facility. The single decimal prefix number is composed of the 3 lowest bits being the syslog - priority and the higher bits the syslog facility number. + priority and the next 8 bits the syslog facility number. If no prefix is given, the priority number is the default kernel log priority and the facility number is set to LOG_USER (1). It @@ -90,13 +90,12 @@ Description: The /dev/kmsg character device node provides userspace access +sound:card0 - subsystem:devname The flags field carries '-' by default. A 'c' indicates a - fragment of a line. All following fragments are flagged with - '+'. Note, that these hints about continuation lines are not - necessarily correct, and the stream could be interleaved with - unrelated messages, but merging the lines in the output - usually produces better human readable results. A similar - logic is used internally when messages are printed to the - console, /proc/kmsg or the syslog() syscall. + fragment of a line. Note, that these hints about continuation + lines are not necessarily correct, and the stream could be + interleaved with unrelated messages, but merging the lines in + the output usually produces better human readable results. A + similar logic is used internally when messages are printed to + the console, /proc/kmsg or the syslog() syscall. By default, kernel tries to avoid fragments by concatenating when it can and fragments are rare; however, when extended diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c index 1d21ebacfdb8..17a9591e54ff 100644 --- a/kernel/printk/braille.c +++ b/kernel/printk/braille.c @@ -11,11 +11,18 @@ int _braille_console_setup(char **str, char **brl_options) { - if (!strncmp(*str, "brl,", 4)) { + size_t len; + + len = str_has_prefix(*str, "brl,"); + if (len) { *brl_options = ""; - *str += 4; - } else if (!strncmp(*str, "brl=", 4)) { - *brl_options = *str + 4; + *str += len; + return 0; + } + + len = str_has_prefix(*str, "brl="); + if (len) { + *brl_options = *str + len; *str = strchr(*brl_options, ','); if (!*str) { pr_err("need port name after brl=\n"); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 1888f6a3b694..ca65327a6de8 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -118,19 +118,29 @@ static unsigned int __read_mostly devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; static int __control_devkmsg(char *str) { + size_t len; + if (!str) return -EINVAL; - if (!strncmp(str, "on", 2)) { + len = str_has_prefix(str, "on"); + if (len) { devkmsg_log = DEVKMSG_LOG_MASK_ON; - return 2; - } else if (!strncmp(str, "off", 3)) { - devkmsg_log = DEVKMSG_LOG_MASK_OFF; - return 3; - } else if (!strncmp(str, "ratelimit", 9)) { - devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; - return 9; + return len; } + + len = str_has_prefix(str, "off"); + if (len) { + devkmsg_log = DEVKMSG_LOG_MASK_OFF; + return len; + } + + len = str_has_prefix(str, "ratelimit"); + if (len) { + devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; + return len; + } + return -EINVAL; } @@ -3274,7 +3284,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, /* move first record forward until length fits into the buffer */ seq = dumper->cur_seq; idx = dumper->cur_idx; - while (l > size && seq < dumper->next_seq) { + while (l >= size && seq < dumper->next_seq) { struct printk_log *msg = log_from_idx(idx); l -= msg_print_text(msg, true, time, NULL, 0); diff --git a/lib/test_printf.c b/lib/test_printf.c index 944eb50f3862..5d94cbff2120 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -455,6 +455,11 @@ dentry(void) test("foo", "%pd", &test_dentry[0]); test("foo", "%pd2", &test_dentry[0]); + test("(null)", "%pd", NULL); + test("(efault)", "%pd", PTR_INVALID); + test("(null)", "%pD", NULL); + test("(efault)", "%pD", PTR_INVALID); + test("romeo", "%pd", &test_dentry[3]); test("alfa/romeo", "%pd2", &test_dentry[3]); test("bravo/alfa/romeo", "%pd3", &test_dentry[3]); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b0967cf17137..e78017a3e1bd 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -869,6 +869,15 @@ char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_sp return widen_string(buf, n, end, spec); } +static noinline_for_stack +char *file_dentry_name(char *buf, char *end, const struct file *f, + struct printf_spec spec, const char *fmt) +{ + if (check_pointer(&buf, end, f, spec)) + return buf; + + return dentry_name(buf, end, f->f_path.dentry, spec, fmt); +} #ifdef CONFIG_BLOCK static noinline_for_stack char *bdev_name(char *buf, char *end, struct block_device *bdev, @@ -2166,9 +2175,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'C': return clock(buf, end, ptr, spec, fmt); case 'D': - return dentry_name(buf, end, - ((const struct file *)ptr)->f_path.dentry, - spec, fmt); + return file_dentry_name(buf, end, ptr, spec, fmt); #ifdef CONFIG_BLOCK case 'g': return bdev_name(buf, end, ptr, spec, fmt);