Переглянути джерело

Merge branch '2021-07-15-assorted-fixes'

- Large number of Coverity reported issues addressed
- m41t62 bugfix
- Support more Android image compression formats
- FIT + DTO bugfix
Tom Rini 2 роки тому
батько
коміт
c39946a2e2

+ 4 - 0
arch/sandbox/cpu/state.c

@@ -78,6 +78,10 @@ static int state_read_file(struct sandbox_state *state, const char *fname)
 err_read:
 	os_close(fd);
 err_open:
+	/*
+	 * tainted scalar, since size is obtained from the file. But we can rely
+	 * on os_malloc() to handle invalid values.
+	 */
 	os_free(state->state_fdt);
 	state->state_fdt = NULL;
 

+ 1 - 1
common/image-android.c

@@ -164,7 +164,7 @@ ulong android_image_get_kcomp(const struct andr_img_hdr *hdr)
 	else if (get_unaligned_le32(p) == LZ4F_MAGIC)
 		return IH_COMP_LZ4;
 	else
-		return IH_COMP_NONE;
+		return image_decomp_type(p, sizeof(u32));
 }
 
 int android_image_get_ramdisk(const struct andr_img_hdr *hdr,

+ 28 - 4
common/image-fit.c

@@ -17,6 +17,7 @@
 #include <u-boot/crc.h>
 #else
 #include <linux/compiler.h>
+#include <linux/sizes.h>
 #include <common.h>
 #include <errno.h>
 #include <log.h>
@@ -2267,10 +2268,10 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
 	ulong load, len;
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
 	ulong image_start, image_end;
-	ulong ovload, ovlen;
+	ulong ovload, ovlen, ovcopylen;
 	const char *uconfig;
 	const char *uname;
-	void *base, *ov;
+	void *base, *ov, *ovcopy = NULL;
 	int i, err, noffset, ov_noffset;
 #endif
 
@@ -2360,7 +2361,7 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
 			addr, &uname, &uconfig,
 			arch, IH_TYPE_FLATDT,
 			BOOTSTAGE_ID_FIT_FDT_START,
-			FIT_LOAD_REQUIRED, &ovload, &ovlen);
+			FIT_LOAD_IGNORED, &ovload, &ovlen);
 		if (ov_noffset < 0) {
 			printf("load of %s failed\n", uname);
 			continue;
@@ -2369,6 +2370,21 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
 				uname, ovload, ovlen);
 		ov = map_sysmem(ovload, ovlen);
 
+		ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K);
+		ovcopy = malloc(ovcopylen);
+		if (!ovcopy) {
+			printf("failed to duplicate DTO before application\n");
+			fdt_noffset = -ENOMEM;
+			goto out;
+		}
+
+		err = fdt_open_into(ov, ovcopy, ovcopylen);
+		if (err < 0) {
+			printf("failed on fdt_open_into for DTO\n");
+			fdt_noffset = err;
+			goto out;
+		}
+
 		base = map_sysmem(load, len + ovlen);
 		err = fdt_open_into(base, base, len + ovlen);
 		if (err < 0) {
@@ -2376,14 +2392,18 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
 			fdt_noffset = err;
 			goto out;
 		}
+
 		/* the verbose method prints out messages on error */
-		err = fdt_overlay_apply_verbose(base, ov);
+		err = fdt_overlay_apply_verbose(base, ovcopy);
 		if (err < 0) {
 			fdt_noffset = err;
 			goto out;
 		}
 		fdt_pack(base);
 		len = fdt_totalsize(base);
+
+		free(ovcopy);
+		ovcopy = NULL;
 	}
 #else
 	printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n");
@@ -2400,6 +2420,10 @@ out:
 	if (fit_uname_configp)
 		*fit_uname_configp = fit_uname_config;
 
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	if (ovcopy)
+		free(ovcopy);
+#endif
 	if (fit_uname_config_copy)
 		free(fit_uname_config_copy);
 	return fdt_noffset;

+ 5 - 1
drivers/clk/clk-uclass.c

@@ -847,13 +847,17 @@ void devm_clk_put(struct udevice *dev, struct clk *clk)
 
 int clk_uclass_post_probe(struct udevice *dev)
 {
+	int ret;
+
 	/*
 	 * when a clock provider is probed. Call clk_set_defaults()
 	 * also after the device is probed. This takes care of cases
 	 * where the DT is used to setup default parents and rates
 	 * using assigned-clocks
 	 */
-	clk_set_defaults(dev, CLK_DEFAULTS_POST);
+	ret = clk_set_defaults(dev, CLK_DEFAULTS_POST);
+	if (ret)
+		return log_ret(ret);
 
 	return 0;
 }

