diff options
author | Masahiko Sawada <msawada@postgresql.org> | 2025-03-11 09:56:40 -0700 |
---|---|---|
committer | Masahiko Sawada <msawada@postgresql.org> | 2025-03-11 09:56:40 -0700 |
commit | bd65cb3cd48a7a5ce48b26f8031ad3968efed87e (patch) | |
tree | fd6ae91a937707f9ab4adefb93ea1cd3a940e4da /src | |
parent | a49927f04cd0c66e1bc41f551160fce50f382d8c (diff) | |
download | postgresql-bd65cb3cd48a7a5ce48b26f8031ad3968efed87e.tar.gz postgresql-bd65cb3cd48a7a5ce48b26f8031ad3968efed87e.zip |
pg_logicalinspect: Fix possible crash when passing a directory path.
Previously, pg_logicalinspect functions were too trusting of their
input and blindly passed it to SnapBuildRestoreSnapshot(). If the
input pointed to a directory, the server could a PANIC error while
attempting to fsync_fname() with isdir=false on a directory.
This commit adds validation checks for input filenames and passes the
LSN extracted from the filename to SnapBuildRestoreSnapshot() instead
of the filename itself. It also adds regression tests for various
input patterns and permission checks.
Bug: #18828
Reported-by: Robins Tharakan <tharakan@gmail.com>
Co-authored-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Co-authored-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/18828-0f4701c635064211@postgresql.org
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/replication/logical/snapbuild.c | 14 | ||||
-rw-r--r-- | src/include/replication/snapbuild_internal.h | 2 |
2 files changed, 8 insertions, 8 deletions
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index bd0680dcbe5..b64e53de017 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1691,12 +1691,17 @@ out: * If 'missing_ok' is true, will not throw an error if the file is not found. */ bool -SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, const char *path, +SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, XLogRecPtr lsn, MemoryContext context, bool missing_ok) { int fd; pg_crc32c checksum; Size sz; + char path[MAXPGPATH]; + + sprintf(path, "%s/%X-%X.snap", + PG_LOGICAL_SNAPSHOTS_DIR, + LSN_FORMAT_ARGS(lsn)); fd = OpenTransientFile(path, O_RDONLY | PG_BINARY); @@ -1788,18 +1793,13 @@ static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) { SnapBuildOnDisk ondisk; - char path[MAXPGPATH]; /* no point in loading a snapshot if we're already there */ if (builder->state == SNAPBUILD_CONSISTENT) return false; - sprintf(path, "%s/%X-%X.snap", - PG_LOGICAL_SNAPSHOTS_DIR, - LSN_FORMAT_ARGS(lsn)); - /* validate and restore the snapshot to 'ondisk' */ - if (!SnapBuildRestoreSnapshot(&ondisk, path, builder->context, true)) + if (!SnapBuildRestoreSnapshot(&ondisk, lsn, builder->context, true)) return false; /* diff --git a/src/include/replication/snapbuild_internal.h b/src/include/replication/snapbuild_internal.h index 081b01b890a..3b915dc8793 100644 --- a/src/include/replication/snapbuild_internal.h +++ b/src/include/replication/snapbuild_internal.h @@ -193,7 +193,7 @@ typedef struct SnapBuildOnDisk /* variable amount of TransactionIds follows */ } SnapBuildOnDisk; -extern bool SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, const char *path, +extern bool SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, XLogRecPtr lsn, MemoryContext context, bool missing_ok); #endif /* SNAPBUILD_INTERNAL_H */ |