diff options
Diffstat (limited to 'src/backend/utils/misc/rls.c')
-rw-r--r-- | src/backend/utils/misc/rls.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/src/backend/utils/misc/rls.c b/src/backend/utils/misc/rls.c index 44cb3743034..7b8d51d956f 100644 --- a/src/backend/utils/misc/rls.c +++ b/src/backend/utils/misc/rls.c @@ -16,9 +16,12 @@ #include "access/htup.h" #include "access/htup_details.h" +#include "access/transam.h" #include "catalog/pg_class.h" +#include "catalog/namespace.h" #include "miscadmin.h" #include "utils/acl.h" +#include "utils/builtins.h" #include "utils/elog.h" #include "utils/rls.h" #include "utils/syscache.h" @@ -37,7 +40,10 @@ 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). + * 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. * * 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 @@ -53,6 +59,17 @@ 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; + + /* + * Check if we have been told to explicitly skip RLS (perhaps because this + * is a foreign key check) + */ + if (InRowLevelSecurityDisabled()) + return RLS_NONE; + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) return RLS_NONE; @@ -111,3 +128,37 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError) /* RLS should be fully enabled for this relation. */ return RLS_ENABLED; } + +/* + * row_security_active + * + * check_enable_rls wrapped as a SQL callable function except + * RLS_NONE_ENV and RLS_NONE are the same for this purpose. + */ +Datum +row_security_active(PG_FUNCTION_ARGS) +{ + /* By OID */ + Oid tableoid = PG_GETARG_OID(0); + int rls_status; + + rls_status = check_enable_rls(tableoid, InvalidOid, true); + PG_RETURN_BOOL(rls_status == RLS_ENABLED); +} + +Datum +row_security_active_name(PG_FUNCTION_ARGS) +{ + /* By qualified name */ + text *tablename = PG_GETARG_TEXT_P(0); + RangeVar *tablerel; + Oid tableoid; + int rls_status; + + /* Look up table name. Can't lock it - we might not have privileges. */ + tablerel = makeRangeVarFromNameList(textToQualifiedNameList(tablename)); + tableoid = RangeVarGetRelid(tablerel, NoLock, false); + + rls_status = check_enable_rls(tableoid, InvalidOid, true); + PG_RETURN_BOOL(rls_status == RLS_ENABLED); +} |