The 512 MiB flat cap on decompressed part size is heuristic.
Since we broke flatpak firefox deltas with incorrect heuristics,
back that out until we come up with a design that is precise and
tighter.
This deliberately reopens <https://github.com/ostreedev/ostree/security/advisories/GHSA-7cgc-gp99-6jmm> for now.
Assisted-by: https://github.com/cgwalters/cgwalters#llms
Signed-off-by: Colin Walters <walters@verbum.org>
g_variant_ref_sink (delta_part_content);
}
- /* Reject parts whose uncompressed payload exceeds the hard limit that
- * consumers enforce (OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES). Without
- * this check, a large --max-chunk-size would produce deltas that every
- * client rejects at apply time (CVE / RHEL-189208).
- */
- {
- gsize payload_size = g_variant_get_size (delta_part_content);
- if (payload_size > OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES)
- return glnx_throw (error,
- "Delta part %u uncompressed payload size %" G_GSIZE_FORMAT
- " bytes exceeds maximum %" G_GUINT64_FORMAT "; reduce --max-chunk-size",
- builder->parts->len, payload_size,
- (guint64)OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES);
- }
-
/* Hardcode xz for now */
compressor = (GConverter *)_ostree_lzma_compressor_new (NULL);
compression_type_char = 'x';
* are known:
* - min-fallback-size: u: Minimum uncompressed size in megabytes to use fallback, 0 to disable
* fallbacks
- * - max-chunk-size: u: Maximum size in megabytes of a delta part (hard cap: 512 MiB)
+ * - max-chunk-size: u: Maximum size in megabytes of a delta part
* - max-bsdiff-size: u: Maximum size in megabytes to consider bsdiff compression
* for input files
* - compression: y: Compression type: 0=none, x=lzma, g=gzip
const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
- /* Decompression-bomb defense: the flat hard cap. A tighter,
- * exact-size-derived limit may be layered on top of this by callers
- * that have that information; see OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES.
- */
- guint64 max_part_usize = OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES;
-
/* We either take a fd or a GBytes reference */
g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);
g_variant_ref_sink (ret_part);
}
- /* Enforce the size limit so that an attacker cannot bypass the
- * decompression-bomb defence by setting compression type to 0.
- */
- if (g_variant_get_size (ret_part) > max_part_usize)
- return glnx_throw (error,
- "Uncompressed delta part size %" G_GSIZE_FORMAT
- " exceeds maximum %" G_GUINT64_FORMAT,
- g_variant_get_size (ret_part), max_part_usize);
-
if (!skip_checksum)
g_checksum_update (checksum, g_variant_get_data (ret_part), g_variant_get_size (ret_part));
{
g_autoptr (GConverter) decomp = (GConverter *)_ostree_lzma_decompressor_new ();
g_autoptr (GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
- g_autoptr (GBytes) buf = ot_map_anonymous_tmpfile_from_content_with_limit (
- convin, max_part_usize, cancellable, error);
+ g_autoptr (GBytes) buf = ot_map_anonymous_tmpfile_from_content (convin, cancellable, error);
if (!buf)
return FALSE;
G_BEGIN_DECLS
-/* Maximum uncompressed size for a single static delta part (512 MiB).
- * Enforced on both generation and consumption sides to prevent
- * decompression bombs from exhausting memory/disk (CVE / RHEL-189208).
- *
- * The delta compiler splits parts at max-chunk-size (default 32 MB), so
- * legitimate parts are typically well under 32 MB uncompressed. 512 MiB
- * provides ~16x headroom over the default, which is generous enough to
- * accommodate large custom --max-chunk-size values while still rejecting
- * decompression bombs that would expand to gigabytes.
- *
- * This is also the sole bound applied to deltas that don't carry the
- * exact-payload-size metadata (see
- * OSTREE_STATIC_DELTA_PART_PAYLOAD_SIZES_KEY below): the declared "usize"
- * in a delta part header only accounts for the final on-disk size of the
- * objects the part will produce, not the mode/xattr tables, opcode
- * bytecode, or raw payload data (including, for bsdiff'd objects, the
- * entire patch stream) that also make up the part's decompressed
- * payload. There is no way to derive a tight, correct bound from usize
- * alone -- a part with a single large bsdiff'd object can have a
- * decompressed payload many times its usize -- so deltas lacking the
- * exact size just fall back to this flat cap.
- */
-#define OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES (512ULL * 1024ULL * 1024ULL)
-
/* 1 byte for object type, 32 bytes for checksum */
#define OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN 33
{ "max-bsdiff-size", 0, 0, G_OPTION_ARG_STRING, &opt_max_bsdiff_size,
"Maximum size in megabytes to consider bsdiff compression for input files", NULL },
{ "max-chunk-size", 0, 0, G_OPTION_ARG_STRING, &opt_max_chunk_size,
- "Maximum size of delta chunks in megabytes (hard cap: 512 MiB)", NULL },
+ "Maximum size of delta chunks in megabytes", NULL },
{ "filename", 0, 0, G_OPTION_ARG_FILENAME, &opt_filename,
"Write the delta content to PATH (a directory). If not specified, the OSTree repository is "
"used",