~ubuntu-branches/ubuntu/utopic/postgresql-9.4/utopic-security

« back to all changes in this revision

Viewing changes to src/bin/pg_basebackup/receivelog.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, CVE-2014-8161
  • Date: 2015-02-06 12:31:46 UTC
  • mfrom: (1.1.5) (7.1.2 utopic-proposed)
  • Revision ID: package-import@ubuntu.com-20150206123146-vtmf30jbkm7w16p8
Tags: 9.4.1-0ubuntu0.14.10
* New upstream security/bug fix release (LP: #1418928)
  - Fix buffer overruns in to_char() [CVE-2015-0241]
  - Fix buffer overruns in contrib/pgcrypto [CVE-2015-0243]
  - Fix possible loss of frontend/backend protocol synchronization after an
    error [CVE-2015-0244]
  - Fix information leak via constraint-violation error messages
    [CVE-2014-8161]
  - See release notes for details about other fixes:
    http://www.postgresql.org/about/news/1569/

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
static PGresult *HandleCopyStream(PGconn *conn, XLogRecPtr startpos,
35
35
                                 uint32 timeline, char *basedir,
36
36
                           stream_stop_callback stream_stop, int standby_message_timeout,
37
 
                                 char *partial_suffix, XLogRecPtr *stoppos);
 
37
                                 char *partial_suffix, XLogRecPtr *stoppos,
 
38
                                 bool mark_done);
38
39
 
39
40
static bool ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos,
40
41
                                                 uint32 *timeline);
41
42
 
 
43
static bool
 
44
mark_file_as_archived(const char *basedir, const char *fname)
 
45
{
 
46
        int fd;
 
47
        static char tmppath[MAXPGPATH];
 
48
 
 
49
        snprintf(tmppath, sizeof(tmppath), "%s/archive_status/%s.done",
 
50
                         basedir, fname);
 
51
 
 
52
        fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR);
 
53
        if (fd < 0)
 
54
        {
 
55
                fprintf(stderr, _("%s: could not create archive status file \"%s\": %s\n"),
 
56
                                progname, tmppath, strerror(errno));
 
57
                return false;
 
58
        }
 
59
 
 
60
        if (fsync(fd) != 0)
 
61
        {
 
62
                fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
 
63
                                progname, tmppath, strerror(errno));
 
64
 
 
65
                close(fd);
 
66
 
 
67
                return false;
 
68
        }
 
69
 
 
70
        close(fd);
 
71
 
 
72
        return true;
 
73
}
 
74
 
42
75
/*
43
76
 * Open a new WAL file in the specified directory.
44
77
 *
132
165
 * and returns false, otherwise returns true.
133
166
 */
134
167
static bool
135
 
close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 
168
close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos, bool mark_done)
136
169
{
137
170
        off_t           currpos;
138
171
 
186
219
                                _("%s: not renaming \"%s%s\", segment is not complete\n"),
187
220
                                progname, current_walfile_name, partial_suffix);
188
221
 
 
222
        /*
 
223
         * Mark file as archived if requested by the caller - pg_basebackup needs
 
224
         * to do so as files can otherwise get archived again after promotion of a
 
225
         * new node. This is in line with walreceiver.c always doing a
 
226
         * XLogArchiveForceDone() after a complete segment.
 
227
         */
 
228
        if (currpos == XLOG_SEG_SIZE && mark_done)
 
229
        {
 
230
                /* writes error message if failed */
 
231
                if (!mark_file_as_archived(basedir, current_walfile_name))
 
232
                        return false;
 
233
        }
 
234
 
189
235
        lastFlushPosition = pos;
190
236
        return true;
191
237
}
228
274
}
229
275
 
230
276
static bool
231
 
writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *content)
 
277
writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename,
 
278
                                                 char *content, bool mark_done)
232
279
{
233
280
        int                     size = strlen(content);
234
281
        char            path[MAXPGPATH];
307
354
                return false;
308
355
        }
309
356
 
 
357
        /* Maintain archive_status, check close_walfile() for details. */
 
358
        if (mark_done)
 
