aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2015-10-03 20:19:57 -0400
committerNoah Misch <noah@leadboat.com>2015-10-03 20:20:50 -0400
commit01ba7894f3f72ea57d1cfdc4f40f6231bc6cd9cd (patch)
tree8153ebad55cc49f2cb534ec4be5c2e8f96d3071c /src
parentcfddb5df5a84923160b23890d6086bcbcd1fd655 (diff)
downloadpostgresql-01ba7894f3f72ea57d1cfdc4f40f6231bc6cd9cd.tar.gz
postgresql-01ba7894f3f72ea57d1cfdc4f40f6231bc6cd9cd.zip
Make BYPASSRLS behave like superuser RLS bypass.
Specifically, make its effect independent from the row_security GUC, and make it affect permission checks pertinent to views the BYPASSRLS role owns. The row_security GUC thereby ceases to change successful-query behavior; it can only make a query fail with an error. Back-patch to 9.5, where BYPASSRLS was introduced.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/misc/rls.c39
-rw-r--r--src/include/catalog/pg_authid.h2
-rw-r--r--src/test/regress/expected/rowsecurity.out14
-rw-r--r--src/test/regress/sql/rowsecurity.sql6
4 files changed, 23 insertions, 38 deletions
diff --git a/src/backend/utils/misc/rls.c b/src/backend/utils/misc/rls.c
index c900c98848b..eaf9d6e66ff 100644
--- a/src/backend/utils/misc/rls.c
+++ b/src/backend/utils/misc/rls.c
@@ -40,10 +40,8 @@ extern int check_enable_rls(Oid relid, Oid checkAsUser, bool noError);
* for the table and the plan cache needs to be invalidated if the environment
* changes.
*
- * Handle checking as another role via checkAsUser (for views, etc). Note that
- * if *not* checking as another role, the caller should pass InvalidOid rather
- * than GetUserId(). Otherwise the check for row_security = OFF is skipped, and
- * so we may falsely report that RLS is active when the user has bypassed it.
+ * Handle checking as another role via checkAsUser (for views, etc). Pass
+ * InvalidOid to check the current user.
*
* If noError is set to 'true' then we just return RLS_ENABLED instead of doing
* an ereport() if the user has attempted to bypass RLS and they are not
@@ -78,32 +76,19 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
return RLS_NONE;
/*
- * Check permissions
- *
- * Table owners always bypass RLS. Note that superuser is always
- * considered an owner. Return RLS_NONE_ENV to indicate that this
- * decision depends on the environment (in this case, the user_id).
+ * Table owners and BYPASSRLS users bypass RLS. Note that a superuser
+ * qualifies as both. Return RLS_NONE_ENV to indicate that this decision
+ * depends on the environment (in this case, the user_id).
*/
- if (pg_class_ownercheck(relid, user_id))
+ if (pg_class_ownercheck(relid, user_id) ||
+ has_bypassrls_privilege(user_id))
return RLS_NONE_ENV;
- /*
- * If the row_security GUC is 'off', check if the user has permission to
- * bypass RLS. row_security is always considered 'on' when querying
- * through a view or other cases where checkAsUser is valid.
- */
- if (!row_security && !checkAsUser)
- {
- if (has_bypassrls_privilege(user_id))
- /* OK to bypass */
- return RLS_NONE_ENV;
- else if (noError)
- return RLS_ENABLED;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("insufficient privilege to bypass row security.")));
- }
+ /* row_security GUC says to bypass RLS, but user lacks permission */
+ if (!row_security && !noError)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("insufficient privilege to bypass row security.")));
/* RLS should be fully enabled for this relation. */
return RLS_ENABLED;
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index d5f19d6aabb..2c8565ea254 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -51,7 +51,7 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MAC
bool rolcreatedb; /* allowed to create databases? */
bool rolcanlogin; /* allowed to log in as session user? */
bool rolreplication; /* role used for streaming replication */
- bool rolbypassrls; /* allowed to bypass row level security? */
+ bool rolbypassrls; /* bypasses row level security? */
int32 rolconnlimit; /* max connections allowed (-1=no limit) */
/* remaining fields may be null; use heap_getattr to read them! */
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index 0cde8fd0e3f..0363dfd07ff 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -2584,10 +2584,15 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
SET row_security TO ON;
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
0,cfcd208495d565ef66e7dff9f98764da
+1,c4ca4238a0b923820dcc509a6f75849b
2,c81e728d9d4c2f636f067f89cc14862c
+3,eccbc87e4b5ce2fe28308fd9f2a7baf3
4,a87ff679a2f3e71d9181a67b7542122c
+5,e4da3b7fbbce2345d7772b0674a318d5
6,1679091c5a880faf6fb5e6087eb1b2dc
+7,8f14e45fceea167a5a36dedd4bea2543
8,c9f0f895fb98ab9159f51fd0297e236d
+9,45c48cce2e2d7fbdea1afc51c7c6ad26
10,d3d9446802a44259755d38e6d163e820
-- Check COPY TO as user without permissions. SET row_security TO OFF;
SET SESSION AUTHORIZATION rls_regress_user2;
@@ -2627,6 +2632,7 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
1,c4ca4238a0b923820dcc509a6f75849b
SET row_security TO ON;
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
+1,c4ca4238a0b923820dcc509a6f75849b
-- Check COPY TO as user without permissions. SET row_security TO OFF;
SET SESSION AUTHORIZATION rls_regress_user2;
SET row_security TO OFF;
@@ -2650,14 +2656,10 @@ SET row_security TO ON;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
--- Check COPY TO as user with permissions and BYPASSRLS
+-- Check COPY FROM as user with permissions and BYPASSRLS
SET SESSION AUTHORIZATION rls_regress_exempt_user;
-SET row_security TO OFF;
-COPY copy_t FROM STDIN; --ok
SET row_security TO ON;
-COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row level security.
-HINT: Use direct INSERT statements instead.
+COPY copy_t FROM STDIN; --ok
-- Check COPY FROM as user without permissions.
SET SESSION AUTHORIZATION rls_regress_user2;
SET row_security TO OFF;
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
index 6ed0daf345f..7f8772fa26c 100644
--- a/src/test/regress/sql/rowsecurity.sql
+++ b/src/test/regress/sql/rowsecurity.sql
@@ -1070,17 +1070,15 @@ COPY copy_t FROM STDIN; --fail - insufficient privilege to bypass rls.
SET row_security TO ON;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
--- Check COPY TO as user with permissions and BYPASSRLS
+-- Check COPY FROM as user with permissions and BYPASSRLS
SET SESSION AUTHORIZATION rls_regress_exempt_user;
-SET row_security TO OFF;
+SET row_security TO ON;
COPY copy_t FROM STDIN; --ok
1 abc
2 bcd
3 cde
4 def
\.
-SET row_security TO ON;
-COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-- Check COPY FROM as user without permissions.
SET SESSION AUTHORIZATION rls_regress_user2;