[PATCH 3/6] libusbg: Remove fixed-size buffers from usbg_config.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Path and name length should not be placed in constant
size buffer but in allocated memory.

Use also PATH_MAX macro from limits.h instead of internal
library macro. Handle overflows of snprintf in related funcitons.

Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx>
---
 include/usbg/usbg.h |    1 +
 src/usbg.c          |   97 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 71 insertions(+), 27 deletions(-)

diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index 354ba38..f19b1b2 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -192,6 +192,7 @@ typedef enum  {
 	USBG_ERROR_NO_DEV = -7,
 	USBG_ERROR_BUSY = -8,
 	USBG_ERROR_NOT_SUPPORTED = -9,
+	USBG_ERROR_PATH_TOO_LONG = -10,
 	USBG_ERROR_OTHER_ERROR = -99
 } usbg_error;
 
diff --git a/src/usbg.c b/src/usbg.c
index 12ef3f3..50b30e1 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <limits.h>
 
 #define STRINGS_DIR "strings"
 #define CONFIGS_DIR "configs"
@@ -60,8 +61,8 @@ struct usbg_config
 	TAILQ_HEAD(bhead, usbg_binding) bindings;
 	usbg_gadget *parent;
 
-	char name[USBG_MAX_NAME_LENGTH];
-	char path[USBG_MAX_PATH_LENGTH];
+	char *name;
+	char *path;
 };
 
 struct usbg_function
@@ -206,6 +207,9 @@ const char *usbg_error_name(usbg_error e)
 	case USBG_ERROR_NOT_SUPPORTED:
 		ret = "USBG_ERROR_NOT_SUPPORTED";
 		break;
+	case USBG_ERROR_PATH_TOO_LONG:
+		ret = "USBG_ERROR_PATH_TOO_LONG";
+		break;
 	case USBG_ERROR_OTHER_ERROR:
 		ret = "USBG_ERROR_OTHER_ERROR";
 		break;
@@ -249,6 +253,9 @@ const char *usbg_strerror(usbg_error e)
 	case USBG_ERROR_NOT_SUPPORTED:
 		ret = "Function not supported";
 		break;
+	case USBG_ERROR_PATH_TOO_LONG:
+		ret = "Created path was too long to process it.";
+		break;
 	case USBG_ERROR_OTHER_ERROR:
 		ret = "Other error";
 		break;
@@ -419,6 +426,8 @@ static void usbg_free_config(usbg_config *c)
 		TAILQ_REMOVE(&c->bindings, b, bnode);
 		usbg_free_binding(b);
 	}
+	free(c->path);
+	free(c->name);
 	free(c);
 }
 
@@ -478,6 +487,29 @@ static usbg_gadget *usbg_allocate_gadget(char *path, char *name,
 	return g;
 }
 
