Commit d62c6f2d authored by Breno Leitao's avatar Breno Leitao Committed by Jakub Kicinski
Browse files

netconsole: return count instead of strnlen(buf, count) from store callbacks



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: 0bcc1816 ("[NET] netconsole: Support dynamic reconfiguration using configfs")
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarBreno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260427-netconsole_ai_fixes-v2-1-59965f29d9cc@debian.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 403e7e34
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -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;