PostgreSQL Source Code git master
Loading...
Searching...
No Matches
dml.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tupdesc.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_class.h"
#include "catalog/pg_inherits.h"
#include "commands/seclabel.h"
#include "commands/tablecmds.h"
#include "executor/executor.h"
#include "nodes/bitmapset.h"
#include "parser/parsetree.h"
#include "sepgsql.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for dml.c:

Go to the source code of this file.

Functions

static Bitmapsetfixup_whole_row_references (Oid relOid, Bitmapset *columns)
 
static Bitmapsetfixup_inherited_columns (Oid parentId, Oid childId, Bitmapset *columns)
 
static bool check_relation_privileges (Oid relOid, Bitmapset *selected, Bitmapset *inserted, Bitmapset *updated, uint32 required, bool abort_on_violation)
 
bool sepgsql_dml_privileges (List *rangeTbls, List *rteperminfos, bool abort_on_violation)
 

Function Documentation

◆ check_relation_privileges()

static bool check_relation_privileges ( Oid  relOid,
Bitmapset selected,
Bitmapset inserted,
Bitmapset updated,
uint32  required,
bool  abort_on_violation 
)
static

Definition at line 142 of file dml.c.

148{
149 ObjectAddress object;
150 char *audit_name;
151 Bitmapset *columns;
152 int index;
153 char relkind = get_rel_relkind(relOid);
154 bool result = true;
155
156 /*
157 * Hardwired Policies: SE-PostgreSQL enforces - clients cannot modify
158 * system catalogs using DMLs - clients cannot reference/modify toast
159 * relations using DMLs
160 */
161 if (sepgsql_getenforce() > 0)
162 {
163 if ((required & (SEPG_DB_TABLE__UPDATE |
165 SEPG_DB_TABLE__DELETE)) != 0 &&
166 IsCatalogRelationOid(relOid))
169 errmsg("SELinux: hardwired security policy violation")));
170
171 if (relkind == RELKIND_TOASTVALUE)
174 errmsg("SELinux: hardwired security policy violation")));
175 }
176
177 /*
178 * Check permissions on the relation
179 */
180 object.classId = RelationRelationId;
181 object.objectId = relOid;
182 object.objectSubId = 0;
183 audit_name = getObjectIdentity(&object, false);
184 switch (relkind)
185 {
186 case RELKIND_RELATION:
188 result = sepgsql_avc_check_perms(&object,
190 required,
193 break;
194
195 case RELKIND_SEQUENCE:
196 Assert((required & ~SEPG_DB_TABLE__SELECT) == 0);
197
198 if (required & SEPG_DB_TABLE__SELECT)
199 result = sepgsql_avc_check_perms(&object,
204 break;
205
206 case RELKIND_VIEW:
207 result = sepgsql_avc_check_perms(&object,
212 break;
213
214 default:
215 /* nothing to be checked */
216 break;
217 }
219
220 /*
221 * Only columns owned by relations shall be checked
222 */
223 if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
224 return true;
225
226 /*
227 * Check permissions on the columns
228 */
229 selected = fixup_whole_row_references(relOid, selected);
232 columns = bms_union(selected, bms_union(inserted, updated));
233
234 index = -1;
235 while ((index = bms_next_member(columns, index)) >= 0)
236 {
239
240 if (bms_is_member(index, selected))
243 {
244 if (required & SEPG_DB_TABLE__INSERT)
246 }
248 {
249 if (required & SEPG_DB_TABLE__UPDATE)
251 }
252 if (column_perms == 0)
253 continue;
254
255 /* obtain column's permission */
257
258 object.classId = RelationRelationId;
259 object.objectId = relOid;
260 object.objectSubId = attnum;
261 audit_name = getObjectDescription(&object, false);
262
263 result = sepgsql_avc_check_perms(&object,
269
270 if (!result)
271 return result;
272 }
273 return true;
274}
int16 AttrNumber
Definition attnum.h:21
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1305
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
#define Assert(condition)
Definition c.h:873
uint32_t uint32
Definition c.h:546
bool IsCatalogRelationOid(Oid relid)
Definition catalog.c:121
static Bitmapset * fixup_whole_row_references(Oid relOid, Bitmapset *columns)
Definition dml.c:39
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
void pfree(void *pointer)
Definition mcxt.c:1616
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
char * getObjectIdentity(const ObjectAddress *object, bool missing_ok)
int16 attnum
static int fb(int x)
bool sepgsql_getenforce(void)
Definition selinux.c:651
#define SEPG_CLASS_DB_TABLE
Definition sepgsql.h:46
#define SEPG_DB_TABLE__DELETE
Definition sepgsql.h:146
#define SEPG_DB_TABLE__INSERT
Definition sepgsql.h:145
#define SEPG_DB_TABLE__UPDATE
Definition sepgsql.h:144
#define SEPG_DB_VIEW__EXPAND
Definition sepgsql.h:213
#define SEPG_CLASS_DB_COLUMN
Definition sepgsql.h:49
#define SEPG_DB_COLUMN__INSERT
Definition sepgsql.h:178
#define SEPG_DB_COLUMN__SELECT
Definition sepgsql.h:176
#define SEPG_DB_TABLE__SELECT
Definition sepgsql.h:143
#define SEPG_DB_COLUMN__UPDATE
Definition sepgsql.h:177
#define SEPG_CLASS_DB_VIEW
Definition sepgsql.h:53
#define SEPG_CLASS_DB_SEQUENCE
Definition sepgsql.h:47
#define SEPG_DB_SEQUENCE__GET_VALUE
Definition sepgsql.h:156
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition uavc.c:420
Definition type.h:96
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References Assert, attnum, bms_is_member(), bms_next_member(), bms_union(), ereport, errcode(), errmsg(), ERROR, fb(), FirstLowInvalidHeapAttributeNumber, fixup_whole_row_references(), get_rel_relkind(), getObjectDescription(), getObjectIdentity(), IsCatalogRelationOid(), pfree(), SEPG_CLASS_DB_COLUMN, SEPG_CLASS_DB_SEQUENCE, SEPG_CLASS_DB_TABLE, SEPG_CLASS_DB_VIEW, SEPG_DB_COLUMN__INSERT, SEPG_DB_COLUMN__SELECT, SEPG_DB_COLUMN__UPDATE, SEPG_DB_SEQUENCE__GET_VALUE, SEPG_DB_TABLE__DELETE, SEPG_DB_TABLE__INSERT, SEPG_DB_TABLE__SELECT, SEPG_DB_TABLE__UPDATE, SEPG_DB_VIEW__EXPAND, sepgsql_avc_check_perms(), and sepgsql_getenforce().

Referenced by sepgsql_dml_privileges().

◆ fixup_inherited_columns()

static Bitmapset * fixup_inherited_columns ( Oid  parentId,
Oid  childId,
Bitmapset columns 
)
static

Definition at line 93 of file dml.c.

94{
95 Bitmapset *result = NULL;
96 int index;
97
98 /*
99 * obviously, no need to do anything here
100 */
101 if (parentId == childId)
102 return columns;
103
104 index = -1;
105 while ((index = bms_next_member(columns, index)) >= 0)
106 {
107 /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */
109 char *attname;
110
111 /*
112 * whole-row-reference shall be fixed-up later
113 */
114 if (attno == InvalidAttrNumber)
115 {
116 result = bms_add_member(result, index);
117 continue;
118 }
119
120 attname = get_attname(parentId, attno, false);
121 attno = get_attnum(childId, attname);
122 if (attno == InvalidAttrNumber)
123 elog(ERROR, "cache lookup failed for attribute %s of relation %u",
125
126 result = bms_add_member(result,
128
129 pfree(attname);
130 }
131
132 return result;
133}
#define InvalidAttrNumber
Definition attnum.h:23
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
#define elog(elevel,...)
Definition elog.h:226
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:934
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:903
NameData attname

References attname, bms_add_member(), bms_next_member(), elog, ERROR, fb(), FirstLowInvalidHeapAttributeNumber, get_attname(), get_attnum(), InvalidAttrNumber, and pfree().

Referenced by sepgsql_dml_privileges().

◆ fixup_whole_row_references()

static Bitmapset * fixup_whole_row_references ( Oid  relOid,
Bitmapset columns 
)
static

Definition at line 39 of file dml.c.

40{
41 Bitmapset *result;
42 HeapTuple tuple;
43 AttrNumber natts;
44 AttrNumber attno;
45 int index;
46
47 /* if no whole-row references, nothing to do */
49 if (!bms_is_member(index, columns))
50 return columns;
51
52 /* obtain number of attributes */
53 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
54 if (!HeapTupleIsValid(tuple))
55 elog(ERROR, "cache lookup failed for relation %u", relOid);
56 natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts;
57 ReleaseSysCache(tuple);
58
59 /* remove bit 0 from column set, add in all the non-dropped columns */
60 result = bms_copy(columns);
61 result = bms_del_member(result, index);
62
63 for (attno = 1; attno <= natts; attno++)
64 {
65 tuple = SearchSysCache2(ATTNUM,
66 ObjectIdGetDatum(relOid),
67 Int16GetDatum(attno));
68 if (!HeapTupleIsValid(tuple))
69 continue; /* unexpected case, should we error? */
70
71 if (!((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
72 {
74 result = bms_add_member(result, index);
75 }
76
77 ReleaseSysCache(tuple);
78 }
79 return result;
80}
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:867
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
FormData_pg_attribute * Form_pg_attribute
FormData_pg_class * Form_pg_class
Definition pg_class.h:156
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition syscache.c:230

References bms_add_member(), bms_copy(), bms_del_member(), bms_is_member(), elog, ERROR, fb(), FirstLowInvalidHeapAttributeNumber, GETSTRUCT(), HeapTupleIsValid, Int16GetDatum(), InvalidAttrNumber, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCache2().

Referenced by check_relation_privileges().

◆ sepgsql_dml_privileges()

bool sepgsql_dml_privileges ( List rangeTbls,
List rteperminfos,
bool  abort_on_violation 
)

Definition at line 282 of file dml.c.

284{
285 ListCell *lr;
286
287 foreach(lr, rteperminfos)
288 {
290 uint32 required = 0;
291 List *tableIds;
292 ListCell *li;
293
294 /*
295 * Find out required permissions
296 */
297 if (perminfo->requiredPerms & ACL_SELECT)
299 if (perminfo->requiredPerms & ACL_INSERT)
301 if (perminfo->requiredPerms & ACL_UPDATE)
302 {
303 if (!bms_is_empty(perminfo->updatedCols))
305 else
307 }
308 if (perminfo->requiredPerms & ACL_DELETE)
310
311 /*
312 * Skip, if nothing to be checked
313 */
314 if (required == 0)
315 continue;
316
317 /*
318 * If this RangeTblEntry is also supposed to reference inherited
319 * tables, we need to check security label of the child tables. So, we
320 * expand rte->relid into list of OIDs of inheritance hierarchy, then
321 * checker routine will be invoked for each relations.
322 */
323 if (!perminfo->inh)
325 else
327
328 foreach(li, tableIds)
329 {
330 Oid tableOid = lfirst_oid(li);
331 Bitmapset *selectedCols;
332 Bitmapset *insertedCols;
333 Bitmapset *updatedCols;
334
335 /*
336 * child table has different attribute numbers, so we need to fix
337 * up them.
338 */
339 selectedCols = fixup_inherited_columns(perminfo->relid, tableOid,
340 perminfo->selectedCols);
341 insertedCols = fixup_inherited_columns(perminfo->relid, tableOid,
342 perminfo->insertedCols);
343 updatedCols = fixup_inherited_columns(perminfo->relid, tableOid,
344 perminfo->updatedCols);
345
346 /*
347 * check permissions on individual tables
348 */
349 if (!check_relation_privileges(tableOid,
350 selectedCols,
351 insertedCols,
352 updatedCols,
353 required, abort_on_violation))
354 return false;
355 }
357 }
358 return true;
359}
#define bms_is_empty(a)
Definition bitmapset.h:118
static bool check_relation_privileges(Oid relOid, Bitmapset *selected, Bitmapset *inserted, Bitmapset *updated, uint32 required, bool abort_on_violation)
Definition dml.c:142
static Bitmapset * fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns)
Definition dml.c:93
void list_free(List *list)
Definition list.c:1546
#define NoLock
Definition lockdefs.h:34
#define ACL_DELETE
Definition parsenodes.h:79
#define ACL_INSERT
Definition parsenodes.h:76
#define ACL_UPDATE
Definition parsenodes.h:78
#define ACL_SELECT
Definition parsenodes.h:77
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define list_make1_oid(x1)
Definition pg_list.h:242
#define lfirst_oid(lc)
Definition pg_list.h:174
unsigned int Oid
#define SEPG_DB_TABLE__LOCK
Definition sepgsql.h:147
Definition pg_list.h:54

References ACL_DELETE, ACL_INSERT, ACL_SELECT, ACL_UPDATE, bms_is_empty, check_relation_privileges(), fb(), find_all_inheritors(), fixup_inherited_columns(), lfirst_node, lfirst_oid, list_free(), list_make1_oid, NoLock, SEPG_DB_TABLE__DELETE, SEPG_DB_TABLE__INSERT, SEPG_DB_TABLE__LOCK, SEPG_DB_TABLE__SELECT, and SEPG_DB_TABLE__UPDATE.

Referenced by sepgsql_exec_check_perms().