Remove the row_security=force GUC value.
authorNoah Misch <[email protected]>
Mon, 21 Sep 2015 00:45:41 +0000 (20:45 -0400)
committerNoah Misch <[email protected]>
Mon, 21 Sep 2015 00:45:41 +0000 (20:45 -0400)
Every query of a single ENABLE ROW SECURITY table has two meanings, with
the row_security GUC selecting between them.  With row_security=force
available, every function author would have been advised to either set
the GUC locally or test both meanings.  Non-compliance would have
threatened reliability and, for SECURITY DEFINER functions, security.
Authors already face an obligation to account for search_path, and we
should not mimic that example.  With this change, only BYPASSRLS roles
need exercise the aforementioned care.  Back-patch to 9.5, where the
row_security GUC was introduced.

Since this narrows the domain of pg_db_role_setting.setconfig and
pg_proc.proconfig, one might bump catversion.  A row_security=force
setting in one of those columns will elicit a clear message, so don't.

doc/src/sgml/config.sgml
doc/src/sgml/ddl.sgml
src/backend/utils/misc/guc.c
src/backend/utils/misc/rls.c
src/include/utils/plancache.h
src/include/utils/rls.h
src/test/regress/expected/rowsecurity.out
src/test/regress/sql/rowsecurity.sql

index 963838c2bafc30beff32a082de2c79956d44afe4..5c6d93fe07a5acf7fc2a884c9652a59d8c368296 100644 (file)
@@ -5549,10 +5549,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         to queries which are run against tables that have row security enabled.
         The default is <literal>on</>.  When set to <literal>on</>, all users,
         except superusers and the owner of the table, will have the row
-        policies for the table applied to their queries. The table owner and
-        superuser can request that row policies be applied to their queries by
-        setting this to <literal>force</>. Lastly, this can also be set to
-        <literal>off</> which will bypass row policies for the table, if
+        policies for the table applied to their queries.  When set to
+        <literal>off</>, queries will bypass row policies for the table, if
         possible, and error if not.
        </para>
 
@@ -5565,13 +5563,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         returned.
        </para>
 
-       <para>
-        The allowed values of <varname>row_security</> are
-        <literal>on</> (apply normally - not to superuser or table owner),
-        <literal>off</> (fail if row security would be applied), and
-        <literal>force</> (apply always - even to superuser and table owner).
-       </para>
-
        <para>
         For more information on row security policies,
         see <xref linkend="SQL-CREATEPOLICY">.
index d78767ddd23fbbe449098e9d41f923b203c00ea7..ab0c19122a0150482441000eee7ef1800c888716 100644 (file)
@@ -1585,16 +1585,13 @@ REVOKE ALL ON accounts FROM PUBLIC;
 
   <para>
    The table owners and superusers bypass the row security system when
-   querying a table, by default.  Row security can be enabled for
-   superusers and table owners by setting
-   <xref linkend="guc-row-security"> to <literal>force</literal>.  Any
-   user can request that row security be bypassed by setting
-   <xref linkend="guc-row-security"> to <literal>off</literal>.  If
-   the user does not have privileges to bypass row security when
-   querying a given table then an error will be returned instead.  Other
-   users can be granted the ability to bypass the row security system
-   with the <literal>BYPASSRLS</literal> role attribute.  This
-   attribute can only be set by a superuser.
+   querying a table.  Any user can request that row security be bypassed by
+   setting <xref linkend="guc-row-security"> to <literal>off</literal>.  If
+   the user does not have privileges to bypass row security when querying a
+   given table then an error will be returned instead.  Other users can be
+   granted the ability to bypass the row security system with
+   the <literal>BYPASSRLS</literal> role attribute.  This attribute can only
+   be set by a superuser.
   </para>
 
   <para>
index 8ebf4246b8e5247e89c08c281cfb75d65caf22dc..fcba3c59d03a93862f27aa4a7d12ab09d0e4b26c 100644 (file)
@@ -379,23 +379,6 @@ static const struct config_enum_entry huge_pages_options[] = {
        {NULL, 0, false}
 };
 
