Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Mar 2012 20:34:26 +0000 (UTC)
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233323 - head/sys/boot/fdt
Message-ID:  <201203222034.q2MKYQm7040279@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: raj
Date: Thu Mar 22 20:34:26 2012
New Revision: 233323
URL: http://svn.freebsd.org/changeset/base/233323

Log:
  Improve FDT handling in loader(8) and make it more robust.
  
  o Fix buffer overflows when using a long property body in node paths.
  o Fix loop end condition when iterating through the symbol table.
  o Better error handling during node modification, better problem reporting.
  o Eliminate build time warnings.
  
  Submitted by:	Lukasz Wojcik
  Obtained from:	Semihalf
  MFC after:	1 week

Modified:
  head/sys/boot/fdt/fdt_loader_cmd.c

Modified: head/sys/boot/fdt/fdt_loader_cmd.c
==============================================================================
--- head/sys/boot/fdt/fdt_loader_cmd.c	Thu Mar 22 20:31:52 2012	(r233322)
+++ head/sys/boot/fdt/fdt_loader_cmd.c	Thu Mar 22 20:34:26 2012	(r233323)
@@ -57,8 +57,6 @@ __FBSDID("$FreeBSD$");
 #define STR(number) #number
 #define STRINGIFY(number) STR(number)
 
-#define MIN(num1, num2)	(((num1) < (num2)) ? (num1):(num2))
-
 #define COPYOUT(s,d,l)	archsw.arch_copyout((vm_offset_t)(s), d, l)
 
 #define FDT_STATIC_DTB_SYMBOL	"fdt_static_dtb"
@@ -110,9 +108,11 @@ fdt_find_static_dtb(void)
 	Elf_Sym *symtab;
 	Elf_Dyn *dyn;
 	char *strtab, *strp;
-	int i;
+	int i, sym_count;
 
-	esym = strtab = symtab = 0;
+	symtab = NULL;
+	dyntab = esym = 0;
+	strtab = strp = NULL;
 
 	offs = __elfN(relocation_offset);
 
@@ -129,6 +129,7 @@ fdt_find_static_dtb(void)
 	if (md == NULL)
 		return (0);
 	COPYOUT(md->md_data, &dyntab, sizeof(dyntab));
+
 	dyntab += offs;
 
 	/* Locate STRTAB and DYNTAB */
@@ -152,6 +153,8 @@ fdt_find_static_dtb(void)
 		return (0);
 	}
 
+	sym_count = (int)((Elf_Sym *)esym - symtab) / sizeof(Elf_Sym);
+
 	/*
 	 * The most efficent way to find a symbol would be to calculate a
 	 * hash, find proper bucket and chain, and thus find a symbol.
@@ -162,7 +165,7 @@ fdt_find_static_dtb(void)
 	 * we are eliminating symbols type of which is not STT_NOTYPE, or(and)
 	 * those which binding attribute is not STB_GLOBAL.
 	 */
