2 F.40. sepgsql — SELinux-, label-based mandatory access control (MAC) security
7 F.40.3. Regression Tests
10 F.40.6. Sepgsql Functions
12 F.40.8. External Resources
15 sepgsql is a loadable module that supports label-based mandatory access
16 control (MAC) based on SELinux security policy.
20 The current implementation has significant limitations, and does not
21 enforce mandatory access control for all actions. See Section F.40.7.
25 This module integrates with SELinux to provide an additional layer of
26 security checking above and beyond what is normally provided by
27 PostgreSQL. From the perspective of SELinux, this module allows
28 PostgreSQL to function as a user-space object manager. Each table or
29 function access initiated by a DML query will be checked against the
30 system security policy. This check is in addition to the usual SQL
31 permissions checking performed by PostgreSQL.
33 SELinux access control decisions are made using security labels, which
34 are represented by strings such as
35 system_u:object_r:sepgsql_table_t:s0. Each access control decision
36 involves two labels: the label of the subject attempting to perform the
37 action, and the label of the object on which the operation is to be
38 performed. Since these labels can be applied to any sort of object,
39 access control decisions for objects stored within the database can be
40 (and, with this module, are) subjected to the same general criteria
41 used for objects of any other type, such as files. This design is
42 intended to allow a centralized security policy to protect information
43 assets independent of the particulars of how those assets are stored.
45 The SECURITY LABEL statement allows assignment of a security label to a
48 F.40.2. Installation #
50 sepgsql can only be used on Linux 2.6.28 or higher with SELinux
51 enabled. It is not available on any other platform. You will also need
52 libselinux 2.1.10 or higher and selinux-policy 3.9.13 or higher
53 (although some distributions may backport the necessary rules into
54 older policy versions).
56 The sestatus command allows you to check the status of SELinux. A
59 SELinux status: enabled
60 SELinuxfs mount: /selinux
61 Current mode: enforcing
62 Mode from config file: enforcing
64 Policy from config file: targeted
66 If SELinux is disabled or not installed, you must set that product up
67 first before installing this module.
69 To build this module, specify --with-selinux (when using make and
70 autoconf ) or -Dselinux={ auto | enabled | disabled } (when using
71 meson). Be sure that the libselinux-devel RPM is installed at build
74 To use this module, you must include sepgsql in the
75 shared_preload_libraries parameter in postgresql.conf. The module will
76 not function correctly if loaded in any other manner. Once the module
77 is loaded, you should execute sepgsql.sql in each database. This will
78 install functions needed for security label management, and assign
79 initial security labels.
81 Here is an example showing how to initialize a fresh database cluster
82 with sepgsql functions and security labels installed. Adjust the paths
83 shown as appropriate for your installation:
84 $ export PGDATA=/path/to/data/directory
86 $ vi $PGDATA/postgresql.conf
88 #shared_preload_libraries = '' # (change requires restart)
90 shared_preload_libraries = 'sepgsql' # (change requires restart)
91 $ for DBNAME in template0 template1 postgres; do
92 postgres --single -F -c exit_on_error=true $DBNAME \
93 </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
96 Please note that you may see some or all of the following notifications
97 depending on the particular versions you have of libselinux and
99 /etc/selinux/targeted/contexts/sepgsql_contexts: line 33 has invalid object typ
101 /etc/selinux/targeted/contexts/sepgsql_contexts: line 36 has invalid object typ
103 /etc/selinux/targeted/contexts/sepgsql_contexts: line 37 has invalid object typ
105 /etc/selinux/targeted/contexts/sepgsql_contexts: line 38 has invalid object typ
107 /etc/selinux/targeted/contexts/sepgsql_contexts: line 39 has invalid object typ
109 /etc/selinux/targeted/contexts/sepgsql_contexts: line 40 has invalid object typ
112 These messages are harmless and should be ignored.
114 If the installation process completes without error, you can now start
117 F.40.3. Regression Tests #
119 The sepgsql test suite is run if PG_TEST_EXTRA contains sepgsql (see
120 Section 31.1.3). This method is suitable during development of
121 PostgreSQL. Alternatively, there is a way to run the tests to checks
122 whether a database instance has been set up properly for sepgsql.
124 Due to the nature of SELinux, running the regression tests for sepgsql
125 requires several extra configuration steps, some of which must be done
128 The manual tests must be run in the contrib/sepgsql directory of a
129 configured PostgreSQL build tree. Although they require a build tree,
130 the tests are designed to be executed against an installed server, that
131 is they are comparable to make installcheck not make check.
133 First, set up sepgsql in a working database according to the
134 instructions in Section F.40.2. Note that the current operating system
135 user must be able to connect to the database as superuser without
136 password authentication.
138 Second, build and install the policy package for the regression test.
139 The sepgsql-regtest policy is a special purpose policy package which
140 provides a set of rules to be allowed during the regression tests. It
141 should be built from the policy source file sepgsql-regtest.te, which
142 is done using make with a Makefile supplied by SELinux. You will need
143 to locate the appropriate Makefile on your system; the path shown below
144 is only an example. (This Makefile is usually supplied by the
145 selinux-policy-devel or selinux-policy RPM.) Once built, install this
146 policy package using the semodule command, which loads supplied policy
147 packages into the kernel. If the package is correctly installed,
148 semodule -l should list sepgsql-regtest as an available policy package:
149 $ cd .../contrib/sepgsql
150 $ make -f /usr/share/selinux/devel/Makefile
151 $ sudo semodule -u sepgsql-regtest.pp
152 $ sudo semodule -l | grep sepgsql
155 Third, turn on sepgsql_regression_test_mode. For security reasons, the
156 rules in sepgsql-regtest are not enabled by default; the
157 sepgsql_regression_test_mode parameter enables the rules needed to
158 launch the regression tests. It can be turned on using the setsebool
160 $ sudo setsebool sepgsql_regression_test_mode on
161 $ getsebool sepgsql_regression_test_mode
162 sepgsql_regression_test_mode --> on
164 Fourth, verify your shell is operating in the unconfined_t domain:
166 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
168 See Section F.40.8 for details on adjusting your working domain, if
171 Finally, run the regression test script:
174 This script will attempt to verify that you have done all the
175 configuration steps correctly, and then it will run the regression
176 tests for the sepgsql module.
178 After completing the tests, it's recommended you disable the
179 sepgsql_regression_test_mode parameter:
180 $ sudo setsebool sepgsql_regression_test_mode off
182 You might prefer to remove the sepgsql-regtest policy entirely:
183 $ sudo semodule -r sepgsql-regtest
185 F.40.4. GUC Parameters #
187 sepgsql.permissive (boolean) #
188 This parameter enables sepgsql to function in permissive mode,
189 regardless of the system setting. The default is off. This
190 parameter can only be set in the postgresql.conf file or on the
193 When this parameter is on, sepgsql functions in permissive mode,
194 even if SELinux in general is working in enforcing mode. This
195 parameter is primarily useful for testing purposes.
197 sepgsql.debug_audit (boolean) #
198 This parameter enables the printing of audit messages regardless
199 of the system policy settings. The default is off, which means
200 that messages will be printed according to the system settings.
202 The security policy of SELinux also has rules to control whether
203 or not particular accesses are logged. By default, access
204 violations are logged, but allowed accesses are not.
206 This parameter forces all possible logging to be turned on,
207 regardless of the system policy.
211 F.40.5.1. Controlled Object Classes #
213 The security model of SELinux describes all the access control rules as
214 relationships between a subject entity (typically, a client of the
215 database) and an object entity (such as a database object), each of
216 which is identified by a security label. If access to an unlabeled
217 object is attempted, the object is treated as if it were assigned the
220 Currently, sepgsql allows security labels to be assigned to schemas,
221 tables, columns, sequences, views, and functions. When sepgsql is in
222 use, security labels are automatically assigned to supported database
223 objects at creation time. This label is called a default security
224 label, and is decided according to the system security policy, which
225 takes as input the creator's label, the label assigned to the new
226 object's parent object and optionally name of the constructed object.
228 A new database object basically inherits the security label of the
229 parent object, except when the security policy has special rules known
230 as type-transition rules, in which case a different label may be
231 applied. For schemas, the parent object is the current database; for
232 tables, sequences, views, and functions, it is the containing schema;
233 for columns, it is the containing table.
235 F.40.5.2. DML Permissions #
237 For tables, db_table:select, db_table:insert, db_table:update or
238 db_table:delete are checked for all the referenced target tables
239 depending on the kind of statement; in addition, db_table:select is
240 also checked for all the tables that contain columns referenced in the
241 WHERE or RETURNING clause, as a data source for UPDATE, and so on.
243 Column-level permissions will also be checked for each referenced
244 column. db_column:select is checked on not only the columns being read
245 using SELECT, but those being referenced in other DML statements;
246 db_column:update or db_column:insert will also be checked for columns
247 being modified by UPDATE or INSERT.
249 For example, consider:
250 UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100;
252 Here, db_column:update will be checked for t1.x, since it is being
253 updated, db_column:{select update} will be checked for t1.y, since it
254 is both updated and referenced, and db_column:select will be checked
255 for t1.z, since it is only referenced. db_table:{select update} will
256 also be checked at the table level.
258 For sequences, db_sequence:get_value is checked when we reference a
259 sequence object using SELECT; however, note that we do not currently
260 check permissions on execution of corresponding functions such as
263 For views, db_view:expand will be checked, then any other required
264 permissions will be checked on the objects being expanded from the
267 For functions, db_procedure:{execute} will be checked when user tries
268 to execute a function as a part of query, or using fast-path
269 invocation. If this function is a trusted procedure, it also checks
270 db_procedure:{entrypoint} permission to check whether it can perform as
271 entry point of trusted procedure.
273 In order to access any schema object, db_schema:search permission is
274 required on the containing schema. When an object is referenced without
275 schema qualification, schemas on which this permission is not present
276 will not be searched (just as if the user did not have USAGE privilege
277 on the schema). If an explicit schema qualification is present, an
278 error will occur if the user does not have the requisite permission on
281 The client must be allowed to access all referenced tables and columns,
282 even if they originated from views which were then expanded, so that we
283 apply consistent access control rules independent of the manner in
284 which the table contents are referenced.
286 The default database privilege system allows database superusers to
287 modify system catalogs using DML commands, and reference or modify
288 toast tables. These operations are prohibited when sepgsql is enabled.
290 F.40.5.3. DDL Permissions #
292 SELinux defines several permissions to control common operations for
293 each object type; such as creation, alter, drop and relabel of security
294 label. In addition, several object types have special permissions to
295 control their characteristic operations; such as addition or deletion
296 of name entries within a particular schema.
298 Creating a new database object requires create permission. SELinux will
299 grant or deny this permission based on the client's security label and
300 the proposed security label for the new object. In some cases,
301 additional privileges are required:
302 * CREATE DATABASE additionally requires getattr permission for the
303 source or template database.
304 * Creating a schema object additionally requires add_name permission
305 on the parent schema.
306 * Creating a table additionally requires permission to create each
307 individual table column, just as if each table column were a
308 separate top-level object.
309 * Creating a function marked as LEAKPROOF additionally requires
310 install permission. (This permission is also checked when LEAKPROOF
311 is set for an existing function.)
313 When DROP command is executed, drop will be checked on the object being
314 removed. Permissions will be also checked for objects dropped
315 indirectly via CASCADE. Deletion of objects contained within a
316 particular schema (tables, views, sequences and procedures)
317 additionally requires remove_name on the schema.
319 When ALTER command is executed, setattr will be checked on the object
320 being modified for each object types, except for subsidiary objects
321 such as the indexes or triggers of a table, where permissions are
322 instead checked on the parent object. In some cases, additional
323 permissions are required:
324 * Moving an object to a new schema additionally requires remove_name
325 permission on the old schema and add_name permission on the new
327 * Setting the LEAKPROOF attribute on a function requires install
329 * Using SECURITY LABEL on an object additionally requires relabelfrom
330 permission for the object in conjunction with its old security
331 label and relabelto permission for the object in conjunction with
332 its new security label. (In cases where multiple label providers
333 are installed and the user tries to set a security label, but it is
334 not managed by SELinux, only setattr should be checked here. This
335 is currently not done due to implementation restrictions.)
337 F.40.5.4. Trusted Procedures #
339 Trusted procedures are similar to security definer functions or setuid
340 commands. SELinux provides a feature to allow trusted code to run using
341 a security label different from that of the client, generally for the
342 purpose of providing highly controlled access to sensitive data (e.g.,
343 rows might be omitted, or the precision of stored values might be
344 reduced). Whether or not a function acts as a trusted procedure is
345 controlled by its security label and the operating system security
347 postgres=# CREATE TABLE customer (
353 postgres=# SECURITY LABEL ON COLUMN customer.credit
354 IS 'system_u:object_r:sepgsql_secret_table_t:s0';
356 postgres=# CREATE FUNCTION show_credit(int) RETURNS text
357 AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
358 FROM customer WHERE cid = $1'
361 postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
362 IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
365 The above operations should be performed by an administrative user.
366 postgres=# SELECT * FROM customer;
367 ERROR: SELinux: security policy violation
368 postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
369 cid | cname | show_credit
370 -----+--------+---------------------
371 1 | taro | 1111-2222-3333-xxxx
372 2 | hanako | 5555-6666-7777-xxxx
375 In this case, a regular user cannot reference customer.credit directly,
376 but a trusted procedure show_credit allows the user to print the credit
377 card numbers of customers with some of the digits masked out.
379 F.40.5.5. Dynamic Domain Transitions #
381 It is possible to use SELinux's dynamic domain transition feature to
382 switch the security label of the client process, the client domain, to
383 a new context, if that is allowed by the security policy. The client
384 domain needs the setcurrent permission and also dyntransition from the
385 old to the new domain.
387 Dynamic domain transitions should be considered carefully, because they
388 allow users to switch their label, and therefore their privileges, at
389 their option, rather than (as in the case of a trusted procedure) as
390 mandated by the system. Thus, the dyntransition permission is only
391 considered safe when used to switch to a domain with a smaller set of
392 privileges than the original one. For example:
393 regression=# select sepgsql_getcon();
395 -------------------------------------------------------
396 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
399 regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0
406 regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0
408 ERROR: SELinux: security policy violation
410 In this example above we were allowed to switch from the larger MCS
411 range c1.c1023 to the smaller range c1.c4, but switching back was
414 A combination of dynamic domain transition and trusted procedure
415 enables an interesting use case that fits the typical process
416 life-cycle of connection pooling software. Even if your connection
417 pooling software is not allowed to run most of SQL commands, you can
418 allow it to switch the security label of the client using the
419 sepgsql_setcon() function from within a trusted procedure; that should
420 take some credential to authorize the request to switch the client
421 label. After that, this session will have the privileges of the target
422 user, rather than the connection pooler. The connection pooler can
423 later revert the security label change by again using sepgsql_setcon()
424 with NULL argument, again invoked from within a trusted procedure with
425 appropriate permissions checks. The point here is that only the trusted
426 procedure actually has permission to change the effective security
427 label, and only does so when given proper credentials. Of course, for
428 secure operation, the credential store (table, procedure definition, or
429 whatever) must be protected from unauthorized access.
431 F.40.5.6. Miscellaneous #
433 We reject the LOAD command across the board, because any module loaded
434 could easily circumvent security policy enforcement.
436 F.40.6. Sepgsql Functions #
438 Table F.32 shows the available functions.
440 Table F.32. Sepgsql Functions
446 sepgsql_getcon () → text
448 Returns the client domain, the current security label of the client.
450 sepgsql_setcon ( text ) → boolean
452 Switches the client domain of the current session to the new domain, if
453 allowed by the security policy. It also accepts NULL input as a request
454 to transition to the client's original domain.
456 sepgsql_mcstrans_in ( text ) → text
458 Translates the given qualified MLS/MCS range into raw format if the
459 mcstrans daemon is running.
461 sepgsql_mcstrans_out ( text ) → text
463 Translates the given raw MLS/MCS range into qualified format if the
464 mcstrans daemon is running.
466 sepgsql_restorecon ( text ) → boolean
468 Sets up initial security labels for all objects within the current
469 database. The argument may be NULL, or the name of a specfile to be
470 used as alternative of the system default.
472 F.40.7. Limitations #
474 Data Definition Language (DDL) Permissions
475 Due to implementation restrictions, some DDL operations do not
478 Data Control Language (DCL) Permissions
479 Due to implementation restrictions, DCL operations do not check
482 Row-level access control
483 PostgreSQL supports row-level access, but sepgsql does not.
486 sepgsql does not try to hide the existence of a certain object,
487 even if the user is not allowed to reference it. For example, we
488 can infer the existence of an invisible object as a result of
489 primary key conflicts, foreign key violations, and so on, even
490 if we cannot obtain the contents of the object. The existence of
491 a top secret table cannot be hidden; we only hope to conceal its
494 F.40.8. External Resources #
496 SE-PostgreSQL Introduction
497 This wiki page provides a brief overview, security design,
498 architecture, administration and upcoming features.
500 SELinux User's and Administrator's Guide
501 This document provides a wide spectrum of knowledge to
502 administer SELinux on your systems. It focuses primarily on Red
503 Hat operating systems, but is not limited to them.
506 This document answers frequently asked questions about SELinux.
507 It focuses primarily on Fedora, but is not limited to Fedora.
511 KaiGai Kohei <kaigai@ak.jp.nec.com>