diff options
| -rw-r--r-- | meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch | 273 | ||||
| -rw-r--r-- | meta-oe/recipes-support/postgresql/postgresql.inc | 1 |
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 @@ | |||
| 1 | From 15a8f97b9d16aaf659f58c981242b9da591cf24c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Noah Misch <noah@leadboat.com> | ||
| 3 | Date: Mon, 17 Feb 2014 09:33:31 -0500 | ||
| 4 | Subject: [PATCH] Shore up ADMIN OPTION restrictions. | ||
| 5 | |||
| 6 | commit 15a8f97b9d16aaf659f58c981242b9da591cf24c REL9_2_STABLE | ||
| 7 | |||
| 8 | Granting a role without ADMIN OPTION is supposed to prevent the grantee | ||
| 9 | from adding or removing members from the granted role. Issuing SET ROLE | ||
| 10 | before the GRANT bypassed that, because the role itself had an implicit | ||
| 11 | right to add or remove members. Plug that hole by recognizing that | ||
| 12 | implicit right only when the session user matches the current role. | ||
| 13 | Additionally, do not recognize it during a security-restricted operation | ||
| 14 | or during execution of a SECURITY DEFINER function. The restriction on | ||
| 15 | SECURITY DEFINER is not security-critical. However, it seems best for a | ||
| 16 | user testing his own SECURITY DEFINER function to see the same behavior | ||
| 17 | others will see. Back-patch to 8.4 (all supported versions). | ||
| 18 | |||
| 19 | The SQL standards do not conflate roles and users as PostgreSQL does; | ||
| 20 | only SQL roles have members, and only SQL users initiate sessions. An | ||
| 21 | application using PostgreSQL users and roles as SQL users and roles will | ||
| 22 | never attempt to grant membership in the role that is the session user, | ||
| 23 | so the implicit right to add or remove members will never arise. | ||
| 24 | |||
| 25 | The security impact was mostly that a role member could revoke access | ||
| 26 | from others, contrary to the wishes of his own grantor. Unapproved role | ||
| 27 | member additions are less notable, because the member can still largely | ||
| 28 | achieve that by creating a view or a SECURITY DEFINER function. | ||
| 29 | |||
| 30 | Reviewed by Andres Freund and Tom Lane. Reported, independently, by | ||
| 31 | Jonas Sundman and Noah Misch. | ||
| 32 | |||
| 33 | Security: CVE-2014-0060 | ||
| 34 | |||
| 35 | |||
| 36 | Upstream-Status: Backport | ||
| 37 | |||
| 38 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
| 39 | --- | ||
| 40 | doc/src/sgml/ref/grant.sgml | 12 ++++--- | ||
| 41 | src/backend/commands/user.c | 11 ++++++- | ||
| 42 | src/backend/utils/adt/acl.c | 50 ++++++++++++++++++++++++------ | ||
| 43 | src/test/regress/expected/privileges.out | 36 +++++++++++++++++++++- | ||
| 44 | src/test/regress/sql/privileges.sql | 29 ++++++++++++++++- | ||
| 45 | 5 files changed, 120 insertions(+), 18 deletions(-) | ||
| 46 | |||
| 47 | diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml | ||
| 48 | index fb81af4..2b5a843 100644 | ||
| 49 | --- a/doc/src/sgml/ref/grant.sgml | ||
| 50 | +++ b/doc/src/sgml/ref/grant.sgml | ||
| 51 | @@ -396,11 +396,13 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace | ||
| 52 | <para> | ||
| 53 | If <literal>WITH ADMIN OPTION</literal> is specified, the member can | ||
| 54 | in turn grant membership in the role to others, and revoke membership | ||
| 55 | - in the role as well. Without the admin option, ordinary users cannot do | ||
| 56 | - that. However, | ||
| 57 | - database superusers can grant or revoke membership in any role to anyone. | ||
| 58 | - Roles having <literal>CREATEROLE</> privilege can grant or revoke | ||
| 59 | - membership in any role that is not a superuser. | ||
| 60 | + in the role as well. Without the admin option, ordinary users cannot | ||
| 61 | + do that. A role is not considered to hold <literal>WITH ADMIN | ||
| 62 | + OPTION</literal> on itself, but it may grant or revoke membership in | ||
| 63 | + itself from a database session where the session user matches the | ||
| 64 | + role. Database superusers can grant or revoke membership in any role | ||
| 65 | + to anyone. Roles having <literal>CREATEROLE</> privilege can grant | ||
| 66 | + or revoke membership in any role that is not a superuser. | ||
| 67 | </para> | ||
| 68 | |||
| 69 | <para> | ||
| 70 | diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c | ||
| 71 | index a22092c..39bf172 100644 | ||
| 72 | --- a/src/backend/commands/user.c | ||
| 73 | +++ b/src/backend/commands/user.c | ||
| 74 | @@ -1334,7 +1334,16 @@ AddRoleMems(const char *rolename, Oid roleid, | ||
| 75 | rolename))); | ||
| 76 | } | ||
| 77 | |||
| 78 | - /* XXX not sure about this check */ | ||
| 79 | + /* | ||
| 80 | + * The role membership grantor of record has little significance at | ||
| 81 | + * present. Nonetheless, inasmuch as users might look to it for a crude | ||
| 82 | + * audit trail, let only superusers impute the grant to a third party. | ||
| 83 | + * | ||
| 84 | + * Before lifting this restriction, give the member == role case of | ||
| 85 | + * is_admin_of_role() a fresh look. Ensure that the current role cannot | ||
| 86 | + * use an explicit grantor specification to take advantage of the session | ||
| 87 | + * user's self-admin right. | ||
| 88 | + */ | ||
| 89 | if (grantorId != GetUserId() && !superuser()) | ||
| 90 | ereport(ERROR, | ||
| 91 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), | ||
| 92 | diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c | ||
| 93 | index 1d6ae8b..9a52edb 100644 | ||
| 94 | --- a/src/backend/utils/adt/acl.c | ||
| 95 | +++ b/src/backend/utils/adt/acl.c | ||
| 96 | @@ -4580,6 +4580,11 @@ pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode) | ||
| 97 | { | ||
| 98 | if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE)) | ||
| 99 | { | ||
| 100 | + /* | ||
| 101 | + * XXX For roleid == role_oid, is_admin_of_role() also examines the | ||
| 102 | + * session and call stack. That suits two-argument pg_has_role(), but | ||
| 103 | + * it gives the three-argument version a lamentable whimsy. | ||
| 104 | + */ | ||
| 105 | if (is_admin_of_role(roleid, role_oid)) | ||
| 106 | return ACLCHECK_OK; | ||
| 107 | } | ||
| 108 | @@ -4897,11 +4902,9 @@ is_member_of_role_nosuper(Oid member, Oid role) | ||
| 109 | |||
| 110 | |||
| 111 | /* | ||
| 112 | - * Is member an admin of role (directly or indirectly)? That is, is it | ||
| 113 | - * a member WITH ADMIN OPTION? | ||
| 114 | - * | ||
| 115 | - * We could cache the result as for is_member_of_role, but currently this | ||
| 116 | - * is not used in any performance-critical paths, so we don't. | ||
| 117 | + * Is member an admin of role? That is, is member the role itself (subject to | ||
| 118 | + * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION, | ||
| 119 | + * or a superuser? | ||
| 120 | */ | ||
| 121 | bool | ||
| 122 | is_admin_of_role(Oid member, Oid role) | ||
| 123 | @@ -4910,14 +4913,41 @@ is_admin_of_role(Oid member, Oid role) | ||
| 124 | List *roles_list; | ||
| 125 | ListCell *l; | ||
| 126 | |||
| 127 | - /* Fast path for simple case */ | ||
| 128 | - if (member == role) | ||
| 129 | - return true; | ||
| 130 | - | ||
| 131 | - /* Superusers have every privilege, so are part of every role */ | ||
| 132 | if (superuser_arg(member)) | ||
| 133 | return true; | ||
| 134 | |||
| 135 | + if (member == role) | ||
| 136 | + /* | ||
| 137 | + * A role can admin itself when it matches the session user and we're | ||
| 138 | + * outside any security-restricted operation, SECURITY DEFINER or | ||
| 139 | + * similar context. SQL-standard roles cannot self-admin. However, | ||
| 140 | + * SQL-standard users are distinct from roles, and they are not | ||
| 141 | + * grantable like roles: PostgreSQL's role-user duality extends the | ||
| 142 | + * standard. Checking for a session user match has the effect of | ||
| 143 | + * letting a role self-admin only when it's conspicuously behaving | ||
| 144 | + * like a user. Note that allowing self-admin under a mere SET ROLE | ||
| 145 | + * would make WITH ADMIN OPTION largely irrelevant; any member could | ||
| 146 | + * SET ROLE to issue the otherwise-forbidden command. | ||
| 147 | + * | ||
| 148 | + * Withholding self-admin in a security-restricted operation prevents | ||
| 149 | + * object owners from harnessing the session user identity during | ||
| 150 | + * administrative maintenance. Suppose Alice owns a database, has | ||
| 151 | + * issued "GRANT alice TO bob", and runs a daily ANALYZE. Bob creates | ||
| 152 | + * an alice-owned SECURITY DEFINER function that issues "REVOKE alice | ||
| 153 | + * FROM carol". If he creates an expression index calling that | ||
| 154 | + * function, Alice will attempt the REVOKE during each ANALYZE. | ||
| 155 | + * Checking InSecurityRestrictedOperation() thwarts that attack. | ||
| 156 | + * | ||
| 157 | + * Withholding self-admin in SECURITY DEFINER functions makes their | ||
| 158 | + * behavior independent of the calling user. There's no security or | ||
| 159 | + * SQL-standard-conformance need for that restriction, though. | ||
| 160 | + * | ||
| 161 | + * A role cannot have actual WITH ADMIN OPTION on itself, because that | ||
| 162 | + * would imply a membership loop. Therefore, we're done either way. | ||
| 163 | + */ | ||
| 164 | + return member == GetSessionUserId() && | ||
| 165 | + !InLocalUserIdChange() && !InSecurityRestrictedOperation(); | ||
| 166 | + | ||
| 167 | /* | ||
| 168 | * Find all the roles that member is a member of, including multi-level | ||
| 169 | * recursion. We build a list in the same way that is_member_of_role does | ||
| 170 | diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out | ||
| 171 | index e8930cb..bc6d731 100644 | ||
| 172 | --- a/src/test/regress/expected/privileges.out | ||
| 173 | +++ b/src/test/regress/expected/privileges.out | ||
| 174 | @@ -32,7 +32,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4; | ||
| 175 | ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate | ||
| 176 | NOTICE: role "regressuser2" is already a member of role "regressgroup2" | ||
| 177 | ALTER GROUP regressgroup2 DROP USER regressuser2; | ||
| 178 | -ALTER GROUP regressgroup2 ADD USER regressuser4; | ||
| 179 | +GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION; | ||
| 180 | -- test owner privileges | ||
| 181 | SET SESSION AUTHORIZATION regressuser1; | ||
| 182 | SELECT session_user, current_user; | ||
| 183 | @@ -929,6 +929,40 @@ SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION') | ||
| 184 | t | ||
| 185 | (1 row) | ||
| 186 | |||
| 187 | +-- Admin options | ||
| 188 | +SET SESSION AUTHORIZATION regressuser4; | ||
| 189 | +CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS | ||
| 190 | + 'GRANT regressgroup2 TO regressuser5'; | ||
| 191 | +GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION | ||
| 192 | +SET ROLE regressgroup2; | ||
| 193 | +GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege | ||
| 194 | +ERROR: must have admin option on role "regressgroup2" | ||
| 195 | +SET SESSION AUTHORIZATION regressuser1; | ||
| 196 | +GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION | ||
| 197 | +ERROR: must have admin option on role "regressgroup2" | ||
| 198 | +SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN | ||
| 199 | +NOTICE: role "regressuser5" is already a member of role "regressgroup2" | ||
| 200 | +CONTEXT: SQL function "dogrant_ok" statement 1 | ||
| 201 | + dogrant_ok | ||
| 202 | +------------ | ||
| 203 | + | ||
| 204 | +(1 row) | ||
| 205 | + | ||
| 206 | +SET ROLE regressgroup2; | ||
| 207 | +GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help | ||
| 208 | +ERROR: must have admin option on role "regressgroup2" | ||
| 209 | +SET SESSION AUTHORIZATION regressgroup2; | ||
| 210 | +GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin | ||
| 211 | +NOTICE: role "regressuser5" is already a member of role "regressgroup2" | ||
| 212 | +CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS | ||
| 213 | + 'GRANT regressgroup2 TO regressuser5'; | ||
| 214 | +SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER | ||
| 215 | +ERROR: must have admin option on role "regressgroup2" | ||
| 216 | +CONTEXT: SQL function "dogrant_fails" statement 1 | ||
| 217 | +DROP FUNCTION dogrant_fails(); | ||
| 218 | +SET SESSION AUTHORIZATION regressuser4; | ||
| 219 | +DROP FUNCTION dogrant_ok(); | ||
| 220 | +REVOKE regressgroup2 FROM regressuser5; | ||
| 221 | -- has_sequence_privilege tests | ||
| 222 | \c - | ||
| 223 | CREATE SEQUENCE x_seq; | ||
| 224 | diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql | ||
| 225 | index d4d328e..5f1018a 100644 | ||
| 226 | --- a/src/test/regress/sql/privileges.sql | ||
| 227 | +++ b/src/test/regress/sql/privileges.sql | ||
| 228 | @@ -37,7 +37,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4; | ||
| 229 | |||
| 230 | ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate | ||
| 231 | ALTER GROUP regressgroup2 DROP USER regressuser2; | ||
| 232 | -ALTER GROUP regressgroup2 ADD USER regressuser4; | ||
| 233 | +GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION; | ||
| 234 | |||
| 235 | -- test owner privileges | ||
| 236 | |||
| 237 | @@ -581,6 +581,33 @@ SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- false | ||
| 238 | SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true | ||
| 239 | |||
| 240 | |||
| 241 | +-- Admin options | ||
| 242 | + | ||
| 243 | +SET SESSION AUTHORIZATION regressuser4; | ||
| 244 | +CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS | ||
| 245 | + 'GRANT regressgroup2 TO regressuser5'; | ||
| 246 | +GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION | ||
| 247 | +SET ROLE regressgroup2; | ||
| 248 | +GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege | ||
| 249 | + | ||
| 250 | +SET SESSION AUTHORIZATION regressuser1; | ||
| 251 | +GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION | ||
| 252 | +SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN | ||
| 253 | +SET ROLE regressgroup2; | ||
| 254 | +GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help | ||
| 255 | + | ||
| 256 | +SET SESSION AUTHORIZATION regressgroup2; | ||
| 257 | +GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin | ||
| 258 | +CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS | ||
| 259 | + 'GRANT regressgroup2 TO regressuser5'; | ||
| 260 | +SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER | ||
| 261 | +DROP FUNCTION dogrant_fails(); | ||
| 262 | + | ||
| 263 | +SET SESSION AUTHORIZATION regressuser4; | ||
| 264 | +DROP FUNCTION dogrant_ok(); | ||
| 265 | +REVOKE regressgroup2 FROM regressuser5; | ||
| 266 | + | ||
| 267 | + | ||
| 268 | -- has_sequence_privilege tests | ||
| 269 | \c - | ||
| 270 | |||
| 271 | -- | ||
| 272 | 1.7.5.4 | ||
| 273 | |||
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 \ | |||
| 32 | file://postgresql.service \ | 32 | file://postgresql.service \ |
| 33 | file://0001-Use-pkg-config-for-libxml2-detection.patch \ | 33 | file://0001-Use-pkg-config-for-libxml2-detection.patch \ |
| 34 | file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \ | 34 | file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \ |
| 35 | file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \ | ||
| 35 | " | 36 | " |
| 36 | 37 | ||
| 37 | LEAD_SONAME = "libpq.so" | 38 | LEAD_SONAME = "libpq.so" |
