Fix server crash bug in 'server' backup target.

When this code executed as superuser it appeared to work because no
system catalog lookups happened, but otherwise it crashes because there
is no transaction environment. Fix that.

Report and code change by me. Test case by Dagfinn Ilmari Mannsåker.

Discussion: http://postgr.es/m/CA+TgmobiKLXne-2AVzYyWRiO8=rChBQ=7ywoxp=2SmcFw=oDDw@mail.gmail.com
This commit is contained in:
Robert Haas 2022-02-02 13:50:33 -05:00
parent 87669de72c
commit 8e2b6d45a0
2 changed files with 15 additions and 1 deletions

View File

@ -10,6 +10,7 @@
*/
#include "postgres.h"
#include "access/xact.h"
#include "catalog/pg_authid.h"
#include "miscadmin.h"
#include "replication/basebackup.h"
@ -67,10 +68,12 @@ bbsink_server_new(bbsink *next, char *pathname)
sink->base.bbs_next = next;
/* Replication permission is not sufficient in this case. */
StartTransactionCommand();
if (!is_member_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of the pg_write_server_files role to create server backup")));
CommitTransactionCommand();
/*
* It's not a good idea to store your backups in the same directory that

View File

@ -10,7 +10,7 @@ use File::Path qw(rmtree);
use Fcntl qw(:seek);
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More tests => 143;
use Test::More;
program_help_ok('pg_basebackup');
program_version_ok('pg_basebackup');
@ -521,6 +521,15 @@ $node->command_ok(
ok(-f "$tempdir/backuponserver/base.tar", 'backup tar was created');
rmtree("$tempdir/backuponserver");
$node->command_ok(
[qw(createuser --replication --role=pg_write_server_files backupuser)],
'create backup user');
$node->command_ok(
[ @pg_basebackup_defs, '-U', 'backupuser', '--target', "server:$real_tempdir/backuponserver", '-X', 'none' ],
'backup target server');
ok(-f "$tempdir/backuponserver/base.tar", 'backup tar was created as non-superuser');
rmtree("$tempdir/backuponserver");
$node->command_fails(
[
@pg_basebackup_defs, '-D',
@ -768,3 +777,5 @@ SKIP:
rmtree("$tempdir/backup_gzip2");
rmtree("$tempdir/backup_gzip3");
}
done_testing();