aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-support')
-rw-r--r--meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch273
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql.inc1
2 files changed, 274 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch b/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch
new file mode 100644
index 0000000000..abbe142495
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch
@@ -0,0 +1,273 @@
+From 15a8f97b9d16aaf659f58c981242b9da591cf24c Mon Sep 17 00:00:00 2001
+From: Noah Misch <noah@leadboat.com>
+Date: Mon, 17 Feb 2014 09:33:31 -0500
+Subject: [PATCH] Shore up ADMIN OPTION restrictions.
+
+commit 15a8f97b9d16aaf659f58c981242b9da591cf24c REL9_2_STABLE
+
+Granting a role without ADMIN OPTION is supposed to prevent the grantee
+from adding or removing members from the granted role. Issuing SET ROLE
+before the GRANT bypassed that, because the role itself had an implicit
+right to add or remove members. Plug that hole by recognizing that
+implicit right only when the session user matches the current role.
+Additionally, do not recognize it during a security-restricted operation
+or during execution of a SECURITY DEFINER function. The restriction on
+SECURITY DEFINER is not security-critical. However, it seems best for a
+user testing his own SECURITY DEFINER function to see the same behavior
+others will see. Back-patch to 8.4 (all supported versions).
+
+The SQL standards do not conflate roles and users as PostgreSQL does;
+only SQL roles have members, and only SQL users initiate sessions. An
+application using PostgreSQL users and roles as SQL users and roles will
+never attempt to grant membership in the role that is the session user,
+so the implicit right to add or remove members will never arise.
+
+The security impact was mostly that a role member could revoke access
+from others, contrary to the wishes of his own grantor. Unapproved role
+member additions are less notable, because the member can still largely
+achieve that by creating a view or a SECURITY DEFINER function.
+
+Reviewed by Andres Freund and Tom Lane. Reported, independently, by
+Jonas Sundman and Noah Misch.
+
+Security: CVE-2014-0060
+
+
+Upstream-Status: Backport
+
+Signed-off-by: Kai Kang <kai.kang@windriver.com>
+---
+ doc/src/sgml/ref/grant.sgml | 12 ++++---
+ src/backend/commands/user.c | 11 ++++++-
+ src/backend/utils/adt/acl.c | 50 ++++++++++++++++++++++++------
+ src/test/regress/expected/privileges.out | 36 +++++++++++++++++++++-
+ src/test/regress/sql/privileges.sql | 29 ++++++++++++++++-
+ 5 files changed, 120 insertions(+), 18 deletions(-)
+
+diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
+index fb81af4..2b5a843 100644
+--- a/doc/src/sgml/ref/grant.sgml
++++ b/doc/src/sgml/ref/grant.sgml
+@@ -396,11 +396,13 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
+ <para>
+ If <literal>WITH ADMIN OPTION</literal> is specified, the member can
+ in turn grant membership in the role to others, and revoke membership
+- in the role as well. Without the admin option, ordinary users cannot do
+- that. However,
+- database superusers can grant or revoke membership in any role to anyone.
+- Roles having <literal>CREATEROLE</> privilege can grant or revoke
+- membership in any role that is not a superuser.
++ in the role as well. Without the admin option, ordinary users cannot
++ do that. A role is not considered to hold <literal>WITH ADMIN
++ OPTION</literal> on itself, but it may grant or revoke membership in
++ itself from a database session where the session user matches the
++ role. Database superusers can grant or revoke membership in any role
++ to anyone. Roles having <literal>CREATEROLE</> privilege can grant
++ or revoke membership in any role that is not a superuser.
+ </para>
+
+ <para>
+diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
+index a22092c..39bf172 100644
+--- a/src/backend/commands/user.c
++++ b/src/backend/commands/user.c
+@@ -1334,7 +1334,16 @@ AddRoleMems(const char *rolename, Oid roleid,
+ rolename)));
+ }
+
+- /* XXX not sure about this check */
++ /*
++ * The role membership grantor of record has little significance at
++ * present. Nonetheless, inasmuch as users might look to it for a crude
++ * audit trail, let only superusers impute the grant to a third party.
++ *
++ * Before lifting this restriction, give the member == role case of
++ * is_admin_of_role() a fresh look. Ensure that the current role cannot
++ * use an explicit grantor specification to take advantage of the session
++ * user's self-admin right.
++ */
+ if (grantorId != GetUserId() && !superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
+index 1d6ae8b..9a52edb 100644
+--- a/src/backend/utils/adt/acl.c
++++ b/src/backend/utils/adt/acl.c
+@@ -4580,6 +4580,11 @@ pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
+ {
+ if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE))
+ {
++ /*
++ * XXX For roleid == role_oid, is_admin_of_role() also examines the
++ * session and call stack. That suits two-argument pg_has_role(), but
++ * it gives the three-argument version a lamentable whimsy.
++ */
+ if (is_admin_of_role(roleid, role_oid))
+ return ACLCHECK_OK;
+ }
+@@ -4897,11 +4902,9 @@ is_member_of_role_nosuper(Oid member, Oid role)
+
+
+ /*
+- * Is member an admin of role (directly or indirectly)? That is, is it
+- * a member WITH ADMIN OPTION?
+- *
+- * We could cache the result as for is_member_of_role, but currently this
+- * is not used in any performance-critical paths, so we don't.
++ * Is member an admin of role? That is, is member the role itself (subject to
++ * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
++ * or a superuser?
+ */
+ bool
+ is_admin_of_role(Oid member, Oid role)
+@@ -4910,14 +4913,41 @@ is_admin_of_role(Oid member, Oid role)
+ List *roles_list;
+ ListCell *l;
+
+- /* Fast path for simple case */
+- if (member == role)
+- return true;
+-
+- /* Superusers have every privilege, so are part of every role */
+ if (superuser_arg(member))
+ return true;
+
++ if (member == role)
++ /*
++ * A role can admin itself when it matches the session user and we're
++ * outside any security-restricted operation, SECURITY DEFINER or
++ * similar context. SQL-standard roles cannot self-admin. However,
++ * SQL-standard users are distinct from roles, and they are not
++ * grantable like roles: PostgreSQL's role-user duality extends the
++ * standard. Checking for a session user match has the effect of
++ * letting a role self-admin only when it's conspicuously behaving
++ * like a user. Note that allowing self-admin under a mere SET ROLE
++ * would make WITH ADMIN OPTION largely irrelevant; any member could
++ * SET ROLE to issue the otherwise-forbidden command.
++ *
++ * Withholding self-admin in a security-restricted operation prevents
++ * object owners from harnessing the session user identity during
++ * administrative maintenance. Suppose Alice owns a database, has
++ * issued "GRANT alice TO bob", and runs a daily ANALYZE. Bob creates
++ * an alice-owned SECURITY DEFINER function that issues "REVOKE alice
++ * FROM carol". If he creates an expression index calling that
++ * function, Alice will attempt the REVOKE during each ANALYZE.
++ * Checking InSecurityRestrictedOperation() thwarts that attack.
++ *
++ * Withholding self-admin in SECURITY DEFINER functions makes their
++ * behavior independent of the calling user. There's no security or
++ * SQL-standard-conformance need for that restriction, though.
++ *
++ * A role cannot have actual WITH ADMIN OPTION on itself, because that
++ * would imply a membership loop. Therefore, we're done either way.
++ */
++ return member == GetSessionUserId() &&
++ !InLocalUserIdChange() && !InSecurityRestrictedOperation();
++
+ /*
+ * Find all the roles that member is a member of, including multi-level
+ * recursion. We build a list in the same way that is_member_of_role does
+diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
+index e8930cb..bc6d731 100644
+--- a/src/test/regress/expected/privileges.out
++++ b/src/test/regress/expected/privileges.out
+@@ -32,7 +32,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4;
+ ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate
+ NOTICE: role "regressuser2" is already a member of role "regressgroup2"
+ ALTER GROUP regressgroup2 DROP USER regressuser2;
+-ALTER GROUP regressgroup2 ADD USER regressuser4;
++GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION;
+ -- test owner privileges
+ SET SESSION AUTHORIZATION regressuser1;
+ SELECT session_user, current_user;
+@@ -929,6 +929,40 @@ SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION')
+ t
+ (1 row)
+
++-- Admin options
++SET SESSION AUTHORIZATION regressuser4;
++CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS
++ 'GRANT regressgroup2 TO regressuser5';
++GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION
++SET ROLE regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege
++ERROR: must have admin option on role "regressgroup2"
++SET SESSION AUTHORIZATION regressuser1;
++GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION
++ERROR: must have admin option on role "regressgroup2"
++SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN
++NOTICE: role "regressuser5" is already a member of role "regressgroup2"
++CONTEXT: SQL function "dogrant_ok" statement 1
++ dogrant_ok
++------------
++
++(1 row)
++
++SET ROLE regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help
++ERROR: must have admin option on role "regressgroup2"
++SET SESSION AUTHORIZATION regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin
++NOTICE: role "regressuser5" is already a member of role "regressgroup2"
++CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS
++ 'GRANT regressgroup2 TO regressuser5';
++SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER
++ERROR: must have admin option on role "regressgroup2"
++CONTEXT: SQL function "dogrant_fails" statement 1
++DROP FUNCTION dogrant_fails();
++SET SESSION AUTHORIZATION regressuser4;
++DROP FUNCTION dogrant_ok();
++REVOKE regressgroup2 FROM regressuser5;
+ -- has_sequence_privilege tests
+ \c -
+ CREATE SEQUENCE x_seq;
+diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
+index d4d328e..5f1018a 100644
+--- a/src/test/regress/sql/privileges.sql
++++ b/src/test/regress/sql/privileges.sql
+@@ -37,7 +37,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4;
+
+ ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate
+ ALTER GROUP regressgroup2 DROP USER regressuser2;
+-ALTER GROUP regressgroup2 ADD USER regressuser4;
++GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION;
+
+ -- test owner privileges
+
+@@ -581,6 +581,33 @@ SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- false
+ SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true
+
+
++-- Admin options
++
++SET SESSION AUTHORIZATION regressuser4;
++CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS
++ 'GRANT regressgroup2 TO regressuser5';
++GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION
++SET ROLE regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege
++
++SET SESSION AUTHORIZATION regressuser1;
++GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION
++SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN
++SET ROLE regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help
++
++SET SESSION AUTHORIZATION regressgroup2;
++GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin
++CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS
++ 'GRANT regressgroup2 TO regressuser5';
++SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER
++DROP FUNCTION dogrant_fails();
++
++SET SESSION AUTHORIZATION regressuser4;
++DROP FUNCTION dogrant_ok();
++REVOKE regressgroup2 FROM regressuser5;
++
++
+ -- has_sequence_privilege tests
+ \c -
+
+--
+1.7.5.4
+
diff --git a/meta-oe/recipes-support/postgresql/postgresql.inc b/meta-oe/recipes-support/postgresql/postgresql.inc
index 9b242e0476..d6a4cd781f 100644
--- a/meta-oe/recipes-support/postgresql/postgresql.inc
+++ b/meta-oe/recipes-support/postgresql/postgresql.inc
@@ -32,6 +32,7 @@ SRC_URI = "http://ftp.postgresql.org/pub/source/v${PV}/${BP}.tar.bz2 \
file://postgresql.service \
file://0001-Use-pkg-config-for-libxml2-detection.patch \
file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \
+ file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \
"
LEAD_SONAME = "libpq.so"