!40 Fix CVE-2021-20229
From: @wang_yue111 Reviewed-by: @wangxiao65,@jimmy_hero Signed-off-by: @jimmy_hero
This commit is contained in:
commit
0620b90377
163
CVE-2021-20229.patch
Normal file
163
CVE-2021-20229.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From eeede2470a8ec902c80de449d2c4822330c689ca Mon Sep 17 00:00:00 2001
|
||||
From: wang_yue111 <648774160@qq.com>
|
||||
Date: Fri, 26 Feb 2021 12:57:48 +0800
|
||||
Subject: [PATCH] Fix mishandling of column-level SELECT privileges for join
|
||||
aliases.
|
||||
|
||||
scanNSItemForColumn, expandNSItemAttrs, and ExpandSingleTable would
|
||||
pass the wrong RTE to markVarForSelectPriv when dealing with a join
|
||||
ParseNamespaceItem: they'd pass the join RTE, when what we need to
|
||||
mark is the base table that the join column came from. The end
|
||||
result was to not fill the base table's selectedCols bitmap correctly,
|
||||
resulting in an understatement of the set of columns that are read
|
||||
by the query. The executor would still insist on there being at
|
||||
least one selectable column; but with a correctly crafted query,
|
||||
a user having SELECT privilege on just one column of a table would
|
||||
nonetheless be allowed to read all its columns.
|
||||
|
||||
To fix, make markRTEForSelectPriv fetch the correct RTE for itself,
|
||||
ignoring the possibly-mismatched RTE passed by the caller. Later,
|
||||
we'll get rid of some now-unused RTE arguments, but that risks
|
||||
API breaks so we won't do it in released branches.
|
||||
|
||||
This problem was introduced by commit 9ce77d75c, so back-patch
|
||||
to v13 where that came in. Thanks to Sven Klemm for reporting
|
||||
the problem.
|
||||
|
||||
Security: CVE-2021-20229
|
||||
|
||||
---
|
||||
src/backend/parser/parse_relation.c | 40 ++++++++++-----------
|
||||
src/backend/parser/parse_target.c | 8 +++--
|
||||
4 files changed, 91 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
|
||||
index bbbb0b6..7ab4ba7 100644
|
||||
--- a/src/backend/parser/parse_relation.c
|
||||
+++ b/src/backend/parser/parse_relation.c
|
||||
@@ -43,7 +43,8 @@ static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
|
||||
int location);
|
||||
static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
|
||||
int location);
|
||||
-static void markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
|
||||
+static void markRTEForSelectPriv(ParseState *pstate,
|
||||
+
|
||||
int rtindex, AttrNumber col);
|
||||
static void expandRelation(Oid relid, Alias *eref,
|
||||
int rtindex, int sublevels_up,
|
||||
@@ -897,20 +898,15 @@ searchRangeTableForCol(ParseState *pstate, const char *alias, char *colname,
|
||||
|
||||
/*
|
||||
* markRTEForSelectPriv
|
||||
- * Mark the specified column of an RTE as requiring SELECT privilege
|
||||
+ * Mark the specified column of the RTE with index rtindex
|
||||
+ * as requiring SELECT privilege
|
||||
*
|
||||
* col == InvalidAttrNumber means a "whole row" reference
|
||||
- *
|
||||
- * The caller should pass the actual RTE if it has it handy; otherwise pass
|
||||
- * NULL, and we'll look it up here. (This uglification of the API is
|
||||
- * worthwhile because nearly all external callers have the RTE at hand.)
|
||||
*/
|
||||
static void
|
||||
-markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
|
||||
- int rtindex, AttrNumber col)
|
||||
+markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col)
|
||||
{
|
||||
- if (rte == NULL)
|
||||
- rte = rt_fetch(rtindex, pstate->p_rtable);
|
||||
+ RangeTblEntry *rte = rt_fetch(rtindex, pstate->p_rtable);
|
||||
|
||||
if (rte->rtekind == RTE_RELATION)
|
||||
{
|
||||
@@ -942,13 +938,13 @@ markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
|
||||
{
|
||||
int varno = ((RangeTblRef *) j->larg)->rtindex;
|
||||
|
||||
- markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
|
||||
+ markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
|
||||
}
|
||||
else if (IsA(j->larg, JoinExpr))
|
||||
{
|
||||
int varno = ((JoinExpr *) j->larg)->rtindex;
|
||||
|
||||
- markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
|
||||
+ markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
@@ -957,13 +953,13 @@ markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
|
||||
{
|
||||
int varno = ((RangeTblRef *) j->rarg)->rtindex;
|
||||
|
||||
- markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
|
||||
+ markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
|
||||
}
|
||||
else if (IsA(j->rarg, JoinExpr))
|
||||
{
|
||||
int varno = ((JoinExpr *) j->rarg)->rtindex;
|
||||
|
||||
- markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
|
||||
+ markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
@@ -994,10 +990,10 @@ markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
|
||||
|
||||
/*
|
||||
* markVarForSelectPriv
|
||||
- * Mark the RTE referenced by a Var as requiring SELECT privilege
|
||||
+ * Mark the RTE referenced by the Var as requiring SELECT privilege
|
||||
+ * for the Var's column (the Var could be a whole-row Var, too)
|
||||
*
|
||||
- * The caller should pass the Var's referenced RTE if it has it handy
|
||||
- * (nearly all do); otherwise pass NULL.
|
||||
+ * The rte argument is unused and will be removed later.
|
||||
*/
|
||||
void
|
||||
markVarForSelectPriv(ParseState *pstate, Var *var, RangeTblEntry *rte)
|
||||
@@ -1008,7 +1004,7 @@ markVarForSelectPriv(ParseState *pstate, Var *var, RangeTblEntry *rte)
|
||||
/* Find the appropriate pstate if it's an uplevel Var */
|
||||
for (lv = 0; lv < var->varlevelsup; lv++)
|
||||
pstate = pstate->parentParseState;
|
||||
- markRTEForSelectPriv(pstate, rte, var->varno, var->varattno);
|
||||
+ markRTEForSelectPriv(pstate, var->varno, var->varattno);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2629,9 +2625,13 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
|
||||
/*
|
||||
* Require read access to the table. This is normally redundant with the
|
||||
* markVarForSelectPriv calls below, but not if the table has zero
|
||||
- * columns.
|
||||
+ * columns. We need not do anything if the nsitem is for a join: its
|
||||
+ * component tables will have been marked ACL_SELECT when they were added
|
||||
+ * to the rangetable. (This step changes things only for the target
|
||||
+ * relation of UPDATE/DELETE, which cannot be under a join.)
|
||||
*/
|
||||
- rte->requiredPerms |= ACL_SELECT;
|
||||
+ if (rte->rtekind == RTE_RELATION)
|
||||
+ rte->requiredPerms |= ACL_SELECT;
|
||||
|
||||
forboth(name, names, var, vars)
|
||||
{
|
||||
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
|
||||
index 64a1b75..c7165cb 100644
|
||||
--- a/src/backend/parser/parse_target.c
|
||||
+++ b/src/backend/parser/parse_target.c
|
||||
@@ -1328,9 +1328,13 @@ ExpandSingleTable(ParseState *pstate, RangeTblEntry *rte,
|
||||
/*
|
||||
* Require read access to the table. This is normally redundant with
|
||||
* the markVarForSelectPriv calls below, but not if the table has zero
|
||||
- * columns.
|
||||
+ * columns. We need not do anything if the nsitem is for a join: its
|
||||
+ * component tables will have been marked ACL_SELECT when they were
|
||||
+ * added to the rangetable. (This step changes things only for the
|
||||
+ * target relation of UPDATE/DELETE, which cannot be under a join.)
|
||||
*/
|
||||
- rte->requiredPerms |= ACL_SELECT;
|
||||
+ if (rte->rtekind == RTE_RELATION)
|
||||
+ rte->requiredPerms |= ACL_SELECT;
|
||||
|
||||
/* Require read access to each column */
|
||||
foreach(l, vars)
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
Name: postgresql
|
||||
Version: 10.5
|
||||
Release: 20
|
||||
Release: 21
|
||||
Summary: PostgreSQL client programs
|
||||
License: PostgreSQL
|
||||
URL: http://www.postgresql.org/
|
||||
@ -43,6 +43,7 @@ Patch6013: CVE-2020-25694-2.patch
|
||||
Patch6014: CVE-2020-25694-3.patch
|
||||
Patch6015: CVE-2020-25695.patch
|
||||
Patch6016: CVE-2020-25696.patch
|
||||
Patch6017: CVE-2021-20229.patch
|
||||
|
||||
BuildRequires: gcc perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk perl(ExtUtils::Embed)
|
||||
BuildRequires: perl-devel perl-generators readline-devel zlib-devel systemd systemd-devel
|
||||
@ -433,6 +434,9 @@ find_lang_bins pltcl.lst pltcl
|
||||
%attr(-,postgres,postgres) %{_libdir}/pgsql/test
|
||||
|
||||
%changelog
|
||||
* Fri Feb 26 2021 wangyue <wangyue92@huawei.com> - 10.5-21
|
||||
- Fix CVE-2021-20229
|
||||
|
||||
* Fri Jan 29 2021 lingsheng <lingsheng@huawei.com> - 10.5-20
|
||||
- Add docbook-style-xsl to BuildRequires
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user