This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new c51a2caa6 config: bound conf_parse_name() loop to CONF_MAX_DIR_DEPTH
c51a2caa6 is described below
commit c51a2caa61526cd7b9d32599d7f75efc82489e58
Author: yi chen <[email protected]>
AuthorDate: Mon Jul 13 09:24:09 2026 +0800
config: bound conf_parse_name() loop to CONF_MAX_DIR_DEPTH
conf_parse_name() tokenized a config name string and wrote each
segment pointer into name_argv[] with no check against the caller's
fixed-size array. All real callers (conf_set_value(), conf_get_value(),
conf_commit(), conf_save_tree()) declare
`char *name_argv[CONF_MAX_DIR_DEPTH]` (8 entries) on the stack and
pass it straight in, so a name with more
than 8 '/'-separated segments overflows the array and corrupts adjacent
stack memory.
This is reachable remotely: config_mgmt.c (mcumgr "config read"/"config
write") copies an attacker-supplied CBOR "name" string of up to
CONF_MAX_NAME_LEN (64) bytes into a local buffer and passes it to
conf_get_value()/conf_set_value() unvalidated for segment count. A name
such as 16 single-character segments ("a/a/a/.../a", 31 bytes, well
under the 64-byte limit) is enough to write 8 pointers past the end of
the 8-slot array.
Bound the tokenizer loop and return an error once CONF_MAX_DIR_DEPTH is
reached. conf_parse_and_lookup() and every caller already treat a
non-zero conf_parse_name() rc / NULL lookup result as an invalid name
(OS_INVALID_PARM), so no other code needed to change.
Verified with a standalone harness reproducing the real stack-frame
layout (name_argc + name_argv[8] + adjacent locals) that the unpatched
function corrupts the trailing memory once fed >8 segments, and that
the patched function rejects over-depth names while leaving normal
parsing (including the exact 8-segment boundary) unchanged.
---
sys/config/src/config.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sys/config/src/config.c b/sys/config/src/config.c
index 3e675b6b1..6fc22893b 100644
--- a/sys/config/src/config.c
+++ b/sys/config/src/config.c
@@ -139,6 +139,9 @@ conf_parse_name(char *name, int *name_argc, char
*name_argv[])
i = 0;
while (tok) {
+ if (i >= CONF_MAX_DIR_DEPTH) {
+ return -1;
+ }
name_argv[i++] = tok;
tok = strtok_r(NULL, sep, &tok_ptr);
}