[PATCH v2] firmware: dmi: Respect buffer size in get_modalias

Cyrill Gorcunov posted 1 patch 8 months, 3 weeks ago
drivers/firmware/dmi-id.c |   30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
[PATCH v2] firmware: dmi: Respect buffer size in get_modalias
Posted by Cyrill Gorcunov 8 months, 3 weeks ago
When we collect data from DMI info the "dmi" prefix is copied unconditionally
which may result in buffer overflow in case of filling uevent environment.
Thus lets use strscpy() helper instead. Same time make all get_modalias()
callers to handler error.

CC: Jean Delvare <jdelvare@suse.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
v2:
 - add comment about reserving space for suffix
 - check for error in callers

 drivers/firmware/dmi-id.c |   30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

Index: linux-tip.git/drivers/firmware/dmi-id.c
===================================================================
--- linux-tip.git.orig/drivers/firmware/dmi-id.c
+++ linux-tip.git/drivers/firmware/dmi-id.c
@@ -103,8 +103,15 @@ static ssize_t get_modalias(char *buffer
 	char *p;
 	const struct mafield *f;
 
-	strcpy(buffer, "dmi");
-	p = buffer + 3; left = buffer_size - 4;
+	l = strscpy(buffer, "dmi", buffer_size);
+	if (l < 0)
+		return -ENOMEM;
+	p = buffer + l;
+
+	/* Reserve place for suffix */
+	left = buffer_size - l - 1;
+	if (left < 0)
+		return -ENOMEM;
 
 	for (f = fields; f->prefix && left > 0; f++) {
 		const char *c;
@@ -125,20 +132,21 @@ static ssize_t get_modalias(char *buffer
 		left -= l;
 	}
 
-	p[0] = ':';
-	p[1] = 0;
+	*p++ = ':';
+	*p = 0;
 
-	return p - buffer + 1;
+	return p - buffer;
 }
 
 static ssize_t sys_dmi_modalias_show(struct device *dev,
 				     struct device_attribute *attr, char *page)
 {
-	ssize_t r;
-	r = get_modalias(page, PAGE_SIZE-1);
-	page[r] = '\n';
-	page[r+1] = 0;
-	return r+1;
+	ssize_t r = get_modalias(page, PAGE_SIZE-1);
+	if (r > 0) {
+		page[r++] = '\n';
+		page[r] = 0;
+	}
+	return r;
 }
 
 static struct device_attribute sys_dmi_modalias_attr =
@@ -163,7 +171,7 @@ static int dmi_dev_uevent(const struct d
 		return -ENOMEM;
 	len = get_modalias(&env->buf[env->buflen - 1],
 			   sizeof(env->buf) - env->buflen);
-	if (len >= (sizeof(env->buf) - env->buflen))
+	if (len < 0)
 		return -ENOMEM;
 	env->buflen += len;
 	return 0;