Skip to content

Commit cef5d0f

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek: - Do not allow use of freed init data and code even when boot consoles are forced to stay. Also check for the init memory more precisely. - Some code clean up by starting contributors. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk: printk: Clean up do_syslog() error handling printk/console: Enhance the check for consoles using init memory printk/console: Always disable boot consoles that use init memory before it is freed printk: Modify operators of printed_len and text_len
2 parents 0fb02e7 + 077a1cc commit cef5d0f

File tree

1 file changed

+32
-37
lines changed

1 file changed

+32
-37
lines changed

kernel/printk/printk.c

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,28 +1434,24 @@ int do_syslog(int type, char __user *buf, int len, int source)
14341434

14351435
error = check_syslog_permissions(type, source);
14361436
if (error)
1437-
goto out;
1437+
return error;
14381438

14391439
switch (type) {
14401440
case SYSLOG_ACTION_CLOSE: /* Close log */
14411441
break;
14421442
case SYSLOG_ACTION_OPEN: /* Open log */
14431443
break;
14441444
case SYSLOG_ACTION_READ: /* Read from log */
1445-
error = -EINVAL;
14461445
if (!buf || len < 0)
1447-
goto out;
1448-
error = 0;
1446+
return -EINVAL;
14491447
if (!len)
1450-
goto out;
1451-
if (!access_ok(VERIFY_WRITE, buf, len)) {
1452-
error = -EFAULT;
1453-
goto out;
1454-
}
1448+
return 0;
1449+
if (!access_ok(VERIFY_WRITE, buf, len))
1450+
return -EFAULT;
14551451
error = wait_event_interruptible(log_wait,
14561452
syslog_seq != log_next_seq);
14571453
if (error)
1458-
goto out;
1454+
return error;
14591455
error = syslog_print(buf, len);
14601456
break;
14611457
/* Read/clear last kernel messages */
@@ -1464,16 +1460,12 @@ int do_syslog(int type, char __user *buf, int len, int source)
14641460
/* FALL THRU */
14651461
/* Read last kernel messages */
14661462
case SYSLOG_ACTION_READ_ALL:
1467-
error = -EINVAL;
14681463
if (!buf || len < 0)
1469-
goto out;
1470-
error = 0;
1464+
return -EINVAL;
14711465
if (!len)
1472-
goto out;
1473-
if (!access_ok(VERIFY_WRITE, buf, len)) {
1474-
error = -EFAULT;
1475-
goto out;
1476-
}
1466+
return 0;
1467+
if (!access_ok(VERIFY_WRITE, buf, len))
1468+
return -EFAULT;
14771469
error = syslog_print_all(buf, len, clear);
14781470
break;
14791471
/* Clear ring buffer */
@@ -1495,15 +1487,13 @@ int do_syslog(int type, char __user *buf, int len, int source)
14951487
break;
14961488
/* Set level of messages printed to console */
14971489
case SYSLOG_ACTION_CONSOLE_LEVEL:
1498-
error = -EINVAL;
14991490
if (len < 1 || len > 8)
1500-
goto out;
1491+
return -EINVAL;
15011492
if (len < minimum_console_loglevel)
15021493
len = minimum_console_loglevel;
15031494
console_loglevel = len;
15041495
/* Implicitly re-enable logging to console */
15051496
saved_console_loglevel = LOGLEVEL_DEFAULT;
1506-
error = 0;
15071497
break;
15081498
/* Number of chars in the log buffer */
15091499
case SYSLOG_ACTION_SIZE_UNREAD:
@@ -1525,7 +1515,6 @@ int do_syslog(int type, char __user *buf, int len, int source)
15251515
u64 seq = syslog_seq;
15261516
u32 idx = syslog_idx;
15271517

1528-
error = 0;
15291518
while (seq < log_next_seq) {
15301519
struct printk_log *msg = log_from_idx(idx);
15311520

@@ -1545,7 +1534,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
15451534
error = -EINVAL;
15461535
break;
15471536
}
1548-
out:
1537+
15491538
return error;
15501539
}
15511540

@@ -1697,10 +1686,10 @@ asmlinkage int vprintk_emit(int facility, int level,
16971686
{
16981687
static char textbuf[LOG_LINE_MAX];
16991688
char *text = textbuf;
1700-
size_t text_len = 0;
1689+
size_t text_len;
17011690
enum log_flags lflags = 0;
17021691
unsigned long flags;
1703-
int printed_len = 0;
1692+
int printed_len;
17041693
bool in_sched = false;
17051694

17061695
if (level == LOGLEVEL_SCHED) {
@@ -1753,7 +1742,7 @@ asmlinkage int vprintk_emit(int facility, int level,
17531742
if (dict)
17541743
lflags |= LOG_PREFIX|LOG_NEWLINE;
17551744

1756-
printed_len += log_output(facility, level, lflags, dict, dictlen, text, text_len);
1745+
printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len);
17571746

17581747
logbuf_unlock_irqrestore(flags);
17591748

@@ -2649,26 +2638,32 @@ void __init console_init(void)
26492638
* makes it difficult to diagnose problems that occur during this time.
26502639
*
26512640
* To mitigate this problem somewhat, only unregister consoles whose memory
2652-
* intersects with the init section. Note that code exists elsewhere to get
2653-
* rid of the boot console as soon as the proper console shows up, so there
2654-
* won't be side-effects from postponing the removal.
2641+
* intersects with the init section. Note that all other boot consoles will
2642+
* get unregistred when the real preferred console is registered.
26552643
*/
26562644
static int __init printk_late_init(void)
26572645
{
26582646
struct console *con;
26592647
int ret;
26602648

26612649
for_each_console(con) {
2662-
if (!keep_bootcon && con->flags & CON_BOOT) {
2650+
if (!(con->flags & CON_BOOT))
2651+
continue;
2652+
2653+
/* Check addresses that might be used for enabled consoles. */
2654+
if (init_section_intersects(con, sizeof(*con)) ||
2655+
init_section_contains(con->write, 0) ||
2656+
init_section_contains(con->read, 0) ||
2657+
init_section_contains(con->device, 0) ||
2658+
init_section_contains(con->unblank, 0) ||
2659+
init_section_contains(con->data, 0)) {
26632660
/*
2664-
* Make sure to unregister boot consoles whose data
2665-
* resides in the init section before the init section
2666-
* is discarded. Boot consoles whose data will stick
2667-
* around will automatically be unregistered when the
2668-
* proper console replaces them.
2661+
* Please, consider moving the reported consoles out
2662+
* of the init section.
26692663
*/
2670-
if (init_section_intersects(con, sizeof(*con)))
2671-
unregister_console(con);
2664+
pr_warn("bootconsole [%s%d] uses init memory and must be disabled even before the real one is ready\n",
2665+
con->name, con->index);
2666+
unregister_console(con);
26722667
}
26732668
}
26742669
ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,

0 commit comments

Comments
 (0)