[GH-ISSUE #97] Malformed OverlayBD index metadata is trusted before buffer allocation #33

Open
opened 2026-10-29 14:18:36 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Jul 31, 2026).
Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/97

Affected component

OverlayBD / image resolution

AgentENV version

  • Commit: f41abb21324f6b0520abf34b7720aa260ddd10eb
  • Local modifications: none for the source analysis below

Host environment

  • OS: Ubuntu 26.04
  • Kernel: 7.0.0-28-generic
  • Architecture: x86_64
  • Storage/filesystem: ext filesystem
  • KVM / ublk: not required; the failure is in layer parsing before a device is created

Operation and configuration

Opening an untrusted or corrupted sealed OverlayBD layer through the normal read-only layer path. No special configuration is required.

The trailer controls both values passed to the index loader:

HeaderTrailer.index_offset ─┐
                            ├─> load_index() ─> allocate index buffer ─> read file
HeaderTrailer.index_size ───┘

At f41abb2, verify_ht validates the trailer magic/type but does not validate the index range. load_index then computes:

let size_bytes = count * size_of::<DiskSegmentMapping>();
let mut raw_bytes = vec![0u8; size_bytes];

The allocation occurs before the implementation checks whether the described range exists in the backing file.

Affected paths:

  • storage/overlaybd/src/lsmt/file/helper.rs — verify_ht, load_index, and load_index_and_reset_tags
  • storage/overlaybd/src/lsmt/file/readonly.rs — passes trailer metadata into the loader
  • storage/overlaybd/src/lsmt/file/stack.rs — parallel lower-layer index loading

Steps to reproduce

This is a source-derived reproduction that avoids deliberately requesting an out-of-memory allocation:

  1. Create a valid sealed OverlayBD layer.
  2. Rewrite its final HeaderTrailer while preserving valid magic/type fields.
  3. Set either:
    • index_offset beyond the start of the trailer;
    • index_size so index_offset + index_size * sizeof(DiskSegmentMapping) exceeds the file; or
    • index_size above the checked multiplication/conversion limit.
  4. Open the layer through LSMTReadOnlyFile or open_file_index.
  5. Observe that the current code reaches index-size calculation and buffer allocation without first proving that the metadata describes bytes inside the file.

The focused regression cases used to validate the proposed invariant are:

cargo test -p overlaybd --lib rejects_sealed_index_offset_out_of_bounds
cargo test -p overlaybd --lib rejects_sealed_index_size_out_of_bounds
cargo test -p overlaybd --lib rejects_index_count_overflow_before_allocation

Expected behavior

Before allocating or reading an index, reject metadata unless all of these conditions hold:

  1. the index starts after the file header;
  2. index_size * sizeof(DiskSegmentMapping) is representable;
  3. the index ends before the sealed trailer (or before the file end for an index-only file); and
  4. the mapping count and byte length fit the host allocation type.
trailer metadata
      │
      ▼
checked size and file-range validation
      ├── valid   ──> allocate and read
      └── invalid ──> return a structured error

Actual behavior

The current loader trusts the trailer-provided count long enough to calculate and allocate the index buffer. File bounds are only discovered by the later read, so an oversized count can cause excessive allocation or arithmetic failure before a normal malformed-layer error is returned.

No server log is required to establish the ordering: the allocation-before-read sequence is directly visible in load_index.

Reproduction frequency

Always for a layer containing the corresponding malformed trailer values.

Regression information

  • Last known good: unknown
  • First known bad: unknown
  • This report establishes behavior at f41abb21324f6b0520abf34b7720aa260ddd10eb.

Scope and acceptance criteria

  • Validate the offset and computed byte range against the actual file length before allocation.
  • Use checked multiplication and checked conversion to usize.
  • Cover out-of-bounds offset, out-of-bounds size, and arithmetic overflow.
  • Preserve valid sealed-layer, index-only, and writable-layer loading behavior.

This report does not claim that an out-of-memory condition was executed on the audit host; that impact follows from the confirmed allocation ordering. The bounded malformed-metadata cases were exercised without KVM or ublk.

Pre-submission checks

  • Searched open and closed issues for a directly related report.
  • Included a minimal source-derived reproduction and bounded regression cases.
  • Included no credentials, private image references, or customer data.
  • This report is not asserting a security vulnerability.