-	for (i = 0; (vm_offset_t)(symtab + i) < esym; i++) {
+	for (i = 0; i < sym_count; i++) {
 		COPYOUT(symtab + i, &sym, sizeof(sym));
 		if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
 		    ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
@@ -190,7 +193,7 @@ fdt_setup_fdtp()
 	 */
 	bfp = file_findfile(NULL, "dtb");
 	if (bfp == NULL) {
-		if ((fdtp = (struct fdt_head *)fdt_find_static_dtb()) == 0) {
+		if ((fdtp = (struct fdt_header *)fdt_find_static_dtb()) == 0) {
 			command_errmsg = "no device tree blob found!";
 			return (CMD_ERROR);
 		}
@@ -842,32 +845,41 @@ fdt_isprint(const void *data, int len, i
 static int
 fdt_data_str(const void *data, int len, int count, char **buf)
 {
-	char tmp[80], *b;
+	char *b, *tmp;
 	const char *d;
-	int i, l;
+	int buf_len, i, l;
 
 	/*
 	 * Calculate the length for the string and allocate memory.
 	 *
-	 * Note len already includes at least one terminator.
+	 * Note that 'len' already includes at least one terminator.
 	 */
-	l = len;
+	buf_len = len;
 	if (count > 1) {
 		/*
 		 * Each token had already a terminator buried in 'len', but we
 		 * only need one eventually, don't count space for these.
 		 */
-		l -= count - 1;
+		buf_len -= count - 1;
 
 		/* Each consecutive token requires a ", " separator. */
-		l += count * 2;
+		buf_len += count * 2;
 	}
-	/* Space for surrounding double quotes. */
-	l += count * 2;
 
-	b = (char *)malloc(l);
+	/* Add some space for surrounding double quotes. */
+	buf_len += count * 2;
+
+	/* Note that string being put in 'tmp' may be as big as 'buf_len'. */
+	b = (char *)malloc(buf_len);
+	tmp = (char *)malloc(buf_len);
 	if (b == NULL)
-		return (1);
+		goto error;
+
+	if (tmp == NULL) {
+		free(b);
+		goto error;
+	}
+
 	b[0] = '\0';
 
 	/*
@@ -887,13 +899,17 @@ fdt_data_str(const void *data, int len, 
 	} while (i < len);
 	*buf = b;
 
+	free(tmp);
+
 	return (0);
+error:
+	return (1);
 }
 
 static int
 fdt_data_cell(const void *data, int len, char **buf)
 {
-	char tmp[80], *b;
+	char *b, *tmp;
 	const uint32_t *c;
 	int count, i, l;
 
@@ -916,8 +932,14 @@ fdt_data_cell(const void *data, int len,
 	l += 3;
 
 	b = (char *)malloc(l);
+	tmp = (char *)malloc(l);
 	if (b == NULL)
-		return (1);
+		goto error;
+
+	if (tmp == NULL) {
+		free(b);
+		goto error;
+	}
 
 	b[0] = '\0';
 	strcat(b, "<");
@@ -931,13 +953,17 @@ fdt_data_cell(const void *data, int len,
 	strcat(b, ">");
 	*buf = b;
 
+	free(tmp);
+
 	return (0);
+error:
+	return (1);
 }
 
 static int
 fdt_data_bytes(const void *data, int len, char **buf)
 {
-	char tmp[80], *b;
+	char *b, *tmp;
 	const char *d;
 	int i, l;
 
@@ -956,8 +982,14 @@ fdt_data_bytes(const void *data, int len
 	l += 3;
 
 	b = (char *)malloc(l);
+	tmp = (char *)malloc(l);
 	if (b == NULL)
-		return (1);
+		goto error;
+
+	if (tmp == NULL) {
+		free(b);
+		goto error;
+	}
 
 	b[0] = '\0';
 	strcat(b, "[");
@@ -969,7 +1001,11 @@ fdt_data_bytes(const void *data, int len
 	strcat(b, "]");
 	*buf = b;
 
+	free(tmp);
+
 	return (0);
+error:
+	return (1);
 }
 
 static int
@@ -1108,6 +1144,14 @@ fdt_modprop(int nodeoff, char *propname,
 		break;
 	}
 
+	if (rv != 0) {
+		if (rv == -FDT_ERR_NOSPACE)
+			sprintf(command_errbuf,
+			    "Device tree blob is too small!\n");
+		else
+			sprintf(command_errbuf,
+			    "Could not add/modify property!\n");
+	}
 	return (rv);
 }
 
@@ -1350,9 +1394,12 @@ fdt_cmd_mknode(int argc, char *argv[])
 	rv = fdt_add_subnode(fdtp, o, nodename);
 
 	if (rv < 0) {
-		sprintf(command_errbuf, "could not delete node %s\n",
-		    (rv == -FDT_ERR_NOTFOUND) ?
-		    "(node does not exist)" : "");
+		if (rv == -FDT_ERR_NOSPACE)
+			sprintf(command_errbuf,
+			    "Device tree blob is too small!\n");
+		else
+			sprintf(command_errbuf,
+			    "Could not add node!\n");
 		return (CMD_ERROR);
 	}
 	return (CMD_OK);
@@ -1361,7 +1408,7 @@ fdt_cmd_mknode(int argc, char *argv[])
 static int
 fdt_cmd_pwd(int argc, char *argv[])
 {
-	char line[80];
+	char line[FDT_CWD_LEN];
 
 	pager_open();
 	sprintf(line, "%s\n", cwd);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203222034.q2MKYQm7040279>