Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * contrib/sepgsql/selinux.c
4 : : *
5 : : * Interactions between userspace and selinux in kernelspace,
6 : : * using libselinux api.
7 : : *
8 : : * Copyright (c) 2010-2024, PostgreSQL Global Development Group
9 : : *
10 : : * -------------------------------------------------------------------------
11 : : */
12 : : #include "postgres.h"
13 : :
14 : : #include "lib/stringinfo.h"
15 : :
16 : : #include "sepgsql.h"
17 : :
18 : : /*
19 : : * selinux_catalog
20 : : *
21 : : * This mapping table enables to translate the name of object classes and
22 : : * access vectors to/from their own codes.
23 : : * When we ask SELinux whether the required privileges are allowed or not,
24 : : * we use security_compute_av(3). It needs us to represent object classes
25 : : * and access vectors using 'external' codes defined in the security policy.
26 : : * It is determined in the runtime, not build time. So, it needs an internal
27 : : * service to translate object class/access vectors which we want to check
28 : : * into the code which kernel want to be given.
29 : : */
30 : : static struct
31 : : {
32 : : const char *class_name;
33 : : uint16 class_code;
34 : : struct
35 : : {
36 : : const char *av_name;
37 : : uint32 av_code;
38 : : } av[32];
39 : : } selinux_catalog[] =
40 : :
41 : : {
42 : : {
43 : : "process", SEPG_CLASS_PROCESS,
44 : : {
45 : : {
46 : : "transition", SEPG_PROCESS__TRANSITION
47 : : },
48 : : {
49 : : "dyntransition", SEPG_PROCESS__DYNTRANSITION
50 : : },
51 : : {
52 : : "setcurrent", SEPG_PROCESS__SETCURRENT
53 : : },
54 : : {
55 : : NULL, 0UL
56 : : }
57 : : }
58 : : },
59 : : {
60 : : "file", SEPG_CLASS_FILE,
61 : : {
62 : : {
63 : : "read", SEPG_FILE__READ
64 : : },
65 : : {
66 : : "write", SEPG_FILE__WRITE
67 : : },
68 : : {
69 : : "create", SEPG_FILE__CREATE
70 : : },
71 : : {
72 : : "getattr", SEPG_FILE__GETATTR
73 : : },
74 : : {
75 : : "unlink", SEPG_FILE__UNLINK
76 : : },
77 : : {
78 : : "rename", SEPG_FILE__RENAME
79 : : },
80 : : {
81 : : "append", SEPG_FILE__APPEND
82 : : },
83 : : {
84 : : NULL, 0UL
85 : : }
86 : : }
87 : : },
88 : : {
89 : : "dir", SEPG_CLASS_DIR,
90 : : {
91 : : {
92 : : "read", SEPG_DIR__READ
93 : : },
94 : : {
95 : : "write", SEPG_DIR__WRITE
96 : : },
97 : : {
98 : : "create", SEPG_DIR__CREATE
99 : : },
100 : : {
101 : : "getattr", SEPG_DIR__GETATTR
102 : : },
103 : : {
104 : : "unlink", SEPG_DIR__UNLINK
105 : : },
106 : : {
107 : : "rename", SEPG_DIR__RENAME
108 : : },
109 : : {
110 : : "search", SEPG_DIR__SEARCH
111 : : },
112 : : {
113 : : "add_name", SEPG_DIR__ADD_NAME
114 : : },
115 : : {
116 : : "remove_name", SEPG_DIR__REMOVE_NAME
117 : : },
118 : : {
119 : : "rmdir", SEPG_DIR__RMDIR
120 : : },
121 : : {
122 : : "reparent", SEPG_DIR__REPARENT
123 : : },
124 : : {
125 : : NULL, 0UL
126 : : }
127 : : }
128 : : },
129 : : {
130 : : "lnk_file", SEPG_CLASS_LNK_FILE,
131 : : {
132 : : {
133 : : "read", SEPG_LNK_FILE__READ
134 : : },
135 : : {
136 : : "write", SEPG_LNK_FILE__WRITE
137 : : },
138 : : {
139 : : "create", SEPG_LNK_FILE__CREATE
140 : : },
141 : : {
142 : : "getattr", SEPG_LNK_FILE__GETATTR
143 : : },
144 : : {
145 : : "unlink", SEPG_LNK_FILE__UNLINK
146 : : },
147 : : {
148 : : "rename", SEPG_LNK_FILE__RENAME
149 : : },
150 : : {
151 : : NULL, 0UL
152 : : }
153 : : }
154 : : },
155 : : {
156 : : "chr_file", SEPG_CLASS_CHR_FILE,
157 : : {
158 : : {
159 : : "read", SEPG_CHR_FILE__READ
160 : : },
161 : : {
162 : : "write", SEPG_CHR_FILE__WRITE
163 : : },
164 : : {
165 : : "create", SEPG_CHR_FILE__CREATE
166 : : },
167 : : {
168 : : "getattr", SEPG_CHR_FILE__GETATTR
169 : : },
170 : : {
171 : : "unlink", SEPG_CHR_FILE__UNLINK
172 : : },
173 : : {
174 : : "rename", SEPG_CHR_FILE__RENAME
175 : : },
176 : : {
177 : : NULL, 0UL
178 : : }
179 : : }
180 : : },
181 : : {
182 : : "blk_file", SEPG_CLASS_BLK_FILE,
183 : : {
184 : : {
185 : : "read", SEPG_BLK_FILE__READ
186 : : },
187 : : {
188 : : "write", SEPG_BLK_FILE__WRITE
189 : : },
190 : : {
191 : : "create", SEPG_BLK_FILE__CREATE
192 : : },
193 : : {
194 : : "getattr", SEPG_BLK_FILE__GETATTR
195 : : },
196 : : {
197 : : "unlink", SEPG_BLK_FILE__UNLINK
198 : : },
199 : : {
200 : : "rename", SEPG_BLK_FILE__RENAME
201 : : },
202 : : {
203 : : NULL, 0UL
204 : : }
205 : : }
206 : : },
207 : : {
208 : : "sock_file", SEPG_CLASS_SOCK_FILE,
209 : : {
210 : : {
211 : : "read", SEPG_SOCK_FILE__READ
212 : : },
213 : : {
214 : : "write", SEPG_SOCK_FILE__WRITE
215 : : },
216 : : {
217 : : "create", SEPG_SOCK_FILE__CREATE
218 : : },
219 : : {
220 : : "getattr", SEPG_SOCK_FILE__GETATTR
221 : : },
222 : : {
223 : : "unlink", SEPG_SOCK_FILE__UNLINK
224 : : },
225 : : {
226 : : "rename", SEPG_SOCK_FILE__RENAME
227 : : },
228 : : {
229 : : NULL, 0UL
230 : : }
231 : : }
232 : : },
233 : : {
234 : : "fifo_file", SEPG_CLASS_FIFO_FILE,
235 : : {
236 : : {
237 : : "read", SEPG_FIFO_FILE__READ
238 : : },
239 : : {
240 : : "write", SEPG_FIFO_FILE__WRITE
241 : : },
242 : : {
243 : : "create", SEPG_FIFO_FILE__CREATE
244 : : },
245 : : {
246 : : "getattr", SEPG_FIFO_FILE__GETATTR
247 : : },
248 : : {
249 : : "unlink", SEPG_FIFO_FILE__UNLINK
250 : : },
251 : : {
252 : : "rename", SEPG_FIFO_FILE__RENAME
253 : : },
254 : : {
255 : : NULL, 0UL
256 : : }
257 : : }
258 : : },
259 : : {
260 : : "db_database", SEPG_CLASS_DB_DATABASE,
261 : : {
262 : : {
263 : : "create", SEPG_DB_DATABASE__CREATE
264 : : },
265 : : {
266 : : "drop", SEPG_DB_DATABASE__DROP
267 : : },
268 : : {
269 : : "getattr", SEPG_DB_DATABASE__GETATTR
270 : : },
271 : : {
272 : : "setattr", SEPG_DB_DATABASE__SETATTR
273 : : },
274 : : {
275 : : "relabelfrom", SEPG_DB_DATABASE__RELABELFROM
276 : : },
277 : : {
278 : : "relabelto", SEPG_DB_DATABASE__RELABELTO
279 : : },
280 : : {
281 : : "access", SEPG_DB_DATABASE__ACCESS
282 : : },
283 : : {
284 : : "load_module", SEPG_DB_DATABASE__LOAD_MODULE
285 : : },
286 : : {
287 : : NULL, 0UL
288 : : },
289 : : }
290 : : },
291 : : {
292 : : "db_schema", SEPG_CLASS_DB_SCHEMA,
293 : : {
294 : : {
295 : : "create", SEPG_DB_SCHEMA__CREATE
296 : : },
297 : : {
298 : : "drop", SEPG_DB_SCHEMA__DROP
299 : : },
300 : : {
301 : : "getattr", SEPG_DB_SCHEMA__GETATTR
302 : : },
303 : : {
304 : : "setattr", SEPG_DB_SCHEMA__SETATTR
305 : : },
306 : : {
307 : : "relabelfrom", SEPG_DB_SCHEMA__RELABELFROM
308 : : },
309 : : {
310 : : "relabelto", SEPG_DB_SCHEMA__RELABELTO
311 : : },
312 : : {
313 : : "search", SEPG_DB_SCHEMA__SEARCH
314 : : },
315 : : {
316 : : "add_name", SEPG_DB_SCHEMA__ADD_NAME
317 : : },
318 : : {
319 : : "remove_name", SEPG_DB_SCHEMA__REMOVE_NAME
320 : : },
321 : : {
322 : : NULL, 0UL
323 : : },
324 : : }
325 : : },
326 : : {
327 : : "db_table", SEPG_CLASS_DB_TABLE,
328 : : {
329 : : {
330 : : "create", SEPG_DB_TABLE__CREATE
331 : : },
332 : : {
333 : : "drop", SEPG_DB_TABLE__DROP
334 : : },
335 : : {
336 : : "getattr", SEPG_DB_TABLE__GETATTR
337 : : },
338 : : {
339 : : "setattr", SEPG_DB_TABLE__SETATTR
340 : : },
341 : : {
342 : : "relabelfrom", SEPG_DB_TABLE__RELABELFROM
343 : : },
344 : : {
345 : : "relabelto", SEPG_DB_TABLE__RELABELTO
346 : : },
347 : : {
348 : : "select", SEPG_DB_TABLE__SELECT
349 : : },
350 : : {
351 : : "update", SEPG_DB_TABLE__UPDATE
352 : : },
353 : : {
354 : : "insert", SEPG_DB_TABLE__INSERT
355 : : },
356 : : {
357 : : "delete", SEPG_DB_TABLE__DELETE
358 : : },
359 : : {
360 : : "lock", SEPG_DB_TABLE__LOCK
361 : : },
362 : : {
363 : : "truncate", SEPG_DB_TABLE__TRUNCATE
364 : : },
365 : : {
366 : : NULL, 0UL
367 : : },
368 : : }
369 : : },
370 : : {
371 : : "db_sequence", SEPG_CLASS_DB_SEQUENCE,
372 : : {
373 : : {
374 : : "create", SEPG_DB_SEQUENCE__CREATE
375 : : },
376 : : {
377 : : "drop", SEPG_DB_SEQUENCE__DROP
378 : : },
379 : : {
380 : : "getattr", SEPG_DB_SEQUENCE__GETATTR
381 : : },
382 : : {
383 : : "setattr", SEPG_DB_SEQUENCE__SETATTR
384 : : },
385 : : {
386 : : "relabelfrom", SEPG_DB_SEQUENCE__RELABELFROM
387 : : },
388 : : {
389 : : "relabelto", SEPG_DB_SEQUENCE__RELABELTO
390 : : },
391 : : {
392 : : "get_value", SEPG_DB_SEQUENCE__GET_VALUE
393 : : },
394 : : {
395 : : "next_value", SEPG_DB_SEQUENCE__NEXT_VALUE
396 : : },
397 : : {
398 : : "set_value", SEPG_DB_SEQUENCE__SET_VALUE
399 : : },
400 : : {
401 : : NULL, 0UL
402 : : },
403 : : }
404 : : },
405 : : {
406 : : "db_procedure", SEPG_CLASS_DB_PROCEDURE,
407 : : {
408 : : {
409 : : "create", SEPG_DB_PROCEDURE__CREATE
410 : : },
411 : : {
412 : : "drop", SEPG_DB_PROCEDURE__DROP
413 : : },
414 : : {
415 : : "getattr", SEPG_DB_PROCEDURE__GETATTR
416 : : },
417 : : {
418 : : "setattr", SEPG_DB_PROCEDURE__SETATTR
419 : : },
420 : : {
421 : : "relabelfrom", SEPG_DB_PROCEDURE__RELABELFROM
422 : : },
423 : : {
424 : : "relabelto", SEPG_DB_PROCEDURE__RELABELTO
425 : : },
426 : : {
427 : : "execute", SEPG_DB_PROCEDURE__EXECUTE
428 : : },
429 : : {
430 : : "entrypoint", SEPG_DB_PROCEDURE__ENTRYPOINT
431 : : },
432 : : {
433 : : "install", SEPG_DB_PROCEDURE__INSTALL
434 : : },
435 : : {
436 : : NULL, 0UL
437 : : },
438 : : }
439 : : },
440 : : {
441 : : "db_column", SEPG_CLASS_DB_COLUMN,
442 : : {
443 : : {
444 : : "create", SEPG_DB_COLUMN__CREATE
445 : : },
446 : : {
447 : : "drop", SEPG_DB_COLUMN__DROP
448 : : },
449 : : {
450 : : "getattr", SEPG_DB_COLUMN__GETATTR
451 : : },
452 : : {
453 : : "setattr", SEPG_DB_COLUMN__SETATTR
454 : : },
455 : : {
456 : : "relabelfrom", SEPG_DB_COLUMN__RELABELFROM
457 : : },
458 : : {
459 : : "relabelto", SEPG_DB_COLUMN__RELABELTO
460 : : },
461 : : {
462 : : "select", SEPG_DB_COLUMN__SELECT
463 : : },
464 : : {
465 : : "update", SEPG_DB_COLUMN__UPDATE
466 : : },
467 : : {
468 : : "insert", SEPG_DB_COLUMN__INSERT
469 : : },
470 : : {
471 : : NULL, 0UL
472 : : },
473 : : }
474 : : },
475 : : {
476 : : "db_tuple", SEPG_CLASS_DB_TUPLE,
477 : : {
478 : : {
479 : : "relabelfrom", SEPG_DB_TUPLE__RELABELFROM
480 : : },
481 : : {
482 : : "relabelto", SEPG_DB_TUPLE__RELABELTO
483 : : },
484 : : {
485 : : "select", SEPG_DB_TUPLE__SELECT
486 : : },
487 : : {
488 : : "update", SEPG_DB_TUPLE__UPDATE
489 : : },
490 : : {
491 : : "insert", SEPG_DB_TUPLE__INSERT
492 : : },
493 : : {
494 : : "delete", SEPG_DB_TUPLE__DELETE
495 : : },
496 : : {
497 : : NULL, 0UL
498 : : },
499 : : }
500 : : },
501 : : {
502 : : "db_blob", SEPG_CLASS_DB_BLOB,
503 : : {
504 : : {
505 : : "create", SEPG_DB_BLOB__CREATE
506 : : },
507 : : {
508 : : "drop", SEPG_DB_BLOB__DROP
509 : : },
510 : : {
511 : : "getattr", SEPG_DB_BLOB__GETATTR
512 : : },
513 : : {
514 : : "setattr", SEPG_DB_BLOB__SETATTR
515 : : },
516 : : {
517 : : "relabelfrom", SEPG_DB_BLOB__RELABELFROM
518 : : },
519 : : {
520 : : "relabelto", SEPG_DB_BLOB__RELABELTO
521 : : },
522 : : {
523 : : "read", SEPG_DB_BLOB__READ
524 : : },
525 : : {
526 : : "write", SEPG_DB_BLOB__WRITE
527 : : },
528 : : {
529 : : "import", SEPG_DB_BLOB__IMPORT
530 : : },
531 : : {
532 : : "export", SEPG_DB_BLOB__EXPORT
533 : : },
534 : : {
535 : : NULL, 0UL
536 : : },
537 : : }
538 : : },
539 : : {
540 : : "db_language", SEPG_CLASS_DB_LANGUAGE,
541 : : {
542 : : {
543 : : "create", SEPG_DB_LANGUAGE__CREATE
544 : : },
545 : : {
546 : : "drop", SEPG_DB_LANGUAGE__DROP
547 : : },
548 : : {
549 : : "getattr", SEPG_DB_LANGUAGE__GETATTR
550 : : },
551 : : {
552 : : "setattr", SEPG_DB_LANGUAGE__SETATTR
553 : : },
554 : : {
555 : : "relabelfrom", SEPG_DB_LANGUAGE__RELABELFROM
556 : : },
557 : : {
558 : : "relabelto", SEPG_DB_LANGUAGE__RELABELTO
559 : : },
560 : : {
561 : : "implement", SEPG_DB_LANGUAGE__IMPLEMENT
562 : : },
563 : : {
564 : : "execute", SEPG_DB_LANGUAGE__EXECUTE
565 : : },
566 : : {
567 : : NULL, 0UL
568 : : },
569 : : }
570 : : },
571 : : {
572 : : "db_view", SEPG_CLASS_DB_VIEW,
573 : : {
574 : : {
575 : : "create", SEPG_DB_VIEW__CREATE
576 : : },
577 : : {
578 : : "drop", SEPG_DB_VIEW__DROP
579 : : },
580 : : {
581 : : "getattr", SEPG_DB_VIEW__GETATTR
582 : : },
583 : : {
584 : : "setattr", SEPG_DB_VIEW__SETATTR
585 : : },
586 : : {
587 : : "relabelfrom", SEPG_DB_VIEW__RELABELFROM
588 : : },
589 : : {
590 : : "relabelto", SEPG_DB_VIEW__RELABELTO
591 : : },
592 : : {
593 : : "expand", SEPG_DB_VIEW__EXPAND
594 : : },
595 : : {
596 : : NULL, 0UL
597 : : },
598 : : }
599 : : },
600 : : };
601 : :
602 : : /*
603 : : * sepgsql_mode
604 : : *
605 : : * SEPGSQL_MODE_DISABLED: Disabled on runtime
606 : : * SEPGSQL_MODE_DEFAULT: Same as system settings
607 : : * SEPGSQL_MODE_PERMISSIVE: Always permissive mode
608 : : * SEPGSQL_MODE_INTERNAL: Same as permissive, except for no audit logs
609 : : */
610 : : static int sepgsql_mode = SEPGSQL_MODE_INTERNAL;
611 : :
612 : : /*
613 : : * sepgsql_is_enabled
614 : : */
615 : : bool
4830 rhaas@postgresql.org 616 :UBC 0 : sepgsql_is_enabled(void)
617 : : {
949 michael@paquier.xyz 618 : 0 : return (sepgsql_mode != SEPGSQL_MODE_DISABLED);
619 : : }
620 : :
621 : : /*
622 : : * sepgsql_get_mode
623 : : */
624 : : int
4830 rhaas@postgresql.org 625 : 0 : sepgsql_get_mode(void)
626 : : {
627 : 0 : return sepgsql_mode;
628 : : }
629 : :
630 : : /*
631 : : * sepgsql_set_mode
632 : : */
633 : : int
634 : 0 : sepgsql_set_mode(int new_mode)
635 : : {
4753 bruce@momjian.us 636 : 0 : int old_mode = sepgsql_mode;
637 : :
4830 rhaas@postgresql.org 638 : 0 : sepgsql_mode = new_mode;
639 : :
640 : 0 : return old_mode;
641 : : }
642 : :
643 : : /*
644 : : * sepgsql_getenforce
645 : : *
646 : : * It returns whether the current working mode tries to enforce access
647 : : * control decision, or not. It shall be enforced when sepgsql_mode is
648 : : * SEPGSQL_MODE_DEFAULT and system is running in enforcing mode.
649 : : */
650 : : bool
651 : 0 : sepgsql_getenforce(void)
652 : : {
653 [ # # # # ]: 0 : if (sepgsql_mode == SEPGSQL_MODE_DEFAULT &&
4609 654 : 0 : selinux_status_getenforce() > 0)
4830 655 : 0 : return true;
656 : :
657 : 0 : return false;
658 : : }
659 : :
660 : : /*
661 : : * sepgsql_audit_log
662 : : *
663 : : * It generates a security audit record. It writes out audit records
664 : : * into standard PG's logfile.
665 : : *
666 : : * SELinux can control what should be audited and should not using
667 : : * "auditdeny" and "auditallow" rules in the security policy. In the
668 : : * default, all the access violations are audited, and all the access
669 : : * allowed are not audited. But we can set up the security policy, so
670 : : * we can have exceptions. So, it is necessary to follow the suggestion
671 : : * come from the security policy. (av_decision.auditallow and auditdeny)
672 : : *
673 : : * Security audit is an important feature, because it enables us to check
674 : : * what was happen if we have a security incident. In fact, ISO/IEC15408
675 : : * defines several security functionalities for audit features.
676 : : */
677 : : void
678 : 0 : sepgsql_audit_log(bool denied,
679 : : bool enforcing,
680 : : const char *scontext,
681 : : const char *tcontext,
682 : : uint16 tclass,
683 : : uint32 audited,
684 : : const char *audit_name)
685 : : {
686 : : StringInfoData buf;
687 : : const char *class_name;
688 : : const char *av_name;
689 : : int i;
690 : :
691 : : /* lookup name of the object class */
692 [ # # ]: 0 : Assert(tclass < SEPG_CLASS_MAX);
693 : 0 : class_name = selinux_catalog[tclass].class_name;
694 : :
695 : : /* lookup name of the permissions */
696 : 0 : initStringInfo(&buf);
697 [ # # ]: 0 : appendStringInfo(&buf, "%s {",
698 : : (denied ? "denied" : "allowed"));
4753 bruce@momjian.us 699 [ # # ]: 0 : for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
700 : : {
4830 rhaas@postgresql.org 701 [ # # ]: 0 : if (audited & (1UL << i))
702 : : {
703 : 0 : av_name = selinux_catalog[tclass].av[i].av_name;
704 : 0 : appendStringInfo(&buf, " %s", av_name);
705 : : }
706 : : }
1746 drowley@postgresql.o 707 : 0 : appendStringInfoString(&buf, " }");
708 : :
709 : : /*
710 : : * Call external audit module, if loaded
711 : : */
4830 rhaas@postgresql.org 712 : 0 : appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s",
713 : : scontext, tcontext, class_name);
714 [ # # ]: 0 : if (audit_name)
4820 715 : 0 : appendStringInfo(&buf, " name=\"%s\"", audit_name);
716 : :
823 tgl@sss.pgh.pa.us 717 [ # # ]: 0 : if (enforcing)
718 : 0 : appendStringInfoString(&buf, " permissive=0");
719 : : else
720 : 0 : appendStringInfoString(&buf, " permissive=1");
721 : :
4830 rhaas@postgresql.org 722 [ # # ]: 0 : ereport(LOG, (errmsg("SELinux: %s", buf.data)));
723 : 0 : }
724 : :
725 : : /*
726 : : * sepgsql_compute_avd
727 : : *
728 : : * It actually asks SELinux what permissions are allowed on a pair of
729 : : * the security contexts and object class. It also returns what permissions
730 : : * should be audited on access violation or allowed.
731 : : * In most cases, subject's security context (scontext) is a client, and
732 : : * target security context (tcontext) is a database object.
733 : : *
734 : : * The access control decision shall be set on the given av_decision.
735 : : * The av_decision.allowed has a bitmask of SEPG_<class>__<perms>
736 : : * to suggest a set of allowed actions in this object class.
737 : : */
738 : : void
739 : 0 : sepgsql_compute_avd(const char *scontext,
740 : : const char *tcontext,
741 : : uint16 tclass,
742 : : struct av_decision *avd)
743 : : {
744 : : const char *tclass_name;
745 : : security_class_t tclass_ex;
746 : : struct av_decision avd_ex;
747 : : int i,
4753 bruce@momjian.us 748 : 0 : deny_unknown = security_deny_unknown();
749 : :
750 : : /* Get external code of the object class */
4830 rhaas@postgresql.org 751 [ # # ]: 0 : Assert(tclass < SEPG_CLASS_MAX);
752 [ # # ]: 0 : Assert(tclass == selinux_catalog[tclass].class_code);
753 : :
754 : 0 : tclass_name = selinux_catalog[tclass].class_name;
755 : 0 : tclass_ex = string_to_security_class(tclass_name);
756 : :
757 [ # # ]: 0 : if (tclass_ex == 0)
758 : : {
759 : : /*
760 : : * If the current security policy does not support permissions
761 : : * corresponding to database objects, we fill up them with dummy data.
762 : : * If security_deny_unknown() returns positive value, undefined
763 : : * permissions should be denied. Otherwise, allowed
764 : : */
765 [ # # ]: 0 : avd->allowed = (security_deny_unknown() > 0 ? 0 : ~0);
766 : 0 : avd->auditallow = 0U;
4753 bruce@momjian.us 767 : 0 : avd->auditdeny = ~0U;
4830 rhaas@postgresql.org 768 : 0 : avd->flags = 0;
769 : :
770 : 0 : return;
771 : : }
772 : :
773 : : /*
774 : : * Ask SELinux what is allowed set of permissions on a pair of the
775 : : * security contexts and the given object class.
776 : : */
1339 michael@paquier.xyz 777 [ # # ]: 0 : if (security_compute_av_flags_raw(scontext,
778 : : tcontext,
779 : : tclass_ex, 0, &avd_ex) < 0)
4830 rhaas@postgresql.org 780 [ # # ]: 0 : ereport(ERROR,
781 : : (errcode(ERRCODE_INTERNAL_ERROR),
782 : : errmsg("SELinux could not compute av_decision: "
783 : : "scontext=%s tcontext=%s tclass=%s: %m",
784 : : scontext, tcontext, tclass_name)));
785 : :
786 : : /*
787 : : * SELinux returns its access control decision as a set of permissions
788 : : * represented in external code which depends on run-time environment. So,
789 : : * we need to translate it to the internal representation before returning
790 : : * results for the caller.
791 : : */
792 : 0 : memset(avd, 0, sizeof(struct av_decision));
793 : :
4753 bruce@momjian.us 794 [ # # ]: 0 : for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
795 : : {
796 : : access_vector_t av_code_ex;
797 : 0 : const char *av_name = selinux_catalog[tclass].av[i].av_name;
798 : 0 : uint32 av_code = selinux_catalog[tclass].av[i].av_code;
799 : :
4830 rhaas@postgresql.org 800 : 0 : av_code_ex = string_to_av_perm(tclass_ex, av_name);
801 [ # # ]: 0 : if (av_code_ex == 0)
802 : : {
803 : : /* fill up undefined permissions */
804 [ # # ]: 0 : if (!deny_unknown)
805 : 0 : avd->allowed |= av_code;
806 : 0 : avd->auditdeny |= av_code;
807 : :
808 : 0 : continue;
809 : : }
810 : :
811 [ # # ]: 0 : if (avd_ex.allowed & av_code_ex)
812 : 0 : avd->allowed |= av_code;
813 [ # # ]: 0 : if (avd_ex.auditallow & av_code_ex)
814 : 0 : avd->auditallow |= av_code;
815 [ # # ]: 0 : if (avd_ex.auditdeny & av_code_ex)
816 : 0 : avd->auditdeny |= av_code;
817 : : }
818 : : }
819 : :
820 : : /*
821 : : * sepgsql_compute_create
822 : : *
823 : : * It returns a default security context to be assigned on a new database
824 : : * object. SELinux compute it based on a combination of client, upper object
825 : : * which owns the new object and object class.
826 : : *
827 : : * For example, when a client (staff_u:staff_r:staff_t:s0) tries to create
828 : : * a new table within a schema (system_u:object_r:sepgsql_schema_t:s0),
829 : : * SELinux looks-up its security policy. If it has a special rule on the
830 : : * combination of these security contexts and object class (db_table),
831 : : * it returns the security context suggested by the special rule.
832 : : * Otherwise, it returns the security context of schema, as is.
833 : : *
834 : : * We expect the caller already applies sanity/validation checks on the
835 : : * given security context.
836 : : *
837 : : * scontext: security context of the subject (mostly, peer process).
838 : : * tcontext: security context of the upper database object.
839 : : * tclass: class code (SEPG_CLASS_*) of the new object in creation
840 : : */
841 : : char *
842 : 0 : sepgsql_compute_create(const char *scontext,
843 : : const char *tcontext,
844 : : uint16 tclass,
845 : : const char *objname)
846 : : {
847 : : char *ncontext;
848 : : security_class_t tclass_ex;
849 : : const char *tclass_name;
850 : : char *result;
851 : :
852 : : /* Get external code of the object class */
853 [ # # ]: 0 : Assert(tclass < SEPG_CLASS_MAX);
854 : :
855 : 0 : tclass_name = selinux_catalog[tclass].class_name;
856 : 0 : tclass_ex = string_to_security_class(tclass_name);
857 : :
858 : : /*
859 : : * Ask SELinux what is the default context for the given object class on a
860 : : * pair of security contexts
861 : : */
1339 michael@paquier.xyz 862 [ # # ]: 0 : if (security_compute_create_name_raw(scontext,
863 : : tcontext,
864 : : tclass_ex,
865 : : objname,
866 : : &ncontext) < 0)
4830 rhaas@postgresql.org 867 [ # # ]: 0 : ereport(ERROR,
868 : : (errcode(ERRCODE_INTERNAL_ERROR),
869 : : errmsg("SELinux could not compute a new context: "
870 : : "scontext=%s tcontext=%s tclass=%s: %m",
871 : : scontext, tcontext, tclass_name)));
872 : :
873 : : /*
874 : : * libselinux returns malloc()'ed string, so we need to copy it on the
875 : : * palloc()'ed region.
876 : : */
877 [ # # ]: 0 : PG_TRY();
878 : : {
879 : 0 : result = pstrdup(ncontext);
880 : : }
1626 peter@eisentraut.org 881 : 0 : PG_FINALLY();
882 : : {
4830 rhaas@postgresql.org 883 : 0 : freecon(ncontext);
884 : : }
885 [ # # ]: 0 : PG_END_TRY();
886 : :
887 : 0 : return result;
888 : : }
|