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-2021, 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
sepgsql_is_enabled(void)616 sepgsql_is_enabled(void)
617 {
618 return (sepgsql_mode != SEPGSQL_MODE_DISABLED ? true : false);
619 }
620
621 /*
622 * sepgsql_get_mode
623 */
624 int
sepgsql_get_mode(void)625 sepgsql_get_mode(void)
626 {
627 return sepgsql_mode;
628 }
629
630 /*
631 * sepgsql_set_mode
632 */
633 int
sepgsql_set_mode(int new_mode)634 sepgsql_set_mode(int new_mode)
635 {
636 int old_mode = sepgsql_mode;
637
638 sepgsql_mode = new_mode;
639
640 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
sepgsql_getenforce(void)651 sepgsql_getenforce(void)
652 {
653 if (sepgsql_mode == SEPGSQL_MODE_DEFAULT &&
654 selinux_status_getenforce() > 0)
655 return true;
656
657 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
sepgsql_audit_log(bool denied,const char * scontext,const char * tcontext,uint16 tclass,uint32 audited,const char * audit_name)678 sepgsql_audit_log(bool denied,
679 const char *scontext,
680 const char *tcontext,
681 uint16 tclass,
682 uint32 audited,
683 const char *audit_name)
684 {
685 StringInfoData buf;
686 const char *class_name;
687 const char *av_name;
688 int i;
689
690 /* lookup name of the object class */
691 Assert(tclass < SEPG_CLASS_MAX);
692 class_name = selinux_catalog[tclass].class_name;
693
694 /* lookup name of the permissions */
695 initStringInfo(&buf);
696 appendStringInfo(&buf, "%s {",
697 (denied ? "denied" : "allowed"));
698 for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
699 {
700 if (audited & (1UL << i))
701 {
702 av_name = selinux_catalog[tclass].av[i].av_name;
703 appendStringInfo(&buf, " %s", av_name);
704 }
705 }
706 appendStringInfoString(&buf, " }");
707
708 /*
709 * Call external audit module, if loaded
710 */
711 appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s",
712 scontext, tcontext, class_name);
713 if (audit_name)
714 appendStringInfo(&buf, " name=\"%s\"", audit_name);
715
716 ereport(LOG, (errmsg("SELinux: %s", buf.data)));
717 }
718
719 /*
720 * sepgsql_compute_avd
721 *
722 * It actually asks SELinux what permissions are allowed on a pair of
723 * the security contexts and object class. It also returns what permissions
724 * should be audited on access violation or allowed.
725 * In most cases, subject's security context (scontext) is a client, and
726 * target security context (tcontext) is a database object.
727 *
728 * The access control decision shall be set on the given av_decision.
729 * The av_decision.allowed has a bitmask of SEPG_<class>__<perms>
730 * to suggest a set of allowed actions in this object class.
731 */
732 void
sepgsql_compute_avd(const char * scontext,const char * tcontext,uint16 tclass,struct av_decision * avd)733 sepgsql_compute_avd(const char *scontext,
734 const char *tcontext,
735 uint16 tclass,
736 struct av_decision *avd)
737 {
738 const char *tclass_name;
739 security_class_t tclass_ex;
740 struct av_decision avd_ex;
741 int i,
742 deny_unknown = security_deny_unknown();
743
744 /* Get external code of the object class */
745 Assert(tclass < SEPG_CLASS_MAX);
746 Assert(tclass == selinux_catalog[tclass].class_code);
747
748 tclass_name = selinux_catalog[tclass].class_name;
749 tclass_ex = string_to_security_class(tclass_name);
750
751 if (tclass_ex == 0)
752 {
753 /*
754 * If the current security policy does not support permissions
755 * corresponding to database objects, we fill up them with dummy data.
756 * If security_deny_unknown() returns positive value, undefined
757 * permissions should be denied. Otherwise, allowed
758 */
759 avd->allowed = (security_deny_unknown() > 0 ? 0 : ~0);
760 avd->auditallow = 0U;
761 avd->auditdeny = ~0U;
762 avd->flags = 0;
763
764 return;
765 }
766
767 /*
768 * Ask SELinux what is allowed set of permissions on a pair of the
769 * security contexts and the given object class.
770 */
771 if (security_compute_av_flags_raw(scontext,
772 tcontext,
773 tclass_ex, 0, &avd_ex) < 0)
774 ereport(ERROR,
775 (errcode(ERRCODE_INTERNAL_ERROR),
776 errmsg("SELinux could not compute av_decision: "
777 "scontext=%s tcontext=%s tclass=%s: %m",
778 scontext, tcontext, tclass_name)));
779
780 /*
781 * SELinux returns its access control decision as a set of permissions
782 * represented in external code which depends on run-time environment. So,
783 * we need to translate it to the internal representation before returning
784 * results for the caller.
785 */
786 memset(avd, 0, sizeof(struct av_decision));
787
788 for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
789 {
790 access_vector_t av_code_ex;
791 const char *av_name = selinux_catalog[tclass].av[i].av_name;
792 uint32 av_code = selinux_catalog[tclass].av[i].av_code;
793
794 av_code_ex = string_to_av_perm(tclass_ex, av_name);
795 if (av_code_ex == 0)
796 {
797 /* fill up undefined permissions */
798 if (!deny_unknown)
799 avd->allowed |= av_code;
800 avd->auditdeny |= av_code;
801
802 continue;
803 }
804
805 if (avd_ex.allowed & av_code_ex)
806 avd->allowed |= av_code;
807 if (avd_ex.auditallow & av_code_ex)
808 avd->auditallow |= av_code;
809 if (avd_ex.auditdeny & av_code_ex)
810 avd->auditdeny |= av_code;
811 }
812 }
813
814 /*
815 * sepgsql_compute_create
816 *
817 * It returns a default security context to be assigned on a new database
818 * object. SELinux compute it based on a combination of client, upper object
819 * which owns the new object and object class.
820 *
821 * For example, when a client (staff_u:staff_r:staff_t:s0) tries to create
822 * a new table within a schema (system_u:object_r:sepgsql_schema_t:s0),
823 * SELinux looks-up its security policy. If it has a special rule on the
824 * combination of these security contexts and object class (db_table),
825 * it returns the security context suggested by the special rule.
826 * Otherwise, it returns the security context of schema, as is.
827 *
828 * We expect the caller already applies sanity/validation checks on the
829 * given security context.
830 *
831 * scontext: security context of the subject (mostly, peer process).
832 * tcontext: security context of the upper database object.
833 * tclass: class code (SEPG_CLASS_*) of the new object in creation
834 */
835 char *
sepgsql_compute_create(const char * scontext,const char * tcontext,uint16 tclass,const char * objname)836 sepgsql_compute_create(const char *scontext,
837 const char *tcontext,
838 uint16 tclass,
839 const char *objname)
840 {
841 char *ncontext;
842 security_class_t tclass_ex;
843 const char *tclass_name;
844 char *result;
845
846 /* Get external code of the object class */
847 Assert(tclass < SEPG_CLASS_MAX);
848
849 tclass_name = selinux_catalog[tclass].class_name;
850 tclass_ex = string_to_security_class(tclass_name);
851
852 /*
853 * Ask SELinux what is the default context for the given object class on a
854 * pair of security contexts
855 */
856 if (security_compute_create_name_raw(scontext,
857 tcontext,
858 tclass_ex,
859 objname,
860 &ncontext) < 0)
861 ereport(ERROR,
862 (errcode(ERRCODE_INTERNAL_ERROR),
863 errmsg("SELinux could not compute a new context: "
864 "scontext=%s tcontext=%s tclass=%s: %m",
865 scontext, tcontext, tclass_name)));
866
867 /*
868 * libselinux returns malloc()'ed string, so we need to copy it on the
869 * palloc()'ed region.
870 */
871 PG_TRY();
872 {
873 result = pstrdup(ncontext);
874 }
875 PG_FINALLY();
876 {
877 freecon(ncontext);
878 }
879 PG_END_TRY();
880
881 return result;
882 }
883
884 /*
885 * sepgsql_check_perms
886 *
887 * It makes access control decision without userspace caching mechanism.
888 * If SELinux denied the required accesses on the pair of security labels,
889 * it raises an error or returns false.
890 *
891 * scontext: security label of the subject (mostly, peer process)
892 * tcontext: security label of the object being referenced
893 * tclass: class code (SEPG_CLASS_*) of the object being referenced
894 * required: a mask of required permissions (SEPG_<class>__<perm>)
895 * audit_name: a human-readable object name for audit logs, or NULL.
896 * abort_on_violation: true, if error shall be raised on access violation
897 */
898 bool
sepgsql_check_perms(const char * scontext,const char * tcontext,uint16 tclass,uint32 required,const char * audit_name,bool abort_on_violation)899 sepgsql_check_perms(const char *scontext,
900 const char *tcontext,
901 uint16 tclass,
902 uint32 required,
903 const char *audit_name,
904 bool abort_on_violation)
905 {
906 struct av_decision avd;
907 uint32 denied;
908 uint32 audited;
909 bool result = true;
910
911 sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
912
913 denied = required & ~avd.allowed;
914
915 if (sepgsql_get_debug_audit())
916 audited = (denied ? denied : required);
917 else
918 audited = (denied ? (denied & avd.auditdeny)
919 : (required & avd.auditallow));
920
921 if (denied &&
922 sepgsql_getenforce() > 0 &&
923 (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) == 0)
924 result = false;
925
926 /*
927 * It records a security audit for the request, if needed. But, when
928 * SE-PgSQL performs 'internal' mode, it needs to keep silent.
929 */
930 if (audited && sepgsql_mode != SEPGSQL_MODE_INTERNAL)
931 {
932 sepgsql_audit_log(denied,
933 scontext,
934 tcontext,
935 tclass,
936 audited,
937 audit_name);
938 }
939
940 if (!result && abort_on_violation)
941 ereport(ERROR,
942 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
943 errmsg("SELinux: security policy violation")));
944 return result;
945 }
946