[syslinux:lwip] dmi: fix incorrect pointer subtraction, add sanity checks

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Tue Apr 26 17:42:02 PDT 2011


Commit-ID:  ae2dd06c076a447ec9ca8f7b02cdf15ef5e6ce15
Gitweb:     http://syslinux.zytor.com/commit/ae2dd06c076a447ec9ca8f7b02cdf15ef5e6ce15
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Tue, 26 Apr 2011 16:57:50 -0700
Committer:  H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Tue, 26 Apr 2011 16:57:50 -0700

dmi: fix incorrect pointer subtraction, add sanity checks

We're dealing with BIOS-provided data, so we better do sanity checks
all over the place.

More immediately, fix a pointer-subtraction bug which would hang the
system.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 core/dmi.c |   32 ++++++++++++++++++++++----------
 1 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/core/dmi.c b/core/dmi.c
index 66597af..988a4e8 100644
--- a/core/dmi.c
+++ b/core/dmi.c
@@ -134,9 +134,12 @@ static const void *dmi_find_data(uint8_t type, uint8_t base, uint8_t length)
     offset = 0;
     tblcount = dmi->nstruc;
 
-    while (offset+2 < dmi->tbllen && tblcount) {
+    while (offset+6 <= dmi->tbllen && tblcount--) {
 	table = (const struct dmi_table *)(dmi->tbladdr + offset);
 
+	if (table->type == 127)	/* End of table */
+	    break;
+	
 	if (table->length < sizeof *table)
 	    break;		/* Invalid length */
 
@@ -146,12 +149,11 @@ static const void *dmi_find_data(uint8_t type, uint8_t base, uint8_t length)
 	    return (const char *)table + base;
 
 	/* Search for a double NUL terminating the string table */
-	while (offset+2 < dmi->tbllen &&
+	while (offset+2 <= dmi->tbllen &&
 	       *(const uint16_t *)(dmi->tbladdr + offset) != 0)
 	    offset++;
 
 	offset += 2;
-	tblcount--;
     }
 
     return NULL;
@@ -175,9 +177,12 @@ static const char *dmi_find_string(uint8_t type, uint8_t base)
     offset = 0;
     tblcount = dmi->nstruc;
 
-    while (offset+2 < dmi->tbllen && tblcount) {
+    while (offset+6 <= dmi->tbllen && tblcount--) {
 	table = (const struct dmi_table *)(dmi->tbladdr + offset);
 
+	if (table->type == 127)	/* End of table */
+	    break;
+	
 	if (table->length < sizeof *table)
 	    break;		/* Invalid length */
 
@@ -186,6 +191,7 @@ static const char *dmi_find_string(uint8_t type, uint8_t base)
 	if (table->type == type && base < table->length) {
 	    uint8_t index = ((const uint8_t *)table)[base];
 	    const char *p = (const char *)table + table->length;
+	    const char *str;
 	    char c;
 
 	    if (!index)
@@ -196,18 +202,24 @@ static const char *dmi_find_string(uint8_t type, uint8_t base)
 		    return NULL;
 
 		do {
-		    c = *p;
-		    if (++offset >= dmi->tbllen)
+		    if (offset++ >= dmi->tbllen)
 			return NULL;
-		    p++;
+		    c = *p++;
 		} while (c);
 	    }
 
-	    return p;
+	    /* Make sure the string is null-terminated */
+	    str = p;
+	    do {
+		if (offset++ >= dmi->tbllen)
+		    return NULL;
+		c = *p++;
+	    } while (c);
+	    return str;
 	}
 
 	/* Search for a double NUL terminating the string table */
-	while (offset+2 < dmi->tbllen &&
+	while (offset+2 <= dmi->tbllen &&
 	       *(const uint16_t *)(dmi->tbladdr + offset) != 0)
 	    offset++;
 
@@ -276,7 +288,7 @@ static const char *dmi_install_string(const char *pfx, const char *str)
 	return NULL;
     memcpy(q, pfx, pfxlen);
     q += pfxlen;
-    memcpy(q, str, ep-p);
+    memcpy(q, str, ep-str);
     q += (ep-p);
     *q = '\0';
 



More information about the Syslinux-commits mailing list