PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
rls.c File Reference
#include "postgres.h"
#include "access/htup.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/elog.h"
#include "utils/lsyscache.h"
#include "utils/rls.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for rls.c:

Go to the source code of this file.

Functions

int check_enable_rls (Oid relid, Oid checkAsUser, bool noError)
 
Datum row_security_active (PG_FUNCTION_ARGS)
 
Datum row_security_active_name (PG_FUNCTION_ARGS)
 

Function Documentation

int check_enable_rls ( Oid  relid,
Oid  checkAsUser,
bool  noError 
)

Definition at line 53 of file rls.c.

References ereport, errcode(), errhint(), errmsg(), ERROR, FirstNormalObjectId, get_rel_name(), GETSTRUCT, GetUserId(), has_bypassrls_privilege(), HeapTupleIsValid, InNoForceRLSOperation(), ObjectIdGetDatum, pg_class_ownercheck(), ReleaseSysCache(), RELOID, RLS_ENABLED, RLS_NONE, RLS_NONE_ENV, row_security, and SearchSysCache1.

Referenced by BuildIndexValueDescription(), DoCopy(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), get_row_security_policies(), intorel_startup(), ri_ReportViolation(), row_security_active(), and row_security_active_name().

54 {
55  Oid user_id = checkAsUser ? checkAsUser : GetUserId();
56  HeapTuple tuple;
57  Form_pg_class classform;
58  bool relrowsecurity;
59  bool relforcerowsecurity;
60  bool amowner;
61 
62  /* Nothing to do for built-in relations */
63  if (relid < (Oid) FirstNormalObjectId)
64  return RLS_NONE;
65 
66  /* Fetch relation's relrowsecurity and relforcerowsecurity flags */
67  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
68  if (!HeapTupleIsValid(tuple))
69  return RLS_NONE;
70  classform = (Form_pg_class) GETSTRUCT(tuple);
71 
72  relrowsecurity = classform->relrowsecurity;
73  relforcerowsecurity = classform->relforcerowsecurity;
74 
75  ReleaseSysCache(tuple);
76 
77  /* Nothing to do if the relation does not have RLS */
78  if (!relrowsecurity)
79  return RLS_NONE;
80 
81  /*
82  * BYPASSRLS users always bypass RLS. Note that superusers are always
83  * considered to have BYPASSRLS.
84  *
85  * Return RLS_NONE_ENV to indicate that this decision depends on the
86  * environment (in this case, the user_id).
87  */
88  if (has_bypassrls_privilege(user_id))
89  return RLS_NONE_ENV;
90 
91  /*
92  * Table owners generally bypass RLS, except if the table has been set (by
93  * an owner) to FORCE ROW SECURITY, and this is not a referential
94  * integrity check.
95  *
96  * Return RLS_NONE_ENV to indicate that this decision depends on the
97  * environment (in this case, the user_id).
98  */
99  amowner = pg_class_ownercheck(relid, user_id);
100  if (amowner)
101  {
102  /*
103  * If FORCE ROW LEVEL SECURITY has been set on the relation then we
104  * should return RLS_ENABLED to indicate that RLS should be applied.
105  * If not, or if we are in an InNoForceRLSOperation context, we return
106  * RLS_NONE_ENV.
107  *
108  * InNoForceRLSOperation indicates that we should not apply RLS even
109  * if the table has FORCE RLS set - IF the current user is the owner.
110  * This is specifically to ensure that referential integrity checks
111  * are able to still run correctly.
112  *
113  * This is intentionally only done after we have checked that the user
114  * is the table owner, which should always be the case for referential
115  * integrity checks.
116  */
117  if (!relforcerowsecurity || InNoForceRLSOperation())
118  return RLS_NONE_ENV;
119  }
120 
121  /*
122  * We should apply RLS. However, the user may turn off the row_security
123  * GUC to get a forced error instead.
124  */
125  if (!row_security && !noError)
126  ereport(ERROR,
127  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
128  errmsg("query would be affected by row-level security policy for table \"%s\"",
129  get_rel_name(relid)),
130  amowner ? errhint("To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.") : 0));
131 
132  /* RLS should be fully enabled for this relation. */
133  return RLS_ENABLED;
134 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
bool InNoForceRLSOperation(void)
Definition: miscinit.c:425
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define FirstNormalObjectId
Definition: transam.h:94
bool has_bypassrls_privilege(Oid roleid)
Definition: aclchk.c:5190
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool row_security
Definition: guc.c:446
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: rls.h:43
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
Datum row_security_active ( PG_FUNCTION_ARGS  )

Definition at line 143 of file rls.c.

References check_enable_rls(), InvalidOid, PG_GETARG_OID, PG_RETURN_BOOL, and RLS_ENABLED.

144 {
145  /* By OID */
146  Oid tableoid = PG_GETARG_OID(0);
147  int rls_status;
148 
149  rls_status = check_enable_rls(tableoid, InvalidOid, true);
150  PG_RETURN_BOOL(rls_status == RLS_ENABLED);
151 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define InvalidOid
Definition: postgres_ext.h:36
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:53
Datum row_security_active_name ( PG_FUNCTION_ARGS  )

Definition at line 154 of file rls.c.

References check_enable_rls(), InvalidOid, makeRangeVarFromNameList(), NoLock, PG_GETARG_TEXT_PP, PG_RETURN_BOOL, RangeVarGetRelid, RLS_ENABLED, and textToQualifiedNameList().

155 {
156  /* By qualified name */
157  text *tablename = PG_GETARG_TEXT_PP(0);
158  RangeVar *tablerel;
159  Oid tableoid;
160  int rls_status;
161 
162  /* Look up table name. Can't lock it - we might not have privileges. */
163  tablerel = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
164  tableoid = RangeVarGetRelid(tablerel, NoLock, false);
165 
166  rls_status = check_enable_rls(tableoid, InvalidOid, true);
167  PG_RETURN_BOOL(rls_status == RLS_ENABLED);
168 }
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3023
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NoLock
Definition: lockdefs.h:34
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3202
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define InvalidOid
Definition: postgres_ext.h:36
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:53
Definition: c.h:439