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);
     }

Reply via email to