]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iio: inkern: only release the device node when done with it
authorNuno Sá <nuno.sa@analog.com>
Fri, 15 Jul 2022 12:28:49 +0000 (14:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Oct 2022 11:15:41 +0000 (13:15 +0200)
[ Upstream commit 79c3e84874c7d14f04ad58313b64955a0d2e9437 ]

'of_node_put()' can potentially release the memory pointed to by
'iiospec.np' which would leave us with an invalid pointer (and we would
still pass it in 'of_xlate()'). Note that it is not guaranteed for the
of_node lifespan to be attached to the device (to which is attached)
lifespan so that there is (even though very unlikely) the possibility
for the node to be freed while the device is still around. Thus, as there
are indeed some of_xlate users which do access the node, a race is indeed
possible.

As such, we can only release the node after we are done with it.

Fixes: 17d82b47a215d ("iio: Add OF support")
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20220715122903.332535-2-nuno.sa@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/iio/inkern.c

index 218cf4567ab58ddc2c83383c57918c1360d47358..13be4c8d7fd36a6f9e7b38e4854658d507cd9a41 100644 (file)
@@ -139,9 +139,10 @@ static int __of_iio_channel_get(struct iio_channel *channel,
 
        idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
                               iio_dev_node_match);
-       of_node_put(iiospec.np);
-       if (idev == NULL)
+       if (idev == NULL) {
+               of_node_put(iiospec.np);
                return -EPROBE_DEFER;
+       }
 
        indio_dev = dev_to_iio_dev(idev);
        channel->indio_dev = indio_dev;
@@ -149,6 +150,7 @@ static int __of_iio_channel_get(struct iio_channel *channel,
                index = indio_dev->info->of_xlate(indio_dev, &iiospec);
        else
                index = __of_iio_simple_xlate(indio_dev, &iiospec);
+       of_node_put(iiospec.np);
        if (index < 0)
                goto err_put;
        channel->channel = &indio_dev->channels[index];