• Stephen Frost's avatar
    RLS fixes, new hooks, and new test module · 0bf22e0c
    Stephen Frost authored
    In prepend_row_security_policies(), defaultDeny was always true, so if
    there were any hook policies, the RLS policies on the table would just
    get discarded.  Fixed to start off with defaultDeny as false and then
    properly set later if we detect that only the default deny policy exists
    for the internal policies.
    
    The infinite recursion detection in fireRIRrules() didn't properly
    manage the activeRIRs list in the case of WCOs, so it would incorrectly
    report infinite recusion if the same relation with RLS appeared more
    than once in the rtable, for example "UPDATE t ... FROM t ...".
    
    Further, the RLS expansion code in fireRIRrules() was handling RLS in
    the main loop through the rtable, which lead to RTEs being visited twice
    if they contained sublink subqueries, which
    prepend_row_security_policies() attempted to handle by exiting early if
    the RTE already had securityQuals.  That doesn't work, however, since
    if the query involved a security barrier view on top of a table with
    RLS, the RTE would already have securityQuals (from the view) by the
    time fireRIRrules() was invoked, and so the table's RLS policies would
    be ignored.  This is fixed in fireRIRrules() by handling RLS in a
    separate loop at the end, after dealing with any other sublink
    subqueries, thus ensuring that each RTE is only visited once for RLS
    expansion.
    
    The inheritance planner code didn't correctly handle non-target
    relations with RLS, which would get turned into subqueries during
    planning. Thus an update of the form "UPDATE t1 ... FROM t2 ..." where
    t1 has inheritance and t2 has RLS quals would fail.  Fix by making sure
    to copy in and update the securityQuals when they exist for non-target
    relations.
    
    process_policies() was adding WCOs to non-target relations, which is
    unnecessary, and could lead to a lot of wasted time in the rewriter and
    the planner. Fix by only adding WCO policies when working on the result
    relation.  Also in process_policies, we should be copying the USING
    policies to the WITH CHECK policies on a per-policy basis, fix by moving
    the copying up into the per-policy loop.
    
    Lastly, as noted by Dean, we were simply adding policies returned by the
    hook provided to the list of quals being AND'd, meaning that they would
    actually restrict records returned and there was no option to have
    internal policies and hook-based policies work together permissively (as
    all internal policies currently work).  Instead, explicitly add support
    for both permissive and restrictive policies by having a hook for each
    and combining the results appropriately.  To ensure this is all done
    correctly, add a new test module (test_rls_hooks) to test the various
    combinations of internal, permissive, and restrictive hook policies.
    
    Largely from Dean Rasheed (thanks!):
    
    CAEZATCVmFUfUOwwhnBTcgi6AquyjQ0-1fyKd0T3xBWJvn+xsFA@mail.gmail.com
    
    Author: Dean Rasheed, though I added the new hooks and test module.
    0bf22e0c
rewriteHandler.c 105 KB