* [PATCH 0/4] nvmem: fixes for 7.3
@ 2026-10-02 10:13 srini
2026-10-02 10:13 ` [PATCH 1/4] nvmem: rockchip-otp: Serialize reads srini
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: srini @ 2026-10-02 10:13 UTC (permalink / raw)
To: gregkh; +Cc: linux-kernel, Srinivas Kandagatla
From: Srinivas Kandagatla <srini@kernel.org>
Hi Greg,
Here are few nvmem fixes for 7.3, Could you please queue
these for 7.3.
Patches include
- rockchip-otp: serialize concurrent reads with a mutex
- layouts: sl28vpd and onie-tlv device_node reference leak
fixes in the error path
- core: fix OOB read for bit offsets of more than one byte
Thanks,
Srini
Alexey Charkov (1):
nvmem: rockchip-otp: Serialize reads
Janne Grunau (1):
nvmem: core: Fix OOB read for bit offsets of more than one byte
Leo Cheng (2):
nvmem: layouts: sl28vpd: fix device_node reference leak in error path
nvmem: layouts: onie-tlv: fix device_node reference leak in error path
drivers/nvmem/core.c | 4 +++-
drivers/nvmem/layouts/onie-tlv.c | 1 +
drivers/nvmem/layouts/sl28vpd.c | 1 +
drivers/nvmem/rockchip-otp.c | 15 ++++++++++++++-
4 files changed, 19 insertions(+), 2 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] nvmem: rockchip-otp: Serialize reads
2026-10-02 10:13 [PATCH 0/4] nvmem: fixes for 7.3 srini
@ 2026-10-02 10:13 ` srini
2026-10-02 10:13 ` [PATCH 2/4] nvmem: layouts: sl28vpd: fix device_node reference leak in error path srini
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: srini @ 2026-10-02 10:13 UTC (permalink / raw)
To: gregkh
Cc: linux-kernel, Alexey Charkov, stable, Miquel Raynal, Srinivas Kandagatla
From: Alexey Charkov <alchark@flipper.net>
The OTP controller is driven through a single set of registers holding a
state machine which has to be stepped through for every word read, yet
nothing keeps two readers out of each other's way. Concurrent reads
interleave, and the outcome is either a reader bailing out:
rockchip-otp 2a580000.otp: timeout during read setup
or, worse, one of them silently taking delivery of the other's data.
Reading two cells in parallel from userspace on RK3576 reproduces both
within 150 iterations - 53 read errors and 9 corrupted results, the latter
either losing their first word or, in one case, ending in the two bytes
which belong to the other reader's cell - whereas the same reads issued
sequentially never fail. Concurrency is not hypothetical here, as six
thermal sensors source their trim values from the OTP and reach the driver
straight from asynchronous driver probing.
Guard the read path with a mutex. Reads are the only way into the hardware,
as the driver registers no write callback, and they always run in process
context, so a plain mutex spanning the whole clock-enable, read,
clock-disable sequence is enough.
Fixes: 755864feb729 ("nvmem: add Rockchip OTP driver")
Cc: stable@vger.kernel.org
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Alexey Charkov <alchark@flipper.net>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
---
drivers/nvmem/rockchip-otp.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 2c0feb036f3f..f8a8c7cece98 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/nvmem-provider.h>
#include <linux/reset.h>
#include <linux/slab.h>
@@ -80,6 +81,8 @@ struct rockchip_otp {
void __iomem *base;
struct reset_control *rst;
const struct rockchip_data *data;
+ /* Serializes access to the OTP controller state machine */
+ struct mutex mutex;
struct clk_bulk_data clks[];
};
@@ -272,10 +275,12 @@ static int rockchip_otp_read(void *context, unsigned int offset,
if (!otp->data || !otp->data->reg_read)
return -EINVAL;
+ mutex_lock(&otp->mutex);
+
ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
if (ret < 0) {
dev_err(otp->dev, "failed to prepare/enable clks\n");
- return ret;
+ goto unlock;
}
offset += otp->data->read_offset;
@@ -308,6 +313,9 @@ static int rockchip_otp_read(void *context, unsigned int offset,
err:
clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
+unlock:
+ mutex_unlock(&otp->mutex);
+
return ret;
}
@@ -431,6 +439,11 @@ static int rockchip_otp_probe(struct platform_device *pdev)
otp->data = data;
otp->dev = dev;
+
+ ret = devm_mutex_init(dev, &otp->mutex);
+ if (ret)
+ return ret;
+
otp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(otp->base))
return dev_err_probe(dev, PTR_ERR(otp->base),
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/4] nvmem: layouts: sl28vpd: fix device_node reference leak in error path
2026-10-02 10:13 [PATCH 0/4] nvmem: fixes for 7.3 srini
2026-10-02 10:13 ` [PATCH 1/4] nvmem: rockchip-otp: Serialize reads srini
@ 2026-10-02 10:13 ` srini
2026-10-02 10:13 ` [PATCH 3/4] nvmem: layouts: onie-tlv: " srini
2026-10-02 10:13 ` [PATCH 4/4] nvmem: core: Fix OOB read for bit offsets of more than one byte srini
3 siblings, 0 replies; 5+ messages in thread
From: srini @ 2026-10-02 10:13 UTC (permalink / raw)
To: gregkh
Cc: linux-kernel, Leo Cheng, Michael Walle, Miquel Raynal,
Srinivas Kandagatla
From: Leo Cheng <leo-cheng@vip.qq.com>
sl28vpd_add_cells() takes a reference on the child node via
of_get_child_by_name() for each entry and passes it to
nvmem_add_one_cell() as info.np. On success the created cell entry
adopts that reference and releases it later via of_node_put() when the
entry is torn down; nvmem_add_one_cell() does not take its own
reference. On failure it does not consume the reference either, so the
caller still owns it, but the error path only puts layout_np before
returning, leaking the child node reference.
Put info.np on the error path as well. of_node_put(NULL) is a no-op, so
this is safe even when of_get_child_by_name() returned NULL.
Fixes: d9fae023fe86 ("nvmem: layouts: sl28vpd: Add new layout driver")
Signed-off-by: Leo Cheng <leo-cheng@vip.qq.com>
Reviewed-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
---
drivers/nvmem/layouts/sl28vpd.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/nvmem/layouts/sl28vpd.c b/drivers/nvmem/layouts/sl28vpd.c
index e93b020b0836..79de1e6947d0 100644
--- a/drivers/nvmem/layouts/sl28vpd.c
+++ b/drivers/nvmem/layouts/sl28vpd.c
@@ -126,6 +126,7 @@ static int sl28vpd_add_cells(struct nvmem_layout *layout)
ret = nvmem_add_one_cell(nvmem, &info);
if (ret) {
+ of_node_put(info.np);
of_node_put(layout_np);
return ret;
}
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/4] nvmem: layouts: onie-tlv: fix device_node reference leak in error path
2026-10-02 10:13 [PATCH 0/4] nvmem: fixes for 7.3 srini
2026-10-02 10:13 ` [PATCH 1/4] nvmem: rockchip-otp: Serialize reads srini
2026-10-02 10:13 ` [PATCH 2/4] nvmem: layouts: sl28vpd: fix device_node reference leak in error path srini
@ 2026-10-02 10:13 ` srini
2026-10-02 10:13 ` [PATCH 4/4] nvmem: core: Fix OOB read for bit offsets of more than one byte srini
3 siblings, 0 replies; 5+ messages in thread
From: srini @ 2026-10-02 10:13 UTC (permalink / raw)
To: gregkh; +Cc: linux-kernel, Leo Cheng, Michael Walle, Srinivas Kandagatla
From: Leo Cheng <leo-cheng@vip.qq.com>
onie_tlv_add_cells() takes a reference on the child node via
of_get_child_by_name() for each parsed TLV and passes it to
nvmem_add_one_cell() as cell.np. On success the created cell entry
adopts that reference and releases it later via of_node_put(); on
failure nvmem_add_one_cell() does not consume it, so the caller still
owns it, but the error path only puts layout before returning, leaking
the child node reference.
Put cell.np on the error path as well. of_node_put(NULL) is a no-op, so
this is safe even when of_get_child_by_name() returned NULL.
Fixes: d3c0d12f6474 ("nvmem: layouts: onie-tlv: Add new layout driver")
Signed-off-by: Leo Cheng <leo-cheng@vip.qq.com>
Reviewed-by: Michael Walle <mwalle@kernel.org>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
---
drivers/nvmem/layouts/onie-tlv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c
index 8b0f3c1b8a0e..4da3a704388e 100644
--- a/drivers/nvmem/layouts/onie-tlv.c
+++ b/drivers/nvmem/layouts/onie-tlv.c
@@ -128,6 +128,7 @@ static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
ret = nvmem_add_one_cell(nvmem, &cell);
if (ret) {
+ of_node_put(cell.np);
of_node_put(layout);
return ret;
}
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 4/4] nvmem: core: Fix OOB read for bit offsets of more than one byte
2026-10-02 10:13 [PATCH 0/4] nvmem: fixes for 7.3 srini
` (2 preceding siblings ...)
2026-10-02 10:13 ` [PATCH 3/4] nvmem: layouts: onie-tlv: " srini
@ 2026-10-02 10:13 ` srini
3 siblings, 0 replies; 5+ messages in thread
From: srini @ 2026-10-02 10:13 UTC (permalink / raw)
To: gregkh
Cc: linux-kernel, Janne Grunau, stable, Dmitry Sinyavin, Srinivas Kandagatla
From: Janne Grunau <j@jannau.net>
When the bit offset is BITS_PER_BYTE or larger the read position is
advanced by `bytes_offset`. This is not taken into account in the
per-byte read loop which still reads `cell->bytes` resulting in an out of
bounds read of `bytes_offset` bytes. The information read OOB does not
leak directly as the erroneously read bits are cleared.
Detected by KASAN while looking for a use-after-free in simplefb.c.
Cc: stable@vger.kernel.org
Fixes: 7a06ef751077 ("nvmem: core: fix bit offsets of more than one byte")
Tested-by: Dmitry Sinyavin <sinyavin@gmail.com>
Signed-off-by: Janne Grunau <j@jannau.net>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
---
drivers/nvmem/core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 0556d140170a..b4e5069d9e38 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1598,12 +1598,14 @@ static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void
*p = *b++ >> bit_offset;
/* setup rest of the bytes if any */
- for (i = 1; i < cell->bytes; i++) {
+ for (i = 1; i < (cell->bytes - bytes_offset); i++) {
/* Get bits from next byte and shift them towards msb */
*p++ |= *b << (BITS_PER_BYTE - bit_offset);
*p = *b++ >> bit_offset;
}
+ /* point to end of the buffer unused bits will be cleared */
+ p = buf + cell->bytes - 1;
} else if (p != b) {
memmove(p, b, cell->bytes - bytes_offset);
p += cell->bytes - 1;
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-02 10:13 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-02 10:13 [PATCH 0/4] nvmem: fixes for 7.3 srini
2026-10-02 10:13 ` [PATCH 1/4] nvmem: rockchip-otp: Serialize reads srini
2026-10-02 10:13 ` [PATCH 2/4] nvmem: layouts: sl28vpd: fix device_node reference leak in error path srini
2026-10-02 10:13 ` [PATCH 3/4] nvmem: layouts: onie-tlv: " srini
2026-10-02 10:13 ` [PATCH 4/4] nvmem: core: Fix OOB read for bit offsets of more than one byte srini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®