-/*
- * Although only "on", "off", and "force" are documented, we
- * accept all the likely variants of "on" and "off".
- */
-static const struct config_enum_entry row_security_options[] = {
-       {"on", ROW_SECURITY_ON, false},
-       {"off", ROW_SECURITY_OFF, false},
-       {"force", ROW_SECURITY_FORCE, false},
-       {"true", ROW_SECURITY_ON, true},
-       {"false", ROW_SECURITY_OFF, true},
-       {"yes", ROW_SECURITY_ON, true},
-       {"no", ROW_SECURITY_OFF, true},
-       {"1", ROW_SECURITY_ON, true},
-       {"0", ROW_SECURITY_OFF, true},
-       {NULL, 0, false}
-};
-
 /*
  * Options for enum values stored in other modules
  */
@@ -421,6 +404,7 @@ bool                log_statement_stats = false;            /* this is sort of all three
 bool           log_btree_build_stats = false;
 char      *event_source;
 
+bool           row_security;
 bool           check_function_bodies = true;
 bool           default_with_oids = false;
 bool           SQL_inheritance = true;
@@ -452,8 +436,6 @@ int                 tcp_keepalives_idle;
 int                    tcp_keepalives_interval;
 int                    tcp_keepalives_count;
 
-int                    row_security;
-
 /*
  * This really belongs in pg_shmem.c, but is defined here so that it doesn't
  * need to be duplicated in all the different implementations of pg_shmem.c.
@@ -1373,6 +1355,15 @@ static struct config_bool ConfigureNamesBool[] =
                false,
                check_transaction_deferrable, NULL, NULL
        },
+       {
+               {"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
+                       gettext_noop("Enable row security."),
+                       gettext_noop("When enabled, row security will be applied to all users.")
+               },
+               &row_security,
+               true,
+               NULL, NULL, NULL
+       },
        {
                {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
                        gettext_noop("Check function bodies during CREATE FUNCTION."),
@@ -3630,16 +3621,6 @@ static struct config_enum ConfigureNamesEnum[] =
                NULL, NULL, NULL
        },
 
-       {
-               {"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
-                       gettext_noop("Enable row security."),
-                       gettext_noop("When enabled, row security will be applied to all users.")
-               },
-               &row_security,
-               ROW_SECURITY_ON, row_security_options,
-               NULL, NULL, NULL
-       },
-
        /* End-of-list marker */
        {
                {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
index 7b8d51d956f2961a081fede0622fd123cf2f6ff2..abaf344506801cbdde3c74608d7558fb77f2f8ef 100644 (file)
@@ -87,32 +87,19 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
        /*
         * Check permissions
         *
-        * If the relation has row level security enabled and the row_security GUC
-        * is off, then check if the user has rights to bypass RLS for this
-        * relation.  Table owners can always bypass, as can any role with the
-        * BYPASSRLS capability.
-        *
-        * If the role is the table owner, then we bypass RLS unless row_security
-        * is set to 'force'.  Note that superuser is always considered an owner.
-        *
-        * Return RLS_NONE_ENV to indicate that this decision depends on the
-        * environment (in this case, what the current values of user_id and
-        * row_security are).
+        * 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).
         */
-       if (row_security != ROW_SECURITY_FORCE
-               && (pg_class_ownercheck(relid, user_id)))
+       if (pg_class_ownercheck(relid, user_id))
                return RLS_NONE_ENV;
 
        /*
-        * If the row_security GUC is 'off' then check if the user has permission
-        * to bypass it.  Note that we have already handled the case where the
-        * user is the table owner above.
-        *
-        * Note that row_security is always considered 'on' when querying through
-        * a view or other cases where checkAsUser is true, so skip this if
-        * checkAsUser is in use.
+        * 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 (!checkAsUser && row_security == ROW_SECURITY_OFF)
+       if (!row_security && !checkAsUser)
        {
                if (has_bypassrls_privilege(user_id))
                        /* OK to bypass */
index 90a018082f09623381c6ece08f167f71ea82dd8e..b683b070e3517c51d0b53157fc0121b3561d3044 100644 (file)
@@ -110,7 +110,7 @@ typedef struct CachedPlanSource
        double          total_custom_cost;              /* total cost of custom plans so far */
        int                     num_custom_plans;               /* number of plans included in total */
        bool            hasRowSecurity; /* planned with row security? */
-       int                     row_security_env;               /* row security setting when planned */
+       bool            row_security_env;               /* row security setting when planned */
        bool            rowSecurityDisabled;    /* is row security disabled? */
 } CachedPlanSource;
 
index 3770ddc2163ea2fb37acdeb01289332b0441f3e2..3e75f06d6cfc70f3e8dac103a9d599faa9a07187 100644 (file)
 #define RLS_H
 
 /* GUC variable */
-extern int     row_security;
-
-/* Possible values for row_security GUC */
-typedef enum RowSecurityConfigType
-{
-       ROW_SECURITY_OFF,                       /* RLS never applied- error thrown if no priv */
-       ROW_SECURITY_ON,                        /* normal case, RLS applied for regular users */
-       ROW_SECURITY_FORCE                      /* RLS applied for superusers and table owners */
-}      RowSecurityConfigType;
+extern bool row_security;
 
 /*
  * Used by callers of check_enable_rls.
@@ -30,7 +22,7 @@ typedef enum RowSecurityConfigType
  * RLS could be completely disabled on the tables involved in the query,
  * which is the simple case, or it may depend on the current environment
  * (the role which is running the query or the value of the row_security
- * GUC- on, off, or force), or it might be simply enabled as usual.
+ * GUC), or it might be simply enabled as usual.
  *
  * If RLS isn't on the table involved then RLS_NONE is returned to indicate
  * that we don't need to worry about invalidating the query plan for RLS
index 7628e52901a270eee86cebec0bb22ee51573d4f7..9d3540fb1ea68a969e7d1763a0db03377d6d914b 100644 (file)
@@ -359,19 +359,6 @@ SELECT * FROM category;
   44 | manga
 (4 rows)
 
--- database superuser does not bypass RLS policy when FORCE enabled.
-RESET SESSION AUTHORIZATION;
-SET row_security TO FORCE;
-SELECT * FROM document;
- did | cid | dlevel | dauthor | dtitle 
------+-----+--------+---------+--------
-(0 rows)
-
-SELECT * FROM category;
- cid | cname 
------+-------
-(0 rows)
-
 -- database superuser does bypass RLS policy when disabled
 RESET SESSION AUTHORIZATION;
 SET row_security TO OFF;
@@ -424,19 +411,6 @@ SELECT * FROM category;
   44 | manga
 (4 rows)
 
--- RLS policy applies to table owner when FORCE enabled.
-SET SESSION AUTHORIZATION rls_regress_user0;
-SET row_security TO FORCE;
-SELECT * FROM document;
- did | cid | dlevel | dauthor | dtitle 
------+-----+--------+---------+--------
-(0 rows)
-
-SELECT * FROM category;
- cid | cname 
------+-------
-(0 rows)
-
 -- RLS policy does not apply to table owner when RLS enabled.
 SET SESSION AUTHORIZATION rls_regress_user0;
 SET row_security TO ON;
@@ -2520,35 +2494,6 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1;
  Seq Scan on t1
 (1 row)
 
--- Check that default deny does apply to superuser when RLS force.
-SET row_security TO FORCE;
-RESET SESSION AUTHORIZATION;
-SELECT * FROM t1;
- a | b 
----+---
-(0 rows)
-
-EXPLAIN (COSTS OFF) SELECT * FROM t1;
-        QUERY PLAN        
---------------------------
- Result
-   One-Time Filter: false
-(2 rows)
-
--- Check that default deny does apply to table owner when RLS force.
-SET SESSION AUTHORIZATION rls_regress_user0;
-SELECT * FROM t1;
- a | b 
----+---
-(0 rows)
-
-EXPLAIN (COSTS OFF) SELECT * FROM t1;
-        QUERY PLAN        
---------------------------
- Result
-   One-Time Filter: false
-(2 rows)
-
 -- Check that default deny applies to non-owner/non-superuser when RLS on.
 SET SESSION AUTHORIZATION rls_regress_user1;
 SET row_security TO ON;
@@ -2616,14 +2561,6 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
 8,c9f0f895fb98ab9159f51fd0297e236d
 9,45c48cce2e2d7fbdea1afc51c7c6ad26
 10,d3d9446802a44259755d38e6d163e820
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
-0,cfcd208495d565ef66e7dff9f98764da
-2,c81e728d9d4c2f636f067f89cc14862c
-4,a87ff679a2f3e71d9181a67b7542122c
-6,1679091c5a880faf6fb5e6087eb1b2dc
-8,c9f0f895fb98ab9159f51fd0297e236d
-10,d3d9446802a44259755d38e6d163e820
 -- Check COPY TO as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
 SET row_security TO OFF;
@@ -2637,14 +2574,6 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
 6,1679091c5a880faf6fb5e6087eb1b2dc
 8,c9f0f895fb98ab9159f51fd0297e236d
 10,d3d9446802a44259755d38e6d163e820
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
-0,cfcd208495d565ef66e7dff9f98764da
-2,c81e728d9d4c2f636f067f89cc14862c
-4,a87ff679a2f3e71d9181a67b7542122c
-6,1679091c5a880faf6fb5e6087eb1b2dc
-8,c9f0f895fb98ab9159f51fd0297e236d
-10,d3d9446802a44259755d38e6d163e820
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
 SET row_security TO OFF;
@@ -2668,14 +2597,6 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
 6,1679091c5a880faf6fb5e6087eb1b2dc
 8,c9f0f895fb98ab9159f51fd0297e236d
 10,d3d9446802a44259755d38e6d163e820
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
-0,cfcd208495d565ef66e7dff9f98764da
-2,c81e728d9d4c2f636f067f89cc14862c
-4,a87ff679a2f3e71d9181a67b7542122c
-6,1679091c5a880faf6fb5e6087eb1b2dc
-8,c9f0f895fb98ab9159f51fd0297e236d
-10,d3d9446802a44259755d38e6d163e820
 -- Check COPY TO as user without permissions. SET row_security TO OFF;
 SET SESSION AUTHORIZATION rls_regress_user2;
 SET row_security TO OFF;
@@ -2684,9 +2605,6 @@ ERROR:  insufficient privilege to bypass row security.
 SET row_security TO ON;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
 ERROR:  permission denied for relation copy_t
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
-ERROR:  permission denied for relation copy_t
 -- Check COPY relation TO; keep it just one row to avoid reordering issues
 RESET SESSION AUTHORIZATION;
 SET row_security TO ON;
@@ -2703,8 +2621,6 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
 1,c4ca4238a0b923820dcc509a6f75849b
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
 -- Check COPY TO as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
 SET row_security TO OFF;
@@ -2712,8 +2628,6 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - insufficient to bypass r
 ERROR:  insufficient privilege to bypass row security.
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
 SET row_security TO OFF;
@@ -2721,8 +2635,6 @@ 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
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
 -- Check COPY TO as user without permissions. SET row_security TO OFF;
 SET SESSION AUTHORIZATION rls_regress_user2;
 SET row_security TO OFF;
@@ -2731,19 +2643,12 @@ ERROR:  permission denied for relation copy_rel_to
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
 ERROR:  permission denied for relation copy_rel_to
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
-ERROR:  permission denied for relation copy_rel_to
 -- Check COPY FROM as Superuser/owner.
 RESET SESSION AUTHORIZATION;
 SET row_security TO OFF;
 COPY copy_t FROM STDIN; --ok
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --ok
-SET row_security TO FORCE;
-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 FROM as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
 SET row_security TO OFF;
@@ -2753,10 +2658,6 @@ 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.
-SET row_security TO FORCE;
-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
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
 SET row_security TO OFF;
@@ -2765,10 +2666,6 @@ 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.
-SET row_security TO FORCE;
-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 FROM as user without permissions.
 SET SESSION AUTHORIZATION rls_regress_user2;
 SET row_security TO OFF;
@@ -2777,9 +2674,6 @@ ERROR:  permission denied for relation copy_t
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --fail - permission denied.
 ERROR:  permission denied for relation copy_t
-SET row_security TO FORCE;
-COPY copy_t FROM STDIN; --fail - permission denied.
-ERROR:  permission denied for relation copy_t
 RESET SESSION AUTHORIZATION;
 DROP TABLE copy_t;
 DROP TABLE copy_rel_to CASCADE;
@@ -2932,16 +2826,17 @@ SELECT attname, most_common_vals FROM pg_stats
 -- Collation support
 --
 BEGIN;
-SET row_security TO FORCE;
 CREATE TABLE coll_t (c) AS VALUES ('bar'::text);
 CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C"));
 ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY;
+GRANT SELECT ON coll_t TO rls_regress_user0;
 SELECT (string_to_array(polqual, ':'))[7] AS inputcollid FROM pg_policy WHERE polrelid = 'coll_t'::regclass;
    inputcollid    
 ------------------
  inputcollid 950 
 (1 row)
 
+SET SESSION AUTHORIZATION rls_regress_user0;
 SELECT * FROM coll_t;
   c  
 -----
@@ -3008,7 +2903,6 @@ ROLLBACK; -- cleanup
 -- Converting table to view
 --
 BEGIN;
-SET ROW_SECURITY = FORCE;
 CREATE TABLE t (c int);
 CREATE POLICY p ON t USING (c % 2 = 1);
 ALTER TABLE t ENABLE ROW LEVEL SECURITY;
@@ -3031,7 +2925,6 @@ ROLLBACK;
 -- Policy expression handling
 --
 BEGIN;
-SET row_security = FORCE;
 CREATE TABLE t (c) AS VALUES ('bar'::text);
 CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in policy expressions
 ERROR:  aggregate functions are not allowed in policy expressions
index e8c09e9043135949112bfc1155c981f514ae6166..933c83e5579a19098e2b6a6fca5272884b24022a 100644 (file)
@@ -164,12 +164,6 @@ SET row_security TO ON;
 SELECT * FROM document;
 SELECT * FROM category;
 
--- database superuser does not bypass RLS policy when FORCE enabled.
-RESET SESSION AUTHORIZATION;
-SET row_security TO FORCE;
-SELECT * FROM document;
-SELECT * FROM category;
-
 -- database superuser does bypass RLS policy when disabled
 RESET SESSION AUTHORIZATION;
 SET row_security TO OFF;
@@ -182,12 +176,6 @@ SET row_security TO OFF;
 SELECT * FROM document;
 SELECT * FROM category;
 
--- RLS policy applies to table owner when FORCE enabled.
-SET SESSION AUTHORIZATION rls_regress_user0;
-SET row_security TO FORCE;
-SELECT * FROM document;
-SELECT * FROM category;
-
 -- RLS policy does not apply to table owner when RLS enabled.
 SET SESSION AUTHORIZATION rls_regress_user0;
 SET row_security TO ON;
@@ -966,17 +954,6 @@ SET SESSION AUTHORIZATION rls_regress_user0;
 SELECT * FROM t1;
 EXPLAIN (COSTS OFF) SELECT * FROM t1;
 
--- Check that default deny does apply to superuser when RLS force.
-SET row_security TO FORCE;
-RESET SESSION AUTHORIZATION;
-SELECT * FROM t1;
-EXPLAIN (COSTS OFF) SELECT * FROM t1;
-
--- Check that default deny does apply to table owner when RLS force.
-SET SESSION AUTHORIZATION rls_regress_user0;
-SELECT * FROM t1;
-EXPLAIN (COSTS OFF) SELECT * FROM t1;
-
 -- Check that default deny applies to non-owner/non-superuser when RLS on.
 SET SESSION AUTHORIZATION rls_regress_user1;
 SET row_security TO ON;
@@ -1007,8 +984,6 @@ SET row_security TO OFF;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
 SET row_security TO ON;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
 
 -- Check COPY TO as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
@@ -1016,8 +991,6 @@ SET row_security TO OFF;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - insufficient to bypass rls
 SET row_security TO ON;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
 
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
@@ -1025,8 +998,6 @@ SET row_security TO OFF;
 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
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
 
 -- Check COPY TO as user without permissions. SET row_security TO OFF;
 SET SESSION AUTHORIZATION rls_regress_user2;
@@ -1034,8 +1005,6 @@ SET row_security TO OFF;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - insufficient to bypass rls
 SET row_security TO ON;
 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
-SET row_security TO FORCE;
-COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
 
 -- Check COPY relation TO; keep it just one row to avoid reordering issues
 RESET SESSION AUTHORIZATION;
@@ -1055,8 +1024,6 @@ SET row_security TO OFF;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
 
 -- Check COPY TO as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
@@ -1064,8 +1031,6 @@ SET row_security TO OFF;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - insufficient to bypass rls
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
 
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
@@ -1073,8 +1038,6 @@ SET row_security TO OFF;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
 
 -- Check COPY TO as user without permissions. SET row_security TO OFF;
 SET SESSION AUTHORIZATION rls_regress_user2;
@@ -1082,8 +1045,6 @@ SET row_security TO OFF;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
 SET row_security TO ON;
 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
-SET row_security TO FORCE;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
 
 -- Check COPY FROM as Superuser/owner.
 RESET SESSION AUTHORIZATION;
@@ -1101,8 +1062,6 @@ COPY copy_t FROM STDIN; --ok
 3      cde
 4      def
 \.
-SET row_security TO FORCE;
-COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
 
 -- Check COPY FROM as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
@@ -1110,8 +1069,6 @@ SET row_security TO OFF;
 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.
-SET row_security TO FORCE;
-COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
 
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
@@ -1124,8 +1081,6 @@ COPY copy_t FROM STDIN; --ok
 \.
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-SET row_security TO FORCE;
-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;
@@ -1133,8 +1088,6 @@ SET row_security TO OFF;
 COPY copy_t FROM STDIN; --fail - permission denied.
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --fail - permission denied.
-SET row_security TO FORCE;
-COPY copy_t FROM STDIN; --fail - permission denied.
 
 RESET SESSION AUTHORIZATION;
 DROP TABLE copy_t;
@@ -1212,11 +1165,12 @@ SELECT attname, most_common_vals FROM pg_stats
 -- Collation support
 --
 BEGIN;
-SET row_security TO FORCE;
 CREATE TABLE coll_t (c) AS VALUES ('bar'::text);
 CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C"));
 ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY;
+GRANT SELECT ON coll_t TO rls_regress_user0;
 SELECT (string_to_array(polqual, ':'))[7] AS inputcollid FROM pg_policy WHERE polrelid = 'coll_t'::regclass;
+SET SESSION AUTHORIZATION rls_regress_user0;
 SELECT * FROM coll_t;
 ROLLBACK;
 
@@ -1268,7 +1222,6 @@ ROLLBACK; -- cleanup
 -- Converting table to view
 --
 BEGIN;
-SET ROW_SECURITY = FORCE;
 CREATE TABLE t (c int);
 CREATE POLICY p ON t USING (c % 2 = 1);
 ALTER TABLE t ENABLE ROW LEVEL SECURITY;
@@ -1293,7 +1246,6 @@ ROLLBACK;
 -- Policy expression handling
 --
 BEGIN;
-SET row_security = FORCE;
 CREATE TABLE t (c) AS VALUES ('bar'::text);
 CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in policy expressions
 ROLLBACK;