Skip to content

Commit 6d2289f

Browse files
committed
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 <[email protected]>
1 parent 36aabff commit 6d2289f

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

include/linux/trace_seq.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ trace_seq_init(struct trace_seq *s)
2525
s->full = 0;
2626
}
2727

28-
#define MAX_MEMHEX_BYTES 8
29-
3028
/*
3129
* Currently only defined when tracing is enabled.
3230
*/

kernel/trace/trace_output.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ do { \
4343

4444
#define SEQ_PUT_HEX_FIELD_RET(s, x) \
4545
do { \
46-
BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \
4746
if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
4847
return TRACE_TYPE_PARTIAL_LINE; \
4948
} while (0)

kernel/trace/trace_seq.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
291291
}
292292
EXPORT_SYMBOL_GPL(trace_seq_putmem);
293293

294+
#define MAX_MEMHEX_BYTES 8U
294295
#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
295296

296297
/**
@@ -310,22 +311,33 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
310311
{
311312
unsigned char hex[HEX_CHARS];
312313
const unsigned char *data = mem;
314+
unsigned int start_len;
313315
int i, j;
316+
int cnt = 0;
314317

315318
if (s->full)
316319
return 0;
317320

321+
while (len) {
322+
start_len = min(len, HEX_CHARS - 1);
318323
#ifdef __BIG_ENDIAN
319-
for (i = 0, j = 0; i < len; i++) {
324+
for (i = 0, j = 0; i < start_len; i++) {
320325
#else
321-
for (i = len-1, j = 0; i >= 0; i--) {
326+
for (i = start_len-1, j = 0; i >= 0; i--) {
322327
#endif
323-
hex[j++] = hex_asc_hi(data[i]);
324-
hex[j++] = hex_asc_lo(data[i]);
325-
}
326-
hex[j++] = ' ';
328+
hex[j++] = hex_asc_hi(data[i]);
329+
hex[j++] = hex_asc_lo(data[i]);
330+
}
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++] = ' ';
327337

328-
return trace_seq_putmem(s, hex, j);
338+
cnt += trace_seq_putmem(s, hex, j);
339+
}
340+
return cnt;
329341
}
330342
EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
331343

0 commit comments

Comments
 (0)