mirror of
https://git.postgresql.org/git/postgresql.git
synced 2026-02-24 23:37:03 +08:00
Fix unsafe coding around PG_TRY in RelationBuildRowSecurity: can't change a variable inside PG_TRY and then use it in PG_CATCH without marking it "volatile". In this case though it seems saner to avoid that by doing a single assignment before entering the TRY block. I started out just intending to fix that, but the more I looked at the row-security code the more distressed I got. This patch also fixes incorrect construction of the RowSecurityPolicy cache entries (there was not sufficient care taken to copy pass-by-ref data into the cache memory context) and a whole bunch of sloppiness around the definition and use of pg_policy.polcmd. You can't use nulls in that column because initdb will mark it NOT NULL --- and I see no particular reason why a null entry would be a good idea anyway, so changing initdb's behavior is not the right answer. The internal value of '\0' wouldn't be suitable in a "char" column either, so after a bit of thought I settled on using '*' to represent ALL. Chasing those changes down also revealed that somebody wasn't paying attention to what the underlying values of ACL_UPDATE_CHR etc really were, and there was a great deal of lackadaiscalness in the catalogs.sgml documentation for pg_policy and pg_policies too. This doesn't pretend to be a complete code review for the row-security stuff, it just fixes the things that were in my face while dealing with the bugs in RelationBuildRowSecurity.
82 lines
2.8 KiB
C
82 lines
2.8 KiB
C
/* -------------------------------------------------------------------------
|
|
*
|
|
* rowsecurity.h
|
|
*
|
|
* prototypes for rewrite/rowsecurity.c and the structures for managing
|
|
* the row security policies for relations in relcache.
|
|
*
|
|
* Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#ifndef ROWSECURITY_H
|
|
#define ROWSECURITY_H
|
|
|
|
#include "nodes/parsenodes.h"
|
|
#include "utils/array.h"
|
|
#include "utils/relcache.h"
|
|
|
|
typedef struct RowSecurityPolicy
|
|
{
|
|
Oid policy_id; /* OID of the policy */
|
|
char *policy_name; /* Name of the policy */
|
|
char polcmd; /* Type of command policy is for */
|
|
ArrayType *roles; /* Array of roles policy is for */
|
|
Expr *qual; /* Expression to filter rows */
|
|
Expr *with_check_qual; /* Expression to limit rows allowed */
|
|
bool hassublinks; /* If either expression has sublinks */
|
|
} RowSecurityPolicy;
|
|
|
|
typedef struct RowSecurityDesc
|
|
{
|
|
MemoryContext rscxt; /* row security memory context */
|
|
List *policies; /* list of row security policies */
|
|
} RowSecurityDesc;
|
|
|
|
/* 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;
|
|
|
|
/*
|
|
* Used by callers of check_enable_rls.
|
|
*
|
|
* 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.
|
|
*
|
|
* 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
|
|
* reasons. If RLS is on the table, but we are bypassing it for now, then
|
|
* we return RLS_NONE_ENV to indicate that, if the environment changes,
|
|
* we need to invalidate and replan. Finally, if RLS should be turned on
|
|
* for the query, then we return RLS_ENABLED, which means we also need to
|
|
* invalidate if the environment changes.
|
|
*/
|
|
enum CheckEnableRlsResult
|
|
{
|
|
RLS_NONE,
|
|
RLS_NONE_ENV,
|
|
RLS_ENABLED
|
|
};
|
|
|
|
typedef List *(*row_security_policy_hook_type)(CmdType cmdtype,
|
|
Relation relation);
|
|
|
|
extern PGDLLIMPORT row_security_policy_hook_type row_security_policy_hook;
|
|
|
|
extern bool prepend_row_security_policies(Query* root, RangeTblEntry* rte,
|
|
int rt_index);
|
|
|
|
extern int check_enable_rls(Oid relid, Oid checkAsUser);
|
|
|
|
#endif /* ROWSECURITY_H */
|