pgsql-v9.1-security-label-2.v1.patch
application/octect-stream
Filename: pgsql-v9.1-security-label-2.v1.patch
Type: application/octect-stream
Part: 0
Message:
security label support, part.2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
Series: patch v9
| File | + | − |
|---|---|---|
| src/backend/commands/seclabel.c | 169 | 0 |
| src/backend/parser/gram.y | 56 | 0 |
| src/backend/tcop/utility.c | 28 | 0 |
| src/include/commands/seclabel.h | 22 | 0 |
| src/include/nodes/nodes.h | 1 | 0 |
| src/include/nodes/parsenodes.h | 14 | 0 |
| src/include/parser/kwlist.h | 1 | 0 |
*** a/src/backend/commands/seclabel.c
--- b/src/backend/commands/seclabel.c
***************
*** 14,27 ****
--- 14,39 ----
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
+ #include "catalog/namespace.h"
+ #include "catalog/pg_inherits_fn.h"
#include "catalog/pg_seclabel.h"
#include "commands/seclabel.h"
+ #include "miscadmin.h"
+ #include "parser/parse_clause.h"
+ #include "storage/lmgr.h"
+ #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+ #include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/tqual.h"
/*
+ * External security providers
+ */
+ check_relation_relabel_type check_relation_relabel_hook = NULL;
+
+ /*
* GetLocalSecLabel
*
* It tries to look up a security label entry for the given OID of the
***************
*** 257,259 **** DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId)
--- 269,428 ----
DeleteLocalSecLabel(classOid, objOid, subId);
}
+
+ /*
+ * ExecAlterRelationLabel
+ *
+ * It relabels a relation and its child tables.
+ */
+ static void
+ ExecAlterRelationLabel(RangeVar *relation, const char *attname,
+ ObjectType objtype, const char *seclabel)
+ {
+ Oid relOid = RangeVarGetRelid(relation, false);
+ bool recurse = interpretInhOption(relation->inhOpt);
+ char relkind;
+ List *child_oids;
+ List *child_numparents;
+ ListCell *lo, *li;
+
+ /*
+ * Sanity checks for relation types
+ */
+ relkind = get_rel_relkind(relOid);
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ Assert(attname == NULL);
+ if (relkind != RELKIND_RELATION &&
+ relkind != RELKIND_SEQUENCE &&
+ relkind != RELKIND_VIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a table, sequence or view",
+ relation->relname)));
+ break;
+
+ case OBJECT_SEQUENCE:
+ Assert(attname == NULL);
+ if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence", relation->relname)));
+ break;
+
+ case OBJECT_VIEW:
+ Assert(attname == NULL);
+ if (relkind != RELKIND_VIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a view", relation->relname)));
+ break;
+
+ case OBJECT_COLUMN:
+ Assert(attname != NULL);
+ if (relkind != RELKIND_RELATION)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s.%s\" is not a column of tables",
+ relation->relname, attname)));
+ break;
+
+ default:
+ elog(ERROR, "unexpected object type %d", (int)objtype);
+ break;
+ }
+
+ /*
+ * Build a list of relations to be altered.
+ * Even if relation->inhOpt is not true, we make a dummy list
+ * and lock the relation to simplify the logic.
+ */
+ if (recurse)
+ {
+ child_oids = find_all_inheritors(relOid,
+ AccessExclusiveLock,
+ &child_numparents);
+ }
+ else
+ {
+ child_oids = list_make1_oid(relOid);
+ child_numparents = list_make1_int(0);
+ /* make sure the relation being already locked */
+ LockRelationOid(relOid, AccessExclusiveLock);
+ }
+
+ /*
+ * Relabel each tables being listed
+ */
+ forboth (lo, child_oids, li, child_numparents)
+ {
+ Oid tableOid = lfirst_oid(lo);
+ Oid numParents = lfirst_int(li);
+ Oid namespaceOid = get_rel_namespace(tableOid);
+ AttrNumber attnum = InvalidAttrNumber;
+
+ /*
+ * Verify existence of attribute
+ */
+ if (attname != NULL)
+ {
+ attnum = get_attnum(tableOid, attname);
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ attname, get_rel_name(tableOid))));
+ }
+ /*
+ * Prevent to relabel system catalogs
+ */
+ if (!allowSystemTableMods &&
+ (IsSystemNamespace(namespaceOid) || IsToastNamespace(namespaceOid)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied: \"%s\" is a system catalog",
+ get_rel_name(tableOid))));
+ /*
+ * Permission checks
+ */
+ if (!pg_class_ownercheck(tableOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ get_rel_name(tableOid));
+
+ if (check_relation_relabel_hook)
+ (*check_relation_relabel_hook)(tableOid, attnum, seclabel,
+ recurse, numParents);
+ /*
+ * Do the actual relabeling
+ */
+ SetSecurityLabel(RelationRelationId, tableOid, attnum, seclabel);
+ }
+ }
+
+ /*
+ * ExecAlterLabelStmt
+ *
+ * ALTER <thing> <name> SECURITY LABEL TO <seclabel> statement.
+ */
+ void
+ ExecAlterLabelStmt(AlterLabelStmt *stmt)
+ {
+ const char *seclabel = strVal(stmt->seclabel);
+
+ switch (stmt->objectType)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_COLUMN:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ ExecAlterRelationLabel(stmt->relation, stmt->addname,
+ stmt->objectType, seclabel);
+ break;
+
+ default:
+ elog(ERROR, "unrecognized object type: %d", (int)stmt->objectType);
+ break;
+ }
+ }
+
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 182,188 **** static TypeName *TableFuncTypeName(List *columns);
%type <node> stmt schema_stmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
--- 182,188 ----
%type <node> stmt schema_stmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! AlterForeignServerStmt AlterGroupStmt AlterLabelStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
***************
*** 422,427 **** static TypeName *TableFuncTypeName(List *columns);
--- 422,429 ----
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option
+ %type <value> label_item
+
%type <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version opt_xml_root_standalone
***************
*** 498,504 **** static TypeName *TableFuncTypeName(List *columns);
KEY
! LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
LOCATION LOCK_P LOGIN_P
--- 500,506 ----
KEY
! LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
LOCATION LOCK_P LOGIN_P
***************
*** 652,657 **** stmt :
--- 654,660 ----
| AlterForeignServerStmt
| AlterFunctionStmt
| AlterGroupStmt
+ | AlterLabelStmt
| AlterObjectSchemaStmt
| AlterOwnerStmt
| AlterSeqStmt
***************
*** 6026,6031 **** AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
--- 6029,6084 ----
}
;
+ /*****************************************************************************
+ *
+ * ALTER THING name SECURITY LABEL TO label
+ *
+ *****************************************************************************/
+
+ AlterLabelStmt: ALTER TABLE relation_expr label_item
+ {
+ AlterLabelStmt *n = makeNode(AlterLabelStmt);
+
+ n->objectType = OBJECT_TABLE;
+ n->relation = $3;
+ n->seclabel = $4;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLE relation_expr ALTER opt_column ColId label_item
+ {
+ AlterLabelStmt *n = makeNode(AlterLabelStmt);
+
+ n->objectType = OBJECT_COLUMN;
+ n->relation = $3;
+ n->addname = $6;
+ n->seclabel = $7;
+ $$ = (Node *)n;
+ }
+ | ALTER SEQUENCE qualified_name label_item
+ {
+ AlterLabelStmt *n = makeNode(AlterLabelStmt);
+
+ n->objectType = OBJECT_SEQUENCE;
+ n->relation = $3;
+ n->seclabel = $4;
+ $$ = (Node *)n;
+ }
+ | ALTER VIEW qualified_name label_item
+ {
+ AlterLabelStmt *n = makeNode(AlterLabelStmt);
+
+ n->objectType = OBJECT_VIEW;
+ n->relation = $3;
+ n->seclabel = $4;
+ $$ = (Node *)n;
+ }
+ ;
+
+ label_item: SECURITY LABEL TO Sconst
+ {
+ $$ = makeString($4);
+ }
+ ;
/*****************************************************************************
*
***************
*** 10921,10926 **** unreserved_keyword:
--- 10974,10980 ----
| INVOKER
| ISOLATION
| KEY
+ | LABEL
| LANGUAGE
| LARGE_P
| LAST_P
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 161,166 **** check_xact_readonly(Node *parsetree)
--- 161,167 ----
case T_AlterDatabaseSetStmt:
case T_AlterDomainStmt:
case T_AlterFunctionStmt:
+ case T_AlterLabelStmt:
case T_AlterRoleStmt:
case T_AlterRoleSetStmt:
case T_AlterObjectSchemaStmt:
***************
*** 696,701 **** standard_ProcessUtility(Node *parsetree,
--- 697,706 ----
ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
break;
+ case T_AlterLabelStmt:
+ ExecAlterLabelStmt((AlterLabelStmt *) parsetree);
+ break;
+
case T_AlterTableStmt:
{
List *stmts;
***************
*** 1760,1765 **** CreateCommandTag(Node *parsetree)
--- 1765,1789 ----
}
break;
+ case T_AlterLabelStmt:
+ switch (((AlterLabelStmt *) parsetree)->objectType)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_COLUMN:
+ tag = "ALTER TABLE";
+ break;
+ case OBJECT_SEQUENCE:
+ tag = "ALTER SEQUENCE";
+ break;
+ case OBJECT_VIEW:
+ tag = "ALTER VIEW";
+ break;
+ default:
+ tag = "???";
+ break;
+ }
+ break;
+
case T_AlterTableStmt:
switch (((AlterTableStmt *) parsetree)->relkind)
{
***************
*** 2352,2357 **** GetCommandLogLevel(Node *parsetree)
--- 2376,2385 ----
lev = LOGSTMT_DDL;
break;
+ case T_AlterLabelStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
case T_AlterTableStmt:
lev = LOGSTMT_DDL;
break;
*** a/src/include/commands/seclabel.h
--- b/src/include/commands/seclabel.h
***************
*** 9,14 ****
--- 9,31 ----
#ifndef SECLABEL_H
#define SECLABEL_H
+ #include "nodes/primnodes.h"
+ #include "nodes/parsenodes.h"
+
+ /*
+ * External security provider hooks
+ */
+
+ /*
+ * check_relation_relabel_hook
+ *
+ * It enables ESP module to make its access control decision on relabeling
+ * the relation/attribute. If violated, it can raise an error to prevent.
+ */
+ typedef void (*check_relation_relabel_type)(Oid, AttrNumber, const char *, bool, int);
+
+ extern check_relation_relabel_type check_relation_relabel_hook;
+
/*
* Internal APIs
*/
***************
*** 17,21 **** extern void SetSecurityLabel(Oid classOid, Oid objOid, int4 subId,
const char *seclabel);
extern void DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId);
! #endif /* SECLABEL_H */
--- 34,42 ----
const char *seclabel);
extern void DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId);
! /*
! * Statement support
! */
! extern void ExecAlterLabelStmt(AlterLabelStmt *stmt);
+ #endif /* SECLABEL_H */
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
***************
*** 347,352 **** typedef enum NodeTag
--- 347,353 ----
T_AlterUserMappingStmt,
T_DropUserMappingStmt,
T_AlterTableSpaceOptionsStmt,
+ T_AlterLabelStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2073,2078 **** typedef struct AlterOwnerStmt
--- 2073,2092 ----
char *newowner; /* the new owner */
} AlterOwnerStmt;
+ /* ----------------------
+ * ALTER object SECURITY LABEL TO Statement
+ * ----------------------
+ */
+ typedef struct AlterLabelStmt
+ {
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case it's a table */
+ List *object; /* in case it's some other object */
+ List *objarg; /* argument types, if applicable */
+ char *addname; /* additional name if needed */
+ Value *seclabel; /* the new security label */
+ } AlterLabelStmt;
/* ----------------------
* Create Rule Statement
*** a/src/include/parser/kwlist.h
--- b/src/include/parser/kwlist.h
***************
*** 208,213 **** PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
--- 208,214 ----
PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
+ PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD)