From: sashiko-bot@kernel.org
To: "Link Mauve" <linkmauve@linkmauve.fr>
Cc: Frank.Li@kernel.org, ojeda@kernel.org, imx@lists.linux.dev,
neil.armstrong@linaro.org, linux-amlogic@lists.infradead.org
Subject: Re: [PATCH v3 2/4] nvmem: make all reg_write callbacks take const void *
Date: Thu, 16 Jul 2026 14:37:28 +0000 [thread overview]
Message-ID: <20260716143729.1353E1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260716142415.28718-3-linkmauve@linkmauve.fr>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
New issues:
- [Medium] Incomplete API migration leaving deprecated reg_write callbacks active
Pre-existing issues:
- [High] kCFI panic due to function pointer cast of regmap_bulk_write
- [High] Hardware state corruption and out-of-bounds read in sprd_efuse_write
- [High] OP-TEE session resource leak on alignment check failure
- [High] Missing locking leads to state corruption across multiple backend drivers
- [High] Sleeping in atomic context within sprd-efuse driver
- [High] Security check bypass during multi-word writes in zynqmp_nvmem_write
--
--- Patch [2]: [PATCH v3 2/4] nvmem: make all reg_write callbacks take const void * ---
commit ec203eda05f126cbe777e1158095fb9e39499796
Author: Link Mauve <linkmauve@linkmauve.fr>
nvmem: make all reg_write callbacks take const void *
This patch updates various nvmem drivers to use the new reg_write_const
callback instead of reg_write, matching a recent API change that passes
immutable data.
> The previous commit switched from a pointer to mutable data to a pointer
> to immutable data, so let’s fix all users of this API.
[Severity: Medium]
Are there some drivers missing from this update? It appears several nvmem
backend drivers are still assigning the deprecated reg_write callback,
which leaves the migration incomplete:
drivers/nvmem/at24.c:at24_probe() {
nvmem_config.reg_write = at24_write;
}
drivers/nvmem/at25.c:at25_probe() {
at25->nvmem_config.reg_write = at25_ee_write;
}
drivers/nvmem/eeprom_93xx46.c:eeprom_93xx46_probe() {
edev->nvmem_config.reg_write = eeprom_93xx46_write;
}
drivers/nvmem/m24lr.c:m24lr_probe() {
nvmem_conf.reg_write = m24lr_nvmem_write;
}
> diff --git a/drivers/nvmem/apple-spmi-nvmem.c b/drivers/nvmem/apple-spmi-nvmem.c
> index 88614005d5ce1..cbf25c53d048d 100644
> --- a/drivers/nvmem/apple-spmi-nvmem.c
> +++ b/drivers/nvmem/apple-spmi-nvmem.c
[ ... ]
> @@ -29,7 +29,7 @@ static int apple_spmi_nvmem_probe(struct spmi_device *sdev)
> .stride = 1,
> .size = 0xffff,
> .reg_read = (void *)regmap_bulk_read,
> - .reg_write = (void *)regmap_bulk_write,
> + .reg_write_const = (void *)regmap_bulk_write,
[Severity: High]
This is a pre-existing issue, but does casting regmap_bulk_write to void *
trigger a kCFI kernel panic? The actual signature of regmap_bulk_write
doesn't match reg_write_const, so calling it via this function pointer
could cause a control-flow integrity trap upon execution.
> };
[ ... ]
> diff --git a/drivers/nvmem/bcm-ocotp.c b/drivers/nvmem/bcm-ocotp.c
> index 2490f44caa409..02adfd787de85 100644
> --- a/drivers/nvmem/bcm-ocotp.c
> +++ b/drivers/nvmem/bcm-ocotp.c
[ ... ]
> @@ -179,11 +179,11 @@ static int bcm_otpc_read(void *context, unsigned int offset, void *val,
> return 0;
> }
>
> -static int bcm_otpc_write(void *context, unsigned int offset, void *val,
> - size_t bytes)
> +static int bcm_otpc_write(void *context, unsigned int offset, const void *val,
> + size_t bytes)
> {
[Severity: High]
This is a pre-existing issue, but does this function lack locking?
Modifying shared command and address registers concurrently without a lock
could corrupt the shared state machine:
drivers/nvmem/bcm-ocotp.c:bcm_otpc_write() {
for (bytes_written = 0; bytes_written < bytes;) {
set_command(priv->base, OTPC_CMD_PROGRAM);
set_cpu_address(priv->base, address++);
...
}
> struct otpc_priv *priv = context;
[ ... ]
> diff --git a/drivers/nvmem/lan9662-otpc.c b/drivers/nvmem/lan9662-otpc.c
> index 62d1d6381bf88..f586ae4cd126b 100644
> --- a/drivers/nvmem/lan9662-otpc.c
> +++ b/drivers/nvmem/lan9662-otpc.c
[ ... ]
> @@ -139,10 +139,10 @@ static int lan9662_otp_read(void *context, unsigned int offset,
> }
>
> static int lan9662_otp_write(void *context, unsigned int offset,
> - void *_val, size_t bytes)
> + const void *_val, size_t bytes)
> {
[Severity: High]
This is a pre-existing issue, but does this function perform unprotected
read-modify-write operations on OTP bytes? Modifying the OTP bytes without
locking could lead to data corruption in concurrent executions:
drivers/nvmem/lan9662-otpc.c:lan9662_otp_write() {
for (i = 0; i < bytes; i++) {
if (val[i]) {
rc = lan9662_otp_read_byte(otp, offset + i, &data);
...
rc = lan9662_otp_write_byte(otp, offset + i, newdata);
}
}
}
> struct lan9662_otp *otp = context;
[ ... ]
> diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c
> index 504155e30bab2..78a35ef095fbd 100644
> --- a/drivers/nvmem/lpc18xx_eeprom.c
> +++ b/drivers/nvmem/lpc18xx_eeprom.c
[ ... ]
> @@ -87,7 +87,7 @@ static int lpc18xx_eeprom_busywait_until_prog(struct lpc18xx_eeprom_dev *eeprom)
> }
>
> static int lpc18xx_eeprom_gather_write(void *context, unsigned int reg,
> - void *val, size_t bytes)
> + const void *val, size_t bytes)
> {
[Severity: High]
This isn't a bug introduced by this patch, but does this function lack
locking when modifying shared power and control registers? Concurrent
accesses could corrupt the shared state:
drivers/nvmem/lpc18xx_eeprom.c:lpc18xx_eeprom_gather_write() {
...
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
LPC18XX_EEPROM_PWRDWN_NO);
...
}
> struct lpc18xx_eeprom_dev *eeprom = context;
[ ... ]
> diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
> index 1de3435df116d..16b7f647a3f6f 100644
> --- a/drivers/nvmem/qfprom.c
> +++ b/drivers/nvmem/qfprom.c
[ ... ]
> @@ -252,13 +252,13 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv,
> *
> * Return: 0 or -err.
> */
> -static int qfprom_reg_write(void *context, unsigned int reg, void *_val,
> +static int qfprom_reg_write(void *context, unsigned int reg, const void *_val,
> size_t bytes)
> {
[Severity: High]
This is a pre-existing issue, but does this function need synchronization?
Modifying shared clocks and voltage states without locking could cause
state corruption:
drivers/nvmem/qfprom.c:qfprom_reg_write() {
...
ret = qfprom_enable_fuse_blowing(priv, &old);
...
}
> struct qfprom_priv *priv = context;
[ ... ]
> diff --git a/drivers/nvmem/sprd-efuse.c b/drivers/nvmem/sprd-efuse.c
> index 1a7e4e5d8b86c..f960fa8cb25cf 100644
> --- a/drivers/nvmem/sprd-efuse.c
> +++ b/drivers/nvmem/sprd-efuse.c
[ ... ]
> @@ -192,7 +192,7 @@ static void sprd_efuse_set_prog_en(struct sprd_efuse *efuse, bool en)
> }
>
> static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub,
> - bool lock, u32 *data)
> + bool lock, const u32 *data)
> {
[Severity: High]
This isn't a bug introduced by this patch, but does this unconditionally
dereference the buffer as a u32 pointer? If the payload is smaller than 4
bytes, this could result in an out-of-bounds read:
drivers/nvmem/sprd-efuse.c:sprd_efuse_raw_prog() {
...
writel(*data, efuse->base + SPRD_EFUSE_MEM(blk));
...
}
> u32 status;
> int ret = 0;
[ ... ]
> @@ -321,7 +321,7 @@ static int sprd_efuse_read(void *context, u32 offset, void *val, size_t bytes)
> return ret;
> }
>
> -static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes)
> +static int sprd_efuse_write(void *context, u32 offset, const void *val, size_t bytes)
> {
[Severity: High]
This is a pre-existing issue, but can this function sleep in atomic context?
If sprd_efuse_lock() acquires a hardware spinlock, calling the sleepable
clk_prepare_enable() could trigger a locking violation and soft lockup.
This seems to affect both sprd_efuse_write() and sprd_efuse_read():
drivers/nvmem/sprd-efuse.c:sprd_efuse_write() {
ret = sprd_efuse_lock(efuse);
if (ret)
return ret;
ret = clk_prepare_enable(efuse->clk);
...
}
Additionally, is the raw byte offset passed directly as a block index here?
Targeting incorrect addresses could lead to hardware state corruption:
drivers/nvmem/sprd-efuse.c:sprd_efuse_write() {
...
ret = sprd_efuse_raw_prog(efuse, offset, blk_double, lock, val);
...
}
> struct sprd_efuse *efuse = context;
[ ... ]
> diff --git a/drivers/nvmem/stm32-bsec-optee-ta.c b/drivers/nvmem/stm32-bsec-optee-ta.c
> index f89ce791dd12a..3184b976b1f91 100644
> --- a/drivers/nvmem/stm32-bsec-optee-ta.c
> +++ b/drivers/nvmem/stm32-bsec-optee-ta.c
[ ... ]
> @@ -203,7 +203,7 @@ int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
>
> /* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */
> int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
> - unsigned int offset, void *buf, size_t bytes)
> + unsigned int offset, const void *buf, size_t bytes)
> { struct tee_shm *shm;
[Severity: High]
This is a pre-existing issue, but does this function leak the OP-TEE
session if the alignment check fails? Returning directly bypasses cleanup:
drivers/nvmem/stm32-bsec-optee-ta.c:stm32_bsec_optee_ta_write() {
ret = stm32_bsec_ta_open_session(ctx, &session_id);
if (ret)
return ret;
/* Allow only writing complete 32-bits aligned words */
if ((bytes % 4) || (offset % 4))
return -EINVAL;
...
}
[ ... ]
> diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
> index d297ff150dc02..54905a608157d 100644
> --- a/drivers/nvmem/zynqmp_nvmem.c
> +++ b/drivers/nvmem/zynqmp_nvmem.c
[ ... ]
> @@ -183,7 +183,7 @@ static int zynqmp_nvmem_read(void *context, unsigned int offset, void *val, size
> }
>
> static int zynqmp_nvmem_write(void *context,
> - unsigned int offset, void *val, size_t bytes)
> + unsigned int offset, const void *val, size_t bytes)
> {
[Severity: High]
This isn't a bug introduced by this patch, but does zynqmp_efuse_access()
bypass local bitmask validations for subsequent words during a multi-word
write? The check seems to only happen on the first word:
drivers/nvmem/zynqmp_nvmem.c:zynqmp_efuse_access() {
if (pufflag == 1 && flag == EFUSE_WRITE) {
memcpy(&value, val, sizeof(value));
if ((offset == EFUSE_PUF_START_OFFSET ||
offset == EFUSE_PUF_MID_OFFSET) &&
value & P_USER_0_64_UPPER_MASK) {
...
}
...
}
> int pufflag = 0;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260716142415.28718-1-linkmauve@linkmauve.fr?part=2
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
next prev parent reply other threads:[~2026-07-16 14:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-16 14:24 [PATCH v3 0/4] nvmem: fix a const-unsoundness in reg_write Link Mauve
2026-07-16 14:24 ` [PATCH v3 1/4] nvmem: core: deprecate reg_write callback and add reg_write_const Link Mauve
2026-07-16 14:24 ` [PATCH v3 2/4] nvmem: make all reg_write callbacks take const void * Link Mauve
2026-07-16 14:37 ` sashiko-bot [this message]
2026-07-16 14:24 ` [PATCH v3 3/4] nvmem: apple-spmi: improve calling safety with wrapper functions Link Mauve
2026-07-16 18:07 ` Andy Shevchenko
2026-07-16 14:24 ` [PATCH v3 4/4] firmware: meson: pass a const buffer to meson_sm_call_write() Link Mauve
2026-07-16 14:36 ` sashiko-bot
2026-07-16 15:23 ` [PATCH v3 0/4] nvmem: fix a const-unsoundness in reg_write Gary Guo
2026-07-16 18:09 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260716143729.1353E1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=imx@lists.linux.dev \
--cc=linkmauve@linkmauve.fr \
--cc=linux-amlogic@lists.infradead.org \
--cc=neil.armstrong@linaro.org \
--cc=ojeda@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox