Git development
 help / color / mirror / Atom feed
From: Toon Claes <toon@iotcl.com>
To: Patrick Steinhardt <ps@pks.im>, git@vger.kernel.org
Cc: oxsignal <awo@kakao.com>, Christian Couder <chriscool@tuxfamily.org>
Subject: Re: [PATCH v2 07/12] reftable/block: fix OOB read with bogus block size
Date: Fri, 03 Jul 2026 11:28:21 +0200	[thread overview]
Message-ID: <87wlvc2zii.fsf@emacs.iotcl.com> (raw)
In-Reply-To: <20260629-pks-reftable-hardening-v2-7-b0228e7d908d@pks.im>

Patrick Steinhardt <ps@pks.im> writes:

> The block size is read from the block header, which is untrusted data.
> We use it without verification to access the restart count at the end of
> the block as well as to compute the restart table offset. With a bogus
> block size that exceeds the data we have actually read this can lead to
> an out-of-bounds read:
>
>   ==1458284==ERROR: AddressSanitizer: SEGV on unknown address 0x7d8ff7de4b7d (pc 0x55555598c339 bp 0x7fffffff4ef0 sp 0x7fffffff4eb0 T0)
>   ==1458284==The signal is caused by a READ memory access.
>       #0 0x55555598c339 in reftable_get_be16 ./build/../reftable/basics.h:118:9
>       #1 0x55555598bee2 in reftable_block_init ./build/../reftable/block.c:344:18
>       #2 0x555555813e0e in test_reftable_block__corrupt_block_size ./build/../t/unit-tests/u-reftable-block.c:540:8
>       #3 0x5555557f684e in clar_run_test ./build/../t/unit-tests/clar/clar.c:335:3
>       #4 0x5555557f2e69 in clar_run_suite ./build/../t/unit-tests/clar/clar.c:431:3
>       #5 0x5555557f2882 in clar_test_run ./build/../t/unit-tests/clar/clar.c:636:4
>       #6 0x5555557f375f in clar_test ./build/../t/unit-tests/clar/clar.c:687:11
>       #7 0x5555557fa49d in cmd_main ./build/../t/unit-tests/unit-test.c:62:8
>       #8 0x55555584b55a in main ./build/../common-main.c:9:11
>       #9 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b284) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
>       #10 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b337) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
>       #11 0x555555694c24 in _start (./build/t/unit-tests+0x140c24)
>
>   ==1458284==Register values:
>   rax = 0x00007d8ff7de4b7d  rbx = 0x00007fffffff4f00  rcx = 0x0000000000000006  rdx = 0x0000000000000010
>   rdi = 0x00007d8ff7de4b7d  rsi = 0x00007bfff5cf0420  rbp = 0x00007fffffff4ef0  rsp = 0x00007fffffff4eb0
>    r8 = 0x00000f807eb960b8   r9 = 0x0000000000000001  r10 = 0x00007bfff5cf05e7  r11 = 0x000000000000000f
>   r12 = 0x00007fffffff58f8  r13 = 0x0000000000000001  r14 = 0x0000555555ee8160  r15 = 0x0000000000000000
>   AddressSanitizer can not provide additional info.
>
> Verify that the claimed block size fits into the block data before using
> it.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  reftable/block.c                |  9 +++++++++
>  t/unit-tests/u-reftable-block.c | 33 +++++++++++++++++++++++++++++++++
>  2 files changed, 42 insertions(+)
>
> diff --git a/reftable/block.c b/reftable/block.c
> index b86cb9ec5a..4d6b11c2e7 100644
> --- a/reftable/block.c
> +++ b/reftable/block.c
> @@ -340,6 +340,15 @@ int reftable_block_init(struct reftable_block *block,
>  		full_block_size = block_size;
>  	}
>  
> +	/*
> +	 * Ensure that we have sufficient data available now to satisfy the
> +	 * claimed block size.
> +	 */
> +	if (block_size > block->block_data.len) {
> +		err = REFTABLE_FORMAT_ERROR;
> +		goto done;
> +	}
> +
>  	restart_count = reftable_get_be16(block->block_data.data + block_size - 2);
>  	restart_off = block_size - 2 - 3 * restart_count;
>  
> diff --git a/t/unit-tests/u-reftable-block.c b/t/unit-tests/u-reftable-block.c
> index 088162483e..43b9d5fb59 100644
> --- a/t/unit-tests/u-reftable-block.c
> +++ b/t/unit-tests/u-reftable-block.c
> @@ -497,3 +497,36 @@ void test_reftable_block__corrupt_log_block_size(void)
>  	reftable_block_release(&block);
>  	reftable_buf_release(&data);
>  }
> +
> +void test_reftable_block__corrupt_block_size(void)
> +{
> +	struct reftable_block_source source = { 0 };
> +	struct reftable_record rec = {
> +		.type = REFTABLE_BLOCK_TYPE_REF,
> +		.u.ref = {
> +			.value_type = REFTABLE_REF_VAL1,
> +			.refname = (char *) "refs/heads/main",
> +		},
> +	};
> +	struct reftable_block block = { 0 };
> +	struct reftable_buf data = REFTABLE_BUF_INIT;
> +
> +	cl_reftable_write_block(&data, REFTABLE_BLOCK_TYPE_REF, &rec, 1);
> +
> +	/*
> +	 * The block size is stored as a big-endian 24-bit integer right after
> +	 * the one-byte block type at the start of the block. Corrupt it to
> +	 * claim a size that is larger than the data we actually have. Reading
> +	 * the restart count and restart table relative to such a bogus block
> +	 * size must not access out-of-bounds memory.
> +	 */
> +	reftable_put_be24((uint8_t *) data.buf + 1, 0xffffff);

Same here, would it make sense to write a size that's `+1` too much?

	uint8_t *p = (uint8_t *)data.buf + 1;
	uint32_t block_size = reftable_get_be24(p);
	cl_assert_equal_i(block_size, 47);
	reftable_put_be24(p, block_size + 1);


> +
> +	block_source_from_buf(&source, &data);
> +	cl_assert_equal_i(reftable_block_init(&block, &source, 0, 0, data.len,
> +					      REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF),
> +			  REFTABLE_FORMAT_ERROR);
> +
> +	reftable_block_release(&block);
> +	reftable_buf_release(&data);
> +}
>
> -- 
> 2.55.0.rc2.803.g1fd1e6609c.dirty
>
>

