Skip to content

Harden index XML parsing against malformed input#614

Open
matejk wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
matejk:fix/index-parsing-hardening
Open

Harden index XML parsing against malformed input#614
matejk wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
matejk:fix/index-parsing-hardening

Conversation

@matejk

@matejk matejk commented Jun 12, 2026

Copy link
Copy Markdown

Defects reachable from a crafted or truncated index while mounting a cartridge. Two commits:

  • Recursion depth bound: _xml_parse_dirtree recurses once per directory level and the index reader sets XML_PARSE_HUGE, which removes libxml2's own nesting limit, so deeply nested <directory> elements could overflow the C stack during mount. The bound (5051) is a stack-safety guard, not an LTFS format limit — the format defines no maximum depth — and is set well above any tree that fits in a conventional PATH_MAX.
  • NULL dereferences and unchecked allocations: xml_next_tag passed a possibly-NULL libxml2 node name to strcmp; decode_entry_name wrote to an allocation of attacker-controlled size without a NULL check; the glob_patterns growth dereferenced an unchecked realloc; an ltfs.vendor.IBM.immutable/appendonly xattr with an empty self-closing value passed NULL to strcmp when deciding WORM flags, crashing the mount.

matejk added 2 commits June 17, 2026 22:06
_xml_parse_dirtree recurses once per directory level, and the index
reader sets XML_PARSE_HUGE, which removes libxml2's own nesting limit.
A crafted index with deeply nested <directory> elements could recurse
until the C stack overflows while mounting an untrusted cartridge.

Add a depth bound (a stack-safety guard, not an LTFS format limit; the
format defines no maximum depth) set well above any tree that fits in a
conventional PATH_MAX, so it cannot reject a volume produced from a real
filesystem. Introduces LTFS_XML_DEEP_NESTING (5051).
Four defects reachable from a crafted or truncated index while
mounting:
- xml_next_tag passed the node name to strcmp; libxml2 returns NULL
  for some node types. Skip NULL names.
- decode_entry_name wrote to a percent-decode buffer allocated from an
  attacker-controlled length without checking the allocation. Return
  -LTFS_NO_MEMORY instead.
- the glob_patterns array growth assigned realloc straight back and
  dereferenced it; on failure the old pointer leaked and the next
  write dereferenced NULL. Use a temporary and fail cleanly.
- an <xattr> named ltfs.vendor.IBM.immutable or appendonly with an
  empty (self-closing) value set xattr->value to NULL, which was then
  passed to strcmp when deciding the WORM flags, crashing the mount.
  Guard the value.
@matejk matejk force-pushed the fix/index-parsing-hardening branch from d031cd7 to 9293668 Compare June 17, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant