pgsql-v9.2-prep-creation-hook-part-4.v1.patch
application/octet-stream
Filename: pgsql-v9.2-prep-creation-hook-part-4.v1.patch
Type: application/octet-stream
Part: 3
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: unified
Series: patch v9
| File | + | − |
|---|---|---|
| contrib/sepgsql/expected/create.out | 13 | 1 |
| contrib/sepgsql/hooks.c | 11 | 1 |
| contrib/sepgsql/proc.c | 109 | 35 |
| contrib/sepgsql/sepgsql.h | 6 | 1 |
| contrib/sepgsql/sql/create.sql | 8 | 0 |
| src/backend/catalog/pg_aggregate.c | 4 | 2 |
| src/backend/catalog/pg_proc.c | 5 | 2 |
| src/backend/commands/aggregatecmds.c | 10 | 1 |
| src/backend/commands/functioncmds.c | 7 | 1 |
| src/backend/commands/proclang.c | 6 | 3 |
| src/backend/commands/typecmds.c | 2 | 1 |
| src/include/catalog/objectaccess.h | 28 | 0 |
| src/include/catalog/pg_aggregate.h | 2 | 1 |
| src/include/catalog/pg_proc_fn.h | 2 | 1 |
contrib/sepgsql/expected/create.out | 14 +++-
contrib/sepgsql/hooks.c | 12 +++-
contrib/sepgsql/proc.c | 144 +++++++++++++++++++++++++--------
contrib/sepgsql/sepgsql.h | 7 ++-
contrib/sepgsql/sql/create.sql | 8 ++
src/backend/catalog/pg_aggregate.c | 6 +-
src/backend/catalog/pg_proc.c | 7 +-
src/backend/commands/aggregatecmds.c | 11 +++-
src/backend/commands/functioncmds.c | 8 ++-
src/backend/commands/proclang.c | 9 ++-
src/backend/commands/typecmds.c | 3 +-
src/include/catalog/objectaccess.h | 28 +++++++
src/include/catalog/pg_aggregate.h | 3 +-
src/include/catalog/pg_proc_fn.h | 3 +-
14 files changed, 213 insertions(+), 50 deletions(-)
diff --git a/contrib/sepgsql/expected/create.out b/contrib/sepgsql/expected/create.out
index d450dc5..68d7e61 100644
--- a/contrib/sepgsql/expected/create.out
+++ b/contrib/sepgsql/expected/create.out
@@ -39,13 +39,25 @@ LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfine
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
CREATE TYPE regtest_type AS (a int, b text);
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+CREATE FUNCTION regtest_func (text) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RAISE NOTICE ''hello => %'', $1; RETURN true; END';
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func(text)"
+CREATE AGGREGATE regtest_agg (
+ sfunc1 = int4pl, basetype = int4, stype1 = int4,
+ initcond1 = '0'
+);
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_agg(integer)"
--
-- clean-up
--
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
DROP SCHEMA IF EXISTS regtest_schema CASCADE;
-NOTICE: drop cascades to 4 other objects
+NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to table regtest_table
drop cascades to view regtest_view
drop cascades to sequence regtest_seq
drop cascades to type regtest_type
+drop cascades to function regtest_func(text)
+drop cascades to function regtest_agg(integer)
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index aa56d9c..1eeec1e 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -155,6 +155,15 @@ sepgsql_object_prep_create(Oid classId, Oid objectId, int subId,
args->pg_class.tupdesc);
break;
+ case ProcedureRelationId:
+ cinfo->ncontext =
+ sepgsql_proc_prep_create(args->pg_proc.proname,
+ args->pg_proc.proargs,
+ args->pg_proc.namespaceId,
+ args->pg_proc.languageId,
+ args->pg_proc.leakproof);
+ break;
+
default:
/* Ignore unsupported object classes */
break;
@@ -196,7 +205,8 @@ sepgsql_object_post_create(Oid classId, Oid objectId, int subId,
break;
case ProcedureRelationId:
- sepgsql_proc_post_create(objectId);
+ sepgsql_proc_post_create(objectId,
+ !cinfo ? NULL : cinfo->ncontext);
break;
default:
diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c
index 9630d45..c0e2c0e 100644
--- a/contrib/sepgsql/proc.c
+++ b/contrib/sepgsql/proc.c
@@ -18,6 +18,7 @@
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "commands/seclabel.h"
+#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/tqual.h"
@@ -25,55 +26,131 @@
#include "sepgsql.h"
/*
- * sepgsql_proc_post_create
+ * sepgsql_proc_prep_create
+ *
+ *
*
- * This routine assigns a default security label on a newly defined
- * procedure.
*/
-void
-sepgsql_proc_post_create(Oid functionId)
+const char *
+sepgsql_proc_prep_create(const char *proname,
+ oidvector *proargs,
+ Oid namespaceId,
+ Oid languageId,
+ bool leakproof)
{
- Relation rel;
- ScanKeyData skey;
- SysScanDesc sscan;
- HeapTuple tuple;
- Oid namespaceId;
- ObjectAddress object;
char *scontext;
char *tcontext;
char *ncontext;
+ uint32 required;
+ StringInfoData audit_name;
+ ObjectAddress object;
+ int i;
/*
- * Fetch namespace of the new procedure. Because pg_proc entry is not
- * visible right now, we need to scan the catalog using SnapshotSelf.
+ * check db_schema:{add_name} permission
*/
- rel = heap_open(ProcedureRelationId, AccessShareLock);
+ object.classId = NamespaceRelationId;
+ object.objectId = namespaceId;
+ object.objectSubId = 0;
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__ADD_NAME,
+ getObjectDescription(&object),
+ true);
- ScanKeyInit(&skey,
- ObjectIdAttributeNumber,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(functionId));
+ /*
+ * compute default security label of new function
+ */
+ scontext = sepgsql_get_client_label();
+ tcontext = sepgsql_get_label(NamespaceRelationId, namespaceId, 0);
+ ncontext = sepgsql_compute_create(scontext, tcontext,
+ SEPG_CLASS_DB_PROCEDURE);
- sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
- SnapshotSelf, 1, &skey);
+ /*
+ * check db_procedure:{create (install)} permission
+ */
+ required = SEPG_DB_PROCEDURE__CREATE;
+ if (leakproof)
+ required |= SEPG_DB_PROCEDURE__INSTALL;
- tuple = systable_getnext(sscan);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "catalog lookup failed for proc %u", functionId);
+ /*
+ * XXX - format_procedure() is not available at this point,
+ * so we need to construct human readable function names by hand.
+ */
+ initStringInfo(&audit_name);
+ appendStringInfo(&audit_name, _("function %s("),
+ quote_identifier(proname));
+ for (i = 0; i < proargs->dim1; i++)
+ {
+ if (i > 0)
+ appendStringInfoChar(&audit_name, ',');
+ appendStringInfoString(&audit_name,
+ format_type_be(proargs->values[i]));
+ }
+ appendStringInfoChar(&audit_name, ')');
+
+ sepgsql_avc_check_perms_label(ncontext,
+ SEPG_CLASS_DB_PROCEDURE,
+ required,
+ audit_name.data,
+ true);
- namespaceId = ((Form_pg_proc) GETSTRUCT(tuple))->pronamespace;
+ /*
+ * XXX - db_language:{implement} also shoule be checked here.
+ */
+ return ncontext;
+}
- systable_endscan(sscan);
- heap_close(rel, AccessShareLock);
+/*
+ * sepgsql_proc_post_create
+ *
+ * This routine assigns a default security label on a newly defined
+ * procedure.
+ */
+void
+sepgsql_proc_post_create(Oid functionId, const char *ncontext)
+{
+ ObjectAddress object;
/*
- * Compute a default security label when we create a new procedure object
- * under the specified namespace.
+ * In the case when system internal functions are constructed,
+ * prep-creation hook is not invoked, security label to be
+ * assigned on is not also computed yet. Thus, we try to obtain
+ * the default security label based on the properties of system
+ * catalogs.
*/
- scontext = sepgsql_get_client_label();
- tcontext = sepgsql_get_label(NamespaceRelationId, namespaceId, 0);
- ncontext = sepgsql_compute_create(scontext, tcontext,
- SEPG_CLASS_DB_PROCEDURE);
+ if (!ncontext)
+ {
+ Relation rel;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Form_pg_proc procForm;
+
+ rel = heap_open(ProcedureRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(functionId));
+
+ sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "catalog lookup failed for proc %u", functionId);
+
+ procForm = (Form_pg_proc) GETSTRUCT(tuple);
+
+ ncontext = sepgsql_proc_prep_create(NameStr(procForm->proname),
+ &procForm->proargtypes,
+ procForm->pronamespace,
+ procForm->prolang,
+ false);
+ systable_endscan(sscan);
+ heap_close(rel, AccessShareLock);
+ }
/*
* Assign the default security label on a new procedure
@@ -82,9 +159,6 @@ sepgsql_proc_post_create(Oid functionId)
object.objectId = functionId;
object.objectSubId = 0;
SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
-
- pfree(tcontext);
- pfree(ncontext);
}
/*
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index cd9c4c6..56d2056 100644
--- a/contrib/sepgsql/sepgsql.h
+++ b/contrib/sepgsql/sepgsql.h
@@ -338,7 +338,12 @@ extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
/*
* proc.c
*/
-extern void sepgsql_proc_post_create(Oid functionId);
+extern const char *sepgsql_proc_prep_create(const char *proname,
+ oidvector *proargs,
+ Oid namespaceId,
+ Oid languageId,
+ bool leakproof);
+extern void sepgsql_proc_post_create(Oid functionId, const char *ncontext);
extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
#endif /* SEPGSQL_H */
diff --git a/contrib/sepgsql/sql/create.sql b/contrib/sepgsql/sql/create.sql
index 4e12411..bc4a664 100644
--- a/contrib/sepgsql/sql/create.sql
+++ b/contrib/sepgsql/sql/create.sql
@@ -21,6 +21,14 @@ CREATE SEQUENCE regtest_seq;
CREATE TYPE regtest_type AS (a int, b text);
+CREATE FUNCTION regtest_func (text) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RAISE NOTICE ''hello => %'', $1; RETURN true; END';
+
+CREATE AGGREGATE regtest_agg (
+ sfunc1 = int4pl, basetype = int4, stype1 = int4,
+ initcond1 = '0'
+);
+
--
-- clean-up
--
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 86e8c6b..0cd0ca3 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -50,7 +50,8 @@ AggregateCreate(const char *aggName,
List *aggfinalfnName,
List *aggsortopName,
Oid aggTransType,
- const char *agginitval)
+ const char *agginitval,
+ Datum hook_private)
{
Relation aggdesc;
HeapTuple tup;
@@ -229,7 +230,8 @@ AggregateCreate(const char *aggName,
NIL, /* parameterDefaults */
PointerGetDatum(NULL), /* proconfig */
1, /* procost */
- 0); /* prorows */
+ 0, /* prorows */
+ hook_private); /* hook_private */
/*
* Okay to create the pg_aggregate entry.
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 8378c36..7fb5ef2 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -85,7 +85,8 @@ ProcedureCreate(const char *procedureName,
List *parameterDefaults,
Datum proconfig,
float4 procost,
- float4 prorows)
+ float4 prorows,
+ Datum hook_private)
{
Oid retval;
int parameterCount;
@@ -646,7 +647,9 @@ ProcedureCreate(const char *procedureName,
heap_freetuple(tup);
/* Post creation hook for new function */
- InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0);
+ InvokeObjectAccessHookArg(OAT_POST_CREATE,
+ ProcedureRelationId, retval, 0,
+ hook_private);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index a2122c1..f02a467 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -25,7 +25,9 @@
#include "access/heapam.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
+#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
@@ -60,6 +62,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
Oid *aggArgTypes;
int numArgs;
Oid transTypeId;
+ Datum hook_private = 0;
ListCell *pl;
/* Convert list of names to a name and namespace */
@@ -192,6 +195,11 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
format_type_be(transTypeId))));
}
+ /* Prep-creation hook for new aggregate functions */
+ InvokePrepCreateProcedureHook(&hook_private, aggName,
+ buildoidvector(aggArgTypes, numArgs),
+ aggNamespace, INTERNALlanguageId, false);
+
/*
* Most of the argument-checking is done inside of AggregateCreate
*/
@@ -203,7 +211,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
finalfuncName, /* final function name */
sortoperatorName, /* sort operator name */
transTypeId, /* transition data type */
- initval); /* initial condition */
+ initval, /* initial condition */
+ hook_private);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 92abd44..33c65be 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -801,6 +801,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
HeapTuple languageTuple;
Form_pg_language languageStruct;
List *as_clause;
+ Datum hook_private = 0;
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
@@ -935,6 +936,10 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("ROWS is not applicable when function does not return a set")));
+ /* Prep-creation hook for new function */
+ InvokePrepCreateProcedureHook(&hook_private, funcname, parameterTypes,
+ namespaceId, languageOid, false);
+
/*
* And now that we have all the parameters, and know we're permitted to do
* so, go ahead and create the function.
@@ -960,7 +965,8 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
parameterDefaults,
PointerGetDatum(proconfig),
procost,
- prorows);
+ prorows,
+ hook_private);
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 98770c5..1392dca 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -146,7 +146,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
NIL,
PointerGetDatum(NULL),
1,
- 0);
+ 0,
+ (Datum) 0);
}
/*
@@ -181,7 +182,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
NIL,
PointerGetDatum(NULL),
1,
- 0);
+ 0,
+ (Datum) 0);
}
}
else
@@ -219,7 +221,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
NIL,
PointerGetDatum(NULL),
1,
- 0);
+ 0,
+ (Datum) 0);
}
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 91488bb..307dcbf 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1461,7 +1461,8 @@ makeRangeConstructor(char *name, Oid namespace, Oid rangeOid, Oid subtype)
NIL, /* parameterDefaults */
PointerGetDatum(NULL), /* proconfig */
1.0, /* procost */
- 0.0); /* prorows */
+ 0.0, /* prorows */
+ (Datum) 0); /* hook_private */
/*
* Make the constructor internally-dependent on the range type so that
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index d151ee5..db57e03 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -65,6 +65,14 @@ typedef union
Oid tablespaceId;
TupleDesc tupdesc;
} pg_class;
+ struct {
+ Datum *private;
+ const char *proname;
+ oidvector *proargs;
+ Oid namespaceId;
+ Oid languageId;
+ bool leakproof;
+ } pg_proc;
} ObjectAccessCreateObjectArgs;
/*
@@ -151,4 +159,24 @@ extern PGDLLIMPORT object_access_hook_type object_access_hook;
} \
} while(0)
+#define InvokePrepCreateProcedureHook(_private,_proname,_proargs, \
+ _namespace,_language,_leakproof) \
+ do { \
+ if (object_access_hook) \
+ { \
+ ObjectAccessCreateObjectArgs __args; \
+ \
+ __args.pg_proc.private = (_private); \
+ __args.pg_proc.proname = (_proname); \
+ __args.pg_proc.proargs = (_proargs); \
+ __args.pg_proc.namespaceId = (_namespace); \
+ __args.pg_proc.languageId = (_language); \
+ __args.pg_proc.leakproof = (_leakproof); \
+ \
+ (*object_access_hook)(OAT_PREP_CREATE, \
+ ProcedureRelationId, InvalidOid, 0, \
+ PointerGetDatum(&__args)); \
+ } \
+ } while(0)
+
#endif /* OBJECTACCESS_H */
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 26966d2..7b2d172 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -237,6 +237,7 @@ extern void AggregateCreate(const char *aggName,
List *aggfinalfnName,
List *aggsortopName,
Oid aggTransType,
- const char *agginitval);
+ const char *agginitval,
+ Datum hook_private);
#endif /* PG_AGGREGATE_H */
diff --git a/src/include/catalog/pg_proc_fn.h b/src/include/catalog/pg_proc_fn.h
index 09d779f..a28786f 100644
--- a/src/include/catalog/pg_proc_fn.h
+++ b/src/include/catalog/pg_proc_fn.h
@@ -37,7 +37,8 @@ extern Oid ProcedureCreate(const char *procedureName,
List *parameterDefaults,
Datum proconfig,
float4 procost,
- float4 prorows);
+ float4 prorows,
+ Datum hook_private);
extern bool function_parse_error_transpose(const char *prosrc);