8000 Restrict accesses to non-system views and foreign tables during pg_dump. · postgrespro/postgres@66e9444 · GitHub
[go: up one dir, main page]

Skip to content

Commit 66e9444

Browse files
Restrict accesses to non-system views and foreign tables during pg_dump.
When pg_dump retrieves the list of database objects and performs the data dump, there was possibility that objects are replaced with others of the same name, such as views, and access them. This vulnerability could result in code execution with superuser privileges during the pg_dump process. This issue can arise when dumping data of sequences, foreign tables (only 13 or later), or tables registered with a WHERE clause in the extension configuration table. To address this, pg_dump now utilizes the newly introduced restrict_nonsystem_relation_kind GUC parameter to restrict the accesses to non-system views and foreign tables during the dump process. This new GUC parameter is added to back branches too, but these changes do not require cluster recreation. Back-patch to all supported branches. Reviewed-by: Noah Misch Security: CVE-2024-7348 Backpatch-through: 12
1 parent ca6fde9 commit 66e9444

File tree

15 files changed

+255
-1
lines changed
  • sql
  • 15 files changed

    +255
    -1
    lines changed

    contrib/postgres_fdw/expected/postgres_fdw.out

    Lines changed: 11 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -637,6 +637,17 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
    637637
    Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
    638638
    (3 rows)
    639639

    640+
    -- test restriction on non-system foreign tables.
    641+
    SET restrict_nonsystem_relation_kind TO 'foreign-table';
    642+
    SELECT * from ft1 where c1 < 1; -- ERROR
    643+
    ERROR: access to non-system foreign table is restricted
    8000 644+
    INSERT INTO ft1 (c1) VALUES (1); -- ERROR
    645+
    ERROR: access to non-system foreign table is restricted
    646+
    DELETE FROM ft1 WHERE c1 = 1; -- ERROR
    647+
    ERROR: access to non-system foreign table is restricted
    648+
    TRUNCATE ft1; -- ERROR
    649+
    ERROR: access to non-system foreign table is restricted
    650+
    RESET restrict_nonsystem_relation_kind;
    640651
    -- ===================================================================
    641652
    -- WHERE with remotely-executable conditions
    642653
    -- ===================================================================

    contrib/postgres_fdw/sql/postgres_fdw.sql

    Lines changed: 8 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -327,6 +327,14 @@ DELETE FROM loct_empty;
    327327
    ANALYZE ft_empty;
    328328
    EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
    329329

    330+
    -- test restriction on non-system foreign tables.
    331+
    SET restrict_nonsystem_relation_kind TO 'foreign-table';
    332+
    SELECT * from ft1 where c1 < 1; -- ERROR
    333+
    INSERT INTO ft1 (c1) VALUES (1); -- ERROR
    334+
    DELETE FROM ft1 WHERE c1 = 1; -- ERROR
    335+
    TRUNCATE ft1; -- ERROR
    336+
    RESET restrict_nonsystem_relation_kind;
    337+
    330338
    -- ===================================================================
    331339
    -- WHERE with remotely-executable conditions
    332340
    -- ===================================================================

    doc/src/sgml/config.sgml

    Lines changed: 17 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -9813,6 +9813,23 @@ SET XML OPTION { DOCUMENT | CONTENT };
    98139813
    </listitem>
    98149814
    </varlistentry>
    98159815

    9816+
    <varlistentry id="guc-restrict-nonsystem-relation-kind" xreflabel="restrict_nonsystem_relation_kind">
    9817+
    <term><varname>restrict_nonsystem_relation_kind</varname> (<type>string</type>)
    9818+
    <indexterm>
    9819+
    <primary><varname>restrict_nonsystem_relation_kind</varname></primary>
    9820+
    <secondary>configuration parameter</secondary>
    9821+
    </indexterm>
    9822+
    </term>
    9823+
    <listitem>
    9824+
    <para>
    9825+
    This variable specifies relation kind to which access is restricted.
    9826+
    It contains a comma-separated list of relation kind. Currently, the
    9827+
    supported relation kinds are <literal>view</literal> and
    9828+
    <literal>foreign-table</literal>.
    9829+
    </para>
    9830+
    </listitem>
    9831+
    </varlistentry>
    9832+
    98169833
    </variablelist>
    98179834
    </sect2>
    98189835
    <sect2 id="runtime-config-client-format">

    doc/src/sgml/ref/pg_dump.sgml

    Lines changed: 8 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1001,6 +1001,14 @@ PostgreSQL documentation
    10011001
    The only exception is that an empty pattern is disallowed.
    10021002
    </para>
    10031003

    1004+
    <note>
    1005+
    <para>
    1006+
    Using wildcards in <option>--include-foreign-data</option> may result
    1007+
    in access to unexpected foreign servers. Also, to use this option securely,
    1008+
    make sure that the named server must have a trusted owner.
    1009+
    </para>
    1010+
    </note>
    1011+
    10041012
    <note>
    10051013
    <para>
    10061014
    When <option>--include-foreign-data</option> is specified,

    src/backend/foreign/foreign.c

    Lines changed: 10 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -22,6 +22,7 @@
    2222
    #include "foreign/foreign.h"
    2323
    #include "funcapi.h"
    2424
    #include "miscadmin.h"
    25+
    #include "tcop/tcopprot.h"
    2526
    #include "utils/builtins.h"
    2627
    #include "utils/memutils.h"
    2728
    #include "utils/rel.h"
    @@ -326,6 +327,15 @@ GetFdwRoutine(Oid fdwhandler)
    326327
    Datum datum;
    327328
    FdwRoutine *routine;
    328329

    330+
    /* Check if the access to foreign tables is restricted */
    331+
    if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
    332+
    {
    333+
    /* there must not be built-in FDW handler */
    334+
    ereport(ERROR,
    335+
    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    336+
    errmsg("access to non-system foreign table is restricted")));
    337+
    }
    338+
    329339
    datum = OidFunctionCall0(fdwhandler);
    330340
    routine = (FdwRoutine *) DatumGetPointer(datum);
    331341

    src/backend/optimizer/plan/createplan.c

    Lines changed: 13 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -41,6 +41,7 @@
    4141
    #include "parser/parse_clause.h"
    4242
    #include "parser/parsetree.h"
    4343
    #include "partitioning/partprune.h"
    44+
    #include "tcop/tcopprot.h"
    4445
    #include "utils/lsyscache.h"
    4546

    4647

    @@ -7136,7 +7137,19 @@ make_modifytable(PlannerInfo *root, Plan *subplan,
    71367137

    71377138
    if (rte->rtekind == RTE_RELATION &&
    71387139
    rte->relkind == RELKIND_FOREIGN_TABLE)
    7140+
    {
    7141+
    /* Check if the access to foreign tables is restricted */
    7142+
    if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
    7143+
    {
    7144+
    /* there must not be built-in foreign tables */
    7145+
    Assert(rte->relid >= FirstNormalObjectId);
    7146+
    ereport(ERROR,
    7147+
    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    7148+
    errmsg("access to non-system foreign table is restricted")));
    7149+
    }
    7150+
    71397151
    fdwroutine = GetFdwRoutineByRelId(rte->relid);
    7152+
    }
    71407153
    else
    71417154
    fdwroutine = NULL;
    71427155
    }

    src/backend/optimizer/util/plancat.c

    Lines changed: 12 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -45,6 +45,7 @@
    4545
    #include "rewrite/rewriteManip.h"
    4646
    #include "statistics/statistics.h"
    4747
    #include "storage/bufmgr.h"
    48+
    #include "tcop/tcopprot.h"
    4849
    #include "utils/builtins.h"
    4950
    #include "utils/lsyscache.h"
    5051
    #include "utils/partcache.h"
    @@ -528,6 +529,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
    528529
    /* Grab foreign-table info using the relcache, while we have it */
    529530
    if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    530531
    {
    532+
    /* Check if the access to foreign tables is restricted */
    533+
    if (unlikely((restrict_n C95D onsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
    534+
    {
    535+
    /* there must not be built-in foreign tables */
    536+
    Assert(RelationGetRelid(relation) >= FirstNormalObjectId);
    537+
    538+
    ereport(ERROR,
    539+
    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    540+
    errmsg("access to non-system foreign table is restricted")));
    541+
    }
    542+
    531543
    rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
    532544
    rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
    533545
    }

    src/backend/rewrite/rewriteHandler.c

    Lines changed: 17 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -40,6 +40,7 @@
    4040
    #include "rewrite/rewriteManip.h"
    4141
    #include "rewrite/rewriteSearchCycle.h"
    4242
    #include "rewrite/rowsecurity.h"
    43+
    #include "tcop/tcopprot.h"
    4344
    #include "utils/builtins.h"
    4445
    #include "utils/lsyscache.h"
    4546
    #include "utils/rel.h"
    @@ -1729,6 +1730,14 @@ ApplyRetrieveRule(Query *parsetree,
    17291730
    if (rule->qual != NULL)
    17301731
    elog(ERROR, "cannot handle qualified ON SELECT rule");
    17311732

    1733+
    /* Check if the expansion of non-system views are restricted */
    1734+
    if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
    1735+
    RelationGetRelid(relation) >= FirstNormalObjectId))
    1736+
    ereport(ERROR,
    1737+
    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1738+
    errmsg("access to non-sys 426B tem view \"%s\" is restricted",
    1739+
    RelationGetRelationName(relation))));
    1740+
    17321741
    if (rt_index == parsetree->resultRelation)
    17331742
    {
    17341743
    /*
    @@ -3212,6 +3221,14 @@ rewriteTargetView(Query *parsetree, Relation view)
    32123221
    }
    32133222
    }
    32143223

    3224+
    /* Check if the expansion of non-system views are restricted */
    3225+
    if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
    3226+
    RelationGetRelid(view) >= FirstNormalObjectId))
    3227+
    ereport(ERROR,
    3228+
    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    3229+
    errmsg("access to non-system view \"%s\" is restricted",
    3230+
    RelationGetRelationName(view))));
    3231+
    32153232
    /*
    32163233
    * The view must be updatable, else fail.
    32173234
    *

    src/backend/tcop/postgres.c

    Lines changed: 64 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -79,6 +79,7 @@
    7979
    #include "utils/snapmgr.h"
    8080
    #include "utils/timeout.h"
    8181
    #include "utils/timestamp.h"
    82+
    #include "utils/varlena.h"
    8283

    8384
    /* ----------------
    8485
    * global variables
    @@ -103,6 +104,9 @@ int PostAuthDelay = 0;
    103104
    /* Time between checks that the client is still connected. */
    104105
    int client_connection_check_interval = 0;
    105106

    107+
    /* flags for non-system relation kinds to restrict use */
    108+
    int restrict_nonsystem_relation_kind;
    109+
    106110
    /* ----------------
    107111
    * private typedefs etc
    108112
    * ----------------
    @@ -3673,6 +3677,66 @@ assign_transaction_timeout(int newval, void *extra)
    36733677
    }
    36743678
    }
    36753679

    3680+
    /*
    3681+
    * GUC check_hook for restrict_nonsystem_relation_kind
    3682+
    */
    3683+
    bool
    3684+
    check_restrict_nonsystem_relation_kind(char **newval, void **extra, GucSource source)
    3685+
    {
    3686+
    char *rawstring;
    3687+
    List *elemlist;
    3688+
    ListCell *l;
    3689+
    int flags = 0;
    3690+
    3691+
    /* Need a modifiable copy of string */
    3692+
    rawstring = pstrdup(*newval);
    3693+
    3694+
    if (!SplitIdentifierString(rawstring, ',', &elemlist))
    3695+
    {
    3696+
    /* syntax error in list */
    3697+
    GUC_check_errdetail("List syntax is invalid.");
    3698+
    pfree(rawstring);
    3699+
    list_free(elemlist);
    3700+
    return false;
    3701+
    }
    3702+
    3703+
    foreach(l, elemlist)
    3704+
    {
    3705+
    char *tok = (char *) lfirst(l);
    3706+
    3707+
    if (pg_strcasecmp(tok, "view") == 0)
    3708+
    flags |= RESTRICT_RELKIND_VIEW;
    3709+
    else if (pg_strcasecmp(tok, "foreign-table") == 0)
    3710+
    flags |= RESTRICT_RELKIND_FOREIGN_TABLE;
    3711+
    else
    3712+
    {
    3713+
    GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
    3714+
    pfree(rawstring);
    3715+
    list_free(elemlist);
    3716+
    return false;
    3717+
    }
    3718+
    }
    3719+
    3720+
    pfree(rawstring);
    3721+
    list_free(elemlist);
    3722+
    3723+
    /* Save the flags in *extra, for use by the assign function */
    3724+
    *extra = guc_malloc(ERROR, sizeof(int));
    3725+
    *((int *) *extra) = flags;
    3726+
    3727+
    return true;
    3728+
    }
    3729+
    3730+
    /*
    3731+
    * GUC assign_hook for restrict_nonsystem_relation_kind
    3732+
    */
    3733+
    void
    3734+
    assign_restrict_nonsystem_relation_kind(const char *newval, void *extra)
    3735+
    {
    3736+
    int *flags = (int *) extra;
    3737+
    3738+
    restrict_nonsystem_relation_kind = *flags;
    3739+
    }
    36763740

    36773741
    /*
    36783742
    * set_debug_options --- apply "-d N" command line option

    src/backend/utils/misc/guc_tables.c

    Lines changed: 12 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -576,6 +576,7 @@ static char *server_encoding_string;
    576576
    static char *server_version_string;
    577577
    static int server_version_num;
    578578
    static char *debug_io_direct_string;
    579+
    static char *restrict_nonsystem_relation_kind_string;
    579580

    580581
    #ifdef HAVE_SYSLOG
    581582
    #define DEFAULT_SYSLOG_FACILITY LOG_LOCAL0
    @@ -4768,6 +4769,17 @@ struct config_string ConfigureNamesString[] =
    47684769
    check_synchronized_standby_slots, assign_synchronized_standby_slots, NULL
    47694770
    },
    47704771

    4772+
    {
    4773+
    {"restrict_nonsystem_relation_kind", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4774+
    gettext_noop("Sets relation kinds of non-system relation to restrict use"),
    4775+
    NULL,
    4776+
    GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
    4777+
    },
    4778+
    &restrict_nonsystem_relation_kind_string,
    4779+
    "",
    4780+
    check_restrict_nonsystem_relation_kind, assign_restrict_nonsystem_relation_kind, NULL
    4781+
    },
    4782+
    47714783
    /* End-of-list marker */
    47724784
    {
    47734785
    {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL

    0 commit comments

    Comments
     (0)
    0