Skip to content

Commit

Permalink
remove lots of IS_ERR_VALUE abuses
Browse files Browse the repository at this point in the history
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: Arnd Bergmann <[email protected]>
Cc: Andrzej Hajda <[email protected]>
Cc: Andrew Morton <[email protected]>
Link: https://lkml.org/lkml/2016/1/7/363
Link: https://lkml.org/lkml/2016/5/27/486
Acked-by: Srinivas Kandagatla <[email protected]> # For nvmem part
Signed-off-by: Linus Torvalds <[email protected]>
arndb authored and torvalds committed May 27, 2016
1 parent 7ded384 commit 287980e
Showing 38 changed files with 102 additions and 103 deletions.
22 changes: 11 additions & 11 deletions drivers/acpi/acpi_dbg.c
Original file line number Diff line number Diff line change
@@ -265,7 +265,7 @@ static int acpi_aml_write_kern(const char *buf, int len)
char *p;

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

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

ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
if (IS_ERR_VALUE(ret))
if (ret < 0)
return ret;
/* sync head before removing logs */
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);
ret = n;
out:
acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !IS_ERR_VALUE(ret));
acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !ret);
return ret;
}

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

ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
if (IS_ERR_VALUE(ret))
if (ret < 0)
return ret;
/* sync tail before inserting cmds */
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);
ret = n;
out:
acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !IS_ERR_VALUE(ret));
acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !ret);
return n;
}

@@ -704,7 +704,7 @@ static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
goto again;
}
}
if (IS_ERR_VALUE(ret)) {
if (ret < 0) {
if (!acpi_aml_running())
ret = 0;
break;
2 changes: 1 addition & 1 deletion drivers/ata/sata_highbank.c
Original file line number Diff line number Diff line change
@@ -197,7 +197,7 @@ static void highbank_set_em_messages(struct device *dev,

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

pdata->sgpio_gpio[i] = err;
2 changes: 1 addition & 1 deletion drivers/clk/tegra/clk-tegra210.c
Original file line number Diff line number Diff line change
@@ -1221,7 +1221,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
p = rate >= params->vco_min ? 1 : -EINVAL;
}

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

cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate);
2 changes: 1 addition & 1 deletion drivers/cpufreq/omap-cpufreq.c
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index)

freq = new_freq * 1000;
ret = clk_round_rate(policy->clk, freq);
if (IS_ERR_VALUE(ret)) {
if (ret < 0) {
dev_warn(mpu_dev,
"CPUfreq: Cannot find matching frequency for %lu\n",
freq);
2 changes: 1 addition & 1 deletion drivers/crypto/caam/ctrl.c
Original file line number Diff line number Diff line change
@@ -402,7 +402,7 @@ int caam_get_era(void)
ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
of_node_put(caam_node);

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

16 changes: 8 additions & 8 deletions drivers/dma/sun4i-dma.c
Original file line number Diff line number Diff line change
@@ -461,25 +461,25 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,

/* Source burst */
ret = convert_burst(sconfig->src_maxburst);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);

/* Destination burst */
ret = convert_burst(sconfig->dst_maxburst);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);

/* Source bus width */
ret = convert_buswidth(sconfig->src_addr_width);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);

/* Destination bus width */
ret = convert_buswidth(sconfig->dst_addr_width);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);

@@ -518,25 +518,25 @@ generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,

/* Source burst */
ret = convert_burst(sconfig->src_maxburst);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);

/* Destination burst */
ret = convert_burst(sconfig->dst_maxburst);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);

/* Source bus width */
ret = convert_buswidth(sconfig->src_addr_width);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);

/* Destination bus width */
ret = convert_buswidth(sconfig->dst_addr_width);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);

2 changes: 1 addition & 1 deletion drivers/gpio/gpio-xlp.c
Original file line number Diff line number Diff line change
@@ -393,7 +393,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
else
irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
if (IS_ERR_VALUE(irq_base)) {
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
return irq_base;
}
4 changes: 2 additions & 2 deletions drivers/gpu/drm/sti/sti_vtg.c
Original file line number Diff line number Diff line change
@@ -437,7 +437,7 @@ static int vtg_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
} else {
vtg->irq = platform_get_irq(pdev, 0);
if (IS_ERR_VALUE(vtg->irq)) {
if (vtg->irq < 0) {
DRM_ERROR("Failed to get VTG interrupt\n");
return vtg->irq;
}
@@ -447,7 +447,7 @@ static int vtg_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
vtg_irq_thread, IRQF_ONESHOT,
dev_name(dev), vtg);
if (IS_ERR_VALUE(ret)) {
if (ret < 0) {
DRM_ERROR("Failed to register VTG interrupt\n");
return ret;
}
2 changes: 1 addition & 1 deletion drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
Original file line number Diff line number Diff line change
@@ -342,7 +342,7 @@ static int tfp410_probe(struct platform_device *pdev)

tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
0, NULL);
if (IS_ERR_VALUE(tfp410_mod->gpio)) {
if (tfp410_mod->gpio < 0) {
dev_warn(&pdev->dev, "No power down GPIO\n");
} else {
ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
2 changes: 1 addition & 1 deletion drivers/gpu/host1x/hw/intr_hw.c
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ static int _host1x_intr_init_host_sync(struct host1x *host, u32 cpm,
err = devm_request_irq(host->dev, host->intr_syncpt_irq,
syncpt_thresh_isr, IRQF_SHARED,
"host1x_syncpt", host);
if (IS_ERR_VALUE(err)) {
if (err < 0) {
WARN_ON(1);
return err;
}
18 changes: 9 additions & 9 deletions drivers/iommu/arm-smmu-v3.c
Original file line number Diff line number Diff line change
@@ -1477,7 +1477,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;

asid = arm_smmu_bitmap_alloc(smmu->asid_map, smmu->asid_bits);
if (IS_ERR_VALUE(asid))
if (asid < 0)
return asid;

cfg->cdptr = dmam_alloc_coherent(smmu->dev, CTXDESC_CD_DWORDS << 3,
@@ -1508,7 +1508,7 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;

vmid = arm_smmu_bitmap_alloc(smmu->vmid_map, smmu->vmid_bits);
if (IS_ERR_VALUE(vmid))
if (vmid < 0)
return vmid;

cfg->vmid = (u16)vmid;
@@ -1569,7 +1569,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
smmu_domain->pgtbl_ops = pgtbl_ops;

ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
if (IS_ERR_VALUE(ret))
if (ret < 0)
free_io_pgtable_ops(pgtbl_ops);

return ret;
@@ -1642,7 +1642,7 @@ static void arm_smmu_detach_dev(struct device *dev)
struct arm_smmu_group *smmu_group = arm_smmu_group_get(dev);

smmu_group->ste.bypass = true;
if (IS_ERR_VALUE(arm_smmu_install_ste_for_group(smmu_group)))
if (arm_smmu_install_ste_for_group(smmu_group) < 0)
dev_warn(dev, "failed to install bypass STE\n");

smmu_group->domain = NULL;
@@ -1694,7 +1694,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
smmu_group->ste.bypass = domain->type == IOMMU_DOMAIN_DMA;

ret = arm_smmu_install_ste_for_group(smmu_group);
if (IS_ERR_VALUE(ret))
if (ret < 0)
smmu_group->domain = NULL;

out_unlock:
@@ -2235,7 +2235,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
arm_smmu_evtq_handler,
arm_smmu_evtq_thread,
0, "arm-smmu-v3-evtq", smmu);
if (IS_ERR_VALUE(ret))
if (ret < 0)
dev_warn(smmu->dev, "failed to enable evtq irq\n");
}

@@ -2244,15 +2244,15 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
ret = devm_request_irq(smmu->dev, irq,
arm_smmu_cmdq_sync_handler, 0,
"arm-smmu-v3-cmdq-sync", smmu);
if (IS_ERR_VALUE(ret))
if (ret < 0)
dev_warn(smmu->dev, "failed to enable cmdq-sync irq\n");
}

irq = smmu->gerr_irq;
if (irq) {
ret = devm_request_irq(smmu->dev, irq, arm_smmu_gerror_handler,
0, "arm-smmu-v3-gerror", smmu);
if (IS_ERR_VALUE(ret))
if (ret < 0)
dev_warn(smmu->dev, "failed to enable gerror irq\n");
}

@@ -2264,7 +2264,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
arm_smmu_priq_thread,
0, "arm-smmu-v3-priq",
smmu);
if (IS_ERR_VALUE(ret))
if (ret < 0)
dev_warn(smmu->dev,
"failed to enable priq irq\n");
else
8 changes: 4 additions & 4 deletions drivers/iommu/arm-smmu.c
Original file line number Diff line number Diff line change
@@ -950,7 +950,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,

ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
smmu->num_context_banks);
if (IS_ERR_VALUE(ret))
if (ret < 0)
goto out_unlock;

cfg->cbndx = ret;
@@ -989,7 +989,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
"arm-smmu-context-fault", domain);
if (IS_ERR_VALUE(ret)) {
if (ret < 0) {
dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
cfg->irptndx, irq);
cfg->irptndx = INVALID_IRPTNDX;
@@ -1099,7 +1099,7 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
for (i = 0; i < cfg->num_streamids; ++i) {
int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
smmu->num_mapping_groups);
if (IS_ERR_VALUE(idx)) {
if (idx < 0) {
dev_err(smmu->dev, "failed to allocate free SMR\n");
goto err_free_smrs;
}
@@ -1233,7 +1233,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)

/* Ensure that the domain is finalised */
ret = arm_smmu_init_domain_context(domain, smmu);
if (IS_ERR_VALUE(ret))
if (ret < 0)
return ret;

/*
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-clps711x.c
Original file line number Diff line number Diff line change
@@ -182,7 +182,7 @@ static int __init _clps711x_intc_init(struct device_node *np,
writel_relaxed(0, clps711x_intc->intmr[2]);

err = irq_alloc_descs(-1, 0, ARRAY_SIZE(clps711x_irqs), numa_node_id());
if (IS_ERR_VALUE(err))
if (err < 0)
goto out_iounmap;

clps711x_intc->ops.map = clps711x_intc_irq_map;
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
@@ -1123,7 +1123,7 @@ static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,

irq_base = irq_alloc_descs(irq_start, 16, gic_irqs,
numa_node_id());
if (IS_ERR_VALUE(irq_base)) {
if (irq_base < 0) {
WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
irq_start);
irq_base = irq_start;
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-hip04.c
Original file line number Diff line number Diff line change
@@ -402,7 +402,7 @@ hip04_of_init(struct device_node *node, struct device_node *parent)
nr_irqs -= hwirq_base; /* calculate # of irqs to allocate */

irq_base = irq_alloc_descs(-1, hwirq_base, nr_irqs, numa_node_id());
if (IS_ERR_VALUE(irq_base)) {
if (irq_base < 0) {
pr_err("failed to allocate IRQ numbers\n");
return -EINVAL;
}
2 changes: 1 addition & 1 deletion drivers/irqchip/spear-shirq.c
Original file line number Diff line number Diff line change
@@ -232,7 +232,7 @@ static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
nr_irqs += shirq_blocks[i]->nr_irqs;

virq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
if (IS_ERR_VALUE(virq_base)) {
if (virq_base < 0) {
pr_err("%s: irq desc alloc failed\n", __func__);
goto err_unmap;
}
Loading

0 comments on commit 287980e

Please sign in to comment.