hexdump: fix for non-aligned buffers
PATCH v6 1/1 hexdump: fix for non-aligned buffers
An 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.
---
Changes in v6:
- Removed unnecessary cast of u64 to unsigned long long, since currently they are equivalent (per Geer Uytterhoeven's indication)
Changes in v5:
- Instead of trying to detect non-unaligned-capable architectures, change all accesses to unconditionally use get_unaligned() (per Andrew Morton's and Geert Uytterhoeven's comments)
Changes in v4:
- Added space before "*/" (per Joe Perches' indication)
Changes in v3:
- Removed trailing whitespace (per Joe Perches' indication)
- Changed mail headers to avoid encoding issues (per Joe Perches' hint)
Changes in v2:
- Changed from ad-hoc calculation to IS_ALIGNED() for readability (per Joe Perches' indication)
- Made the explanation clearer (aligned vs naturally aligned)
--- lib/hexdump.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
lib/hexdump.c +4 -3
@@ -11,6 +11,7 @@#include <linux/ctype.h> #include <linux/kernel.h> #include <linux/export.h> +#include <asm/unaligned.h> const char hex_asc[] ="0123456789abcdef" ;EXPORT_SYMBOL (hex_asc);
@@ -139,7 +140,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,for (j =0 ; j < ngroups; j++) { ret =snprintf (linebuf + lx, linebuflen - lx,"%s%16.16llx" , j ?" " :"" , - (unsigned long long )*(ptr8 + j)); +get_unaligned (ptr8 + j));if (ret >= linebuflen - lx) goto overflow1; lx += ret;
@@ -150,7 +151,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,for (j =0 ; j < ngroups; j++) { ret =snprintf (linebuf + lx, linebuflen - lx,"%s%8.8x" , j ?" " :"" , - *(ptr4 + j)); +get_unaligned (ptr4 + j));if (ret >= linebuflen - lx) goto overflow1; lx += ret;
@@ -161,7 +162,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,for (j =0 ; j < ngroups; j++) { ret =snprintf (linebuf + lx, linebuflen - lx,"%s%4.4x" , j ?" " :"" , - *(ptr2 + j)); +get_unaligned (ptr2 + j));if (ret >= linebuflen - lx) goto overflow1; lx += ret;
Signature · 1 line
2.1.4