tracing: Make trace_seq_putmem_hex() more robust

Currently trace_seq_putmem_hex() can only take as a parameter a pointer
to something that is 8 bytes or less, otherwise it will overflow the
buffer. This is protected by a macro that encompasses the call to
trace_seq_putmem_hex() that has a BUILD_BUG_ON() for the variable before
it is passed in. This is not very robust and if trace_seq_putmem_hex() ever
gets used outside that macro it will cause issues.

Instead of only being able to produce a hex output of memory that is for
a single word, change it to be more robust and allow any size input.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c
index 0fabca7..88c0f80 100644
--- a/kernel/trace/trace_seq.c
+++ b/kernel/trace/trace_seq.c
@@ -291,6 +291,7 @@
 }
 EXPORT_SYMBOL_GPL(trace_seq_putmem);
 
+#define MAX_MEMHEX_BYTES	8U
 #define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
 
 /**
@@ -310,22 +311,33 @@
 {
 	unsigned char hex[HEX_CHARS];
 	const unsigned char *data = mem;
+	unsigned int start_len;
 	int i, j;
+	int cnt = 0;
 
 	if (s->full)
 		return 0;
 
+	while (len) {
+		start_len = min(len, HEX_CHARS - 1);
 #ifdef __BIG_ENDIAN
-	for (i = 0, j = 0; i < len; i++) {
+		for (i = 0, j = 0; i < start_len; i++) {
 #else
-	for (i = len-1, j = 0; i >= 0; i--) {
+		for (i = start_len-1, j = 0; i >= 0; i--) {
 #endif
-		hex[j++] = hex_asc_hi(data[i]);
-		hex[j++] = hex_asc_lo(data[i]);
-	}
-	hex[j++] = ' ';
+			hex[j++] = hex_asc_hi(data[i]);
+			hex[j++] = hex_asc_lo(data[i]);
+		}
+		if (WARN_ON_ONCE(j == 0 || j/2 > len))
+			break;
 
-	return trace_seq_putmem(s, hex, j);
+		/* j increments twice per loop */
+		len -= j / 2;
+		hex[j++] = ' ';
+
+		cnt += trace_seq_putmem(s, hex, j);
+	}
+	return cnt;
 }
 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);