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>
This commit is contained in:
Steven Rostedt (Red Hat) 2014-06-20 23:31:26 -04:00 committed by Steven Rostedt
parent 36aabfff50
commit 6d2289f3fa
3 changed files with 19 additions and 10 deletions

View File

@ -25,8 +25,6 @@ trace_seq_init(struct trace_seq *s)
s->full = 0; s->full = 0;
} }
#define MAX_MEMHEX_BYTES 8
/* /*
* Currently only defined when tracing is enabled. * Currently only defined when tracing is enabled.
*/ */

View File

@ -43,7 +43,6 @@ do { \
#define SEQ_PUT_HEX_FIELD_RET(s, x) \ #define SEQ_PUT_HEX_FIELD_RET(s, x) \
do { \ do { \
BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \
if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \ if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
return TRACE_TYPE_PARTIAL_LINE; \ return TRACE_TYPE_PARTIAL_LINE; \
} while (0) } while (0)

View File

@ -291,6 +291,7 @@ int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
} }
EXPORT_SYMBOL_GPL(trace_seq_putmem); EXPORT_SYMBOL_GPL(trace_seq_putmem);
#define MAX_MEMHEX_BYTES 8U
#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) #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]; unsigned char hex[HEX_CHARS];
const unsigned char *data = mem; const unsigned char *data = mem;
unsigned int start_len;
int i, j; int i, j;
int cnt = 0;
if (s->full) if (s->full)
return 0; return 0;
while (len) {
start_len = min(len, HEX_CHARS - 1);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
for (i = 0, j = 0; i < len; i++) { for (i = 0, j = 0; i < start_len; i++) {
#else #else
for (i = len-1, j = 0; i >= 0; i--) { for (i = start_len-1, j = 0; i >= 0; i--) {
#endif #endif
hex[j++] = hex_asc_hi(data[i]); hex[j++] = hex_asc_hi(data[i]);
hex[j++] = hex_asc_lo(data[i]); hex[j++] = hex_asc_lo(data[i]);
} }
hex[j++] = ' '; 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); EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);