Remove the SECURITY_ROW_LEVEL_DISABLED security context bit.
authorNoah Misch <[email protected]>
Mon, 21 Sep 2015 00:47:17 +0000 (20:47 -0400)
committerPavan Deolasee <[email protected]>
Wed, 26 Oct 2016 07:55:36 +0000 (13:25 +0530)
This commit's parent made superfluous the bit's sole usage.  Referential
integrity checks have long run as the subject table's owner, and that
now implies RLS bypass.  Safe use of the bit was tricky, requiring
strict control over the SQL expressions evaluating therein.  Back-patch
to 9.5, where the bit was introduced.

Based on a patch by Stephen Frost.

src/backend/utils/adt/ri_triggers.c
src/backend/utils/cache/plancache.c
src/backend/utils/misc/rls.c
src/include/miscadmin.h
src/include/utils/plancache.h

index 2b6116b667e9009b21510a55792554d9024d8362..3f9d56876033626cb8c7f051febc117b0685e1e7 100644 (file)
@@ -2977,7 +2977,6 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
        Relation        query_rel;
        Oid                     save_userid;
        int                     save_sec_context;
-       int                     temp_sec_context;
 
        /*
         * Use the query type code to determine whether the query is run against
@@ -2990,22 +2989,8 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
 
        /* Switch to proper UID to perform check as */
        GetUserIdAndSecContext(&save_userid, &save_sec_context);
-
-       /*
-        * Row-level security should be disabled in the case where a foreign-key
-        * relation is queried to check existence of tuples that references the
-        * primary-key being modified.
-        */
-       temp_sec_context = save_sec_context | SECURITY_LOCAL_USERID_CHANGE;
-       if (qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK
-               || qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK_FROM_PK
-               || qkey->constr_queryno == RI_PLAN_RESTRICT_DEL_CHECKREF
-               || qkey->constr_queryno == RI_PLAN_RESTRICT_UPD_CHECKREF)
-               temp_sec_context |= SECURITY_ROW_LEVEL_DISABLED;
-
-
        SetUserIdAndSecContext(RelationGetForm(query_rel)->relowner,
-                                                  temp_sec_context);
+                                                  save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
 
        /* Create the plan */
        qplan = SPI_prepare(querystr, nargs, argtypes);
index 466af13bb98ce0a95cf5fa5a7b14f8b1ae5a5669..49c047e0724952e2ebe866220f44547ebf9f3540 100644 (file)
@@ -225,8 +225,6 @@ CreateCachedPlan(Node *raw_parse_tree,
        plansource->total_custom_cost = 0;
        plansource->num_custom_plans = 0;
        plansource->hasRowSecurity = false;
-       plansource->rowSecurityDisabled
-               = (security_context & SECURITY_ROW_LEVEL_DISABLED) != 0;
        plansource->planUserId = InvalidOid;
        plansource->row_security_env = false;
 
@@ -650,17 +648,10 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
        }
 
        /*
-        * Check if row security is enabled for this query and things have changed
-        * such that we need to invalidate this plan and rebuild it.  Note that if
-        * row security was explicitly disabled (eg: this is a FK check plan) then
-        * we don't invalidate due to RLS.
-        *
-        * Otherwise, if the plan has a possible RLS dependency, force a replan if
-        * either the role under which the plan was planned or the row_security
-        * setting has been changed.
+        * If the plan has a possible RLS dependency, force a replan if either the
+        * role or the row_security setting has changed.
         */
        if (plansource->is_valid
-               && !plansource->rowSecurityDisabled
                && plansource->hasRowSecurity
                && (plansource->planUserId != GetUserId()
                        || plansource->row_security_env != row_security))
index 44cb3743034a16fcba4f5bac39160e743fd00136..3350f10c9f689e770ff51c0d8fd9a25b903eec43 100644 (file)
@@ -53,6 +53,10 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
        bool            relrowsecurity;
        Oid                     user_id = checkAsUser ? checkAsUser : GetUserId();
 
+       /* Nothing to do for built-in relations */
+       if (relid < FirstNormalObjectId)
+               return RLS_NONE;
+
        tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
        if (!HeapTupleIsValid(tuple))
                return RLS_NONE;
index b6ea2ae7425cc6b3aded6910cdc851368136dc72..be1cb664dfa85f4b46c2810a6d5a73e05fb3b057 100644 (file)
@@ -291,7 +291,6 @@ extern int  trace_recovery(int trace_level);
 /* flags to be OR'd to form sec_context */
 #define SECURITY_LOCAL_USERID_CHANGE   0x0001
 #define SECURITY_RESTRICTED_OPERATION  0x0002
-#define SECURITY_ROW_LEVEL_DISABLED            0x0004
 
 extern char *DatabasePath;
 
index 19654fb48c37726aaa76526d1473e6130432e029..af73478c4041f6091f2bc900198676b76a337c9b 100644 (file)
@@ -113,9 +113,8 @@ typedef struct CachedPlanSource
 #ifdef PGXC
        char       *stmt_name;          /* If set, this is a copy of prepared stmt name */
 #endif
-       bool            hasRowSecurity;                 /* planned with row security? */
-       int                     row_security_env;               /* row security setting when planned */
-       bool            rowSecurityDisabled;    /* is row security disabled? */
+       bool            hasRowSecurity; /* planned with row security? */
+       bool            row_security_env;               /* row security setting when planned */
 } CachedPlanSource;
 
 /*