summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2022-01-27 20:12:32 +0200
committerPetr Mladek <pmladek@suse.com>2022-02-10 13:16:50 +0100
commitd75b26f880f60ead301e79ba0f4a635c5a60767f (patch)
tree5c99a6af6518edb2f07237cc519dbf41f479bf56
parenta229327733b86aa585effdb0d27a87b12aa51597 (diff)
downloadlinux-d75b26f880f60ead301e79ba0f4a635c5a60767f.tar.gz
linux-d75b26f880f60ead301e79ba0f4a635c5a60767f.tar.bz2
linux-d75b26f880f60ead301e79ba0f4a635c5a60767f.zip
vsprintf: Fix potential unaligned access
The %p4cc specifier in some cases might get an unaligned pointer. Due to this we need to make copy to local variable once to avoid potential crashes on some architectures due to improper access. Fixes: af612e43de6d ("lib/vsprintf: Add support for printing V4L2 and DRM fourccs") Cc: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20220127181233.72910-1-andriy.shevchenko@linux.intel.com
-rw-r--r--lib/vsprintf.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 53d6081f9e8b..3e416a3cb66d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -49,6 +49,7 @@
#include <asm/page.h> /* for PAGE_SIZE */
#include <asm/byteorder.h> /* cpu_to_le16 */
+#include <asm/unaligned.h>
#include <linux/string_helpers.h>
#include "kstrtox.h"
@@ -1771,7 +1772,7 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
char output[sizeof("0123 little-endian (0x01234567)")];
char *p = output;
unsigned int i;
- u32 val;
+ u32 orig, val;
if (fmt[1] != 'c' || fmt[2] != 'c')
return error_string(buf, end, "(%p4?)", spec);
@@ -1779,21 +1780,22 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
if (check_pointer(&buf, end, fourcc, spec))
return buf;
- val = *fourcc & ~BIT(31);
+ orig = get_unaligned(fourcc);
+ val = orig & ~BIT(31);
- for (i = 0; i < sizeof(*fourcc); i++) {
+ for (i = 0; i < sizeof(u32); i++) {
unsigned char c = val >> (i * 8);
/* Print non-control ASCII characters as-is, dot otherwise */
*p++ = isascii(c) && isprint(c) ? c : '.';
}
- strcpy(p, *fourcc & BIT(31) ? " big-endian" : " little-endian");
+ strcpy(p, orig & BIT(31) ? " big-endian" : " little-endian");
p += strlen(p);
*p++ = ' ';
*p++ = '(';
- p = special_hex_number(p, output + sizeof(output) - 2, *fourcc, sizeof(u32));
+ p = special_hex_number(p, output + sizeof(output) - 2, orig, sizeof(u32));
*p++ = ')';
*p = '\0';