[PATCH net v2 1/4] netconsole: return count instead of strnlen(buf, count) from store callbacks

From: Breno Leitao

Date: Mon Apr 27 2026 - 10:36:23 EST


Several configfs store callbacks in netconsole end with:

ret = strnlen(buf, count);

This under-reports the number of bytes consumed when the input
contains an embedded NUL within count, telling the VFS that fewer
bytes were written than userspace actually handed in. A conformant
partial-write loop would then retry the trailing bytes against a
callback that has already accepted them.

Every other configfs driver in the tree returns count directly from
its store callbacks once parsing has succeeded, including
drivers/nvme/target/configfs.c, drivers/gpio/gpio-sim.c,
drivers/most/configfs.c, drivers/block/null_blk/main.c,
drivers/pci/endpoint/pci-ep-cfs.c, and the rest of the configfs
users. netconsole was the outlier (along with
drivers/infiniband/core/cma_configfs.c, which has the same latent
issue).

Align netconsole with the rest of the configfs ecosystem: return
count once the parser/validator has accepted the input. The numeric
and boolean parsers (kstrtobool, kstrtou16, mac_pton,
netpoll_parse_ip_addr) have already validated the meaningful prefix;
any trailing bytes are padding and should simply be reported as
consumed.

Fixes: 0bcc1816188e ("[NET] netconsole: Support dynamic reconfiguration using configfs")
Reviewed-by: Simon Horman <horms@xxxxxxxxxx>
Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>
---
drivers/net/netconsole.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 205384dab89a6..76d7fbf9e1883 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -752,7 +752,7 @@ static ssize_t enabled_store(struct config_item *item,
unregister_netcons_consoles();
}

- ret = strnlen(buf, count);
+ ret = count;
/* Deferred cleanup */
netconsole_process_cleanups();
out_unlock:
@@ -781,7 +781,7 @@ static ssize_t release_store(struct config_item *item, const char *buf,

nt->release = release;

- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -807,7 +807,7 @@ static ssize_t extended_store(struct config_item *item, const char *buf,
goto out_unlock;

nt->extended = extended;
- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -830,7 +830,7 @@ static ssize_t dev_name_store(struct config_item *item, const char *buf,
trim_newline(nt->np.dev_name, IFNAMSIZ);

dynamic_netconsole_mutex_unlock();
- return strnlen(buf, count);
+ return count;
}

static ssize_t local_port_store(struct config_item *item, const char *buf,
@@ -849,7 +849,7 @@ static ssize_t local_port_store(struct config_item *item, const char *buf,
ret = kstrtou16(buf, 10, &nt->np.local_port);
if (ret < 0)
goto out_unlock;
- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -871,7 +871,7 @@ static ssize_t remote_port_store(struct config_item *item,
ret = kstrtou16(buf, 10, &nt->np.remote_port);
if (ret < 0)
goto out_unlock;
- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -896,7 +896,7 @@ static ssize_t local_ip_store(struct config_item *item, const char *buf,
goto out_unlock;
nt->np.ipv6 = !!ipv6;

- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -921,7 +921,7 @@ static ssize_t remote_ip_store(struct config_item *item, const char *buf,
goto out_unlock;
nt->np.ipv6 = !!ipv6;

- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -957,7 +957,7 @@ static ssize_t remote_mac_store(struct config_item *item, const char *buf,
goto out_unlock;
memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);

- ret = strnlen(buf, count);
+ ret = count;
out_unlock:
dynamic_netconsole_mutex_unlock();
return ret;
@@ -1133,7 +1133,7 @@ static ssize_t sysdata_msgid_enabled_store(struct config_item *item,
disable_sysdata_feature(nt, SYSDATA_MSGID);

unlock_ok:
- ret = strnlen(buf, count);
+ ret = count;
dynamic_netconsole_mutex_unlock();
mutex_unlock(&netconsole_subsys.su_mutex);
return ret;
@@ -1162,7 +1162,7 @@ static ssize_t sysdata_release_enabled_store(struct config_item *item,
disable_sysdata_feature(nt, SYSDATA_RELEASE);

unlock_ok:
- ret = strnlen(buf, count);
+ ret = count;
dynamic_netconsole_mutex_unlock();
mutex_unlock(&netconsole_subsys.su_mutex);
return ret;
@@ -1191,7 +1191,7 @@ static ssize_t sysdata_taskname_enabled_store(struct config_item *item,
disable_sysdata_feature(nt, SYSDATA_TASKNAME);

unlock_ok:
- ret = strnlen(buf, count);
+ ret = count;
dynamic_netconsole_mutex_unlock();
mutex_unlock(&netconsole_subsys.su_mutex);
return ret;
@@ -1225,7 +1225,7 @@ static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
disable_sysdata_feature(nt, SYSDATA_CPU_NR);

unlock_ok:
- ret = strnlen(buf, count);
+ ret = count;
dynamic_netconsole_mutex_unlock();
mutex_unlock(&netconsole_subsys.su_mutex);
return ret;

--
2.52.0