crypto: talitos - Prevent panic in probe error path

The probe error path for this driver, for all intents and purposes,
is the talitos_remove() function due to the common "goto err_out".

Without this patch applied, talitos_remove() will panic under these
two conditions:

1. If the RNG device hasn't been registered via
   talitos_register_rng() prior to entry into talitos_remove(),
   then the attempt to unregister the RNG "device" will cause a panic.

2. If the priv->chan array has not been allocated prior to entry
   into talitos_remove(), then the per-channel FIFO cleanup will panic
   because of the dereference of that NULL "array".

Both of the above scenarios occur if talitos_probe_irq() fails.

This patch resolves issue #1 by introducing a boolean to mask the
hwrng_unregister() call in talitos_unregister_rng() if RNG device
registration was unsuccessful.

It resolves issue #2 by checking that priv->chan is not NULL in the
per-channel FIFO cleanup for loop.

Signed-off-by: Aaron Sierra <asierra@xes-inc.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Aaron Sierra 2015-08-05 16:52:08 -05:00 committed by Herbert Xu
parent ab86ca0755
commit 35a3bb3d39
2 changed files with 12 additions and 2 deletions

View File

@ -766,6 +766,7 @@ static int talitos_rng_init(struct hwrng *rng)
static int talitos_register_rng(struct device *dev) static int talitos_register_rng(struct device *dev)
{ {
struct talitos_private *priv = dev_get_drvdata(dev); struct talitos_private *priv = dev_get_drvdata(dev);
int err;
priv->rng.name = dev_driver_string(dev), priv->rng.name = dev_driver_string(dev),
priv->rng.init = talitos_rng_init, priv->rng.init = talitos_rng_init,
@ -773,14 +774,22 @@ static int talitos_register_rng(struct device *dev)
priv->rng.data_read = talitos_rng_data_read, priv->rng.data_read = talitos_rng_data_read,
priv->rng.priv = (unsigned long)dev; priv->rng.priv = (unsigned long)dev;
return hwrng_register(&priv->rng); err = hwrng_register(&priv->rng);
if (!err)
priv->rng_registered = true;
return err;
} }
static void talitos_unregister_rng(struct device *dev) static void talitos_unregister_rng(struct device *dev)
{ {
struct talitos_private *priv = dev_get_drvdata(dev); struct talitos_private *priv = dev_get_drvdata(dev);
if (!priv->rng_registered)
return;
hwrng_unregister(&priv->rng); hwrng_unregister(&priv->rng);
priv->rng_registered = false;
} }
/* /*
@ -2673,7 +2682,7 @@ static int talitos_remove(struct platform_device *ofdev)
if (hw_supports(dev, DESC_HDR_SEL0_RNG)) if (hw_supports(dev, DESC_HDR_SEL0_RNG))
talitos_unregister_rng(dev); talitos_unregister_rng(dev);
for (i = 0; i < priv->num_channels; i++) for (i = 0; priv->chan && i < priv->num_channels; i++)
kfree(priv->chan[i].fifo); kfree(priv->chan[i].fifo);
kfree(priv->chan); kfree(priv->chan);

View File

@ -149,6 +149,7 @@ struct talitos_private {
/* hwrng device */ /* hwrng device */
struct hwrng rng; struct hwrng rng;
bool rng_registered;
}; };
extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,