1 <!-- doc/src/sgml/sepgsql.sgml -->
3 <sect1 id="sepgsql" xreflabel="sepgsql">
6 <indexterm zone="sepgsql">
7 <primary>sepgsql</primary>
11 <filename>sepgsql</> is a loadable module that supports label-based
12 mandatory access control (MAC) based on <productname>SELinux</> security
18 The current implementation has significant limitations, and does not
19 enforce mandatory access control for all actions. See
20 <xref linkend="sepgsql-limitations">.
24 <sect2 id="sepgsql-overview">
25 <title>Overview</title>
28 This module integrates with <productname>SELinux</> to provide an
29 additional layer of security checking above and beyond what is normally
30 provided by <productname>PostgreSQL</productname>. From the perspective of
31 <productname>SELinux</>, this module allows
32 <productname>PostgreSQL</productname> to function as a user-space object
33 manager. Each table or function access initiated by a DML query will be
34 checked against the system security policy. This check is in addition to
35 the usual SQL permissions checking performed by
36 <productname>PostgreSQL</productname>.
40 <productname>SELinux</productname> access control decisions are made using
41 security labels, which are represented by strings such as
42 <literal>system_u:object_r:sepgsql_table_t:s0</>. Each access control
43 decision involves two labels: the label of the subject attempting to
44 perform the action, and the label of the object on which the operation is
45 to be performed. Since these labels can be applied to any sort of object,
46 access control decisions for objects stored within the database can be
47 (and, with this module, are) subjected to the same general criteria used
48 for objects of any other type, such as files. This design is intended to
49 allow a centralized security policy to protect information assets
50 independent of the particulars of how those assets are stored.
54 The <xref linkend="sql-security-label"> statement allows assignment of
55 a security label to a database object.
59 <sect2 id="sepgsql-installation">
60 <title>Installation</title>
63 <filename>sepgsql</> can only be used on <productname>Linux</productname>
64 2.6.28 or higher with <productname>SELinux</productname> enabled.
65 It is not available on any other platform. You will also need
66 <productname>libselinux</> 2.0.99 or higher and
67 <productname>selinux-policy</> 3.9.13 or higher (although some
68 distributions may backport the necessary rules into older policy
73 The <command>sestatus</> command allows you to check the status of
74 <productname>SELinux</productname>. A typical display is:
77 SELinux status: enabled
78 SELinuxfs mount: /selinux
79 Current mode: enforcing
80 Mode from config file: enforcing
82 Policy from config file: targeted
84 If <productname>SELinux</> is disabled or not installed, you must set
85 that product up first before installing this module.
89 To build this module, include the option <literal>--with-selinux</> in
90 your PostgreSQL <literal>configure</> command. Be sure that the
91 <filename>libselinux-devel</> RPM is installed at build time.
95 To use this module, you must include <literal>sepgsql</>
96 in the <xref linkend="guc-shared-preload-libraries"> parameter in
97 <filename>postgresql.conf</>. The module will not function correctly
98 if loaded in any other manner. Once the module is loaded, you
99 should execute <filename>sepgsql.sql</filename> in each database.
100 This will install functions needed for security label management, and
101 assign initial security labels.
105 Here is an example showing how to initialize a fresh database cluster
106 with <filename>sepgsql</> functions and security labels installed.
107 Adjust the paths shown as appropriate for your installation:
111 $ export PGDATA=/path/to/data/directory
113 $ vi $PGDATA/postgresql.conf
115 #shared_preload_libraries = '' # (change requires restart)
117 shared_preload_libraries = 'sepgsql' # (change requires restart)
118 $ for DBNAME in template0 template1 postgres; do
119 postgres --single -F -c exit_on_error=true $DBNAME \
120 </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
125 Please note that you may see some or all of the following notifications
126 depending on the particular versions you have of
127 <productname>libselinux</> and <productname>selinux-policy</>:
129 /etc/selinux/targeted/contexts/sepgsql_contexts: line 33 has invalid object type db_blobs
130 /etc/selinux/targeted/contexts/sepgsql_contexts: line 36 has invalid object type db_language
131 /etc/selinux/targeted/contexts/sepgsql_contexts: line 37 has invalid object type db_language
132 /etc/selinux/targeted/contexts/sepgsql_contexts: line 38 has invalid object type db_language
133 /etc/selinux/targeted/contexts/sepgsql_contexts: line 39 has invalid object type db_language
134 /etc/selinux/targeted/contexts/sepgsql_contexts: line 40 has invalid object type db_language
136 These messages are harmless and should be ignored.
140 If the installation process completes without error, you can now start the
145 <sect2 id="sepgsql-regression">
146 <title>Regression Tests</title>
149 Due to the nature of <productname>SELinux</productname>, running the
150 regression tests for <filename>sepgsql</> requires several extra
151 configuration steps, some of which must be done as root.
152 The regression tests will not be run by an ordinary
153 <literal>make check</> or <literal>make installcheck</> command; you must
154 set up the configuration and then invoke the test script manually.
155 The tests must be run in the <filename>contrib/sepgsql</> directory
156 of a configured PostgreSQL build tree. Although they require a build tree,
157 the tests are designed to be executed against an installed server,
158 that is they are comparable to <literal>make installcheck</> not
159 <literal>make check</>.
163 First, set up <filename>sepgsql</filename> in a working database
164 according to the instructions in <xref linkend="sepgsql-installation">.
165 Note that the current operating system user must be able to connect to the
166 database as superuser without password authentication.
170 Second, build and install the policy package for the regression test.
171 The <filename>sepgsql-regtest</> policy is a special purpose policy package
172 which provides a set of rules to be allowed during the regression tests.
173 It should be built from the policy source file
174 <filename>sepgsql-regtest.te</>, which is done using
175 <command>make</command> with a Makefile supplied by SELinux.
176 You will need to locate the appropriate
177 Makefile on your system; the path shown below is only an example.
178 Once built, install this policy package using the
179 <command>semodule</> command, which loads supplied policy packages
180 into the kernel. If the package is correctly installed,
181 <literal><command>semodule</> -l</> should list <literal>sepgsql-regtest</literal> as an
182 available policy package:
186 $ cd .../contrib/sepgsql
187 $ make -f /usr/share/selinux/devel/Makefile
188 $ sudo semodule -u sepgsql-regtest.pp
189 $ sudo semodule -l | grep sepgsql
194 Third, turn on <literal>sepgsql_regression_test_mode</>.
195 For security reasons, the rules in <filename>sepgsql-regtest</>
196 are not enabled by default;
197 the <literal>sepgsql_regression_test_mode</literal> parameter enables
198 the rules needed to launch the regression tests.
199 It can be turned on using the <command>setsebool</> command:
203 $ sudo setsebool sepgsql_regression_test_mode on
204 $ getsebool sepgsql_regression_test_mode
205 sepgsql_regression_test_mode --> on
209 Fourth, verify your shell is operating in the <literal>unconfined_t</>
214 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
218 See <xref linkend="sepgsql-resources"> for details on adjusting your
219 working domain, if necessary.
223 Finally, run the regression test script:
230 This script will attempt to verify that you have done all the configuration
231 steps correctly, and then it will run the regression tests for the
232 <filename>sepgsql</> module.
236 After completing the tests, it's recommended you disable
237 the <literal>sepgsql_regression_test_mode</literal> parameter:
241 $ sudo setsebool sepgsql_regression_test_mode off
245 You might prefer to remove the <filename>sepgsql-regtest</> policy
250 $ sudo semodule -r sepgsql-regtest
254 <sect2 id="sepgsql-parameters">
255 <title>GUC Parameters</title>
258 <varlistentry id="guc-sepgsql-permissive" xreflabel="sepgsql.permissive">
259 <term><varname>sepgsql.permissive</> (<type>boolean</type>)</term>
261 <primary><varname>sepgsql.permissive</> configuration parameter</primary>
265 This parameter enables <filename>sepgsql</> to function
266 in permissive mode, regardless of the system setting.
268 This parameter can only be set in the <filename>postgresql.conf</>
269 file or on the server command line.
273 When this parameter is on, <filename>sepgsql</> functions
274 in permissive mode, even if SELinux in general is working in enforcing
275 mode. This parameter is primarily useful for testing purposes.
280 <varlistentry id="guc-sepgsql-debug-audit" xreflabel="sepgsql.debug_audit">
281 <term><varname>sepgsql.debug_audit</> (<type>boolean</>)</>
283 <primary><varname>sepgsql.debug_audit</> configuration parameter</>
287 This parameter enables the printing of audit messages regardless of
288 the system policy settings.
289 The default is off, which means that messages will be printed according
290 to the system settings.
294 The security policy of <productname>SELinux</> also has rules to
295 control whether or not particular accesses are logged.
296 By default, access violations are logged, but allowed
301 This parameter forces all possible logging to be turned on, regardless
302 of the system policy.
309 <sect2 id="sepgsql-features">
310 <title>Features</title>
312 <title>Controlled Object Classes</title>
314 The security model of <productname>SELinux</> describes all the access
315 control rules as relationships between a subject entity (typically,
316 a client of the database) and an object entity (such as a database
317 object), each of which is
318 identified by a security label. If access to an unlabelled object is
319 attempted, the object is treated as if it were assigned the label
320 <literal>unlabeled_t</>.
324 Currently, <filename>sepgsql</filename> allows security labels to be
325 assigned to schemas, tables, columns, sequences, views, and functions.
326 When <filename>sepgsql</filename> is in use, security labels are
327 automatically assigned to supported database objects at creation time.
328 This label is called a default security label, and is decided according
329 to the system security policy, which takes as input the creator's label
330 and the label assigned to the new object's parent object.
334 A new database object basically inherits the security label of the parent
335 object, except when the security policy has special rules known as
336 type-transition rules, in which case a different label may be applied.
337 For schemas, the parent object is the current database; for tables,
338 sequences, views, and functions, it is the containing schema; for columns,
339 it is the containing table.
344 <title>DML Permissions</title>
347 For tables, <literal>db_table:select</>, <literal>db_table:insert</>,
348 <literal>db_table:update</> or <literal>db_table:delete</> are
349 checked for all the referenced target tables depending on the kind of
350 statement; in addition, <literal>db_table:select</> is also checked for
351 all the tables that contain columns referenced in the
352 <literal>WHERE</> or <literal>RETURNING</> clause, as a data source
353 for <literal>UPDATE</>, and so on.
357 Column-level permissions will also be checked for each referenced column.
358 <literal>db_column:select</> is checked on not only the columns being
359 read using <literal>SELECT</>, but those being referenced in other DML
360 statements; <literal>db_column:update</> or <literal>db_column:insert</>
361 will also be checked for columns being modified by <literal>UPDATE</> or
366 For example, consider:
368 UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
371 Here, <literal>db_column:update</> will be checked for
372 <literal>t1.x</>, since it is being updated,
373 <literal>db_column:{select update}</> will be checked for
374 <literal>t1.y</>, since it is both updated and referenced, and
375 <literal>db_column:select</> will be checked for <literal>t1.z</>, since
376 it is only referenced.
377 <literal>db_table:{select update}</> will also be checked
382 For sequences, <literal>db_sequence:get_value</> is checked when we
383 reference a sequence object using <literal>SELECT</>; however, note that we
384 do not currently check permissions on execution of corresponding functions
385 such as <literal>lastval()</>.
389 For views, <literal>db_view:expand</> will be checked, then any other
390 required permissions will be checked on the objects being
391 expanded from the view, individually.
395 For functions, <literal>db_procedure:{execute}</> is defined, but is not
396 checked in this version.
400 The client must be allowed to access all referenced tables and
401 columns, even if they originated from views which were then expanded,
402 so that we apply consistent access control rules independent of the manner
403 in which the table contents are referenced.
407 The default database privilege system allows database superusers to
408 modify system catalogs using DML commands, and reference or modify
409 toast tables. These operations are prohibited when
410 <filename>sepgsql</> is enabled.
415 <title>DDL Permissions</title>
417 <productname>SELinux</> defines several permissions to control common
418 operations for each object type; such as creation, alter, drop and
419 relabel of security label. In addition, several object types have
420 special permissions to control their characteristic operations; such as
421 addition or deletion of name entries within a particular schema.
424 When a <literal>CREATE</> command is executed, <literal>create</> will
425 be checked on the object being constructed for each object types.
426 A default security label will be assigned to the new database object,
427 and the <literal>create</> permission will be checked on the pair
428 of security label of the client and the new object itself.
429 We consider <xref linkend="sql-createtable"> to construct a table and
430 underlying columns at the same time, so it requires the users to have
431 permission to create both the table and its columns.
434 A few additional checks are applied depending on object types.
435 On <xref linkend="sql-createdatabase">, <literal>getattr</> permission
436 will be checked on the source or template database of the new database,
437 not only <literal>create</> on the new database.
438 On creation of objects within a particular schema (tables, views,
439 sequences and procedures), <literal>add_name</> will be also checked
440 on the schema, not only <literal>create</> on the new object itself.
441 On <xref linkend="sql-createfunction">, <literal>install</> permission
442 will be checked if <literal>leakproof</> attribute was given, not only
443 <literal>create</> on the new function. This permission will be also
444 checked when user tries to turn on <literal>leakproof</> attribute
445 using <xref linkend="sql-alterfunction"> command, with
446 <literal>setattr</> permission on the function being altered.
450 When <literal>DROP</> command is executed, <literal>drop</> will be
451 checked on the object being removed for each object types. Permissions
452 will be also checked for objects dropped indirectly via <literal>CASCADE</>.
453 Deletion of objects contained within a particular schema (tables, views,
454 sequences and procedures) additionally requires
455 <literal>remove_name</> on the schema.
459 When <literal>ALTER</> command is executed, <literal>setattr</> will be
460 checked on the object being modified for each object types.
461 In addition, <literal>remove_name</> and <literal>add_name</>
462 will be checked on the old and new schemas, respectively, when an
463 object is moved to a new schema.
464 For certain object types, additional checks are performed.
468 When objects that are subsidiary of other objects (such as a table's
469 indexes or triggers) are created, dropped or altered,
470 <literal>setattr</> permission will be checked on the main object,
471 instead of the subsidiary object itself.
475 When <xref linkend="sql-security-label"> is executed, <literal>setattr</>
476 and <literal>relabelfrom</> will be checked on the object being relabeled
477 with its old security label, then <literal>relabelto</> with the supplied
482 In the case where multiple label providers are installed and the user tries
483 to set a security label, but it is not managed by <productname>SELinux</>,
484 only <literal>setattr</> should be checked here.
485 This is currently not done due to implementation restrictions.
490 <title>Trusted Procedures</title>
492 Trusted procedures are similar to security definer functions or setuid
493 commands. <productname>SELinux</> provides a feature to allow trusted
494 code to run using a security label different from that of the client,
495 generally for the purpose of providing highly controlled access to
496 sensitive data (e.g. rows might be omitted, or the precision of stored
497 values might be reduced). Whether or not a function acts as a trusted
498 procedure is controlled by its security label and the operating system
499 security policy. For example:
503 postgres=# CREATE TABLE customer (
509 postgres=# SECURITY LABEL ON COLUMN customer.credit
510 IS 'system_u:object_r:sepgsql_secret_table_t:s0';
512 postgres=# CREATE FUNCTION show_credit(int) RETURNS text
513 AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
514 FROM customer WHERE cid = $1'
517 postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
518 IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
523 The above operations should be performed by an administrative user.
527 postgres=# SELECT * FROM customer;
528 ERROR: SELinux: security policy violation
529 postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
530 cid | cname | show_credit
531 -----+--------+---------------------
532 1 | taro | 1111-2222-3333-xxxx
533 2 | hanako | 5555-6666-7777-xxxx
538 In this case, a regular user cannot reference <literal>customer.credit</>
539 directly, but a trusted procedure <literal>show_credit</> allows him
540 to print the credit card numbers of customers with some of the digits
546 <title>Dynamic Domain Transitions</title>
548 It is possible to use SELinux's dynamic domain transition feature
549 to switch the security label of the client process, the client domain,
550 to a new context, if that is allowed by the security policy.
551 The client domain needs the <literal>setcurrent</> permission and also
552 <literal>dyntransition</> from the old to the new domain.
555 Dynamic domain transitions should be considered carefully, because they
556 allow users to switch their label, and therefore their privileges,
557 at their option, rather than (as in the case of a trusted procedure)
558 as mandated by the system.
559 Thus, the <literal>dyntransition</literal> permission is only considered
560 safe when used to switch to a domain with a smaller set of privileges than
561 the original one. For example:
564 regression=# select sepgsql_getcon();
566 -------------------------------------------------------
567 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
570 regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
576 regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
577 ERROR: SELinux: security policy violation
580 In this example above we were allowed to switch from the larger MCS
581 range <literal>c1.c1023</> to the smaller range <literal>c1.c4</>, but
582 switching back was denied.
585 A combination of dynamic domain transition and trusted procedure
586 enables an interesting use case that fits the typical process life-cycle
587 of connection pooling software.
588 Even if your connection pooling software is not allowed to run most
589 of SQL commands, you can allow it to switch the security label
590 of the client using the <literal>sepgsql_setcon()</literal> function
591 from within a trusted procedure; that should take some
592 credential to authorize the request to switch the client label.
593 After that, this session will have the privileges of the target user,
594 rather than the connection pooler.
595 The connection pooler can later revert the security label change by
596 again using <literal>sepgsql_setcon()</literal> with
597 <literal>NULL</literal> argument, again invoked from within a trusted
598 procedure with appropriate permissions checks.
599 The point here is that only the trusted procedure actually has permission
600 to change the effective security label, and only does so when given proper
601 credentials. Of course, for secure operation, the credential store
602 (table, procedure definition, or whatever) must be protected from
608 <title>Miscellaneous</title>
610 We reject the <xref linkend="sql-load"> command across the board, because
611 any module loaded could easily circumvent security policy enforcement.
617 <sect2 id="sepgsql-functions">
618 <title>Sepgsql Functions</title>
620 <xref linkend="sepgsql-functions-table"> shows the available functions.
623 <table id="sepgsql-functions-table">
624 <title>Sepgsql Functions</title>
628 <entry><literal>sepgsql_getcon() returns text</literal></entry>
630 Returns the client domain, the current security label of the client.
634 <entry><literal>sepgsql_setcon(text) returns bool</literal></entry>
636 Switches the client domain of the current session to the new domain,
637 if allowed by the security policy.
638 It also accepts <literal>NULL</literal> input as a request to transition
639 to the client's original domain.
643 <entry><literal>sepgsql_mcstrans_in(text) returns text</literal></entry>
644 <entry>Translates the given qualifies MLS/MCS range into raw format if
645 the mcstrans daemon is running.
649 <entry><literal>sepgsql_mcstrans_out(text) returns text</literal></entry>
650 <entry>Translates the given raw MCS/MCS range into qualified format if
651 the mcstrans daemon is running.
655 <entry><literal>sepgsql_restorecon(text) returns bool</literal></entry>
657 Sets up initial security labels for all objects within the
658 current database. The argument may be NULL, or the name of a specfile
659 to be used as alternative of the system default.
667 <sect2 id="sepgsql-limitations">
668 <title>Limitations</title>
672 <term>Data Definition Language (DDL) Permissions</term>
675 Due to implementation restrictions, some DDL operations do not
682 <term>Data Control Language (DCL) Permissions</term>
685 Due to implementation restrictions, DCL operations do not check
692 <term>Row-level access control</term>
695 <productname>PostgreSQL</> does not support row-level access; therefore,
696 <filename>sepgsql</filename> does not support it either.
702 <term>Covert channels</term>
705 <filename>sepgsql</> does not try to hide the existence of
706 a certain object, even if the user is not allowed to reference it.
707 For example, we can infer the existence of an invisible object as
708 a result of primary key conflicts, foreign key violations, and so on,
709 even if we cannot obtain the contents of the object. The existence
710 of a top secret table cannot be hidden; we only hope to conceal its
718 <sect2 id="sepgsql-resources">
719 <title>External Resources</title>
722 <term><ulink url="http://wiki.postgresql.org/wiki/SEPostgreSQL">SE-PostgreSQL Introduction</ulink></term>
725 This wiki page provides a brief overview, security design, architecture,
726 administration and upcoming features.
731 <term><ulink url="http://docs.fedoraproject.org/selinux-user-guide/">Fedora SELinux User Guide</ulink></term>
734 This document provides a wide spectrum of knowledge to administer
735 <productname>SELinux</> on your systems.
736 It focuses primarily on Fedora, but is not limited to Fedora.
741 <term><ulink url="http://docs.fedoraproject.org/selinux-faq">Fedora SELinux FAQ</ulink></term>
744 This document answers frequently asked questions about
745 <productname>SELinux</productname>.
746 It focuses primarily on Fedora, but is not limited to Fedora.
753 <sect2 id="sepgsql-author">
754 <title>Author</title>
756 KaiGai Kohei <email>kaigai@ak.jp.nec.com</email>