-- 
Cheers,
Toon

  reply	other threads:[~2026-07-03  9:28 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-24  8:23 [PATCH 00/11] reftable: harden against corrupted tables Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 01/11] meson: support building fuzzers with libFuzzer Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 02/11] oss-fuzz: add fuzzer for parsing reftables Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 03/11] reftable/basics: fix OOB read on binary search of empty range Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 04/11] reftable/record: don't abort when decoding invalid ref value type Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 05/11] reftable/block: fix OOB write with bogus inflated log size Patrick Steinhardt
2026-06-26  7:48   ` Christian Couder
2026-06-29  7:08     ` Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 06/11] reftable/block: fix OOB read with bogus block size Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 07/11] reftable/block: fix OOB read with bogus restart count Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 08/11] reftable/block: fix use of uninitialized memory when binsearch fails Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 09/11] reftable/block: fix OOB read with bogus restart offset Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 10/11] reftable/table: fix NULL pointer access when seeking to bogus offsets Patrick Steinhardt
2026-06-24  8:23 ` [PATCH 11/11] reftable/table: fix OOB read on truncated table Patrick Steinhardt
2026-06-29  9:02 ` [PATCH v2 00/12] reftable: harden against corrupted tables Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 01/12] meson: support building fuzzers with libFuzzer Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 02/12] oss-fuzz: add fuzzer for parsing reftables Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 03/12] reftable/basics: fix OOB read on binary search of empty range Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 04/12] reftable/record: don't abort when decoding invalid ref value type Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 05/12] t/unit-tests: introduce test helper to write reftable blocks Patrick Steinhardt
2026-06-30 17:25     ` Junio C Hamano
2026-07-02  9:31     ` Christian Couder
2026-07-03  2:52       ` Junio C Hamano
2026-06-29  9:02   ` [PATCH v2 06/12] reftable/block: fix OOB write with bogus inflated log size Patrick Steinhardt
2026-07-03  9:23     ` Toon Claes
2026-07-03 10:32       ` Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 07/12] reftable/block: fix OOB read with bogus block size Patrick Steinhardt
2026-07-03  9:28     ` Toon Claes [this message]
2026-07-03 10:32       ` Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 08/12] reftable/block: fix OOB read with bogus restart count Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 09/12] reftable/block: fix use of uninitialized memory when binsearch fails Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 10/12] reftable/block: fix OOB read with bogus restart offset Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 11/12] reftable/table: fix NULL pointer access when seeking to bogus offsets Patrick Steinhardt
2026-06-29  9:02   ` [PATCH v2 12/12] reftable/table: fix OOB read on truncated table Patrick Steinhardt
2026-07-03 12:58 ` [PATCH v3 00/12] reftable: harden against corrupted tables Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 01/12] meson: support building fuzzers with libFuzzer Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 02/12] oss-fuzz: add fuzzer for parsing reftables Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 03/12] reftable/basics: fix OOB read on binary search of empty range Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 04/12] reftable/record: don't abort when decoding invalid ref value type Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 05/12] t/unit-tests: introduce test helper to write reftable blocks Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 06/12] reftable/block: fix OOB write with bogus inflated log size Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 07/12] reftable/block: fix OOB read with bogus block size Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 08/12] reftable/block: fix OOB read with bogus restart count Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 09/12] reftable/block: fix use of uninitialized memory when binsearch fails Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 10/12] reftable/block: fix OOB read with bogus restart offset Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 11/12] reftable/table: fix NULL pointer access when seeking to bogus offsets Patrick Steinhardt
2026-07-03 12:58   ` [PATCH v3 12/12] reftable/table: fix OOB read on truncated table Patrick Steinhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87wlvc2zii.fsf@emacs.iotcl.com \
    --to=toon@iotcl.com \
    --cc=awo@kakao.com \
    --cc=chriscool@tuxfamily.org \
    --cc=git@vger.kernel.org \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox