Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 287980e4 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Linus Torvalds
Browse files

remove lots of IS_ERR_VALUE abuses



Most users of IS_ERR_VALUE() in the kernel are wrong, as they
pass an 'int' into a function that takes an 'unsigned long'
argument. This happens to work because the type is sign-extended
on 64-bit architectures before it gets converted into an
unsigned type.

However, anything that passes an 'unsigned short' or 'unsigned int'
argument into IS_ERR_VALUE() is guaranteed to be broken, as are
8-bit integers and types that are wider than 'unsigned long'.

Andrzej Hajda has already fixed a lot of the worst abusers that
were causing actual bugs, but it would be nice to prevent any
users that are not passing 'unsigned long' arguments.

This patch changes all users of IS_ERR_VALUE() that I could find
on 32-bit ARM randconfig builds and x86 allmodconfig. For the
moment, this doesn't change the definition of IS_ERR_VALUE()
because there are probably still architecture specific users
elsewhere.

Almost all the warnings I got are for files that are better off
using 'if (err)' or 'if (err < 0)'.
The only legitimate user I could find that we get a warning for
is the (32-bit only) freescale fman driver, so I did not remove
the IS_ERR_VALUE() there but changed the type to 'unsigned long'.
For 9pfs, I just worked around one user whose calling conventions
are so obscure that I did not dare change the behavior.

I was using this definition for testing:

 #define IS_ERR_VALUE(x) ((unsigned long*)NULL == (typeof (x)*)NULL && \
       unlikely((unsigned long long)(x) >= (unsigned long long)(typeof(x))-MAX_ERRNO))

which ends up making all 16-bit or wider types work correctly with
the most plausible interpretation of what IS_ERR_VALUE() was supposed
to return according to its users, but also causes a compile-time
warning for any users that do not pass an 'unsigned long' argument.

I suggested this approach earlier this year, but back then we ended
up deciding to just fix the users that are obviously broken. After
the initial warning that caused me to get involved in the discussion
(fs/gfs2/dir.c) showed up again in the mainline kernel, Linus
asked me to send the whole thing again.

[ Updated the 9p parts as per Al Viro  - Linus ]

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: https://lkml.org/lkml/2016/1/7/363
Link: https://lkml.org/lkml/2016/5/27/486


Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> # For nvmem part
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7ded384a
Loading
Loading
Loading
Loading
+11 −11
Original line number Original line Diff line number Diff line
@@ -265,7 +265,7 @@ static int acpi_aml_write_kern(const char *buf, int len)
	char *p;
	char *p;


	ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
	ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
	if (IS_ERR_VALUE(ret))
	if (ret < 0)
		return ret;
		return ret;
	/* sync tail before inserting logs */
	/* sync tail before inserting logs */
	smp_mb();
	smp_mb();
@@ -286,7 +286,7 @@ static int acpi_aml_readb_kern(void)
	char *p;
	char *p;


	ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
	ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
	if (IS_ERR_VALUE(ret))
	if (ret < 0)
		return ret;
		return ret;
	/* sync head before removing cmds */
	/* sync head before removing cmds */
	smp_rmb();
	smp_rmb();
@@ -330,7 +330,7 @@ static ssize_t acpi_aml_write_log(const char *msg)
				goto again;
				goto again;
			break;
			break;
		}
		}
		if (IS_ERR_VALUE(ret))
		if (ret < 0)
			break;
			break;
		size += ret;
		size += ret;
		count -= ret;
		count -= ret;
@@ -373,7 +373,7 @@ static ssize_t acpi_aml_read_cmd(char *msg, size_t count)
			if (ret == 0)
			if (ret == 0)
				goto again;
				goto again;
		}
		}
		if (IS_ERR_VALUE(ret))
		if (ret < 0)
			break;
			break;
		*(msg + size) = (char)ret;
		*(msg + size) = (char)ret;
		size++;
		size++;
@@ -526,7 +526,7 @@ static int acpi_aml_open(struct inode *inode, struct file *file)
	}
	}
	acpi_aml_io.users++;
	acpi_aml_io.users++;
err_lock:
err_lock:
	if (IS_ERR_VALUE(ret)) {
	if (ret < 0) {
		if (acpi_aml_active_reader == file)
		if (acpi_aml_active_reader == file)
			acpi_aml_active_reader = NULL;
			acpi_aml_active_reader = NULL;
	}
	}
