On Thu, 2012-12-06 at 18:09 +0100, Sylvain Munaut wrote:
> The "%5lu" part of the sprintf only guarantees a minimum length,
> not a maximum one. This patch should make it correct for any
> possible timestamp.
> 
> This problem dates back from the printk conversion to records AFAICT.
> 
> I've tested this locally both by verifying 'dmesg' no longer
> segfaulted and also by checking that before this patch the
> buffer was overrun by exactly the number of char corresponding to
> extra digits in the timestamps.
> 
> Cc: Kay Sievers <k...@vrfy.org>
> Cc: sta...@kernel.org
> Signed-off-by: Sylvain Munaut <s.mun...@whatever-company.com>
> ---
>  kernel/printk.c |   13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/printk.c b/kernel/printk.c
> index 66a2ea3..2ceceea 100644
> --- a/kernel/printk.c
> +++ b/kernel/printk.c
> @@ -847,8 +847,17 @@ static size_t print_time(u64 ts, char *buf)
>       if (!printk_time)
>               return 0;
>  
> -     if (!buf)
> -             return 15;
> +     if (!buf) {
> +             size_t len = 15;
> +             u64 ts_limit = (u64)100000 * (u64)1000000000;
> +
> +             while ((ts > ts_limit) && (len < 21)) {
> +                     len++;
> +                     ts_limit = 10 * ts_limit;
> +             }

Perhaps use snprintf for sizing something like below?
(untested/uncompiled)

static size_t print_time(u64 ts, char *buf)
{
        unsigned long rem_nsec;
        char *tmpbuf = buf;
        int size = 15;                  /* expected size of non-null buf */
        char local_buf[1];

        if (!printk_time)
                return 0;

        if (!buf) {                     /* emit to a dummy buf instead */
                tmpbuf = local_buf;
                size = sizeof(local_buf);
        }
        
        rem_nsec = do_div(ts, 1000000000);

        return snprintf(tmpbuf, size, "[%5lu.%06lu] ",
                        (unsigned long)ts, rem_nsec / 1000);
}

It's perhaps unfortunate that print_time doesn't take a
a buffer and a size_t of buffer.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to