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-2017, 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 NULL, 0UL
364 },
365 }
366 },
367 {
368 "db_sequence", SEPG_CLASS_DB_SEQUENCE,
369 {
370 {
371 "create", SEPG_DB_SEQUENCE__CREATE
372 },
373 {
374 "drop", SEPG_DB_SEQUENCE__DROP
375 },
376 {
377 "getattr", SEPG_DB_SEQUENCE__GETATTR
378 },
379 {
380 "setattr", SEPG_DB_SEQUENCE__SETATTR
381 },
382 {
383 "relabelfrom", SEPG_DB_SEQUENCE__RELABELFROM
384 },
385 {
386 "relabelto", SEPG_DB_SEQUENCE__RELABELTO
387 },
388 {
389 "get_value", SEPG_DB_SEQUENCE__GET_VALUE
390 },
391 {
392 "next_value", SEPG_DB_SEQUENCE__NEXT_VALUE
393 },
394 {
395 "set_value", SEPG_DB_SEQUENCE__SET_VALUE
396 },
397 {
398 NULL, 0UL
399 },
400 }
401 },
402 {
403 "db_procedure", SEPG_CLASS_DB_PROCEDURE,
404 {
405 {
406 "create", SEPG_DB_PROCEDURE__CREATE
407 },
408 {
409 "drop", SEPG_DB_PROCEDURE__DROP
410 },
411 {
412 "getattr", SEPG_DB_PROCEDURE__GETATTR
413 },
414 {
415 "setattr", SEPG_DB_PROCEDURE__SETATTR
416 },
417 {
418 "relabelfrom", SEPG_DB_PROCEDURE__RELABELFROM
419 },
420 {
421 "relabelto", SEPG_DB_PROCEDURE__RELABELTO
422 },
423 {
424 "execute", SEPG_DB_PROCEDURE__EXECUTE
425 },
426 {
427 "entrypoint", SEPG_DB_PROCEDURE__ENTRYPOINT
428 },
429 {
430 "install", SEPG_DB_PROCEDURE__INSTALL
431 },
432 {
433 NULL, 0UL
434 },
435 }
436 },
437 {
438 "db_column", SEPG_CLASS_DB_COLUMN,
439 {
440 {
441 "create", SEPG_DB_COLUMN__CREATE
442 },
443 {
444 "drop", SEPG_DB_COLUMN__DROP
445 },
446 {
447 "getattr", SEPG_DB_COLUMN__GETATTR
448 },
449 {
450 "setattr", SEPG_DB_COLUMN__SETATTR
451 },
452 {
453 "relabelfrom", SEPG_DB_COLUMN__RELABELFROM
454 },
455 {
456 "relabelto", SEPG_DB_COLUMN__RELABELTO
457 },
458 {
459 "select", SEPG_DB_COLUMN__SELECT
460 },
461 {
462 "update", SEPG_DB_COLUMN__UPDATE
463 },
464 {
465 "insert", SEPG_DB_COLUMN__INSERT
466 },
467 {
468 NULL, 0UL
469 },
470 }
471 },
472 {
473 "db_tuple", SEPG_CLASS_DB_TUPLE,
474 {
475 {
476 "relabelfrom", SEPG_DB_TUPLE__RELABELFROM
477 },
478 {
479 "relabelto", SEPG_DB_TUPLE__RELABELTO
480 },
481 {
482 "select", SEPG_DB_TUPLE__SELECT
483 },
484 {
485 "update", SEPG_DB_TUPLE__UPDATE
486 },
487 {
488 "insert", SEPG_DB_TUPLE__INSERT
489 },
490 {
491 "delete", SEPG_DB_TUPLE__DELETE
492 },
493 {
494 NULL, 0UL
495 },
496 }
497 },
498 {
499 "db_blob", SEPG_CLASS_DB_BLOB,
500 {
501 {
502 "create", SEPG_DB_BLOB__CREATE
503 },
504 {
505 "drop", SEPG_DB_BLOB__DROP
506 },
507 {
508 "getattr", SEPG_DB_BLOB__GETATTR
509 },
510 {
511 "setattr", SEPG_DB_BLOB__SETATTR
512 },
513 {
514 "relabelfrom", SEPG_DB_BLOB__RELABELFROM
515 },
516 {
517 "relabelto", SEPG_DB_BLOB__RELABELTO
518 },
519 {
520 "read", SEPG_DB_BLOB__READ
521 },
522 {
523 "write", SEPG_DB_BLOB__WRITE
524 },
525 {
526 "import", SEPG_DB_BLOB__IMPORT
527 },
528 {
529 "export", SEPG_DB_BLOB__EXPORT
530 },
531 {
532 NULL, 0UL
533 },
534 }
535 },
536 {
537 "db_language", SEPG_CLASS_DB_LANGUAGE,
538 {
539 {
540 "create", SEPG_DB_LANGUAGE__CREATE
541 },
542 {
543 "drop", SEPG_DB_LANGUAGE__DROP
544 },
545 {
546 "getattr", SEPG_DB_LANGUAGE__GETATTR
547 },
548 {
549 "setattr", SEPG_DB_LANGUAGE__SETATTR
550 },
551 {
552 "relabelfrom", SEPG_DB_LANGUAGE__RELABELFROM
553 },
554 {
555 "relabelto", SEPG_DB_LANGUAGE__RELABELTO
556 },
557 {
558 "implement", SEPG_DB_LANGUAGE__IMPLEMENT
559 },
560 {
561 "execute", SEPG_DB_LANGUAGE__EXECUTE
562 },
563 {
564 NULL, 0UL
565 },
566 }
567 },
568 {
569 "db_view", SEPG_CLASS_DB_VIEW,
570 {
571 {
572 "create", SEPG_DB_VIEW__CREATE
573 },
574 {
575 "drop", SEPG_DB_VIEW__DROP
576 },
577 {
578 "getattr", SEPG_DB_VIEW__GETATTR
579 },
580 {
581 "setattr", SEPG_DB_VIEW__SETATTR
582 },
583 {
584 "relabelfrom", SEPG_DB_VIEW__RELABELFROM
585 },
586 {
587 "relabelto", SEPG_DB_VIEW__RELABELTO
588 },
589 {
590 "expand", SEPG_DB_VIEW__EXPAND
591 },
592 {
593 NULL, 0UL
594 },
595 }
596 },
597 };
598
599 /*
600 * sepgsql_mode
601 *
602 * SEPGSQL_MODE_DISABLED: Disabled on runtime
603 * SEPGSQL_MODE_DEFAULT: Same as system settings
604 * SEPGSQL_MODE_PERMISSIVE: Always permissive mode
605 * SEPGSQL_MODE_INTERNAL: Same as permissive, except for no audit logs
606 */
607 static int sepgsql_mode = SEPGSQL_MODE_INTERNAL;
608
609 /*
610 * sepgsql_is_enabled
611 */
612 bool
sepgsql_is_enabled(void)613 sepgsql_is_enabled(void)
614 {
615 return (sepgsql_mode != SEPGSQL_MODE_DISABLED ? true : false);
616 }
617
618 /*
619 * sepgsql_get_mode
620 */
621 int
sepgsql_get_mode(void)622 sepgsql_get_mode(void)
623 {
624 return sepgsql_mode;
625 }
626
627 /*
628 * sepgsql_set_mode
629 */
630 int
sepgsql_set_mode(int new_mode)631 sepgsql_set_mode(int new_mode)
632 {
633 int old_mode = sepgsql_mode;
634
635 sepgsql_mode = new_mode;
636
637 return old_mode;
638 }
639
640 /*
641 * sepgsql_getenforce
642 *
643 * It returns whether the current working mode tries to enforce access
644 * control decision, or not. It shall be enforced when sepgsql_mode is
645 * SEPGSQL_MODE_DEFAULT and system is running in enforcing mode.
646 */
647 bool
sepgsql_getenforce(void)648 sepgsql_getenforce(void)
649 {
650 if (sepgsql_mode == SEPGSQL_MODE_DEFAULT &&
651 selinux_status_getenforce() > 0)
652 return true;
653
654 return false;
655 }
656
657 /*
658 * sepgsql_audit_log
659 *
660 * It generates a security audit record. In the default, it writes out
661 * audit records into standard PG's logfile. It also allows to set up
662 * external audit log receiver, such as auditd in Linux, using the
663 * sepgsql_audit_hook.
664 *
665 * SELinux can control what should be audited and should not using
666 * "auditdeny" and "auditallow" rules in the security policy. In the
667 * default, all the access violations are audited, and all the access
668 * allowed are not audited. But we can set up the security policy, so
669 * we can have exceptions. So, it is necessary to follow the suggestion
670 * come from the security policy. (av_decision.auditallow and auditdeny)
671 *
672 * Security audit is an important feature, because it enables us to check
673 * what was happen if we have a security incident. In fact, ISO/IEC15408
674 * defines several security functionalities for audit features.
675 */
676 void
sepgsql_audit_log(bool denied,const char * scontext,const char * tcontext,uint16 tclass,uint32 audited,const char * audit_name)677 sepgsql_audit_log(bool denied,
678 const char *scontext,
679 const char *tcontext,
680 uint16 tclass,
681 uint32 audited,
682 const char *audit_name)
683 {
684 StringInfoData buf;
685 const char *class_name;
686 const char *av_name;
687 int i;
688
689 /* lookup name of the object class */
690 Assert(tclass < SEPG_CLASS_MAX);
691 class_name = selinux_catalog[tclass].class_name;
692
693 /* lookup name of the permissions */
694 initStringInfo(&buf);
695 appendStringInfo(&buf, "%s {",
696 (denied ? "denied" : "allowed"));
697 for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
698 {
699 if (audited & (1UL << i))
700 {
701 av_name = selinux_catalog[tclass].av[i].av_name;
702 appendStringInfo(&buf, " %s", av_name);
703 }
704 }
705 appendStringInfo(&buf, " }");
706
707 /*
708 * Call external audit module, if loaded
709 */
710 appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s",
711 scontext, tcontext, class_name);
712 if (audit_name)
713 appendStringInfo(&buf, " name=\"%s\"", audit_name);
714
715 ereport(LOG, (errmsg("SELinux: %s", buf.data)));
716 }
717
718 /*
719 * sepgsql_compute_avd
720 *
721 * It actually asks SELinux what permissions are allowed on a pair of
722 * the security contexts and object class. It also returns what permissions
723 * should be audited on access violation or allowed.
724 * In most cases, subject's security context (scontext) is a client, and
725 * target security context (tcontext) is a database object.
726 *
727 * The access control decision shall be set on the given av_decision.
728 * The av_decision.allowed has a bitmask of SEPG_<class>__<perms>
729 * to suggest a set of allowed actions in this object class.
730 */
731 void
sepgsql_compute_avd(const char * scontext,const char * tcontext,uint16 tclass,struct av_decision * avd)732 sepgsql_compute_avd(const char *scontext,
733 const char *tcontext,
734 uint16 tclass,
735 struct av_decision *avd)
736 {
737 const char *tclass_name;
738 security_class_t tclass_ex;
739 struct av_decision avd_ex;
740 int i,
741 deny_unknown = security_deny_unknown();
742
743 /* Get external code of the object class */
744 Assert(tclass < SEPG_CLASS_MAX);
745 Assert(tclass == selinux_catalog[tclass].class_code);
746
747 tclass_name = selinux_catalog[tclass].class_name;
748 tclass_ex = string_to_security_class(tclass_name);
749
750 if (tclass_ex == 0)
751 {
752 /*
753 * If the current security policy does not support permissions
754 * corresponding to database objects, we fill up them with dummy data.
755 * If security_deny_unknown() returns positive value, undefined
756 * permissions should be denied. Otherwise, allowed
757 */
758 avd->allowed = (security_deny_unknown() > 0 ? 0 : ~0);
759 avd->auditallow = 0U;
760 avd->auditdeny = ~0U;
761 avd->flags = 0;
762
763 return;
764 }
765
766 /*
767 * Ask SELinux what is allowed set of permissions on a pair of the
768 * security contexts and the given object class.
769 */
770 if (security_compute_av_flags_raw((security_context_t) scontext,
771 (security_context_t) tcontext,
772 tclass_ex, 0, &avd_ex) < 0)
773 ereport(ERROR,
774 (errcode(ERRCODE_INTERNAL_ERROR),
775 errmsg("SELinux could not compute av_decision: "
776 "scontext=%s tcontext=%s tclass=%s: %m",
777 scontext, tcontext, tclass_name)));
778
779 /*
780 * SELinux returns its access control decision as a set of permissions
781 * represented in external code which depends on run-time environment. So,
782 * we need to translate it to the internal representation before returning
783 * results for the caller.
784 */
785 memset(avd, 0, sizeof(struct av_decision));
786
787 for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
788 {
789 access_vector_t av_code_ex;
790 const char *av_name = selinux_catalog[tclass].av[i].av_name;
791 uint32 av_code = selinux_catalog[tclass].av[i].av_code;
792
793 av_code_ex = string_to_av_perm(tclass_ex, av_name);
794 if (av_code_ex == 0)
795 {
796 /* fill up undefined permissions */
797 if (!deny_unknown)
798 avd->allowed |= av_code;
799 avd->auditdeny |= av_code;
800
801 continue;
802 }
803
804 if (avd_ex.allowed & av_code_ex)
805 avd->allowed |= av_code;
806 if (avd_ex.auditallow & av_code_ex)
807 avd->auditallow |= av_code;
808 if (avd_ex.auditdeny & av_code_ex)
809 avd->auditdeny |= av_code;
810 }
811
812 return;
813 }
814
815 /*
816 * sepgsql_compute_create
817 *
818 * It returns a default security context to be assigned on a new database
819 * object. SELinux compute it based on a combination of client, upper object
820 * which owns the new object and object class.
821 *
822 * For example, when a client (staff_u:staff_r:staff_t:s0) tries to create
823 * a new table within a schema (system_u:object_r:sepgsql_schema_t:s0),
824 * SELinux looks-up its security policy. If it has a special rule on the
825 * combination of these security contexts and object class (db_table),
826 * it returns the security context suggested by the special rule.
827 * Otherwise, it returns the security context of schema, as is.
828 *
829 * We expect the caller already applies sanity/validation checks on the
830 * given security context.
831 *
832 * scontext: security context of the subject (mostly, peer process).
833 * tcontext: security context of the upper database object.
834 * tclass: class code (SEPG_CLASS_*) of the new object in creation
835 */
836 char *
sepgsql_compute_create(const char * scontext,const char * tcontext,uint16 tclass,const char * objname)837 sepgsql_compute_create(const char *scontext,
838 const char *tcontext,
839 uint16 tclass,
840 const char *objname)
841 {
842 security_context_t ncontext;
843 security_class_t tclass_ex;
844 const char *tclass_name;
845 char *result;
846
847 /* Get external code of the object class */
848 Assert(tclass < SEPG_CLASS_MAX);
849
850 tclass_name = selinux_catalog[tclass].class_name;
851 tclass_ex = string_to_security_class(tclass_name);
852
853 /*
854 * Ask SELinux what is the default context for the given object class on a
855 * pair of security contexts
856 */
857 if (security_compute_create_name_raw((security_context_t) scontext,
858 (security_context_t) tcontext,
859 tclass_ex,
860 objname,
861 &ncontext) < 0)
862 ereport(ERROR,
863 (errcode(ERRCODE_INTERNAL_ERROR),
864 errmsg("SELinux could not compute a new context: "
865 "scontext=%s tcontext=%s tclass=%s: %m",
866 scontext, tcontext, tclass_name)));
867
868 /*
869 * libselinux returns malloc()'ed string, so we need to copy it on the
870 * palloc()'ed region.
871 */
872 PG_TRY();
873 {
874 result = pstrdup(ncontext);
875 }
876 PG_CATCH();
877 {
878 freecon(ncontext);
879 PG_RE_THROW();
880 }
881 PG_END_TRY();
882 freecon(ncontext);
883
884 return result;
885 }
886
887 /*
888 * sepgsql_check_perms
889 *
890 * It makes access control decision without userspace caching mechanism.
891 * If SELinux denied the required accesses on the pair of security labels,
892 * it raises an error or returns false.
893 *
894 * scontext: security label of the subject (mostly, peer process)
895 * tcontext: security label of the object being referenced
896 * tclass: class code (SEPG_CLASS_*) of the object being referenced
897 * required: a mask of required permissions (SEPG_<class>__<perm>)
898 * audit_name: a human readable object name for audit logs, or NULL.
899 * abort_on_violation: true, if error shall be raised on access violation
900 */
901 bool
sepgsql_check_perms(const char * scontext,const char * tcontext,uint16 tclass,uint32 required,const char * audit_name,bool abort_on_violation)902 sepgsql_check_perms(const char *scontext,
903 const char *tcontext,
904 uint16 tclass,
905 uint32 required,
906 const char *audit_name,
907 bool abort_on_violation)
908 {
909 struct av_decision avd;
910 uint32 denied;
911 uint32 audited;
912 bool result = true;
913
914 sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
915
916 denied = required & ~avd.allowed;
917
918 if (sepgsql_get_debug_audit())
919 audited = (denied ? denied : required);
920 else
921 audited = (denied ? (denied & avd.auditdeny)
922 : (required & avd.auditallow));
923
924 if (denied &&
925 sepgsql_getenforce() > 0 &&
926 (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) == 0)
927 result = false;
928
929 /*
930 * It records a security audit for the request, if needed. But, when
931 * SE-PgSQL performs 'internal' mode, it needs to keep silent.
932 */
933 if (audited && sepgsql_mode != SEPGSQL_MODE_INTERNAL)
934 {
935 sepgsql_audit_log(denied,
936 scontext,
937 tcontext,
938 tclass,
939 audited,
940 audit_name);
941 }
942
943 if (!result && abort_on_violation)
944 ereport(ERROR,
945 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
946 errmsg("SELinux: security policy violation")));
947 return result;
948 }
949