Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 85d85ff

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 9c32da5 commit 85d85ff

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

src/backend/replication/basebackup.c

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

119119
#if defined(HAVE_READLINK) || defined(WIN32)
120-
rllen = readlink(fullpath, linkpath, sizeof(linkpath) - 1);
120+
rllen = readlink(fullpath, linkpath, sizeof(linkpath));
121121
if (rllen < 0)
122122
{
123123
ereport(WARNING,
124-
(errmsg("could not read symbolic link \"%s\": %m", fullpath)));
124+
(errmsg("could not read symbolic link \"%s\": %m",
125+
fullpath)));
125126
continue;
126127
}
127128
else if (rllen >= sizeof(linkpath))
128129
{
129130
ereport(WARNING,
130-
(errmsg("symbolic link \"%s\" target is too long", fullpath)));
131+
(errmsg("symbolic link \"%s\" target is too long",
132+
fullpath)));
131133
continue;
132134
}
133135
linkpath[rllen] = '\0';
@@ -139,9 +141,9 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
139141
tablespaces = lappend(tablespaces, ti);
140142
#else
141143
/*
142-
* If the platform does not have symbolic links, it should not be possible
143-
* to have tablespaces - clearly somebody else created them. Warn about it
144-
* and ignore.
144+
* If the platform does not have symbolic links, it should not be
145+
* possible to have tablespaces - clearly somebody else created
146+
* them. Warn about it and ignore.
145147
*/
146148
ereport(WARNING,
147149
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -635,24 +637,45 @@ sendDir(char *path, int basepathlen, bool sizeonly)
635637
continue; /* don't recurse into pg_xlog */
636638
}
637639

640+
/* Allow symbolic links in pg_tblspc only */
641+
if (strcmp(path, "./pg_tblspc") == 0 &&
638642
#ifndef WIN32
639-
if (S_ISLNK(statbuf.st_mode) && strcmp(path, "./pg_tblspc") == 0)
643+
S_ISLNK(statbuf.st_mode)
640644
#else
641-
if (pgwin32_is_junction(pathbuf) && strcmp(path, "./pg_tblspc") == 0)
645+
pgwin32_is_junction(pathbuf)
642646
#endif
647+
)
643648
{
644-
/* Allow symbolic links in pg_tblspc */
649+
#if defined(HAVE_READLINK) || defined(WIN32)
645650
char linkpath[MAXPGPATH];
651+
int rllen;
646652

647-
MemSet(linkpath, 0, sizeof(linkpath));
648-
if (readlink(pathbuf, linkpath, sizeof(linkpath) - 1) == -1)
653+
rllen = readlink(pathbuf, linkpath, sizeof(linkpath));
654+
if (rllen < 0)
649655
ereport(ERROR,
650656
(errcode_for_file_access(),
651657
errmsg("could not read symbolic link \"%s\": %m",
652658
pathbuf)));
659+
if (rllen >= sizeof(linkpath))
660+
ereport(ERROR,
661+
(errmsg("symbolic link \"%s\" target is too long",
662+
pathbuf)));
663+
linkpath[rllen] = '\0';
664+
653665
if (!sizeonly)
654666
_tarWriteHeader(pathbuf + basepathlen + 1, linkpath, &statbuf);
655667
size += 512; /* Size of the header just added */
668+
#else
669+
/*
670+
* If the platform does not have symbolic links, it should not be
671+
* possible to have tablespaces - clearly somebody else created
672+
* them. Warn about it and ignore.
673+
*/
674+
ereport(WARNING,
675+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
676+
errmsg("tablespaces are not supported on this platform")));
677+
continue;
678+
#endif /* HAVE_READLINK */
656679
}
657680
else if (S_ISDIR(statbuf.st_mode))
658681
{
@@ -800,7 +823,8 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
800823

801824

802825
static void
803-
_tarWriteHeader(const char *filename, char *linktarget, struct stat * statbuf)
826+
_tarWriteHeader(const char *filename, const char *linktarget,
827+
struct stat * statbuf)
804828
{
805829
char h[512];
806830
int lastSum = 0;
@@ -848,7 +872,7 @@ _tarWriteHeader(const char *filename, char *linktarget, struct stat * statbuf)
848872
{
849873
/* Type - Symbolic link */
850874
sprintf(&h[156], "2");
851-
strcpy(&h[157], linktarget);
875+
sprintf(&h[157], "%.99s", linktarget);
852876
}
853877
else if (S_ISDIR(statbuf->st_mode))
854878
/* Type - directory */

0 commit comments

Comments
 (0)