BUG #19452: heap-buffer-overflow in `pg_basebackup --format=tar --gzip`

Поиск
Список
Период
Сортировка
От PG Bug reporting form
Тема BUG #19452: heap-buffer-overflow in `pg_basebackup --format=tar --gzip`
Дата
Msg-id 19452-4e6c86f7c5eb55ac@postgresql.org
обсуждение исходный текст
Ответы Re: BUG #19452: heap-buffer-overflow in `pg_basebackup --format=tar --gzip`
Список pgsql-bugs
The following bug has been logged on the website:

Bug reference:      19452
Logged by:          Alexander Kurdakov
Email address:      alexander.kurdakov@tantorlabs.ru
PostgreSQL version: 18.0
Operating system:   Ubuntu 22.04.5 LTS
Description:

Build (based on Cirrus CI ASan task configuration):

./configure \
  --prefix=$(pwd)/build \
  --enable-cassert \
  --enable-tap-tests \
  --enable-debug \
  CFLAGS="-Og -ggdb -fno-sanitize-recover=all -fsanitize=address" \
  LDFLAGS="-fsanitize=address"

make -j$(nproc)
make install

export PATH=$(pwd)/build/bin:$PATH
export
ASAN_OPTIONS="print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0"

Reproduction:

initdb -D /tmp/pgdata
pg_ctl -D /tmp/pgdata -l /tmp/pg.log start

pg_basebackup --format=tar --gzip -X fetch --write-recovery-conf \
  -D /tmp/backup --no-sync --checkpoint=fast

ASan output:

==192019==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x5120000002e1 at pc 0x59338d50dc17 bp 0x7ffe6e687f50 sp 0x7ffe6e6876f8
READ of size 287 at 0x5120000002e1 thread T0
    #0 __interceptor_memcpy (pg_basebackup+0x9ec16)
    #1 (/lib/x86_64-linux-gnu/libz.so.1+0x12050)
    #2 gzwrite (/lib/x86_64-linux-gnu/libz.so.1+0x12219)
    #3 astreamer_gzip_writer_content astreamer_gzip.c:162
    #4 astreamer_content astreamer.h:140
    #5 astreamer_tar_archiver_content astreamer_tar.c:435
    #6 astreamer_content astreamer.h:140
    #7 astreamer_tar_parser_content astreamer_tar.c:225
    #8 astreamer_content astreamer.h:140
    #9 ReceiveArchiveStreamChunk pg_basebackup.c:1441
    #10 ReceiveCopyData pg_basebackup.c:1046

0x5120000002e1 is located 0 bytes to the right of 289-byte region
allocated by pqGetCopyData3 (fe-protocol3.c:1931)

Analysis:

In astreamer_tar_parser_content(), the ASTREAMER_MEMBER_TRAILER case
passes the wrong pointer to astreamer_content().

astreamer_buffer_until() accumulates padding bytes into bbs_buffer and
advances *data past the consumed bytes. The server always sends tar
padding as a separate CopyData message (_tarWritePadding calls
bbsink_archive_contents with exactly pad_bytes bytes), so after
buffering, *data points one byte past the end of the malloc'd
PQgetCopyData() buffer.

The code passes this stale *data pointer instead of
streamer->bbs_buffer.data. The downstream gzip writer's deflate()
then reads pad_bytes bytes of out-of-bounds memory.

Any file whose size is not a multiple of 512 triggers this.
PG_VERSION (3 bytes, padding=509) and postgresql.auto.conf (88 bytes,
padding=424) are present in every initdb, so the overflow happens on
every run with the flags above.

Fix (pass bbs_buffer.data instead of data):

--- a/src/fe_utils/astreamer_tar.c
+++ b/src/fe_utils/astreamer_tar.c
@@ -222,7 +222,8 @@
                        /* OK, now we can send it. */
                        astreamer_content(mystreamer->base.bbs_next,
&mystreamer->member,
-                                                         data,
mystreamer->pad_bytes_expected,
+
mystreamer->base.bbs_buffer.data,
+
mystreamer->pad_bytes_expected,
ASTREAMER_MEMBER_TRAILER);





В списке pgsql-bugs по дате отправления: