Commit e79e6c4d authored by Peter Eisentraut's avatar Peter Eisentraut

Fix CRC check handling in get_controlfile

The previous patch broke this by returning NULL for a failed CRC check,
which pg_controldata would then try to read.  Fix by returning the
result of the CRC check in a separate argument.

Michael Paquier and myself
parent 308985b0
...@@ -34,6 +34,7 @@ pg_control_system(PG_FUNCTION_ARGS) ...@@ -34,6 +34,7 @@ pg_control_system(PG_FUNCTION_ARGS)
TupleDesc tupdesc; TupleDesc tupdesc;
HeapTuple htup; HeapTuple htup;
ControlFileData *ControlFile; ControlFileData *ControlFile;
bool crc_ok;
/* /*
* Construct a tuple descriptor for the result row. This must match this * Construct a tuple descriptor for the result row. This must match this
...@@ -51,8 +52,8 @@ pg_control_system(PG_FUNCTION_ARGS) ...@@ -51,8 +52,8 @@ pg_control_system(PG_FUNCTION_ARGS)
tupdesc = BlessTupleDesc(tupdesc); tupdesc = BlessTupleDesc(tupdesc);
/* read the control file */ /* read the control file */
ControlFile = get_controlfile(DataDir, NULL); ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
if (!ControlFile) if (!crc_ok)
ereport(ERROR, ereport(ERROR,
(errmsg("calculated CRC checksum does not match value stored in file"))); (errmsg("calculated CRC checksum does not match value stored in file")));
...@@ -83,6 +84,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS) ...@@ -83,6 +84,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
ControlFileData *ControlFile; ControlFileData *ControlFile;
XLogSegNo segno; XLogSegNo segno;
char xlogfilename[MAXFNAMELEN]; char xlogfilename[MAXFNAMELEN];
bool crc_ok;
/* /*
* Construct a tuple descriptor for the result row. This must match this * Construct a tuple descriptor for the result row. This must match this
...@@ -130,8 +132,8 @@ pg_control_checkpoint(PG_FUNCTION_ARGS) ...@@ -130,8 +132,8 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
tupdesc = BlessTupleDesc(tupdesc); tupdesc = BlessTupleDesc(tupdesc);
/* Read the control file. */ /* Read the control file. */
ControlFile = get_controlfile(DataDir, NULL); ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
if (!ControlFile) if (!crc_ok)
ereport(ERROR, ereport(ERROR,
(errmsg("calculated CRC checksum does not match value stored in file"))); (errmsg("calculated CRC checksum does not match value stored in file")));
...@@ -216,6 +218,7 @@ pg_control_recovery(PG_FUNCTION_ARGS) ...@@ -216,6 +218,7 @@ pg_control_recovery(PG_FUNCTION_ARGS)
TupleDesc tupdesc; TupleDesc tupdesc;
HeapTuple htup; HeapTuple htup;
ControlFileData *ControlFile; ControlFileData *ControlFile;
bool crc_ok;
/* /*
* Construct a tuple descriptor for the result row. This must match this * Construct a tuple descriptor for the result row. This must match this
...@@ -235,8 +238,8 @@ pg_control_recovery(PG_FUNCTION_ARGS) ...@@ -235,8 +238,8 @@ pg_control_recovery(PG_FUNCTION_ARGS)
tupdesc = BlessTupleDesc(tupdesc); tupdesc = BlessTupleDesc(tupdesc);
/* read the control file */ /* read the control file */
ControlFile = get_controlfile(DataDir, NULL); ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
if (!ControlFile) if (!crc_ok)
ereport(ERROR, ereport(ERROR,
(errmsg("calculated CRC checksum does not match value stored in file"))); (errmsg("calculated CRC checksum does not match value stored in file")));
...@@ -268,6 +271,7 @@ pg_control_init(PG_FUNCTION_ARGS) ...@@ -268,6 +271,7 @@ pg_control_init(PG_FUNCTION_ARGS)
TupleDesc tupdesc; TupleDesc tupdesc;
HeapTuple htup; HeapTuple htup;
ControlFileData *ControlFile; ControlFileData *ControlFile;
bool crc_ok;
/* /*
* Construct a tuple descriptor for the result row. This must match this * Construct a tuple descriptor for the result row. This must match this
...@@ -303,8 +307,8 @@ pg_control_init(PG_FUNCTION_ARGS) ...@@ -303,8 +307,8 @@ pg_control_init(PG_FUNCTION_ARGS)
tupdesc = BlessTupleDesc(tupdesc); tupdesc = BlessTupleDesc(tupdesc);
/* read the control file */ /* read the control file */
ControlFile = get_controlfile(DataDir, NULL); ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
if (!ControlFile) if (!crc_ok)
ereport(ERROR, ereport(ERROR,
(errmsg("calculated CRC checksum does not match value stored in file"))); (errmsg("calculated CRC checksum does not match value stored in file")));
......
...@@ -86,6 +86,7 @@ int ...@@ -86,6 +86,7 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
ControlFileData *ControlFile; ControlFileData *ControlFile;
bool crc_ok;
char *DataDir = NULL; char *DataDir = NULL;
time_t time_tmp; time_t time_tmp;
char pgctime_str[128]; char pgctime_str[128];
...@@ -155,8 +156,8 @@ main(int argc, char *argv[]) ...@@ -155,8 +156,8 @@ main(int argc, char *argv[])
} }
/* get a copy of the control file */ /* get a copy of the control file */
ControlFile = get_controlfile(DataDir, progname); ControlFile = get_controlfile(DataDir, progname, &crc_ok);
if (!ControlFile) if (!crc_ok)
printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n" printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
"Either the file is corrupt, or it has a different layout than this program\n" "Either the file is corrupt, or it has a different layout than this program\n"
"is expecting. The results below are untrustworthy.\n\n")); "is expecting. The results below are untrustworthy.\n\n"));
......
...@@ -2147,28 +2147,18 @@ static DBState ...@@ -2147,28 +2147,18 @@ static DBState
get_control_dbstate(void) get_control_dbstate(void)
{ {
DBState ret; DBState ret;
bool crc_ok;
ControlFileData *control_file_data = get_controlfile(pg_data, progname, &crc_ok);
for (;;) if (!crc_ok)
{ {
ControlFileData *control_file_data = get_controlfile(pg_data, progname); write_stderr(_("%s: control file appears to be corrupt\n"), progname);
exit(1);
}
if (control_file_data)
{
ret = control_file_data->state; ret = control_file_data->state;
pfree(control_file_data); pfree(control_file_data);
return ret; return ret;
}
if (wait_seconds > 0)
{
pg_usleep(1000000); /* 1 sec */
wait_seconds--;
continue;
}
write_stderr(_("%s: control file appears to be corrupt\n"), progname);
exit(1);
}
} }
......
...@@ -29,21 +29,24 @@ ...@@ -29,21 +29,24 @@
#include "port/pg_crc32c.h" #include "port/pg_crc32c.h"
/* /*
* get_controlfile(char *DataDir, const char *progname) * get_controlfile(char *DataDir, const char *progname, bool *crc_ok_p)
* *
* Get controlfile values. The caller is responsible * Get controlfile values. The result is returned as a palloc'd copy of the
* for pfreeing the result. * control file data.
* *
* Returns NULL if the CRC did not match. * crc_ok_p can be used by the caller to see whether the CRC of the control
* file data is correct.
*/ */
ControlFileData * ControlFileData *
get_controlfile(const char *DataDir, const char *progname) get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p)
{ {
ControlFileData *ControlFile; ControlFileData *ControlFile;
int fd; int fd;
char ControlFilePath[MAXPGPATH]; char ControlFilePath[MAXPGPATH];
pg_crc32c crc; pg_crc32c crc;
AssertArg(crc_ok_p);
ControlFile = palloc(sizeof(ControlFileData)); ControlFile = palloc(sizeof(ControlFileData));
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir); snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
...@@ -83,11 +86,7 @@ get_controlfile(const char *DataDir, const char *progname) ...@@ -83,11 +86,7 @@ get_controlfile(const char *DataDir, const char *progname)
offsetof(ControlFileData, crc)); offsetof(ControlFileData, crc));
FIN_CRC32C(crc); FIN_CRC32C(crc);
if (!EQ_CRC32C(crc, ControlFile->crc)) *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
{
pfree(ControlFile);
return NULL;
}
/* Make sure the control file is valid byte order. */ /* Make sure the control file is valid byte order. */
if (ControlFile->pg_control_version % 65536 == 0 && if (ControlFile->pg_control_version % 65536 == 0 &&
......
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
#include "catalog/pg_control.h" #include "catalog/pg_control.h"
extern ControlFileData *get_controlfile(const char *DataDir, const char *progname); extern ControlFileData *get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p);
#endif /* COMMON_CONTROLDATA_UTILS_H */ #endif /* COMMON_CONTROLDATA_UTILS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment