144 lines
6.6 KiB
Diff
144 lines
6.6 KiB
Diff
From b49f309aa16febeddb65e82526640a91bbba3be3 Mon Sep 17 00:00:00 2001
|
|
From: Patrick Steinhardt <ps@pks.im>
|
|
Date: Thu, 1 Dec 2022 15:46:30 +0100
|
|
Subject: [PATCH] pretty: fix out-of-bounds read when left-flushing with
|
|
stealing
|
|
|
|
With the `%>>(<N>)` pretty formatter, you can ask git-log(1) et al to
|
|
steal spaces. To do so we need to look ahead of the next token to see
|
|
whether there are spaces there. This loop takes into account ANSI
|
|
sequences that end with an `m`, and if it finds any it will skip them
|
|
until it finds the first space. While doing so it does not take into
|
|
account the buffer's limits though and easily does an out-of-bounds
|
|
read.
|
|
|
|
Add a test that hits this behaviour. While we don't have an easy way to
|
|
verify this, the test causes the following failure when run with
|
|
`SANITIZE=address`:
|
|
|
|
==37941==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000000baf at pc 0x55ba6f88e0d0 bp 0x7ffc84c50d20 sp 0x7ffc84c50d10
|
|
READ of size 1 at 0x603000000baf thread T0
|
|
#0 0x55ba6f88e0cf in format_and_pad_commit pretty.c:1712
|
|
#1 0x55ba6f88e7b4 in format_commit_item pretty.c:1801
|
|
#2 0x55ba6f9b1ae4 in strbuf_expand strbuf.c:429
|
|
#3 0x55ba6f88f020 in repo_format_commit_message pretty.c:1869
|
|
#4 0x55ba6f890ccf in pretty_print_commit pretty.c:2161
|
|
#5 0x55ba6f7884c8 in show_log log-tree.c:781
|
|
#6 0x55ba6f78b6ba in log_tree_commit log-tree.c:1117
|
|
#7 0x55ba6f40fed5 in cmd_log_walk_no_free builtin/log.c:508
|
|
#8 0x55ba6f41035b in cmd_log_walk builtin/log.c:549
|
|
#9 0x55ba6f4131a2 in cmd_log builtin/log.c:883
|
|
#10 0x55ba6f2ea993 in run_builtin git.c:466
|
|
#11 0x55ba6f2eb397 in handle_builtin git.c:721
|
|
#12 0x55ba6f2ebb07 in run_argv git.c:788
|
|
#13 0x55ba6f2ec8a7 in cmd_main git.c:923
|
|
#14 0x55ba6f581682 in main common-main.c:57
|
|
#15 0x7f2d08c3c28f (/usr/lib/libc.so.6+0x2328f)
|
|
#16 0x7f2d08c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
|
|
#17 0x55ba6f2e60e4 in _start ../sysdeps/x86_64/start.S:115
|
|
|
|
0x603000000baf is located 1 bytes to the left of 24-byte region [0x603000000bb0,0x603000000bc8)
|
|
allocated by thread T0 here:
|
|
#0 0x7f2d08ebe7ea in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
|
|
#1 0x55ba6fa5b494 in xrealloc wrapper.c:136
|
|
#2 0x55ba6f9aefdc in strbuf_grow strbuf.c:99
|
|
#3 0x55ba6f9b0a06 in strbuf_add strbuf.c:298
|
|
#4 0x55ba6f9b1a25 in strbuf_expand strbuf.c:418
|
|
#5 0x55ba6f88f020 in repo_format_commit_message pretty.c:1869
|
|
#6 0x55ba6f890ccf in pretty_print_commit pretty.c:2161
|
|
#7 0x55ba6f7884c8 in show_log log-tree.c:781
|
|
#8 0x55ba6f78b6ba in log_tree_commit log-tree.c:1117
|
|
#9 0x55ba6f40fed5 in cmd_log_walk_no_free builtin/log.c:508
|
|
#10 0x55ba6f41035b in cmd_log_walk builtin/log.c:549
|
|
#11 0x55ba6f4131a2 in cmd_log builtin/log.c:883
|
|
#12 0x55ba6f2ea993 in run_builtin git.c:466
|
|
#13 0x55ba6f2eb397 in handle_builtin git.c:721
|
|
#14 0x55ba6f2ebb07 in run_argv git.c:788
|
|
#15 0x55ba6f2ec8a7 in cmd_main git.c:923
|
|
#16 0x55ba6f581682 in main common-main.c:57
|
|
#17 0x7f2d08c3c28f (/usr/lib/libc.so.6+0x2328f)
|
|
#18 0x7f2d08c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
|
|
#19 0x55ba6f2e60e4 in _start ../sysdeps/x86_64/start.S:115
|
|
|
|
SUMMARY: AddressSanitizer: heap-buffer-overflow pretty.c:1712 in format_and_pad_commit
|
|
Shadow bytes around the buggy address:
|
|
0x0c067fff8120: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
|
|
0x0c067fff8130: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
|
|
0x0c067fff8140: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
|
|
0x0c067fff8150: fa fa fd fd fd fd fa fa 00 00 00 fa fa fa fd fd
|
|
0x0c067fff8160: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
|
|
=>0x0c067fff8170: fd fd fd fa fa[fa]00 00 00 fa fa fa 00 00 00 fa
|
|
0x0c067fff8180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
|
0x0c067fff8190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
|
0x0c067fff81a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
|
0x0c067fff81b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
|
0x0c067fff81c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
|
Shadow byte legend (one shadow byte represents 8 application bytes):
|
|
Addressable: 00
|
|
Partially addressable: 01 02 03 04 05 06 07
|
|
Heap left redzone: fa
|
|
Freed heap region: fd
|
|
Stack left redzone: f1
|
|
Stack mid redzone: f2
|
|
Stack right redzone: f3
|
|
Stack after return: f5
|
|
Stack use after scope: f8
|
|
Global redzone: f9
|
|
Global init order: f6
|
|
Poisoned by user: f7
|
|
Container overflow: fc
|
|
Array cookie: ac
|
|
Intra object redzone: bb
|
|
ASan internal: fe
|
|
Left alloca redzone: ca
|
|
Right alloca redzone: cb
|
|
|
|
Luckily enough, this would only cause us to copy the out-of-bounds data
|
|
into the formatted commit in case we really had an ANSI sequence
|
|
preceding our buffer. So this bug likely has no security consequences.
|
|
|
|
Fix it regardless by not traversing past the buffer's start.
|
|
|
|
Reported-by: Patrick Steinhardt <ps@pks.im>
|
|
Reported-by: Eric Sesterhenn <eric.sesterhenn@x41-dsec.de>
|
|
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
---
|
|
pretty.c | 2 +-
|
|
t/t4205-log-pretty-formats.sh | 6 ++++++
|
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/pretty.c b/pretty.c
|
|
index a1a01492c1..692a6382a1 100644
|
|
--- a/pretty.c
|
|
+++ b/pretty.c
|
|
@@ -1514,7 +1514,7 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
|
|
if (*ch != 'm')
|
|
break;
|
|
p = ch - 1;
|
|
- while (ch - p < 10 && *p != '\033')
|
|
+ while (p > sb->buf && ch - p < 10 && *p != '\033')
|
|
p--;
|
|
if (*p != '\033' ||
|
|
ch + 1 - p != display_mode_esc_sequence_len(p))
|
|
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
|
|
index fff3e05615..126dc20f23 100755
|
|
--- a/t/t4205-log-pretty-formats.sh
|
|
+++ b/t/t4205-log-pretty-formats.sh
|
|
@@ -867,6 +867,12 @@ test_expect_success 'log --pretty=reference is colored appropriately' '
|
|
test_cmp expect actual
|
|
'
|
|
|
|
+test_expect_success 'log --pretty with space stealing' '
|
|
+ printf mm0 >expect &&
|
|
+ git log -1 --pretty="format:mm%>>|(1)%x30" >actual &&
|
|
+ test_cmp expect actual
|
|
+'
|
|
+
|
|
test_expect_success EXPENSIVE,SIZE_T_IS_64BIT 'log --pretty with huge commit message' '
|
|
# We only assert that this command does not crash. This needs to be
|
|
# executed with the address sanitizer to demonstrate failure.
|
|
--
|
|
2.27.0
|
|
|