Skip to content

Commit 0d0ec52

Browse files
committed
Fix corner cases in readlink() usage.
Make sure all calls are protected by HAVE_READLINK, and get the buffer overflow tests right. Be a bit more paranoid about string length in _tarWriteHeader(), too.
1 parent 0d9b092 commit 0d0ec52

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

src/backend/replication/basebackup.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static int64 sendDir(char *path, int basepathlen, bool sizeonly);
4747
static void sendFile(char *readfilename, char *tarfilename,
4848
struct stat * statbuf);
4949
static void sendFileWithContent(const char *filename, const char *content);
50-
static void _tarWriteHeader(const char *filename, char *linktarget,
50+
static void _tarWriteHeader(const char *filename, const char *linktarget,
5151
struct stat * statbuf);
5252
static void send_int8_string(StringInfoData *buf, int64 intval);
5353
static void SendBackupHeader(List *tablespaces);
@@ -118,17 +118,19 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
118118
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
119119

120120
#if defined(HAVE_READLINK) || defined(WIN32)
121-
rllen = readlink(fullpath, linkpath, sizeof(linkpath) - 1);
121+
rllen = readlink(fullpath, linkpath, sizeof(linkpath));
122122
if (rllen < 0)
123123
{
124124
ereport(WARNING,
125-
(errmsg("could not read symbolic link \"%s\": %m", fullpath)));
125+
(errmsg("could not read symbolic link \"%s\": %m",
126+
fullpath)));
126127
continue;
127128
}
128129
else if (rllen >= sizeof(linkpath))
129130
{
130131
ereport(WARNING,
131-
(errmsg("symbolic link \"%s\" target is too long", fullpath)));
132+
(errmsg("symbolic link \"%s\" target is too long",
133+
fullpath)));
132134
continue;
133135
}
134136
linkpath[rllen] = '\0';
@@ -140,9 +142,9 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
140142
tablespaces = lappend(tablespaces, ti);
141143
#else
142144
/*
143-
* If the platform does not have symbolic links, it should not be possible
144-
* to have tablespaces - clearly somebody else created them. Warn about it
145-
* and ignore.
145+
* If the platform does not have symbolic links, it should not be
146+
* possible to have tablespaces - clearly somebody else created
147+
* them. Warn about it and ignore.
146148
*/
147149
ereport(WARNING,
148150
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -641,24 +643,45 @@ sendDir(char *path, int basepathlen, bool sizeonly)
641643
continue; /* don't recurse into pg_xlog */
642644
}
643645

646+
/* Allow symbolic links in pg_tblspc only */
647+
if (strcmp(path, "./pg_tblspc") == 0 &&
644648
#ifndef WIN32
645-
if (S_ISLNK(statbuf.st_mode) && strcmp(path, "./pg_tblspc") == 0)
649+
S_ISLNK(statbuf.st_mode)
646650
#else
647-
if (pgwin32_is_junction(pathbuf) && strcmp(path, "./pg_tblspc") == 0)
651+
pgwin32_is_junction(pathbuf)
648652
#endif
653+
)
649654
{
650-
/* Allow symbolic links in pg_tblspc */
655+
#if defined(HAVE_READLINK) || defined(WIN32)
651656
char linkpath[MAXPGPATH];
657+
int rllen;
652658

653-
MemSet(linkpath, 0, sizeof(linkpath));
654-
if (readlink(pathbuf, linkpath, sizeof(linkpath) - 1) == -1)
659+
rllen = readlink(pathbuf, linkpath, sizeof(linkpath));
660+
if (rllen < 0)
655661
ereport(ERROR,
656662
(errcode_for_file_access(),
657663
errmsg("could not read symbolic link \"%s\": %m",
658664
pathbuf)));
665+
if (rllen >= sizeof(linkpath))
666+
ereport(ERROR,
667+
(errmsg("symbolic link \"%s\" target is too long",
668+
pathbuf)));
669+
linkpath[rllen] = '\0';
670+
659671
if (!sizeonly)
660672
_tarWriteHeader(pathbuf + basepathlen + 1, linkpath, &statbuf);
661673
size += 512; /* Size of the header just added */
674+
#else
675+
/*
676+
* If the platform does not have symbolic links, it should not be
677+
* possible to have tablespaces - clearly somebody else created
678+
* them. Warn about it and ignore.
679+
*/
680+
ereport(WARNING,
681+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
682+
errmsg("tablespaces are not supported on this platform")));
683+
continue;
684+
#endif /* HAVE_READLINK */
662685
}
663686
else if (S_ISDIR(statbuf.st_mode))
664687
{
@@ -806,7 +829,8 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
806829

807830

808831
static void
809-
_tarWriteHeader(const char *filename, char *linktarget, struct stat * statbuf)
832+
_tarWriteHeader(const char *filename, const char *linktarget,
833+
struct stat * statbuf)
810834
{
811835
char h[512];
812836
int lastSum = 0;
@@ -854,7 +878,7 @@ _tarWriteHeader(const char *filename, char *linktarget, struct stat * statbuf)
854878
{
855879
/* Type - Symbolic link */
856880
sprintf(&h[156], "2");
857-
strcpy(&h[157], linktarget);
881+
sprintf(&h[157], "%.99s", linktarget);
858882
}
859883
else if (S_ISDIR(statbuf->st_mode))
860884
/* Type - directory */

src/backend/utils/adt/misc.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
274274
int rllen;
275275

276276
/*
277-
* Return empty string for our two default tablespace
277+
* Return empty string for our default tablespaces
278278
*/
279279
if (tablespaceOid == DEFAULTTABLESPACE_OID ||
280280
tablespaceOid == GLOBALTABLESPACE_OID)
@@ -286,20 +286,24 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
286286
* in pg_tblspc/<oid>.
287287
*/
288288
snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
289-
rllen =readlink(sourcepath, targetpath, sizeof(targetpath));
289+
290+
rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
290291
if (rllen < 0)
291292
ereport(ERROR,
292-
(errmsg("could not read symbolic link \"%s\": %m", sourcepath)));
293+
(errmsg("could not read symbolic link \"%s\": %m",
294+
sourcepath)));
293295
else if (rllen >= sizeof(targetpath))
294296
ereport(ERROR,
295-
(errmsg("symbolic link \"%s\" target is too long", sourcepath)));
297+
(errmsg("symbolic link \"%s\" target is too long",
298+
sourcepath)));
296299
targetpath[rllen] = '\0';
297300

298301
PG_RETURN_TEXT_P(cstring_to_text(targetpath));
299302
#else
300303
ereport(ERROR,
301304
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
302305
errmsg("tablespaces are not supported on this platform")));
306+
PG_RETURN_NULL();
303307
#endif
304308
}
305309

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy