Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions contrib/postgres_fdw/expected/postgres_fdw.out
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,17 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
(3 rows)

-- test restriction on non-system foreign tables.
SET restrict_nonsystem_relation_kind TO 'foreign-table';
SELECT * from ft1 where c1 < 1; -- ERROR
ERROR: access to non-system foreign table is restricted
INSERT INTO ft1 (c1) VALUES (1); -- ERROR
ERROR: access to non-system foreign table is restricted
DELETE FROM ft1 WHERE c1 = 1; -- ERROR
ERROR: access to non-system foreign table is restricted
TRUNCATE ft1; -- ERROR
ERROR: access to non-system foreign table is restricted
RESET restrict_nonsystem_relation_kind;
-- ===================================================================
-- WHERE with remotely-executable conditions
-- ===================================================================
Expand Down
8 changes: 8 additions & 0 deletions contrib/postgres_fdw/sql/postgres_fdw.sql
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ DELETE FROM loct_empty;
ANALYZE ft_empty;
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;

-- test restriction on non-system foreign tables.
SET restrict_nonsystem_relation_kind TO 'foreign-table';
SELECT * from ft1 where c1 < 1; -- ERROR
INSERT INTO ft1 (c1) VALUES (1); -- ERROR
DELETE FROM ft1 WHERE c1 = 1; -- ERROR
TRUNCATE ft1; -- ERROR
RESET restrict_nonsystem_relation_kind;

-- ===================================================================
-- WHERE with remotely-executable conditions
-- ===================================================================
Expand Down
17 changes: 17 additions & 0 deletions doc/src/sgml/config.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -9012,6 +9012,23 @@ SET XML OPTION { DOCUMENT | CONTENT };
</listitem>
</varlistentry>

<varlistentry id="guc-restrict-nonsystem-relation-kind" xreflabel="restrict_nonsystem_relation_kind">
<term><varname>restrict_nonsystem_relation_kind</varname> (<type>string</type>)
<indexterm>
<primary><varname>restrict_nonsystem_relation_kind</varname></primary>
<secondary>configuration parameter</secondary>
</indexterm>
</term>
<listitem>
<para>
This variable specifies relation kind to which access is restricted.
It contains a comma-separated list of relation kind. Currently, the
supported relation kinds are <literal>view</literal> and
<literal>foreign-table</literal>.
</para>
</listitem>
</varlistentry>

</variablelist>
</sect2>
<sect2 id="runtime-config-client-format">
Expand Down
8 changes: 8 additions & 0 deletions doc/src/sgml/ref/pg_dump.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,14 @@ PostgreSQL documentation
The only exception is that an empty pattern is disallowed.
</para>

<note>
<para>
Using wildcards in <option>--include-foreign-data</option> may result
in access to unexpected foreign servers. Also, to use this option securely,
make sure that the named server must have a trusted owner.
</para>
</note>

<note>
<para>
When <option>--include-foreign-data</option> is specified,
Expand Down
10 changes: 10 additions & 0 deletions src/backend/foreign/foreign.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Expand Down Expand Up @@ -590,6 +591,15 @@ GetFdwRoutine(Oid fdwhandler)
Datum datum;
FdwRoutine *routine;

/* Check if the access to foreign tables is restricted */
if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
{
/* there must not be built-in FDW handler */
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("access to non-system foreign table is restricted")));
}

datum = OidFunctionCall0(fdwhandler);
routine = (FdwRoutine *) DatumGetPointer(datum);

Expand Down
13 changes: 13 additions & 0 deletions src/backend/optimizer/plan/createplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "parser/parsetree.h"
#include "partitioning/partdesc.h"
#include "partitioning/partprune.h"
#include "tcop/tcopprot.h"
#include "utils/lsyscache.h"
#include "utils/uri.h"

Expand Down Expand Up @@ -8482,7 +8483,19 @@ make_modifytable(PlannerInfo *root, Plan *subplan,

Assert(rte->rtekind == RTE_RELATION);
if (rte->relkind == RELKIND_FOREIGN_TABLE)
{
/* Check if the access to foreign tables is restricted */
if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
{
/* there must not be built-in foreign tables */
Assert(rte->relid >= FirstNormalObjectId);
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("access to non-system foreign table is restricted")));
}

fdwroutine = GetFdwRoutineByRelId(rte->relid);
}
else
fdwroutine = NULL;
}
Expand Down
12 changes: 12 additions & 0 deletions src/backend/optimizer/util/plancat.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "rewrite/rewriteManip.h"
#include "statistics/statistics.h"
#include "storage/bufmgr.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
Expand Down Expand Up @@ -468,6 +469,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
/* Grab foreign-table info using the relcache, while we have it */
if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
/* Check if the access to foreign tables is restricted */
if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
{
/* there must not be built-in foreign tables */
Assert(RelationGetRelid(relation) >= FirstNormalObjectId);

ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("access to non-system foreign table is restricted")));
}

rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
rel->segSeverids = GetForeignServerSegsByRelId(RelationGetRelid(relation));
rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
Expand Down
17 changes: 17 additions & 0 deletions src/backend/rewrite/rewriteHandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSearchCycle.h"
#include "rewrite/rowsecurity.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
Expand Down Expand Up @@ -1789,6 +1790,14 @@ ApplyRetrieveRule(Query *parsetree,
if (rule->qual != NULL)
elog(ERROR, "cannot handle qualified ON SELECT rule");

/* Check if the expansion of non-system views are restricted */
if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
RelationGetRelid(relation) >= FirstNormalObjectId))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("access to non-system view \"%s\" is restricted",
RelationGetRelationName(relation))));

if (rt_index == parsetree->resultRelation)
{
/*
Expand Down Expand Up @@ -3172,6 +3181,14 @@ rewriteTargetView(Query *parsetree, Relation view)
}
}

/* Check if the expansion of non-system views are restricted */
if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
RelationGetRelid(view) >= FirstNormalObjectId))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("access to non-system view \"%s\" is restricted",
RelationGetRelationName(view))));

/*
* For INSERT/UPDATE the modified columns must all be updatable. Note that
* we get the modified columns from the query's targetlist, not from the
Expand Down
63 changes: 63 additions & 0 deletions src/backend/tcop/postgres.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#include "utils/snapmgr.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "utils/varlena.h"

#include "cdb/cdbutil.h"
#include "cdb/cdbvars.h"
Expand Down Expand Up @@ -151,6 +152,8 @@ cancel_pending_hook_type cancel_pending_hook = NULL;
* Hook for query execution.
*/
exec_simple_query_hook_type exec_simple_query_hook = NULL;
/* flags for non-system relation kinds to restrict use */
int restrict_nonsystem_relation_kind;

/* ----------------
* private typedefs etc
Expand Down Expand Up @@ -4546,6 +4549,66 @@ assign_max_stack_depth(int newval, void *extra)
max_stack_depth_bytes = newval_bytes;
}

/*
* GUC check_hook for restrict_nonsystem_relation_kind
*/
bool
check_restrict_nonsystem_relation_kind(char **newval, void **extra, GucSource source)
{
char *rawstring;
List *elemlist;
ListCell *l;
int flags = 0;

/* Need a modifiable copy of string */
rawstring = pstrdup(*newval);

if (!SplitIdentifierString(rawstring, ',', &elemlist))
{
/* syntax error in list */
GUC_check_errdetail("List syntax is invalid.");
pfree(rawstring);
list_free(elemlist);
return false;
}

foreach(l, elemlist)
{
char *tok = (char *) lfirst(l);

if (pg_strcasecmp(tok, "view") == 0)
flags |= RESTRICT_RELKIND_VIEW;
else if (pg_strcasecmp(tok, "foreign-table") == 0)
flags |= RESTRICT_RELKIND_FOREIGN_TABLE;
else
{
GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
pfree(rawstring);
list_free(elemlist);
return false;
}
}

pfree(rawstring);
list_free(elemlist);

/* Save the flags in *extra, for use by the assign function */
*extra = malloc(sizeof(int));
*((int *) *extra) = flags;

return true;
}

/*
* GUC assign_hook for restrict_nonsystem_relation_kind
*/
void
assign_restrict_nonsystem_relation_kind(const char *newval, void *extra)
{
int *flags = (int *) extra;

restrict_nonsystem_relation_kind = *flags;
}

