• Roland Dreier's avatar
    printk: fix incorrect length from print_time() when seconds > 99999 · 35dac27c
    Roland Dreier authored
    print_prefix() passes a NULL buf to print_time() to get the length of
    the time prefix; when printk times are enabled, the current code just
    returns the constant 15, which matches the format "[%5lu.%06lu] " used
    to print the time value.  However, this is obviously incorrect when the
    whole seconds part of the time gets beyond 5 digits (100000 seconds is a
    bit more than a day of uptime).
    
    The simple fix is to use snprintf(NULL, 0, ...) to calculate the actual
    length of the time prefix.  This could be micro-optimized but it seems
    better to have simpler, more readable code here.
    
    The bug leads to the syslog system call miscomputing which messages fit
    into the userspace buffer.  If there are enough messages to fill
    log_buf_len and some have a timestamp >= 100000, dmesg may fail with:
    
        # dmesg
        klogctl: Bad address
    
    When this happens, strace shows that the failure is indeed EFAULT due to
    the kernel mistakenly accessing past the end of dmesg's buffer, since
    dmesg asks the kernel how big a buffer it needs, allocates a bit more,
    and then gets an error when it asks the kernel to fill it:
    
        syslog(0xa, 0, 0)                       = 1048576
        mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa4d25d2000
        syslog(0x3, 0x7fa4d25d2010, 0x100008)   = -1 EFAULT (Bad address)
    
    As far as I can see, the bug has been there as long as print_time(),
    which comes from commit 084681d1 ("printk: flush continuation lines
    immediately to console") in 3.5-rc5.
    Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Cc: Joe Perches <joe@perches.com>
    Cc: Sylvain Munaut <s.munaut@whatever-company.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    35dac27c
printk.c 70.2 KB