359
        {
 
360
                /* writes error message if failed */
 
361
                if (!mark_file_as_archived(basedir, histfname))
 
362
                        return false;
 
363
        }
 
364
 
310
365
        return true;
311
366
}
312
367
 
423
478
ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
424
479
                                  char *sysidentifier, char *basedir,
425
480
                                  stream_stop_callback stream_stop,
426
 
                                  int standby_message_timeout, char *partial_suffix)
 
481
                                  int standby_message_timeout, char *partial_suffix,
 
482
                                  bool mark_done)
427
483
{
428
484
        char            query[128];
429
485
        char            slotcmd[128];
538
594
                        /* Write the history file to disk */
539
595
                        writeTimeLineHistoryFile(basedir, timeline,
540
596
                                                                         PQgetvalue(res, 0, 0),
541
 
                                                                         PQgetvalue(res, 0, 1));
 
597
                                                                         PQgetvalue(res, 0, 1),
 
598
                                                                         mark_done);
542
599
 
543
600
                        PQclear(res);
544
601
                }
568
625
                /* Stream the WAL */
569
626
                res = HandleCopyStream(conn, startpos, timeline, basedir, stream_stop,
570
627
                                                           standby_message_timeout, partial_suffix,
571
 
                                                           &stoppos);
 
628
                                                           &stoppos, mark_done);
572
629
                if (res == NULL)
573
630
                        goto error;
574
631
 
733
790
HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
734
791
                                 char *basedir, stream_stop_callback stream_stop,
735
792
                                 int standby_message_timeout, char *partial_suffix,
736
 
                                 XLogRecPtr *stoppos)
 
793
                                 XLogRecPtr *stoppos, bool mark_done)
737
794
{
738
795
        char       *copybuf = NULL;
739
796
        int64           last_status = -1;
760
817
                 */
761
818
                if (still_sending && stream_stop(blockpos, timeline, false))
762
819
                {
763
 
                        if (!close_walfile(basedir, partial_suffix, blockpos))
 
820
                        if (!close_walfile(basedir, partial_suffix, blockpos, mark_done))
764
821
                        {
765
822
                                /* Potential error message is written by close_walfile */
766
823
                                goto error;
859
916
                         */
860
917
                        if (still_sending)
861
918
                        {
862
 
                                if (!close_walfile(basedir, partial_suffix, blockpos))
 
919
                                if (!close_walfile(basedir, partial_suffix, blockpos, mark_done))
863
920
                                {
864
921
                                        /* Error message written in close_walfile() */
865
922
                                        PQclear(res);
918
975
                        /* If the server requested an immediate reply, send one. */
919
976
                        if (replyRequested && still_sending)
920
977
                        {
 
978
                                if (reportFlushPosition && lastFlushPosition < blockpos &&
 
979
                                        walfile != -1)
 
980
                                {
 
981
                                        /*
 
982
                                         * If a valid flush location needs to be reported,
 
983
                                         * flush the current WAL file so that the latest flush
 
984
                                         * location is sent back to the server. This is necessary to
 
985
                                         * see whether the last WAL data has been successfully
 
986
                                         * replicated or not, at the normal shutdown of the server.
 
987
                                         */
 
988
                                        if (fsync(walfile) != 0)
 
989
                                        {
 
990
                                                fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
 
991
                                                                progname, current_walfile_name, strerror(errno));
 
992
                                                goto error;
 
993
                                        }
 
994
                                        lastFlushPosition = blockpos;
 
995
                                }
 
996
 
921
997
                                now = feGetCurrentTimestamp();
922
998
                                if (!sendFeedback(conn, blockpos, now, false))
923
999
                                        goto error;
1027
1103
                                /* Did we reach the end of a WAL segment? */
1028
1104
                                if (blockpos % XLOG_SEG_SIZE == 0)
1029
1105
                                {
1030
 
                                        if (!close_walfile(basedir, partial_suffix, blockpos))
 
1106
                                        if (!close_walfile(basedir, partial_suffix, blockpos, mark_done))
1031
1107
                                                /* Error message written in close_walfile() */
1032
1108
                                                goto error;
1033
1109