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-2019, 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