@@ -587,7 +587,7 @@ static int acpi_aml_read_user(char __user *buf, int len)
	char *p;
	char *p;


	ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
	ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
	if (IS_ERR_VALUE(ret))
	if (ret < 0)
		return ret;
		return ret;
	/* sync head before removing logs */
	/* sync head before removing logs */
	smp_rmb();
	smp_rmb();
@@ -602,7 +602,7 @@ static int acpi_aml_read_user(char __user *buf, int len)
	crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
	crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
	ret = n;
	ret = n;
out:
out:
	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !IS_ERR_VALUE(ret));
	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !ret);
	return ret;
	return ret;
}
}


@@ -634,7 +634,7 @@ static ssize_t acpi_aml_read(struct file *file, char __user *buf,
					goto again;
					goto again;
			}
			}
		}
		}
		if (IS_ERR_VALUE(ret)) {
		if (ret < 0) {
			if (!acpi_aml_running())
			if (!acpi_aml_running())
				ret = 0;
				ret = 0;
			break;
			break;
@@ -657,7 +657,7 @@ static int acpi_aml_write_user(const char __user *buf, int len)
	char *p;
	char *p;


	ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
	ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
	if (IS_ERR_VALUE(ret))
	if (ret < 0)
		return ret;
		return ret;
	/* sync tail before inserting cmds */
	/* sync tail before inserting cmds */
	smp_mb();
	smp_mb();
@@ -672,7 +672,7 @@ static int acpi_aml_write_user(const char __user *buf, int len)
	crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
	crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
	ret = n;
	ret = n;
out:
out:
	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !IS_ERR_VALUE(ret));
	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !ret);
	return n;
	return n;
}
}


@@ -704,7 +704,7 @@ static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
					goto again;
					goto again;
			}
			}
		}
		}
		if (IS_ERR_VALUE(ret)) {
		if (ret < 0) {
			if (!acpi_aml_running())
			if (!acpi_aml_running())
				ret = 0;
				ret = 0;
			break;
			break;
+1 −1
Original line number Original line Diff line number Diff line
@@ -197,7 +197,7 @@ static void highbank_set_em_messages(struct device *dev,


	for (i = 0; i < SGPIO_PINS; i++) {
	for (i = 0; i < SGPIO_PINS; i++) {
		err = of_get_named_gpio(np, "calxeda,sgpio-gpio", i);
		err = of_get_named_gpio(np, "calxeda,sgpio-gpio", i);
		if (IS_ERR_VALUE(err))
		if (err < 0)
			return;
			return;


		pdata->sgpio_gpio[i] = err;
		pdata->sgpio_gpio[i] = err;
+1 −1
Original line number Original line Diff line number Diff line
@@ -1221,7 +1221,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
		p = rate >= params->vco_min ? 1 : -EINVAL;
		p = rate >= params->vco_min ? 1 : -EINVAL;
	}
	}


	if (IS_ERR_VALUE(p))
	if (p < 0)
		return -EINVAL;
		return -EINVAL;


	cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate);
	cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate);
+1 −1
Original line number Original line Diff line number Diff line
@@ -54,7 +54,7 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index)


	freq = new_freq * 1000;
	freq = new_freq * 1000;
	ret = clk_round_rate(policy->clk, freq);
	ret = clk_round_rate(policy->clk, freq);
	if (IS_ERR_VALUE(ret)) {
	if (ret < 0) {
		dev_warn(mpu_dev,
		dev_warn(mpu_dev,
			 "CPUfreq: Cannot find matching frequency for %lu\n",
			 "CPUfreq: Cannot find matching frequency for %lu\n",
			 freq);
			 freq);
+1 −1
Original line number Original line Diff line number Diff line
@@ -402,7 +402,7 @@ int caam_get_era(void)
	ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
	ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
	of_node_put(caam_node);
	of_node_put(caam_node);


	return IS_ERR_VALUE(ret) ? -ENOTSUPP : prop;
	return ret ? -ENOTSUPP : prop;
}
}
EXPORT_SYMBOL(caam_get_era);
EXPORT_SYMBOL(caam_get_era);


Loading