aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_seq.c
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-06-20 23:31:26 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-07-01 07:13:37 -0400
commit6d2289f3faa71dcc5bba15c7aeba4f31c185b6df (patch)
tree8425f1195f29a670dcb1ad00e56ee1836514ab02 /kernel/trace/trace_seq.c
parent36aabfff50b6a03bcfd2c3cfbd7b83eb0a9ce0c1 (diff)
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>
Diffstat (limited to 'kernel/trace/trace_seq.c')
-rw-r--r--kernel/trace/trace_seq.c26
1 files changed, 19 insertions, 7 deletions
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)
291} 291}
292EXPORT_SYMBOL_GPL(trace_seq_putmem); 292EXPORT_SYMBOL_GPL(trace_seq_putmem);
293 293
294#define MAX_MEMHEX_BYTES 8U
294#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) 295#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
295 296
296/** 297/**
@@ -310,22 +311,33 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
310{ 311{
311 unsigned char hex[HEX_CHARS]; 312 unsigned char hex[HEX_CHARS];
312 const unsigned char *data = mem; 313 const unsigned char *data = mem;
314 unsigned int start_len;
313 int i, j; 315 int i, j;
316 int cnt = 0;
314 317
315 if (s->full) 318 if (s->full)
316 return 0; 319 return 0;
317 320
321 while (len) {
322 start_len = min(len, HEX_CHARS - 1);
318#ifdef __BIG_ENDIAN 323#ifdef __BIG_ENDIAN
319 for (i = 0, j = 0; i < len; i++) { 324 for (i = 0, j = 0; i < start_len; i++) {
320#else 325#else
321 for (i = len-1, j = 0; i >= 0; i--) { 326 for (i = start_len-1, j = 0; i >= 0; i--) {
322#endif 327#endif
323 hex[j++] = hex_asc_hi(data[i]); 328 hex[j++] = hex_asc_hi(data[i]);
324 hex[j++] = hex_asc_lo(data[i]); 329 hex[j++] = hex_asc_lo(data[i]);
325 } 330 }
326 hex[j++] = ' '; 331 if (WARN_ON_ONCE(j == 0 || j/2 > len))
332 break;
333
334 /* j increments twice per loop */
335 len -= j / 2;
336 hex[j++] = ' ';
327 337
328 return trace_seq_putmem(s, hex, j); 338 cnt += trace_seq_putmem(s, hex, j);
339 }
340 return cnt;
329} 341}
330EXPORT_SYMBOL_GPL(trace_seq_putmem_hex); 342EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
331 343