+ 4 - 3
drivers/core/dump.c

@@ -130,18 +130,19 @@ void dm_dump_drivers(void)
 	struct driver *entry;
 	struct udevice *udev;
 	struct uclass *uc;
+	int ret;
 	int i;
 
 	puts("Driver                    uid uclass               Devices\n");
 	puts("----------------------------------------------------------\n");
 
 	for (entry = d; entry < d + n_ents; entry++) {
-		uclass_get(entry->id, &uc);
+		ret = uclass_get(entry->id, &uc);
 
 		printf("%-25.25s %-3.3d %-20.20s ", entry->name, entry->id,
-		       uc ? uc->uc_drv->name : "<no uclass>");
+		       !ret ? uc->uc_drv->name : "<no uclass>");
 
-		if (!uc) {
+		if (ret) {
 			puts("\n");
 			continue;
 		}

+ 1 - 0
drivers/core/regmap.c

@@ -293,6 +293,7 @@ struct regmap *devm_regmap_init(struct udevice *dev,
 	int rc;
 	struct regmap **mapp, *map;
 
+	/* this looks like a leak, but devres takes care of it */
 	mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
 			    __GFP_ZERO);
 	if (unlikely(!mapp))

+ 7 - 5
drivers/misc/cros_ec_sandbox.c

@@ -5,6 +5,8 @@
  * Copyright (c) 2013 The Chromium OS Authors.
  */
 
+#define LOG_CATEGORY UCLASS_CROS_EC
+
 #include <common.h>
 #include <cros_ec.h>
 #include <dm.h>
@@ -221,11 +223,12 @@ static int keyscan_read_fdt_matrix(struct ec_state *ec, ofnode node)
 	int len;
 
 	cell = ofnode_get_property(node, "linux,keymap", &len);
+	if (!cell)
+		return log_msg_ret("prop", -EINVAL);
 	ec->matrix_count = len / 4;
 	ec->matrix = calloc(ec->matrix_count, sizeof(*ec->matrix));
 	if (!ec->matrix) {
-		debug("%s: Out of memory for key matrix\n", __func__);
-		return -1;
+		return log_msg_ret("mem", -ENOMEM);
 	}
 
 	/* Now read the data */
@@ -243,13 +246,12 @@ static int keyscan_read_fdt_matrix(struct ec_state *ec, ofnode node)
 		    matrix->col >= KEYBOARD_COLS) {
 			debug("%s: Matrix pos out of range (%d,%d)\n",
 			      __func__, matrix->row, matrix->col);
-			return -1;
+			return log_msg_ret("matrix", -ERANGE);
 		}
 	}
 
 	if (upto != ec->matrix_count) {
-		debug("%s: Read mismatch from key matrix\n", __func__);
-		return -1;
+		return log_msg_ret("matrix", -E2BIG);
 	}
 
 	return 0;

+ 1 - 1
drivers/net/sandbox-raw.c

