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

+32 -37
+32 -37
kernel/printk/printk.c
··· 1434 1435 error = check_syslog_permissions(type, source); 1436 if (error) 1437 - goto out; 1438 1439 switch (type) { 1440 case SYSLOG_ACTION_CLOSE: /* Close log */ ··· 1442 case SYSLOG_ACTION_OPEN: /* Open log */ 1443 break; 1444 case SYSLOG_ACTION_READ: /* Read from log */ 1445 - error = -EINVAL; 1446 if (!buf || len < 0) 1447 - goto out; 1448 - error = 0; 1449 if (!len) 1450 - goto out; 1451 - if (!access_ok(VERIFY_WRITE, buf, len)) { 1452 - error = -EFAULT; 1453 - goto out; 1454 - } 1455 error = wait_event_interruptible(log_wait, 1456 syslog_seq != log_next_seq); 1457 if (error) 1458 - goto out; 1459 error = syslog_print(buf, len); 1460 break; 1461 /* Read/clear last kernel messages */ ··· 1460 /* FALL THRU */ 1461 /* Read last kernel messages */ 1462 case SYSLOG_ACTION_READ_ALL: 1463 - error = -EINVAL; 1464 if (!buf || len < 0) 1465 - goto out; 1466 - error = 0; 1467 if (!len) 1468 - goto out; 1469 - if (!access_ok(VERIFY_WRITE, buf, len)) { 1470 - error = -EFAULT; 1471 - goto out; 1472 - } 1473 error = syslog_print_all(buf, len, clear); 1474 break; 1475 /* Clear ring buffer */ ··· 1487 break; 1488 /* Set level of messages printed to console */ 1489 case SYSLOG_ACTION_CONSOLE_LEVEL: 1490 - error = -EINVAL; 1491 if (len < 1 || len > 8) 1492 - goto out; 1493 if (len < minimum_console_loglevel) 1494 len = minimum_console_loglevel; 1495 console_loglevel = len; 1496 /* Implicitly re-enable logging to console */ 1497 saved_console_loglevel = LOGLEVEL_DEFAULT; 1498 - error = 0; 1499 break; 1500 /* Number of chars in the log buffer */ 1501 case SYSLOG_ACTION_SIZE_UNREAD: ··· 1515 u64 seq = syslog_seq; 1516 u32 idx = syslog_idx; 1517 1518 - error = 0; 1519 while (seq < log_next_seq) { 1520 struct printk_log *msg = log_from_idx(idx); 1521 ··· 1534 error = -EINVAL; 1535 break; 1536 } 1537 - out: 1538 return error; 1539 } 1540 ··· 1686 { 1687 static char textbuf[LOG_LINE_MAX]; 1688 char *text = textbuf; 1689 - size_t text_len = 0; 1690 enum log_flags lflags = 0; 1691 unsigned long flags; 1692 - int printed_len = 0; 1693 bool in_sched = false; 1694 1695 if (level == LOGLEVEL_SCHED) { ··· 1742 if (dict) 1743 lflags |= LOG_PREFIX|LOG_NEWLINE; 1744 1745 - printed_len += log_output(facility, level, lflags, dict, dictlen, text, text_len); 1746 1747 logbuf_unlock_irqrestore(flags); 1748 ··· 2638 * makes it difficult to diagnose problems that occur during this time. 2639 * 2640 * To mitigate this problem somewhat, only unregister consoles whose memory 2641 - * intersects with the init section. Note that code exists elsewhere to get 2642 - * rid of the boot console as soon as the proper console shows up, so there 2643 - * won't be side-effects from postponing the removal. 2644 */ 2645 static int __init printk_late_init(void) 2646 { ··· 2647 int ret; 2648 2649 for_each_console(con) { 2650 - if (!keep_bootcon && con->flags & CON_BOOT) { 2651 /* 2652 - * Make sure to unregister boot consoles whose data 2653 - * resides in the init section before the init section 2654 - * is discarded. Boot consoles whose data will stick 2655 - * around will automatically be unregistered when the 2656 - * proper console replaces them. 2657 */ 2658 - if (init_section_intersects(con, sizeof(*con))) 2659 - unregister_console(con); 2660 } 2661 } 2662 ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,
··· 1434 1435 error = check_syslog_permissions(type, source); 1436 if (error) 1437 + return error; 1438 1439 switch (type) { 1440 case SYSLOG_ACTION_CLOSE: /* Close log */ ··· 1442 case SYSLOG_ACTION_OPEN: /* Open log */ 1443 break; 1444 case SYSLOG_ACTION_READ: /* Read from log */ 1445 if (!buf || len < 0) 1446 + return -EINVAL; 1447 if (!len) 1448 + return 0; 1449 + if (!access_ok(VERIFY_WRITE, buf, len)) 1450 + return -EFAULT; 1451 error = wait_event_interruptible(log_wait, 1452 syslog_seq != log_next_seq); 1453 if (error) 1454 + return error; 1455 error = syslog_print(buf, len); 1456 break; 1457 /* Read/clear last kernel messages */ ··· 1464 /* FALL THRU */ 1465 /* Read last kernel messages */ 1466 case SYSLOG_ACTION_READ_ALL: 1467 if (!buf || len < 0) 1468 + return -EINVAL; 1469 if (!len) 1470 + return 0; 1471 + if (!access_ok(VERIFY_WRITE, buf, len)) 1472 + return -EFAULT; 1473 error = syslog_print_all(buf, len, clear); 1474 break; 1475 /* Clear ring buffer */ ··· 1495 break; 1496 /* Set level of messages printed to console */ 1497 case SYSLOG_ACTION_CONSOLE_LEVEL: 1498 if (len < 1 || len > 8) 1499 + return -EINVAL; 1500 if (len < minimum_console_loglevel) 1501 len = minimum_console_loglevel; 1502 console_loglevel = len; 1503 /* Implicitly re-enable logging to console */ 1504 saved_console_loglevel = LOGLEVEL_DEFAULT; 1505 break; 1506 /* Number of chars in the log buffer */ 1507 case SYSLOG_ACTION_SIZE_UNREAD: ··· 1525 u64 seq = syslog_seq; 1526 u32 idx = syslog_idx; 1527 1528 while (seq < log_next_seq) { 1529 struct printk_log *msg = log_from_idx(idx); 1530 ··· 1545 error = -EINVAL; 1546 break; 1547 } 1548 + 1549 return error; 1550 } 1551 ··· 1697 { 1698 static char textbuf[LOG_LINE_MAX]; 1699 char *text = textbuf; 1700 + size_t text_len; 1701 enum log_flags lflags = 0; 1702 unsigned long flags; 1703 + int printed_len; 1704 bool in_sched = false; 1705 1706 if (level == LOGLEVEL_SCHED) { ··· 1753 if (dict) 1754 lflags |= LOG_PREFIX|LOG_NEWLINE; 1755 1756 + printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len); 1757 1758 logbuf_unlock_irqrestore(flags); 1759 ··· 2649 * makes it difficult to diagnose problems that occur during this time. 2650 * 2651 * To mitigate this problem somewhat, only unregister consoles whose memory 2652 + * intersects with the init section. Note that all other boot consoles will 2653 + * get unregistred when the real preferred console is registered. 2654 */ 2655 static int __init printk_late_init(void) 2656 { ··· 2659 int ret; 2660 2661 for_each_console(con) { 2662 + if (!(con->flags & CON_BOOT)) 2663 + continue; 2664 + 2665 + /* Check addresses that might be used for enabled consoles. */ 2666 + if (init_section_intersects(con, sizeof(*con)) || 2667 + init_section_contains(con->write, 0) || 2668 + init_section_contains(con->read, 0) || 2669 + init_section_contains(con->device, 0) || 2670 + init_section_contains(con->unblank, 0) || 2671 + init_section_contains(con->data, 0)) { 2672 /* 2673 + * Please, consider moving the reported consoles out 2674 + * of the init section. 2675 */ 2676 + pr_warn("bootconsole [%s%d] uses init memory and must be disabled even before the real one is ready\n", 2677 + con->name, con->index); 2678 + unregister_console(con); 2679 } 2680 } 2681 ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,