PostgreSQL Source Code  git master
proc.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  *
3  * contrib/sepgsql/proc.c
4  *
5  * Routines corresponding to procedure objects
6  *
7  * Copyright (c) 2010-2024, PostgreSQL Global Development Group
8  *
9  * -------------------------------------------------------------------------
10  */
11 #include "postgres.h"
12 
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"
29 
30 /*
31  * sepgsql_proc_post_create
32  *
33  * This routine assigns a default security label on a newly defined
34  * procedure.
35  */
36 void
38 {
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;
48  int i;
49  StringInfoData audit_name;
50  ObjectAddress object;
51  Form_pg_proc proForm;
52 
53  /*
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.
56  */
57  rel = table_open(ProcedureRelationId, AccessShareLock);
58 
59  ScanKeyInit(&skey,
60  Anum_pg_proc_oid,
61  BTEqualStrategyNumber, F_OIDEQ,
62  ObjectIdGetDatum(functionId));
63 
64  sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
65  SnapshotSelf, 1, &skey);
66 
67  tuple = systable_getnext(sscan);
68  if (!HeapTupleIsValid(tuple))
69  elog(ERROR, "could not find tuple for function %u", functionId);
70 
71  proForm = (Form_pg_proc) GETSTRUCT(tuple);
72 
73  /*
74  * check db_schema:{add_name} permission of the namespace
75  */
76  object.classId = NamespaceRelationId;
77  object.objectId = proForm->pronamespace;
78  object.objectSubId = 0;
82  getObjectIdentity(&object, false),
83  true);
84 
85  /*
86  * XXX - db_language:{implement} also should be checked here
87  */
88 
89 
90  /*
91  * Compute a default security label when we create a new procedure object
92  * under the specified namespace.
93  */
94  scontext = sepgsql_get_client_label();
95  tcontext = sepgsql_get_label(NamespaceRelationId,
96  proForm->pronamespace, 0);
97  ncontext = sepgsql_compute_create(scontext, tcontext,
99  NameStr(proForm->proname));
100 
101  /*
102  * check db_procedure:{create (install)} permission
103  */
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++)
109  {
110  if (i > 0)
111  appendStringInfoChar(&audit_name, ',');
112 
113  object.classId = TypeRelationId;
114  object.objectId = proForm->proargtypes.values[i];
115  object.objectSubId = 0;
116  appendStringInfoString(&audit_name, getObjectIdentity(&object, false));
117  }
118  appendStringInfoChar(&audit_name, ')');
119 
121  if (proForm->proleakproof)
123 
126  required,
127  audit_name.data,
128  true);
129 
130  /*
131  * Assign the default security label on a new procedure
132  */
133  object.classId = ProcedureRelationId;
134  object.objectId = functionId;
135  object.objectSubId = 0;
136  SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
137 
138  /*
139  * Cleanup
140  */
141  systable_endscan(sscan);
143 
144  pfree(audit_name.data);
145  pfree(tcontext);
146  pfree(ncontext);
147 }
148 
149 /*
150  * sepgsql_proc_drop
151  *
152  * It checks privileges to drop the supplied function.
153  */
154 void
156 {
157  ObjectAddress object;
158  char *audit_name;
159 
160  /*
161  * check db_schema:{remove_name} permission
162  */
163  object.classId = NamespaceRelationId;
164  object.objectId = get_func_namespace(functionId);
165  object.objectSubId = 0;
166  audit_name = getObjectIdentity(&object, false);
167 
168  sepgsql_avc_check_perms(&object,
171  audit_name,
172  true);
173  pfree(audit_name);
174 
175  /*
176  * check db_procedure:{drop} permission
177  */
178  object.classId = ProcedureRelationId;
179  object.objectId = functionId;
180  object.objectSubId = 0;
181  audit_name = getObjectIdentity(&object, false);
182 
183  sepgsql_avc_check_perms(&object,
186  audit_name,
187  true);
188  pfree(audit_name);
189 }
190 
191 /*
192  * sepgsql_proc_relabel
193  *
194  * It checks privileges to relabel the supplied function
195  * by the `seclabel'.
196  */
197 void
198 sepgsql_proc_relabel(Oid functionId, const char *seclabel)
199 {
200  ObjectAddress object;
201  char *audit_name;
202 
203  object.classId = ProcedureRelationId;
204  object.objectId = functionId;
205  object.objectSubId = 0;
206  audit_name = getObjectIdentity(&object, false);
207 
208  /*
209  * check db_procedure:{setattr relabelfrom} permission
210  */
211  sepgsql_avc_check_perms(&object,
215  audit_name,
216  true);
217 
218  /*
219  * check db_procedure:{relabelto} permission
220  */
224  audit_name,
225  true);
226  pfree(audit_name);
227 }
228 
229 /*
230  * sepgsql_proc_setattr
231  *
232  * It checks privileges to alter the supplied function.
233  */
234 void
236 {
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;
245  ObjectAddress object;
246  char *audit_name;
247 
248  /*
249  * Fetch newer catalog
250  */
251  rel = table_open(ProcedureRelationId, AccessShareLock);
252 
253  ScanKeyInit(&skey,
254  Anum_pg_proc_oid,
255  BTEqualStrategyNumber, F_OIDEQ,
256  ObjectIdGetDatum(functionId));
257 
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);
264 
265  /*
266  * Fetch older catalog
267  */
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);
272 
273  /*
274  * Does this ALTER command takes operation to namespace?
275  */
276  if (newform->pronamespace != oldform->pronamespace)
277  {
278  sepgsql_schema_remove_name(oldform->pronamespace);
279  sepgsql_schema_add_name(oldform->pronamespace);
280  }
281  if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
282  sepgsql_schema_rename(oldform->pronamespace);
283 
284  /*
285  * check db_procedure:{setattr (install)} permission
286  */
288  if (!oldform->proleakproof && newform->proleakproof)
290 
291  object.classId = ProcedureRelationId;
292  object.objectId = functionId;
293  object.objectSubId = 0;
294  audit_name = getObjectIdentity(&object, false);
295 
296  sepgsql_avc_check_perms(&object,
298  required,
299  audit_name,
300  true);
301  /* cleanups */
302  pfree(audit_name);
303 
304  ReleaseSysCache(oldtup);
305  systable_endscan(sscan);
307 }
308 
309 /*
310  * sepgsql_proc_execute
311  *
312  * It checks privileges to execute the supplied function
313  */
314 void
316 {
317  ObjectAddress object;
318  char *audit_name;
319 
320  /*
321  * check db_procedure:{execute} permission
322  */
323  object.classId = ProcedureRelationId;
324  object.objectId = functionId;
325  object.objectSubId = 0;
326  audit_name = getObjectIdentity(&object, false);
327  sepgsql_avc_check_perms(&object,
330  audit_name,
331  true);
332  pfree(audit_name);
333 }
#define NameStr(name)
Definition: c.h:725
unsigned int uint32
Definition: c.h:492
void sepgsql_proc_post_create(Oid functionId)
Definition: proc.c:37
void sepgsql_proc_relabel(Oid functionId, const char *seclabel)
Definition: proc.c:198
void sepgsql_proc_setattr(Oid functionId)
Definition: proc.c:235
void sepgsql_proc_drop(Oid functionId)
Definition: proc.c:155
void sepgsql_proc_execute(Oid functionId)
Definition: proc.c:315
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:511
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:72
char * sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
Definition: label.c:445
char * sepgsql_get_client_label(void)
Definition: label.c:80
#define AccessShareLock
Definition: lockdefs.h:36
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
Oid get_func_namespace(Oid funcid)
Definition: lsyscache.c:1632
void pfree(void *pointer)
Definition: mcxt.c:1521
char * getObjectIdentity(const ObjectAddress *object, bool missing_ok)
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12952
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void sepgsql_schema_rename(Oid namespaceId)
Definition: schema.c:229
void sepgsql_schema_remove_name(Oid namespaceId)
Definition: schema.c:223
void sepgsql_schema_add_name(Oid namespaceId)
Definition: schema.c:217
void SetSecurityLabel(const ObjectAddress *object, const char *provider, const char *label)
Definition: seclabel.c:404
char * sepgsql_compute_create(const char *scontext, const char *tcontext, uint16 tclass, const char *objname)
Definition: selinux.c:842
#define SEPG_CLASS_DB_SCHEMA
Definition: sepgsql.h:45
#define SEPG_DB_PROCEDURE__CREATE
Definition: sepgsql.h:160
#define SEPG_DB_PROCEDURE__RELABELFROM
Definition: sepgsql.h:164
#define SEPG_DB_SCHEMA__REMOVE_NAME
Definition: sepgsql.h:135
bool sepgsql_avc_check_perms_label(const char *tcontext, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:337
#define SEPG_DB_PROCEDURE__INSTALL
Definition: sepgsql.h:168
#define SEPG_DB_PROCEDURE__DROP
Definition: sepgsql.h:161
#define SEPG_DB_SCHEMA__ADD_NAME
Definition: sepgsql.h:134
#define SEPG_DB_PROCEDURE__EXECUTE
Definition: sepgsql.h:166
#define SEPG_DB_PROCEDURE__RELABELTO
Definition: sepgsql.h:165
#define SEPG_DB_PROCEDURE__SETATTR
Definition: sepgsql.h:163
#define SEPG_CLASS_DB_PROCEDURE
Definition: sepgsql.h:48
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:420
#define SnapshotSelf
Definition: snapmgr.h:32
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40