@@ -161,7 +161,7 @@ static int sb_eth_raw_of_to_plat(struct udevice *dev)
 
 	ifname = dev_read_string(dev, "host-raw-interface");
 	if (ifname) {
-		strncpy(priv->host_ifname, ifname, IFNAMSIZ);
+		strlcpy(priv->host_ifname, ifname, IFNAMSIZ);
 		printf(": Using %s from DT\n", priv->host_ifname);
 	}
 	if (dev_read_u32(dev, "host-raw-interface-idx",

+ 1 - 0
drivers/pinctrl/pinctrl-single.c

@@ -471,6 +471,7 @@ static int single_probe(struct udevice *dev)
 		return -ENOMEM;
 	#endif
 
+	/* looks like a possible divide by 0, but data->width avoids this */
 	priv->npins = size / (pdata->width / BITS_PER_BYTE);
 	if (pdata->bits_per_mux) {
 		if (!pdata->mask) {

+ 2 - 0
drivers/reset/reset-uclass.c

@@ -325,6 +325,8 @@ struct reset_ctl_bulk *devm_reset_bulk_get_by_node(struct udevice *dev,
 	bulk = devres_alloc(devm_reset_bulk_release,
 			    sizeof(struct reset_ctl_bulk),
 			    __GFP_ZERO);
+
+	/* this looks like a leak, but devres takes care of it */
 	if (unlikely(!bulk))
 		return ERR_PTR(-ENOMEM);
 

+ 2 - 2
drivers/rtc/m41t62.c

@@ -213,13 +213,13 @@ static int m41t62_rtc_restart_osc(struct udevice *dev)
 
 	/* 1. Set stop bit */
 	val |= M41T62_SEC_ST;
-	ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+	ret = dm_i2c_write(dev, M41T62_REG_SEC, &val, sizeof(val));
 	if (ret)
 		return ret;
 
 	/* 2. Clear stop bit */
 	val &= ~M41T62_SEC_ST;
-	ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+	ret = dm_i2c_write(dev, M41T62_REG_SEC, &val, sizeof(val));
 	if (ret)
 		return ret;
 

+ 4 - 2
drivers/video/pwm_backlight.c

@@ -235,8 +235,10 @@ static int pwm_backlight_of_to_plat(struct udevice *dev)
 		priv->levels = malloc(len);
 		if (!priv->levels)
 			return log_ret(-ENOMEM);
-		dev_read_u32_array(dev, "brightness-levels", priv->levels,
-				   count);
+		ret = dev_read_u32_array(dev, "brightness-levels", priv->levels,
+					 count);
+		if (ret)
+			return log_msg_ret("levels", ret);
 		priv->num_levels = count;
 		priv->default_level = priv->levels[index];
 		priv->max_level = priv->levels[count - 1];

+ 2 - 0
fs/cbfs/cbfs.c

@@ -167,6 +167,8 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
 		}
 
 		swap_file_header(&header, file_header);
+		if (header.offset >= size)
+			return log_msg_ret("range", -E2BIG);
 		ret = fill_node(node, start, &header);
 		if (ret) {
 			priv->result = CBFS_BAD_FILE;

+ 5 - 0
lib/tpm-common.c

@@ -176,6 +176,11 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
 	}
 
 	size = tpm_command_size(command);
+
+	/* sanity check, which also helps coverity */
+	if (size > COMMAND_BUFFER_SIZE)
+		return log_msg_ret("size", -E2BIG);
+
 	log_debug("TPM request [size:%d]: ", size);
 	for (i = 0; i < size; i++)
 		log_debug("%02x ", ((u8 *)command)[i]);

+ 6 - 16
lib/vsprintf.c

@@ -434,9 +434,9 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
  * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
  *       currently the same
  *
- * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
- * function pointers are really function descriptors, which contain a
- * pointer to the real address.
+ * Note: IPv6 support is currently if(0)'ed out. If you ever need
+ * %pI6, please add an IPV6 Kconfig knob, make your code select or
+ * depend on that, and change the 0 below to CONFIG_IS_ENABLED(IPV6).
  */
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		int field_width, int precision, int flags)
@@ -481,7 +481,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		flags |= SPECIAL;
 		/* Fallthrough */
 	case 'I':
-		if (fmt[1] == '6')
+		/* %pI6 currently unused */
+		if (0 && fmt[1] == '6')
 			return ip6_addr_string(buf, end, ptr, field_width,
 					       precision, flags);
 		if (fmt[1] == '4')
@@ -787,22 +788,11 @@ int printf(const char *fmt, ...)
 {
 	va_list args;
 	uint i;
-	char printbuffer[CONFIG_SYS_PBSIZE];
 
 	va_start(args, fmt);
-
-	/*
-	 * For this to work, printbuffer must be larger than
-	 * anything we ever want to print.
-	 */
-	i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+	i = vprintf(fmt, args);
 	va_end(args);
 
-	/* Handle error */
-	if (i <= 0)
-		return i;
-	/* Print the string */
-	puts(printbuffer);
 	return i;
 }
 

+ 0 - 2
test/cmd/setexpr.c

@@ -270,8 +270,6 @@ static int setexpr_test_backref(struct unit_test_state *uts)
 	ut_asserteq_str("us this is surely! a test is it? yes us this is indeed! a test",
 			buf);
 
-	/* The following checks fail at present due to a bug in setexpr */
-	return 0;
 	for (i = BUF_SIZE; i < 0x1000; i++) {
 		ut_assertf(buf[i] == (char)i,
 			   "buf byte at %x should be %02x, got %02x)\n",

+ 4 - 4
tools/image-host.c

@@ -329,7 +329,7 @@ static int get_random_data(void *data, int size)
 {
 	unsigned char *tmp = data;
 	struct timespec date;
-	int i, ret = 0;
+	int i, ret;
 
 	if (!tmp) {
 		printf("%s: pointer data is NULL\n", __func__);
@@ -338,9 +338,9 @@ static int get_random_data(void *data, int size)
 	}
 
 	ret = clock_gettime(CLOCK_MONOTONIC, &date);
-	if (ret < 0) {
-		printf("%s: clock_gettime has failed (err=%d, str=%s)\n",
-		       __func__, ret, strerror(errno));
+	if (ret) {
+		printf("%s: clock_gettime has failed (%s)\n", __func__,
+		       strerror(errno));
 		goto out;
 	}