+static usbg_config *usbg_allocate_config(char *path, char *name,
+		usbg_gadget *parent)
+{
+	usbg_config *c;
+
+	c = malloc(sizeof(usbg_config));
+	if (c) {
+		TAILQ_INIT(&c->bindings);
+		c->name = strdup(name);
+		c->path = strdup(path);
+		c->parent = parent;
+
+		if (!(c->name) || !(c->path)) {
+			free(c->name);
+			free(c->path);
+			free(c);
+			c = NULL;
+		}
+	}
+
+	return c;
+}
+
 static int usbg_parse_function_net_attrs(usbg_function *f,
 		usbg_function_attrs *f_attrs)
 {
@@ -686,20 +718,20 @@ static int usbg_parse_configs(char *path, usbg_gadget *g)
 	int i, n;
 	int ret = USBG_SUCCESS;
 	struct dirent **dent;
-	char cpath[USBG_MAX_PATH_LENGTH];
+	char cpath[PATH_MAX];
 
-	sprintf(cpath, "%s/%s/%s", path, g->name, CONFIGS_DIR);
+	n = snprintf(cpath, PATH_MAX, "%s/%s/%s", path, g->name, CONFIGS_DIR);
+	if (n >= PATH_MAX) {
+		ret = USBG_ERROR_PATH_TOO_LONG;
+		goto out;
+	}
 
 	n = scandir(cpath, &dent, file_select, alphasort);
 	if (n >= 0) {
 		for (i = 0; i < n; i++) {
 			if (ret == USBG_SUCCESS) {
-				c = malloc(sizeof(usbg_config));
+				c = usbg_allocate_config(cpath, dent[i]->d_name, g);
 				if (c) {
-					c->parent = g;
-					strcpy(c->name, dent[i]->d_name);
-					strcpy(c->path, cpath);
-					TAILQ_INIT(&c->bindings);
 					ret = usbg_parse_config_bindings(c);
 					if (ret == USBG_SUCCESS)
 						TAILQ_INSERT_TAIL(&g->configs, c, cnode);
@@ -716,6 +748,7 @@ static int usbg_parse_configs(char *path, usbg_gadget *g)
 		ret = usbg_translate_error(errno);
 	}
 
+out:
 	return ret;
 }
 
@@ -1374,12 +1407,13 @@ int usbg_create_function(usbg_gadget *g, usbg_function_type type,
 int usbg_create_config(usbg_gadget *g, char *name,
 		usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, usbg_config **c)
 {
-	char cpath[USBG_MAX_PATH_LENGTH];
+	char cpath[PATH_MAX];
 	usbg_config *conf;
 	int ret = USBG_ERROR_INVALID_PARAM;
+	int n;
 
 	if (!g || !c)
-		return ret;
+		goto out;
 
 	/**
 	 * @todo Check for legal configuration name
@@ -1387,19 +1421,28 @@ int usbg_create_config(usbg_gadget *g, char *name,
 	conf = usbg_get_config(g, name);
 	if (conf) {
 		ERROR("duplicate configuration name\n");
-		return USBG_ERROR_EXIST;
+		ret = USBG_ERROR_EXIST;
+		goto out;
 	}
 
-	sprintf(cpath, "%s/%s/%s/%s", g->path, g->name, CONFIGS_DIR, name);
+	n = snprintf(cpath, PATH_MAX, "%s/%s/%s", g->path, g->name,
+			CONFIGS_DIR);
+	if (n >= PATH_MAX) {
+		ret =  USBG_ERROR_PATH_TOO_LONG;
+		goto out;
+	}
 
-	*c = malloc(sizeof(usbg_config));
+	*c = usbg_allocate_config(cpath, name, g);
 	conf = *c;
-	if (conf) {
-		TAILQ_INIT(&conf->bindings);
-		strcpy(conf->name, name);
-		sprintf(conf->path, "%s/%s/%s", g->path, g->name, CONFIGS_DIR);
+	if (!conf) {
+		ERRORNO("allocating configuration\n");
+		ret = USBG_ERROR_NO_MEM;
+		goto out;
+	}
 
-		ret = mkdir(cpath, S_IRWXU|S_IRWXG|S_IRWXO);
+	n = snprintf(&(cpath[n]), PATH_MAX, "/%s", name);
+	if (n < PATH_MAX) {
+		ret = mkdir(cpath, S_IRWXU | S_IRWXG | S_IRWXO);
 		if (!ret) {
 			ret = USBG_SUCCESS;
 			if (c_attrs)
@@ -1408,20 +1451,20 @@ int usbg_create_config(usbg_gadget *g, char *name,
 			if (ret == USBG_SUCCESS && c_strs)
 				ret = usbg_set_config_string(conf, LANG_US_ENG,
 						c_strs->configuration);
-
 		} else {
 			ret = usbg_translate_error(errno);
 		}
-
-		if (ret == USBG_SUCCESS)
-			INSERT_TAILQ_STRING_ORDER(&g->configs, chead, name, conf, cnode);
-		else
-			usbg_free_config(conf);
 	} else {
-		ERRORNO("allocating configuration\n");
-		ret = USBG_ERROR_NO_MEM;
+		ret = USBG_ERROR_PATH_TOO_LONG;
 	}
 
+	if (ret == USBG_SUCCESS)
+		INSERT_TAILQ_STRING_ORDER(&g->configs, chead, name,
+				conf, cnode);
+	else
+		usbg_free_config(conf);
+
+out:
 	return ret;
 }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux