printk: fix buffer overflow when calling log_prefix function from call_console_drivers

This patch corrects a buffer overflow in kernels from 3.0 to 3.4 when calling
log_prefix() function from call_console_drivers().

This bug existed in previous releases but has been revealed with commit
162a7e7500f9664636e649ba59defe541b7c2c60 (2.6.39 => 3.0) that made changes
about how to allocate memory for early printk buffer (use of memblock_alloc).
It disappears with commit 7ff9554bb578ba02166071d2d487b7fc7d860d62 (3.4 => 3.5)
that does a refactoring of printk buffer management.

In log_prefix(), the access to "p[0]", "p[1]", "p[2]" or
"simple_strtoul(&p[1], &endp, 10)" may cause a buffer overflow as this
function is called from call_console_drivers by passing "&LOG_BUF(cur_index)"
where the index must be masked to do not exceed the buffer's boundary.

The trick is to prepare in call_console_drivers() a buffer with the necessary
data (PRI field of syslog message) to be safely evaluated in log_prefix().

This patch can be applied to stable kernel branches 3.0.y, 3.2.y and 3.4.y.

Without this patch, one can freeze a server running this loop from shell :
  $ export DUMMY=`cat /dev/urandom | tr -dc '12345AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn' | head -c255`
  $ while true do ; echo $DUMMY > /dev/kmsg ; done

The "server freeze" depends on where memblock_alloc does allocate printk buffer :
if the buffer overflow is inside another kernel allocation the problem may not
be revealed, else the server may hangs up.

Signed-off-by: Alexandre SIMON <Alexandre.Simon@univ-lorraine.fr>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
void kmsg_dump(enum kmsg_dump_reason reason)
{
	unsigned long end;
	unsigned chars;
	struct kmsg_dumper *dumper;
	const char *s1, *s2;
	unsigned long l1, l2;
	unsigned long flags;

	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
		return;

	/* Theoretically, the log could move on after we do this, but
	   there's not a lot we can do about that. The new messages
	   will overwrite the start of what we dump. */
	raw_spin_lock_irqsave(&logbuf_lock, flags);
	end = log_end & LOG_BUF_MASK;
	chars = logged_chars;
	raw_spin_unlock_irqrestore(&logbuf_lock, flags);

	if (chars > end) {
		s1 = log_buf + log_buf_len - chars + end;
		l1 = chars - end;

		s2 = log_buf;
		l2 = end;
	} else {
		s1 = "";
		l1 = 0;

		s2 = log_buf + end - chars;
		l2 = chars;
	}

	rcu_read_lock();
	list_for_each_entry_rcu(dumper, &dump_list, list)
		dumper->dump(dumper, reason, s1, l1, s2, l2);
	rcu_read_unlock();
}

void kmsg_dump(enum kmsg_dump_reason reason)
{
	unsigned long end;
	unsigned chars;
	struct kmsg_dumper *dumper;
	const char *s1, *s2;
	unsigned long l1, l2;
	unsigned long flags;

	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
		return;

	/* Theoretically, the log could move on after we do this, but
	   there's not a lot we can do about that. The new messages
	   will overwrite the start of what we dump. */
	raw_spin_lock_irqsave(&logbuf_lock, flags);
	end = log_end & LOG_BUF_MASK;
	chars = logged_chars;
	raw_spin_unlock_irqrestore(&logbuf_lock, flags);

	if (chars > end) {
		s1 = log_buf + log_buf_len - chars + end;
		l1 = chars - end;

		s2 = log_buf;
		l2 = end;
	} else {
		s1 = "";
		l1 = 0;

		s2 = log_buf + end - chars;
		l2 = chars;
	}

	rcu_read_lock();
	list_for_each_entry_rcu(dumper, &dump_list, list)
		dumper->dump(dumper, reason, s1, l1, s2, l2);
	rcu_read_unlock();
}