/*
* set_debug_options --- apply "-d N" command line option
Expand Down
15 changes: 14 additions & 1 deletion src/backend/utils/misc/guc.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,8 @@ static char *recovery_target_xid_string;
static char *recovery_target_name_string;
static char *recovery_target_lsn_string;
static char *file_encryption_method_str;
static char *restrict_nonsystem_relation_kind_string;


/* should be static, but commands/variable.c needs to get at this */
char *role_string;
Expand Down Expand Up @@ -4761,7 +4763,18 @@ static struct config_string ConfigureNamesString[] =
"",
NULL, NULL, NULL
},


{
{"restrict_nonsystem_relation_kind", PGC_USERSET, CLIENT_CONN_STATEMENT,
gettext_noop("Sets relation kinds of non-system relation to restrict use"),
NULL,
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
},
&restrict_nonsystem_relation_kind_string,
"",
check_restrict_nonsystem_relation_kind, assign_restrict_nonsystem_relation_kind, NULL
},

/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
Expand Down
48 changes: 48 additions & 0 deletions src/bin/pg_dump/pg_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
const char *prefix, Archive *fout);
static char *get_synchronized_snapshot(Archive *fout);
static void setupDumpWorker(Archive *AHX);
static void set_restrict_relation_kind(Archive *AH, const char *value);
static TableInfo *getRootTableInfo(const TableInfo *tbinfo);
static bool forcePartitionRootLoad(const TableInfo *tbinfo);

Expand Down Expand Up @@ -1447,6 +1448,13 @@ setup_connection(Archive *AH, const char *dumpencoding,
ExecuteSqlStatement(AH, "SET row_security = off");
}

/*
* For security reasons, we restrict the expansion of non-system views and
* access to foreign tables during the pg_dump process. This restriction
* is adjusted when dumping foreign table data.
*/
set_restrict_relation_kind(AH, "view, foreign-table");

/*
* Start transaction-snapshot mode transaction to dump consistent data.
*/
Expand Down Expand Up @@ -2341,6 +2349,11 @@ dumpTableData_copy(Archive *fout, const void *dcontext)
*/
if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE)
{
/* Temporary allows to access to foreign tables to dump data */
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
set_restrict_relation_kind(fout, "view");

/* Note: this syntax is only supported in 8.2 and up */
appendPQExpBufferStr(q, "COPY (SELECT ");
/* klugery to get rid of parens in column list */
if (strlen(column_list) > 2)
Expand Down Expand Up @@ -2452,6 +2465,11 @@ dumpTableData_copy(Archive *fout, const void *dcontext)
classname);

destroyPQExpBuffer(q);

/* Revert back the setting */
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
set_restrict_relation_kind(fout, "view, foreign-table");

return 1;
}

Expand All @@ -2478,6 +2496,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext)
int rows_per_statement = dopt->dump_inserts;
int rows_this_statement = 0;

/* Temporary allows to access to foreign tables to dump data */
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
set_restrict_relation_kind(fout, "view");

/*
* If we're going to emit INSERTs with column names, the most efficient
* way to deal with generated columns is to exclude them entirely. For
Expand Down Expand Up @@ -2717,6 +2739,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext)
destroyPQExpBuffer(insertStmt);
free(attgenerated);

/* Revert back the setting */
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
set_restrict_relation_kind(fout, "view, foreign-table");

return 1;
}

Expand Down Expand Up @@ -4779,6 +4805,28 @@ is_superuser(Archive *fout)
return false;
}

/*
* Set the given value to restrict_nonsystem_relation_kind value. Since
* restrict_nonsystem_relation_kind is introduced in minor version releases,
* the setting query is effective only where available.
*/
static void
set_restrict_relation_kind(Archive *AH, const char *value)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;

appendPQExpBuffer(query,
"SELECT set_config(name, '%s', false) "
"FROM pg_settings "
"WHERE name = 'restrict_nonsystem_relation_kind'",
value);
res = ExecuteSqlQuery(AH, query->data, PGRES_TUPLES_OK);

PQclear(res);
destroyPQExpBuffer(query);
}

/*
* getSubscriptions
* get information about subscriptions
Expand Down
Loading
Loading