From: "Steven Rostedt (Red Hat)" 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 --- include/linux/trace_seq.h | 2 -- kernel/trace/trace_output.h | 1 - kernel/trace/trace_seq.c | 26 +++++++++++++++++++------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h index 1f05317f51c4..8283762ab7ef 100644 --- a/include/linux/trace_seq.h +++ b/include/linux/trace_seq.h @@ -25,8 +25,6 @@ trace_seq_init(struct trace_seq *s) s->full = 0; } -#define MAX_MEMHEX_BYTES 8 - /* * Currently only defined when tracing is enabled. */ diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h index bf7daf2237ed..80b25b585a70 100644 --- a/kernel/trace/trace_output.h +++ b/kernel/trace/trace_output.h @@ -43,7 +43,6 @@ do { \ #define SEQ_PUT_HEX_FIELD_RET(s, x) \ do { \ - BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \ if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \ return TRACE_TYPE_PARTIAL_LINE; \ } while (0) diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c index 0fabca773e51..88c0f80f0a1f 100644 --- a/kernel/trace/trace_seq.c +++ b/kernel/trace/trace_seq.c @@ -291,6 +291,7 @@ int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len) } EXPORT_SYMBOL_GPL(trace_seq_putmem); +#define MAX_MEMHEX_BYTES 8U #define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) /** @@ -310,22 +311,33 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, { 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; + + /* j increments twice per loop */ + len -= j / 2; + hex[j++] = ' '; - return trace_seq_putmem(s, hex, j); + cnt += trace_seq_putmem(s, hex, j); + } + return cnt; } EXPORT_SYMBOL_GPL(trace_seq_putmem_hex); -- 2.0.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/