]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netconsole: return count instead of strnlen(buf, count) from store callbacks
authorBreno Leitao <leitao@debian.org>
Mon, 27 Apr 2026 14:30:35 +0000 (07:30 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 29 Apr 2026 01:28:11 +0000 (18:28 -0700)
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@kernel.org>
Signed-off-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260427-netconsole_ai_fixes-v2-1-59965f29d9cc@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/netconsole.c

index 205384dab89a6948eef960e0287342a59eedeac0..76d7fbf9e1883fa24d8d7ba0480468c09b27103b 100644 (file)
@@ -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;