Skip to content

Commit 7f3d08b

Browse files
committed
Merge tag 'printk-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux
Pull printk updates from Petr Mladek: - Stop synchronizing kernel log buffer readers by logbuf_lock. As a result, the access to the buffer is fully lockless now. Note that printk() itself still uses locks because it tries to flush the messages to the console immediately. Also the per-CPU temporary buffers are still there because they prevent infinite recursion and serialize backtraces from NMI. All this is going to change in the future. - kmsg_dump API rework and cleanup as a side effect of the logbuf_lock removal. - Make bstr_printf() aware that %pf and %pF formats could deference the given pointer. - Show also page flags by %pGp format. - Clarify the documentation for plain pointer printing. - Do not show no_hash_pointers warning multiple times. - Update Senozhatsky email address. - Some clean up. * tag 'printk-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux: (24 commits) lib/vsprintf.c: remove leftover 'f' and 'F' cases from bstr_printf() printk: clarify the documentation for plain pointer printing kernel/printk.c: Fixed mundane typos printk: rename vprintk_func to vprintk vsprintf: dump full information of page flags in pGp mm, slub: don't combine pr_err with INFO mm, slub: use pGp to print page flags MAINTAINERS: update Senozhatsky email address lib/vsprintf: do not show no_hash_pointers message multiple times printk: console: remove unnecessary safe buffer usage printk: kmsg_dump: remove _nolock() variants printk: remove logbuf_lock printk: introduce a kmsg_dump iterator printk: kmsg_dumper: remove @Active field printk: add syslog_lock printk: use atomic64_t for devkmsg_user.seq printk: use seqcount_latch for clear_seq printk: introduce CONSOLE_LOG_MAX printk: consolidate kmsg_dump_get_buffer/syslog_print_all code printk: refactor kmsg_dump_get_buffer() ...
2 parents 916a759 + c8dbea6 commit 7f3d08b

File tree

16 files changed

+502
-340
lines changed

16 files changed

+502
-340
lines changed

Documentation/core-api/printk-formats.rst

+26-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,19 @@ Pointers printed without a specifier extension (i.e unadorned %p) are
7979
hashed to prevent leaking information about the kernel memory layout. This
8080
has the added benefit of providing a unique identifier. On 64-bit machines
8181
the first 32 bits are zeroed. The kernel will print ``(ptrval)`` until it
82-
gathers enough entropy. If you *really* want the address see %px below.
82+
gathers enough entropy.
83+
84+
When possible, use specialised modifiers such as %pS or %pB (described below)
85+
to avoid the need of providing an unhashed address that has to be interpreted
86+
post-hoc. If not possible, and the aim of printing the address is to provide
87+
more information for debugging, use %p and boot the kernel with the
88+
``no_hash_pointers`` parameter during debugging, which will print all %p
89+
addresses unmodified. If you *really* always want the unmodified address, see
90+
%px below.
91+
92+
If (and only if) you are printing addresses as a content of a virtual file in
93+
e.g. procfs or sysfs (using e.g. seq_printf(), not printk()) read by a
94+
userspace process, use the %pK modifier described below instead of %p or %px.
8395

8496
Error Pointers
8597
--------------
@@ -139,6 +151,11 @@ For printing kernel pointers which should be hidden from unprivileged
139151
users. The behaviour of %pK depends on the kptr_restrict sysctl - see
140152
Documentation/admin-guide/sysctl/kernel.rst for more details.
141153

154+
This modifier is *only* intended when producing content of a file read by
155+
userspace from e.g. procfs or sysfs, not for dmesg. Please refer to the
156+
section about %p above for discussion about how to manage hashing pointers
157+
in printk().
158+
142159
Unmodified Addresses
143160
--------------------
144161

@@ -153,6 +170,13 @@ equivalent to %lx (or %lu). %px is preferred because it is more uniquely
153170
grep'able. If in the future we need to modify the way the kernel handles
154171
printing pointers we will be better equipped to find the call sites.
155172

173+
Before using %px, consider if using %p is sufficient together with enabling the
174+
``no_hash_pointers`` kernel parameter during debugging sessions (see the %p
175+
description above). One valid scenario for %px might be printing information
176+
immediately before a panic, which prevents any sensitive information to be
177+
exploited anyway, and with %px there would be no need to reproduce the panic
178+
with no_hash_pointers.
179+
156180
Pointer Differences
157181
-------------------
158182

@@ -540,7 +564,7 @@ Flags bitfields such as page flags, gfp_flags
540564

541565
::
542566

543-
%pGp referenced|uptodate|lru|active|private
567+
%pGp referenced|uptodate|lru|active|private|node=0|zone=2|lastcpupid=0x1fffff
544568
%pGg GFP_USER|GFP_DMA32|GFP_NOWARN
545569
%pGv read|exec|mayread|maywrite|mayexec|denywrite
546570

MAINTAINERS

+4-4
Original file line numberDiff line numberDiff line change
@@ -14535,7 +14535,7 @@ F: kernel/sched/psi.c
1453514535

1453614536
PRINTK
1453714537
M: Petr Mladek <pmladek@suse.com>
14538-
M: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
14538+
M: Sergey Senozhatsky <senozhatsky@chromium.org>
1453914539
R: Steven Rostedt <rostedt@goodmis.org>
1454014540
R: John Ogness <john.ogness@linutronix.de>
1454114541
S: Maintained
@@ -19388,7 +19388,7 @@ F: drivers/net/vrf.c
1938819388
VSPRINTF
1938919389
M: Petr Mladek <pmladek@suse.com>
1939019390
M: Steven Rostedt <rostedt@goodmis.org>
19391-
M: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
19391+
M: Sergey Senozhatsky <senozhatsky@chromium.org>
1939219392
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
1939319393
R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
1939419394
S: Maintained
@@ -20039,7 +20039,7 @@ F: drivers/staging/media/zoran/
2003920039
ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
2004020040
M: Minchan Kim <minchan@kernel.org>
2004120041
M: Nitin Gupta <ngupta@vflare.org>
20042-
R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
20042+
R: Sergey Senozhatsky <senozhatsky@chromium.org>
2004320043
L: linux-kernel@vger.kernel.org
2004420044
S: Maintained
2004520045
F: Documentation/admin-guide/blockdev/zram.rst
@@ -20053,7 +20053,7 @@ F: drivers/tty/serial/zs.*
2005320053
ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
2005420054
M: Minchan Kim <minchan@kernel.org>
2005520055
M: Nitin Gupta <ngupta@vflare.org>
20056-
R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
20056+
R: Sergey Senozhatsky <senozhatsky@chromium.org>
2005720057
L: linux-mm@kvack.org
2005820058
S: Maintained
2005920059
F: Documentation/vm/zsmalloc.rst

arch/powerpc/kernel/nvram_64.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
647647
{
648648
struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
649649
static unsigned int oops_count = 0;
650+
static struct kmsg_dump_iter iter;
650651
static bool panicking = false;
651652
static DEFINE_SPINLOCK(lock);
652653
unsigned long flags;
@@ -681,13 +682,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
681682
return;
682683

683684
if (big_oops_buf) {
684-
kmsg_dump_get_buffer(dumper, false,
685+
kmsg_dump_rewind(&iter);
686+
kmsg_dump_get_buffer(&iter, false,
685687
big_oops_buf, big_oops_buf_sz, &text_len);
686688
rc = zip_oops(text_len);
687689
}
688690
if (rc != 0) {
689-
kmsg_dump_rewind(dumper);
690-
kmsg_dump_get_buffer(dumper, false,
691+
kmsg_dump_rewind(&iter);
692+
kmsg_dump_get_buffer(&iter, false,
691693
oops_data, oops_data_sz, &text_len);
692694
err_type = ERR_TYPE_KERNEL_PANIC;
693695
oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);

arch/powerpc/xmon/xmon.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -3001,7 +3001,7 @@ print_address(unsigned long addr)
30013001
static void
30023002
dump_log_buf(void)
30033003
{
3004-
struct kmsg_dumper dumper = { .active = 1 };
3004+
struct kmsg_dump_iter iter;
30053005
unsigned char buf[128];
30063006
size_t len;
30073007

@@ -3013,9 +3013,9 @@ dump_log_buf(void)
30133013
catch_memory_errors = 1;
30143014
sync();
30153015

3016-
kmsg_dump_rewind_nolock(&dumper);
3016+
kmsg_dump_rewind(&iter);
30173017
xmon_start_pagination();
3018-
while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
3018+
while (kmsg_dump_get_line(&iter, false, buf, sizeof(buf), &len)) {
30193019
buf[len] = '\0';
30203020
printf("%s", buf);
30213021
}

arch/um/kernel/kmsg_dump.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/kmsg_dump.h>
3+
#include <linux/spinlock.h>
34
#include <linux/console.h>
45
#include <linux/string.h>
56
#include <shared/init.h>
@@ -9,8 +10,11 @@
910
static void kmsg_dumper_stdout(struct kmsg_dumper *dumper,
1011
enum kmsg_dump_reason reason)
1112
{
13+
static struct kmsg_dump_iter iter;
14+
static DEFINE_SPINLOCK(lock);
1215
static char line[1024];
1316
struct console *con;
17+
unsigned long flags;
1418
size_t len = 0;
1519

1620
/* only dump kmsg when no console is available */
@@ -29,11 +33,18 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper,
2933
if (con)
3034
return;
3135

36+
if (!spin_trylock_irqsave(&lock, flags))
37+
return;
38+
39+
kmsg_dump_rewind(&iter);
40+
3241
printf("kmsg_dump:\n");
33-
while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len)) {
42+
while (kmsg_dump_get_line(&iter, true, line, sizeof(line), &len)) {
3443
line[len] = '\0';
3544
printf("%s", line);
3645
}
46+
47+
spin_unlock_irqrestore(&lock, flags);
3748
}
3849

3950
static struct kmsg_dumper kmsg_dumper = {

drivers/hv/vmbus_drv.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id)
13991399
static void hv_kmsg_dump(struct kmsg_dumper *dumper,
14001400
enum kmsg_dump_reason reason)
14011401
{
1402+
struct kmsg_dump_iter iter;
14021403
size_t bytes_written;
14031404

14041405
/* We are only interested in panics. */
@@ -1409,7 +1410,8 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper,
14091410
* Write dump contents to the page. No need to synchronize; panic should
14101411
* be single-threaded.
14111412
*/
1412-
kmsg_dump_get_buffer(dumper, false, hv_panic_page, HV_HYP_PAGE_SIZE,
1413+
kmsg_dump_rewind(&iter);
1414+
kmsg_dump_get_buffer(&iter, false, hv_panic_page, HV_HYP_PAGE_SIZE,
14131415
&bytes_written);
14141416
if (!bytes_written)
14151417
return;

drivers/mtd/mtdoops.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static struct mtdoops_context {
5252
int nextcount;
5353
unsigned long *oops_page_used;
5454

55+
unsigned long oops_buf_busy;
5556
void *oops_buf;
5657
} oops_cxt;
5758

@@ -180,6 +181,9 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
180181
u32 *hdr;
181182
int ret;
182183

184+
if (test_and_set_bit(0, &cxt->oops_buf_busy))
185+
return;
186+
183187
/* Add mtdoops header to the buffer */
184188
hdr = cxt->oops_buf;
185189
hdr[0] = cxt->nextcount;
@@ -190,7 +194,7 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
190194
record_size, &retlen, cxt->oops_buf);
191195
if (ret == -EOPNOTSUPP) {
192196
printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
193-
return;
197+
goto out;
194198
}
195199
} else
196200
ret = mtd_write(mtd, cxt->nextpage * record_size,
@@ -203,6 +207,8 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
203207
memset(cxt->oops_buf, 0xff, record_size);
204208

205209
mtdoops_inc_counter(cxt);
210+
out:
211+
clear_bit(0, &cxt->oops_buf_busy);
206212
}
207213

208214
static void mtdoops_workfunc_write(struct work_struct *work)
@@ -271,13 +277,19 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper,
271277
{
272278
struct mtdoops_context *cxt = container_of(dumper,
273279
struct mtdoops_context, dump);
280+
struct kmsg_dump_iter iter;
274281

275282
/* Only dump oopses if dump_oops is set */
276283
if (reason == KMSG_DUMP_OOPS && !dump_oops)
277284
return;
278285

279-
kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
286+
kmsg_dump_rewind(&iter);
287+
288+
if (test_and_set_bit(0, &cxt->oops_buf_busy))
289+
return;
290+
kmsg_dump_get_buffer(&iter, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
280291
record_size - MTDOOPS_HEADER_SIZE, NULL);
292+
clear_bit(0, &cxt->oops_buf_busy);
281293

282294
if (reason != KMSG_DUMP_OOPS) {
283295
/* Panics must be written immediately */
@@ -394,6 +406,7 @@ static int __init mtdoops_init(void)
394406
return -ENOMEM;
395407
}
396408
memset(cxt->oops_buf, 0xff, record_size);
409+
cxt->oops_buf_busy = 0;
397410

398411
INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase);
399412
INIT_WORK(&cxt->work_write, mtdoops_workfunc_write);

fs/pstore/platform.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ void pstore_record_init(struct pstore_record *record,
385385
static void pstore_dump(struct kmsg_dumper *dumper,
386386
enum kmsg_dump_reason reason)
387387
{
388+
struct kmsg_dump_iter iter;
388389
unsigned long total = 0;
389390
const char *why;
390391
unsigned int part = 1;
@@ -405,6 +406,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
405406
}
406407
}
407408

409+
kmsg_dump_rewind(&iter);
410+
408411
oopscount++;
409412
while (total < kmsg_bytes) {
410413
char *dst;
@@ -435,7 +438,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
435438
dst_size -= header_size;
436439

437440
/* Write dump contents. */
438-
if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
441+
if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
439442
dst_size, &dump_size))
440443
break;
441444

include/linux/kmsg_dump.h

+17-30
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ enum kmsg_dump_reason {
2929
KMSG_DUMP_MAX
3030
};
3131

32+
/**
33+
* struct kmsg_dump_iter - iterator for retrieving kernel messages
34+
* @cur_seq: Points to the oldest message to dump
35+
* @next_seq: Points after the newest message to dump
36+
*/
37+
struct kmsg_dump_iter {
38+
u64 cur_seq;
39+
u64 next_seq;
40+
};
41+
3242
/**
3343
* struct kmsg_dumper - kernel crash message dumper structure
3444
* @list: Entry in the dumper list (private)
@@ -41,31 +51,19 @@ struct kmsg_dumper {
4151
struct list_head list;
4252
void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
4353
enum kmsg_dump_reason max_reason;
44-
bool active;
4554
bool registered;
46-
47-
/* private state of the kmsg iterator */
48-
u32 cur_idx;
49-
u32 next_idx;
50-
u64 cur_seq;
51-
u64 next_seq;
5255
};
5356

5457
#ifdef CONFIG_PRINTK
5558
void kmsg_dump(enum kmsg_dump_reason reason);
5659

57-
bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
58-
char *line, size_t size, size_t *len);
59-
60-
bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
60+
bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog,
6161
char *line, size_t size, size_t *len);
6262

63-
bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
64-
char *buf, size_t size, size_t *len);
65-
66-
void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper);
63+
bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
64+
char *buf, size_t size, size_t *len_out);
6765

68-
void kmsg_dump_rewind(struct kmsg_dumper *dumper);
66+
void kmsg_dump_rewind(struct kmsg_dump_iter *iter);
6967

7068
int kmsg_dump_register(struct kmsg_dumper *dumper);
7169

@@ -77,30 +75,19 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason)
7775
{
7876
}
7977

80-
static inline bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper,
81-
bool syslog, const char *line,
82-
size_t size, size_t *len)
83-
{
84-
return false;
85-
}
86-
87-
static inline bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
78+
static inline bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog,
8879
const char *line, size_t size, size_t *len)
8980
{
9081
return false;
9182
}
9283

93-
static inline bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
84+
static inline bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
9485
char *buf, size_t size, size_t *len)
9586
{
9687
return false;
9788
}
9889

99-
static inline void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
100-
{
101-
}
102-
103-
static inline void kmsg_dump_rewind(struct kmsg_dumper *dumper)
90+
static inline void kmsg_dump_rewind(struct kmsg_dump_iter *iter)
10491
{
10592
}
10693

0 commit comments

Comments
 (0)