Allow non-btree speculative insertion indexes
[pgsql.git] / contrib / sepgsql / proc.c
blob0d2723d44596d6f24ea462cb514be47e2b7603a3
1 /* -------------------------------------------------------------------------
3 * contrib/sepgsql/proc.c
5 * Routines corresponding to procedure objects
7 * Copyright (c) 2010-2025, PostgreSQL Global Development Group
9 * -------------------------------------------------------------------------
11 #include "postgres.h"
13 #include "access/genam.h"
14 #include "access/htup_details.h"
15 #include "access/sysattr.h"
16 #include "access/table.h"
17 #include "catalog/dependency.h"
18 #include "catalog/pg_namespace.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "commands/seclabel.h"
22 #include "lib/stringinfo.h"
23 #include "sepgsql.h"
24 #include "utils/builtins.h"
25 #include "utils/fmgroids.h"
26 #include "utils/lsyscache.h"
27 #include "utils/snapmgr.h"
28 #include "utils/syscache.h"
31 * sepgsql_proc_post_create
33 * This routine assigns a default security label on a newly defined
34 * procedure.
36 void
37 sepgsql_proc_post_create(Oid functionId)
39 Relation rel;
40 ScanKeyData skey;
41 SysScanDesc sscan;
42 HeapTuple tuple;
43 char *nsp_name;
44 char *scontext;
45 char *tcontext;
46 char *ncontext;
47 uint32 required;
48 int i;
49 StringInfoData audit_name;
50 ObjectAddress object;
51 Form_pg_proc proForm;
54 * Fetch namespace of the new procedure. Because pg_proc entry is not
55 * visible right now, we need to scan the catalog using SnapshotSelf.
57 rel = table_open(ProcedureRelationId, AccessShareLock);
59 ScanKeyInit(&skey,
60 Anum_pg_proc_oid,
61 BTEqualStrategyNumber, F_OIDEQ,
62 ObjectIdGetDatum(functionId));
64 sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
65 SnapshotSelf, 1, &skey);
67 tuple = systable_getnext(sscan);
68 if (!HeapTupleIsValid(tuple))
69 elog(ERROR, "could not find tuple for function %u", functionId);
71 proForm = (Form_pg_proc) GETSTRUCT(tuple);
74 * check db_schema:{add_name} permission of the namespace
76 object.classId = NamespaceRelationId;
77 object.objectId = proForm->pronamespace;
78 object.objectSubId = 0;
79 sepgsql_avc_check_perms(&object,
80 SEPG_CLASS_DB_SCHEMA,
81 SEPG_DB_SCHEMA__ADD_NAME,
82 getObjectIdentity(&object, false),
83 true);
86 * XXX - db_language:{implement} also should be checked here
91 * Compute a default security label when we create a new procedure object
92 * under the specified namespace.
94 scontext = sepgsql_get_client_label();
95 tcontext = sepgsql_get_label(NamespaceRelationId,
96 proForm->pronamespace, 0);
97 ncontext = sepgsql_compute_create(scontext, tcontext,
98 SEPG_CLASS_DB_PROCEDURE,
99 NameStr(proForm->proname));
102 * check db_procedure:{create (install)} permission
104 initStringInfo(&audit_name);
105 nsp_name = get_namespace_name(proForm->pronamespace);
106 appendStringInfo(&audit_name, "%s(",
107 quote_qualified_identifier(nsp_name, NameStr(proForm->proname)));
108 for (i = 0; i < proForm->pronargs; i++)
110 if (i > 0)
111 appendStringInfoChar(&audit_name, ',');
113 object.classId = TypeRelationId;
114 object.objectId = proForm->proargtypes.values[i];
115 object.objectSubId = 0;
116 appendStringInfoString(&audit_name, getObjectIdentity(&object, false));
118 appendStringInfoChar(&audit_name, ')');
120 required = SEPG_DB_PROCEDURE__CREATE;
121 if (proForm->proleakproof)
122 required |= SEPG_DB_PROCEDURE__INSTALL;
124 sepgsql_avc_check_perms_label(ncontext,
125 SEPG_CLASS_DB_PROCEDURE,
126 required,
127 audit_name.data,
128 true);
131 * Assign the default security label on a new procedure
133 object.classId = ProcedureRelationId;
134 object.objectId = functionId;
135 object.objectSubId = 0;
136 SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
139 * Cleanup
141 systable_endscan(sscan);
142 table_close(rel, AccessShareLock);
144 pfree(audit_name.data);
145 pfree(tcontext);
146 pfree(ncontext);
150 * sepgsql_proc_drop
152 * It checks privileges to drop the supplied function.
154 void
155 sepgsql_proc_drop(Oid functionId)
157 ObjectAddress object;
158 char *audit_name;
161 * check db_schema:{remove_name} permission
163 object.classId = NamespaceRelationId;
164 object.objectId = get_func_namespace(functionId);
165 object.objectSubId = 0;
166 audit_name = getObjectIdentity(&object, false);
168 sepgsql_avc_check_perms(&object,
169 SEPG_CLASS_DB_SCHEMA,
170 SEPG_DB_SCHEMA__REMOVE_NAME,
171 audit_name,
172 true);
173 pfree(audit_name);
176 * check db_procedure:{drop} permission
178 object.classId = ProcedureRelationId;
179 object.objectId = functionId;
180 object.objectSubId = 0;
181 audit_name = getObjectIdentity(&object, false);
183 sepgsql_avc_check_perms(&object,
184 SEPG_CLASS_DB_PROCEDURE,
185 SEPG_DB_PROCEDURE__DROP,
186 audit_name,
187 true);
188 pfree(audit_name);
192 * sepgsql_proc_relabel
194 * It checks privileges to relabel the supplied function
195 * by the `seclabel'.
197 void
198 sepgsql_proc_relabel(Oid functionId, const char *seclabel)
200 ObjectAddress object;
201 char *audit_name;
203 object.classId = ProcedureRelationId;
204 object.objectId = functionId;
205 object.objectSubId = 0;
206 audit_name = getObjectIdentity(&object, false);
209 * check db_procedure:{setattr relabelfrom} permission
211 sepgsql_avc_check_perms(&object,
212 SEPG_CLASS_DB_PROCEDURE,
213 SEPG_DB_PROCEDURE__SETATTR |
214 SEPG_DB_PROCEDURE__RELABELFROM,
215 audit_name,
216 true);
219 * check db_procedure:{relabelto} permission
221 sepgsql_avc_check_perms_label(seclabel,
222 SEPG_CLASS_DB_PROCEDURE,
223 SEPG_DB_PROCEDURE__RELABELTO,
224 audit_name,
225 true);
226 pfree(audit_name);
230 * sepgsql_proc_setattr
232 * It checks privileges to alter the supplied function.
234 void
235 sepgsql_proc_setattr(Oid functionId)
237 Relation rel;
238 ScanKeyData skey;
239 SysScanDesc sscan;
240 HeapTuple oldtup;
241 HeapTuple newtup;
242 Form_pg_proc oldform;
243 Form_pg_proc newform;
244 uint32 required;
245 ObjectAddress object;
246 char *audit_name;
249 * Fetch newer catalog
251 rel = table_open(ProcedureRelationId, AccessShareLock);
253 ScanKeyInit(&skey,
254 Anum_pg_proc_oid,
255 BTEqualStrategyNumber, F_OIDEQ,
256 ObjectIdGetDatum(functionId));
258 sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
259 SnapshotSelf, 1, &skey);
260 newtup = systable_getnext(sscan);
261 if (!HeapTupleIsValid(newtup))
262 elog(ERROR, "could not find tuple for function %u", functionId);
263 newform = (Form_pg_proc) GETSTRUCT(newtup);
266 * Fetch older catalog
268 oldtup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
269 if (!HeapTupleIsValid(oldtup))
270 elog(ERROR, "cache lookup failed for function %u", functionId);
271 oldform = (Form_pg_proc) GETSTRUCT(oldtup);
274 * Does this ALTER command takes operation to namespace?
276 if (newform->pronamespace != oldform->pronamespace)
278 sepgsql_schema_remove_name(oldform->pronamespace);
279 sepgsql_schema_add_name(oldform->pronamespace);
281 if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
282 sepgsql_schema_rename(oldform->pronamespace);
285 * check db_procedure:{setattr (install)} permission
287 required = SEPG_DB_PROCEDURE__SETATTR;
288 if (!oldform->proleakproof && newform->proleakproof)
289 required |= SEPG_DB_PROCEDURE__INSTALL;
291 object.classId = ProcedureRelationId;
292 object.objectId = functionId;
293 object.objectSubId = 0;
294 audit_name = getObjectIdentity(&object, false);
296 sepgsql_avc_check_perms(&object,
297 SEPG_CLASS_DB_PROCEDURE,
298 required,
299 audit_name,
300 true);
301 /* cleanups */
302 pfree(audit_name);
304 ReleaseSysCache(oldtup);
305 systable_endscan(sscan);
306 table_close(rel, AccessShareLock);
310 * sepgsql_proc_execute
312 * It checks privileges to execute the supplied function
314 void
315 sepgsql_proc_execute(Oid functionId)
317 ObjectAddress object;
318 char *audit_name;
321 * check db_procedure:{execute} permission
323 object.classId = ProcedureRelationId;
324 object.objectId = functionId;
325 object.objectSubId = 0;
326 audit_name = getObjectIdentity(&object, false);
327 sepgsql_avc_check_perms(&object,
328 SEPG_CLASS_DB_PROCEDURE,
329 SEPG_DB_PROCEDURE__EXECUTE,
330 audit_name,
331 true);
332 pfree(audit_name);