char *to_revision;
guint i;
guint64 size;
+ guint64 usize;
guint n_retries_remaining;
} FetchStaticDeltaData;
in = g_unix_input_stream_new (g_steal_fd (&tmpf.fd), TRUE);
/* TODO - make async */
- if (!_ostree_static_delta_part_open (in, NULL, 0, fetch_data->expected_checksum, &part,
- pull_data->cancellable, error))
+ if (!_ostree_static_delta_part_open (in, NULL, 0, fetch_data->expected_checksum,
+ fetch_data->usize, &part, pull_data->cancellable, error))
goto out;
_ostree_static_delta_part_execute_async (pull_data->repo, fetch_data->objects, part,
fetch_data->objects = g_variant_ref (objects);
fetch_data->expected_checksum = ostree_checksum_from_bytes_v (csum_v);
fetch_data->size = size;
+ fetch_data->usize = usize;
fetch_data->i = i;
fetch_data->n_retries_remaining = pull_data->n_network_retries;
/* For inline parts we are relying on per-commit GPG, so don't bother checksumming. */
if (!_ostree_static_delta_part_open (memin, inline_part_bytes,
OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM, NULL,
- &inline_delta_part, cancellable, error))
+ usize, &inline_delta_part, cancellable, error))
{
fetch_static_delta_data_free (fetch_data);
return FALSE;
delta_open_flags |= OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM;
if (!_ostree_static_delta_part_open (part_in, inline_part_bytes, delta_open_flags, NULL,
- &part, cancellable, error))
+ usize, &part, cancellable, error))
return FALSE;
}
else
part_in = g_unix_input_stream_new (part_fd, FALSE);
- if (!_ostree_static_delta_part_open (part_in, NULL, delta_open_flags, checksum, &part,
- cancellable, error))
+ if (!_ostree_static_delta_part_open (part_in, NULL, delta_open_flags, checksum, usize,
+ &part, cancellable, error))
return FALSE;
}
gboolean
_ostree_static_delta_part_open (GInputStream *part_in, GBytes *inline_part_bytes,
OstreeStaticDeltaOpenFlags flags, const char *expected_checksum,
- GVariant **out_part, GCancellable *cancellable, GError **error)
+ guint64 expected_usize, GVariant **out_part,
+ GCancellable *cancellable, GError **error)
{
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;
+ /* Use the declared usize from the delta header as the decompression limit
+ * when available, capped to the hard maximum. If the caller passes 0
+ * (e.g. the show/dump path) fall back to the hard cap alone.
+ */
+ guint64 max_part_usize = OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES;
+ if (expected_usize > 0 && expected_usize < max_part_usize)
+ max_part_usize = expected_usize;
+
/* 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 same size limit as for compressed parts so that an
- * attacker cannot bypass the decompression-bomb defence simply by
- * setting compression type to 0 (CVE / RHEL-189208).
+ /* 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) > OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES)
- return glnx_throw (
- error,
- "Uncompressed delta part size %" G_GSIZE_FORMAT " exceeds maximum %" G_GUINT64_FORMAT,
- g_variant_get_size (ret_part), (guint64)OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES);
+ 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, OSTREE_STATIC_DELTA_PART_MAX_USIZE_BYTES, cancellable, error);
+ convin, max_part_usize, cancellable, error);
if (!buf)
return FALSE;
g_autoptr (GVariant) part = NULL;
if (!_ostree_static_delta_part_open (part_in, NULL, OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM,
- NULL, &part, cancellable, error))
+ NULL, 0, &part, cancellable, error))
return FALSE;
{