Skip to content

Commit 5955208

Browse files
committed
[BACKPORT 2025.1][yugabyte#26547] YSQL: Fix use after free in ysql_dump by using pg_strdup for tablegroup_name
Summary: As part of D36859 / 0dbe7d6, backup and restore support for colocated tables when multiple tablespaces exist was introduced. Upon fetching the tablegroup_name from `pg_yb_tablegroup`, the value was read and assigned via `PQgetvalue` without copying. This led to a use-after-free bug when the tablegroup_name was later read in dumpTableSchema since the result from the SQL query is immediately cleared in the next line (`PQclear`). ``` [P-yb-controller-1] ==3037==ERROR: AddressSanitizer: heap-use-after-free on address 0x51d0002013e6 at pc 0x55615b0a1f92 bp 0x7fff92475970 sp 0x7fff92475118 [P-yb-controller-1] READ of size 8 at 0x51d0002013e6 thread T0 [P-yb-controller-1] #0 0x55615b0a1f91 in strcmp ${YB_LLVM_TOOLCHAIN_DIR}/src/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:470:5 [P-yb-controller-1] #1 0x55615b1b90ba in dumpTableSchema ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15789:8 [P-yb-controller-1] #2 0x55615b178163 in dumpTable ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15299:4 [P-yb-controller-1] #3 0x55615b178163 in dumpDumpableObject ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:10216:4 [P-yb-controller-1] #4 0x55615b178163 in main ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:1019:3 [P-yb-controller-1] #5 0x7f3c0184e7e4 in __libc_start_main (/lib64/libc.so.6+0x3a7e4) (BuildId: fd70eb98f80391a177070fcb8d757a63fe49b802) [P-yb-controller-1] #6 0x55615b0894bd in _start (${BUILD_ROOT}/postgres/bin/ysql_dump+0x10d4bd) [P-yb-controller-1] [P-yb-controller-1] 0x51d0002013e6 is located 358 bytes inside of 2048-byte region [0x51d000201280,0x51d000201a80) [P-yb-controller-1] freed by thread T0 here: [P-yb-controller-1] #0 0x55615b127196 in free ${YB_LLVM_TOOLCHAIN_DIR}/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 [P-yb-controller-1] #1 0x7f3c02d65e85 in PQclear ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:755:3 [P-yb-controller-1] #2 0x55615b1c0103 in getYbTablePropertiesAndReloptions ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:19108:4 [P-yb-controller-1] #3 0x55615b1b8fab in dumpTableSchema ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15765:3 [P-yb-controller-1] #4 0x55615b178163 in dumpTable ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15299:4 [P-yb-controller-1] #5 0x55615b178163 in dumpDumpableObject ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:10216:4 [P-yb-controller-1] #6 0x55615b178163 in main ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:1019:3 [P-yb-controller-1] #7 0x7f3c0184e7e4 in __libc_start_main (/lib64/libc.so.6+0x3a7e4) (BuildId: fd70eb98f80391a177070fcb8d757a63fe49b802) [P-yb-controller-1] [P-yb-controller-1] previously allocated by thread T0 here: [P-yb-controller-1] #0 0x55615b12742f in malloc ${YB_LLVM_TOOLCHAIN_DIR}/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3 [P-yb-controller-1] #1 0x7f3c02d680a7 in pqResultAlloc ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:633:28 [P-yb-controller-1] #2 0x7f3c02d81294 in getRowDescriptions ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-protocol3.c:544:4 [P-yb-controller-1] #3 0x7f3c02d7f793 in pqParseInput3 ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-protocol3.c:324:11 [P-yb-controller-1] #4 0x7f3c02d6bcc8 in parseInput ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:2014:2 [P-yb-controller-1] #5 0x7f3c02d6bcc8 in PQgetResult ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:2100:3 [P-yb-controller-1] #6 0x7f3c02d6cd87 in PQexecFinish ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:2417:19 [P-yb-controller-1] #7 0x7f3c02d6cd87 in PQexec ${YB_SRC_ROOT}/src/postgres/src/interfaces/libpq/fe-exec.c:2256:9 [P-yb-controller-1] yugabyte#8 0x55615b1f45df in ExecuteSqlQuery ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_backup_db.c:296:8 [P-yb-controller-1] yugabyte#9 0x55615b1f4213 in ExecuteSqlQueryForSingleRow ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_backup_db.c:311:8 [P-yb-controller-1] yugabyte#10 0x55615b1c008d in getYbTablePropertiesAndReloptions ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:19102:10 [P-yb-controller-1] yugabyte#11 0x55615b1b8fab in dumpTableSchema ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15765:3 [P-yb-controller-1] yugabyte#12 0x55615b178163 in dumpTable ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:15299:4 [P-yb-controller-1] yugabyte#13 0x55615b178163 in dumpDumpableObject ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:10216:4 [P-yb-controller-1] yugabyte#14 0x55615b178163 in main ${YB_SRC_ROOT}/src/postgres/src/bin/pg_dump/pg_dump.c:1019:3 [P-yb-controller-1] yugabyte#15 0x7f3c0184e7e4 in __libc_start_main (/lib64/libc.so.6+0x3a7e4) (BuildId: fd70eb98f80391a177070fcb8d757a63fe49b802) ``` This revision fixes the issue by using pg_strdup to make a copy of the string. Jira: DB-15915 Original commit: 7eea1de / D43386 Test Plan: ./yb_build.sh asan --cxx-test integration-tests_xcluster_ddl_replication-test --gtest_filter XClusterDDLReplicationTest.DDLReplicationTablesNotColocated Reviewers: aagrawal, skumar, mlillibridge, sergei Reviewed By: aagrawal Subscribers: yql, sergei Differential Revision: https://phorge.dev.yugabyte.com/D43421
1 parent 4c1f1f4 commit 5955208

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/postgres/src/bin/pg_dump/pg_dump.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15772,6 +15772,17 @@ dumpTablegroup(Archive *fout, const YbTablegroupInfo *tginfo)
1577215772
free(namecopy);
1577315773
}
1577415774

