Skip to contentSkip to conversation

vsprintf: Fix potential unaligned access

PATCH In review Andy Shevchenko 2 participants 4 messages Jan 27, 2022 – Feb 10, 2022

Subsystems (2)
lore
Share & tools
lore

Andy Shevchenko

author reviewer
#0 lore raw

PATCH v4 1/2 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 <[email protected]>

---
v4: no changes

 lib/vsprintf.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
lib/vsprintf.c +7 -5
index 61528094ec87..4e8f3e9acb99 100644
@@ -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"
@@ -1762,7 +1763,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);
@@ -1770,21 +1771,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';
 
Signature · 1 line
2.34.1
author reviewer
#1 lore raw

PATCH v4 2/2 vsprintf: Move space out of string literals in fourcc_string()

The literals "big-endian" and "little-endian" may be potentially occurred in other places. Dropping space allows linker to merge them by using only a single copy.

---
v4: dropped stpcpy() use (Kees), replaced "compress" with merge (Nick)

 lib/vsprintf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
lib/vsprintf.c +2 -1
index 4e8f3e9acb99..a1babe5e07d1 100644
@@ -1781,7 +1781,8 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
 		*p++ = isascii(c) && isprint(c) ? c : '.';
 	}
 
-	strcpy(p, orig & BIT(31) ? " big-endian" : " little-endian");
+	*p++ = ' ';
+	strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
 	p += strlen(p);
 
 	*p++ = ' ';
Signature · 1 line
2.34.1
maintainer Reviewed-by on v4 2/2
#2 lore raw

Re: [PATCH v4 2/2] vsprintf: Move space out of string literals in fourcc_string()

Quoted 6 lines · Andy Shevchenko

The literals "big-endian" and "little-endian" may be potentially occurred in other places. Dropping space allows linker to merge them by using only a single copy.

Best Regards,
Petr

PS: I have vacation the following week and will have limited internet
access. I am going to push this patchset after I am back unless there are some complains.

maintainer
#3 lore raw
In reply to Andy Shevchenko
Quoted 8 lines · Andy Shevchenko

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 <[email protected]>

Both patches have been committed into printk/linux.git, branch for-5.18-vsprintf-fourcc-fixup .

Best Regards,
Petr