Originally created by @morluto on GitHub (Jul 31, 2026). Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/97 ## Affected component OverlayBD / image resolution ## AgentENV version - Commit: `f41abb21324f6b0520abf34b7720aa260ddd10eb` - Local modifications: none for the source analysis below ## Host environment - OS: Ubuntu 26.04 - Kernel: `7.0.0-28-generic` - Architecture: `x86_64` - Storage/filesystem: ext filesystem - KVM / ublk: not required; the failure is in layer parsing before a device is created ## Operation and configuration Opening an untrusted or corrupted sealed OverlayBD layer through the normal read-only layer path. No special configuration is required. The trailer controls both values passed to the index loader: ```text HeaderTrailer.index_offset ─┐ ├─> load_index() ─> allocate index buffer ─> read file HeaderTrailer.index_size ───┘ ``` At `f41abb2`, `verify_ht` validates the trailer magic/type but does not validate the index range. `load_index` then computes: ```rust let size_bytes = count * size_of::<DiskSegmentMapping>(); let mut raw_bytes = vec![0u8; size_bytes]; ``` The allocation occurs before the implementation checks whether the described range exists in the backing file. Affected paths: - `storage/overlaybd/src/lsmt/file/helper.rs` — `verify_ht`, `load_index`, and `load_index_and_reset_tags` - `storage/overlaybd/src/lsmt/file/readonly.rs` — passes trailer metadata into the loader - `storage/overlaybd/src/lsmt/file/stack.rs` — parallel lower-layer index loading ## Steps to reproduce This is a source-derived reproduction that avoids deliberately requesting an out-of-memory allocation: 1. Create a valid sealed OverlayBD layer. 2. Rewrite its final `HeaderTrailer` while preserving valid magic/type fields. 3. Set either: - `index_offset` beyond the start of the trailer; - `index_size` so `index_offset + index_size * sizeof(DiskSegmentMapping)` exceeds the file; or - `index_size` above the checked multiplication/conversion limit. 4. Open the layer through `LSMTReadOnlyFile` or `open_file_index`. 5. Observe that the current code reaches index-size calculation and buffer allocation without first proving that the metadata describes bytes inside the file. The focused regression cases used to validate the proposed invariant are: ```shell cargo test -p overlaybd --lib rejects_sealed_index_offset_out_of_bounds cargo test -p overlaybd --lib rejects_sealed_index_size_out_of_bounds cargo test -p overlaybd --lib rejects_index_count_overflow_before_allocation ``` ## Expected behavior Before allocating or reading an index, reject metadata unless all of these conditions hold: 1. the index starts after the file header; 2. `index_size * sizeof(DiskSegmentMapping)` is representable; 3. the index ends before the sealed trailer (or before the file end for an index-only file); and 4. the mapping count and byte length fit the host allocation type. ```text trailer metadata │ ▼ checked size and file-range validation ├── valid ──> allocate and read └── invalid ──> return a structured error ``` ## Actual behavior The current loader trusts the trailer-provided count long enough to calculate and allocate the index buffer. File bounds are only discovered by the later read, so an oversized count can cause excessive allocation or arithmetic failure before a normal malformed-layer error is returned. No server log is required to establish the ordering: the allocation-before-read sequence is directly visible in `load_index`. ## Reproduction frequency Always for a layer containing the corresponding malformed trailer values. ## Regression information - Last known good: unknown - First known bad: unknown - This report establishes behavior at `f41abb21324f6b0520abf34b7720aa260ddd10eb`. ## Scope and acceptance criteria - Validate the offset and computed byte range against the actual file length before allocation. - Use checked multiplication and checked conversion to `usize`. - Cover out-of-bounds offset, out-of-bounds size, and arithmetic overflow. - Preserve valid sealed-layer, index-only, and writable-layer loading behavior. This report does not claim that an out-of-memory condition was executed on the audit host; that impact follows from the confirmed allocation ordering. The bounded malformed-metadata cases were exercised without KVM or ublk. ## Pre-submission checks - [x] Searched open and closed issues for a directly related report. - [x] Included a minimal source-derived reproduction and bounded regression cases. - [x] Included no credentials, private image references, or customer data. - [x] This report is not asserting a security vulnerability.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kvcache-ai/AgentENV#33
No description provided.