15775+
static void
15776+
freeYbcTablePropertiesIfRequired(YbcTableProperties yb_properties)
15777+
{
15778+
if (!yb_properties)
15779+
return;
15780+
15781+
if (yb_properties->tablegroup_name)
15782+
free(yb_properties->tablegroup_name);
15783+
free(yb_properties);
15784+
}
15785+
1577515786
/*
1577615787
* dumpTableSchema
1577715788
* write the declaration (not data) of one user-defined table or view
@@ -15946,7 +15957,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1594615957
(tbinfo->relkind == RELKIND_RELATION || tbinfo->relkind == RELKIND_INDEX
1594715958
|| tbinfo->relkind == RELKIND_MATVIEW || tbinfo->relkind == RELKIND_PARTITIONED_TABLE))
1594815959
{
15949-
yb_properties = (YbcTableProperties) pg_malloc(sizeof(YbcTablePropertiesData));
15960+
yb_properties = (YbcTableProperties) pg_malloc0(sizeof(YbcTablePropertiesData));
1595015961
}
1595115962
PQExpBuffer yb_reloptions = createPQExpBuffer();
1595215963

@@ -16628,6 +16639,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1662816639
free(ftoptions);
1662916640
if (srvname)
1663016641
free(srvname);
16642+
16643+
freeYbcTablePropertiesIfRequired(yb_properties);
1663116644
}
1663216645

1663316646
/*
@@ -16943,7 +16956,7 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
1694316956
{
1694416957
YbcTableProperties yb_properties;
1694516958

16946-
yb_properties = (YbcTableProperties) pg_malloc(sizeof(YbcTablePropertiesData));
16959+
yb_properties = (YbcTableProperties) pg_malloc0(sizeof(YbcTablePropertiesData));
1694716960
PQExpBuffer yb_reloptions = createPQExpBuffer();
1694816961

1694916962
getYbTablePropertiesAndReloptions(fout, yb_properties,
@@ -16968,6 +16981,8 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
1696816981
}
1696916982
}
1697016983
destroyPQExpBuffer(yb_reloptions);
16984+
16985+
freeYbcTablePropertiesIfRequired(yb_properties);
1697116986
}
1697216987
/* Plain secondary index */
1697316988
appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
@@ -19291,7 +19306,7 @@ getYbTablePropertiesAndReloptions(Archive *fout, YbcTableProperties properties,
1929119306
int i_grpname = PQfnumber(res, "grpname");
1929219307

1929319308
properties->tablegroup_name =
19294-
PQgetisnull(res, 0, i_grpname) ? "" : PQgetvalue(res, 0, i_grpname);
19309+
PQgetisnull(res, 0, i_grpname) ? pg_strdup("") : pg_strdup(PQgetvalue(res, 0, i_grpname));
1929519310

1929619311
PQclear(res);
1929719312
destroyPQExpBuffer(query);

0 commit comments

Comments
 (0)