ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 8.3.16, 9.0.7, 8.0.37, 7.0.48
    • Affects Version/s: 8.3.3, 8.3.4, 8.3.5, 8.2.12, 8.3.6, 8.2.13, 8.0.28, 8.3.7, 8.0.29, 8.3.8, 8.3.9, 9.0.0, 9.0.1, 9.0.2, 9.0.3, 9.0.4, 9.0.5
    • Component/s: None
    • None
    • Storage Execution
    • Fully Compatible
    • ALL
    • v9.0, v8.3, v8.0, v7.0
    • Storage Execution 2026-10-12, Storage Execution 2026-10-26, Storage Execution 2026-11-09, Storage Execution 2026-11-23
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Problem

      The strict time-series bucket validator, which runs by default on raw bucket inserts and updates (validateBucketConsistency, dispatched from CollectionImpl::checkValidation), rebuilds a bucket's min/max summaries by merging every measurement value in a data column into a MinMax structure backed by FlatBSONStore (_validateUncompressedMinMax).

      When a field path is an object in some measurements and an array in others, this merge can desynchronize FlatBSONStore's fast field lookup map from its entry list. A later lookup can then return the wrong entry, or a position outside the object's child run entirely. An update routed through that lookup resizes and frees a value buffer that another entry still owns. The result is a use-after-free, followed by a double-free, on memory whose contents are attacker-controlled.

      How the desync happens

      FlatBSONStore keeps array element entries, which all share one reserved field name (kArrayFieldName), in the same positional child list as named object fields. An object field merged onto an array placeholder entry renames that entry in place (Element::claimArrayFieldNameForObject, called from _updateObj). When the parent object has already built its fast lookup map (_fieldNameToIndex, built once a search exceeds kMaxLinearSearchLength = 12, populated here), the rename leaves the map stale:

      • The map still keys the renamed entry under the reserved array name and has no key for the new name.
      • A later search for the new name misses in the fast lookup path, so a duplicate entry with the same name gets inserted (the duplicate check in Obj::insert passes, since the map lacks the new name).
      • The insert offset fixup increments the map slot once per entry currently carrying that name (here), so the slot drifts further from the real position on every subsequent insert.
      • With enough drift, the stored offset lands outside the object's child run, inside spare capacity of the flat entries vector.

      A lookup that follows the stale offset treats whatever bytes it finds there as an entry. If those bytes resemble an entry whose value buffer pointer aliases a live buffer, an update through the lookup calls BSONElementValueBuffer::set, which resizes and frees that live buffer while its real owner still references it. A later allocation of the same size class reclaims the freed memory, the real owner reads the replacement bytes when the validation result is built, and the buffer is freed a second time when the MinMax structure is destroyed.

      Reachability

      • A single raw insert (rawData: true) of a crafted uncompressed (control.version: 1) bucket into any time-series collection reaches the merge before the write is rejected. Document validation runs before the op-observer mixed-schema check (CannotInsertTimeseriesBucketsWithMixedSchema), so the mixed-schema write guard does not protect this path.
      • The compressed-column validation path shares the same MinMax machinery and has the same exposure (_validateCompressedMinMax).
      • The Schema structure used on bucket reopen shares the FlatBSON code and carries the same latent defect (generateSchemaFromBucketDoc).
      • Requires an authenticated user with insert privileges on a time-series collection.

      Impact

      Heap corruption in the mongod process during document validation. Confirmed to crash the server with a segmentation fault in a single request. An external reporter demonstrates escalation to arbitrary command execution with the privileges of the mongod OS user.

      Affected versions

      Affects 8.0.28+, 8.2.12+, 8.3.3+, 9.0.0+; 7.0 not affected via the strict-validation path, with the catalog-reopen path still under investigation. Strict bucket validator introduced in SERVER-118985 pulled the FlatBSON MinMax merge within reach of the attacker-controlled raw bucket input. The underlying FlatBSON rename is older, but it was not reachable with attacker-controlled mixed shapes before the validator existed.

            Assignee:
            Ernesto Rodriguez Reina
            Reporter:
            Ernesto Rodriguez Reina
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: