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

Commit 35a3bb3d authored by Aaron Sierra's avatar Aaron Sierra Committed by Herbert Xu
Browse files

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: default avatarAaron Sierra <asierra@xes-inc.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent ab86ca07
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -766,6 +766,7 @@ static int talitos_rng_init(struct hwrng *rng)
static int talitos_register_rng(struct device *dev)
{
	struct talitos_private *priv = dev_get_drvdata(dev);
	int err;

	priv->rng.name		= dev_driver_string(dev),
	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.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)
{
	struct talitos_private *priv = dev_get_drvdata(dev);

	if (!priv->rng_registered)
		return;

	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))
		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);
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ struct talitos_private {

	/* hwrng device */
	struct hwrng rng;
	bool rng_registered;
};

extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,