diff options
author | Horacio Mijail Anton Quiles <hmijail@gmail.com> | 2015-07-17 19:24:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-17 19:39:53 -0400 |
commit | 0f70fe605fad0f3215818ba79fc12617c0ec7f90 (patch) | |
tree | 4e0e1768928926e774f92081fa5236df02df8fe2 | |
parent | b4749e96a4a872c2496602566f205547c4e3c950 (diff) |
hexdump: fix for non-aligned buffers
A hexdump with a buf not aligned to the groupsize causes
non-naturally-aligned memory accesses. This was causing a kernel panic
on the processor BlackFin BF527, when such an unaligned buffer was fed
by the function ubifs_scanned_corruption in fs/ubifs/scan.c .
To fix this, change accesses to the contents of the buffer so they go
through get_unaligned(). This change should be harmless to unaligned-
access-capable architectures, and any performance hit should be anyway
dwarfed by the snprintf() processing time.
Signed-off-by: Horacio Mijail Antón Quiles <hmijail@gmail.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Joe Perches <joe@perches.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | lib/hexdump.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/lib/hexdump.c b/lib/hexdump.c index 7ea09699855d..8d74c20d8595 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/ctype.h> | 11 | #include <linux/ctype.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <asm/unaligned.h> | ||
14 | 15 | ||
15 | const char hex_asc[] = "0123456789abcdef"; | 16 | const char hex_asc[] = "0123456789abcdef"; |
16 | EXPORT_SYMBOL(hex_asc); | 17 | EXPORT_SYMBOL(hex_asc); |
@@ -139,7 +140,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, | |||
139 | for (j = 0; j < ngroups; j++) { | 140 | for (j = 0; j < ngroups; j++) { |
140 | ret = snprintf(linebuf + lx, linebuflen - lx, | 141 | ret = snprintf(linebuf + lx, linebuflen - lx, |
141 | "%s%16.16llx", j ? " " : "", | 142 | "%s%16.16llx", j ? " " : "", |
142 | (unsigned long long)*(ptr8 + j)); | 143 | get_unaligned(ptr8 + j)); |
143 | if (ret >= linebuflen - lx) | 144 | if (ret >= linebuflen - lx) |
144 | goto overflow1; | 145 | goto overflow1; |
145 | lx += ret; | 146 | lx += ret; |
@@ -150,7 +151,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, | |||
150 | for (j = 0; j < ngroups; j++) { | 151 | for (j = 0; j < ngroups; j++) { |
151 | ret = snprintf(linebuf + lx, linebuflen - lx, | 152 | ret = snprintf(linebuf + lx, linebuflen - lx, |
152 | "%s%8.8x", j ? " " : "", | 153 | "%s%8.8x", j ? " " : "", |
153 | *(ptr4 + j)); | 154 | get_unaligned(ptr4 + j)); |
154 | if (ret >= linebuflen - lx) | 155 | if (ret >= linebuflen - lx) |
155 | goto overflow1; | 156 | goto overflow1; |
156 | lx += ret; | 157 | lx += ret; |
@@ -161,7 +162,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, | |||
161 | for (j = 0; j < ngroups; j++) { | 162 | for (j = 0; j < ngroups; j++) { |
162 | ret = snprintf(linebuf + lx, linebuflen - lx, | 163 | ret = snprintf(linebuf + lx, linebuflen - lx, |
163 | "%s%4.4x", j ? " " : "", | 164 | "%s%4.4x", j ? " " : "", |
164 | *(ptr2 + j)); | 165 | get_unaligned(ptr2 + j)); |
165 | if (ret >= linebuflen - lx) | 166 | if (ret >= linebuflen - lx) |
166 | goto overflow1; | 167 | goto overflow1; |
167 | lx += ret; | 168 | lx += ret; |