⬢ DragonFlyBSD Kernel Audit
DF-5719 / fix.diff
← back to finding ↓ download raw
diff -ru a/sys/libkern/bcd.c b/sys/libkern/bcd.c
--- a/sys/libkern/bcd.c
+++ b/sys/libkern/bcd.c
@@ -2,6 +2,12 @@
 /*
  * Some data-tables that are often used.
  * Cannot be copyrighted.
+ *
+ * DOMAIN CONTRACT (indexed via the macros in sys/sys/libkern.h, which
+ * wrap indices into range):
+ *   bcd2bin_data[154]  valid BCD byte indices 0x00..0x99
+ *   bin2bcd_data[100]  valid binary indices 0..99
+ *   hex2ascii_data[37] radix-36 digits 0..35 plus NUL
  */
 
 #include <sys/libkern.h>
diff -ru a/sys/sys/libkern.h b/sys/sys/libkern.h
--- a/sys/sys/libkern.h
+++ b/sys/sys/libkern.h
@@ -56,9 +56,15 @@
 extern u_char const	bin2bcd_data[];
 extern char const	hex2ascii_data[];
 
-#define	bcd2bin(bcd)	(bcd2bin_data[bcd])
-#define	bin2bcd(bin)	(bin2bcd_data[bin])
-#define	hex2ascii(hex)	(hex2ascii_data[hex])
+/*
+ * The tables in sys/libkern/bcd.c are sized exactly for their valid
+ * domains: bin2bcd_data[100] (0..99), bcd2bin_data[154] (0x00..0x99)
+ * and hex2ascii_data[37] (0..35 + NUL).  Wrap the index into the object
+ * so device- or ioctl-supplied bytes cannot read past the end.
+ */
+#define	bcd2bin(bcd)	(bcd2bin_data[(u_int)(bcd) % 154])
+#define	bin2bcd(bin)	(bin2bcd_data[(u_char)(bin) % 100])
+#define	hex2ascii(hex)	(hex2ascii_data[(u_char)(hex) % 37])
 
 /*
  * Number of bytes needed for hexadecimal representation