diff options
Diffstat (limited to 'doc/src/sgml/sepgsql.sgml')
-rw-r--r-- | doc/src/sgml/sepgsql.sgml | 828 |
1 files changed, 828 insertions, 0 deletions
diff --git a/doc/src/sgml/sepgsql.sgml b/doc/src/sgml/sepgsql.sgml new file mode 100644 index 0000000..9961569 --- /dev/null +++ b/doc/src/sgml/sepgsql.sgml @@ -0,0 +1,828 @@ +<!-- doc/src/sgml/sepgsql.sgml --> + +<sect1 id="sepgsql" xreflabel="sepgsql"> + <title>sepgsql</title> + + <indexterm zone="sepgsql"> + <primary>sepgsql</primary> + </indexterm> + + <para> + <filename>sepgsql</filename> is a loadable module that supports label-based + mandatory access control (MAC) based on <productname>SELinux</productname> security + policy. + </para> + + <warning> + <para> + The current implementation has significant limitations, and does not + enforce mandatory access control for all actions. See + <xref linkend="sepgsql-limitations"/>. + </para> + </warning> + + <sect2 id="sepgsql-overview"> + <title>Overview</title> + + <para> + This module integrates with <productname>SELinux</productname> to provide an + additional layer of security checking above and beyond what is normally + provided by <productname>PostgreSQL</productname>. From the perspective of + <productname>SELinux</productname>, this module allows + <productname>PostgreSQL</productname> to function as a user-space object + manager. Each table or function access initiated by a DML query will be + checked against the system security policy. This check is in addition to + the usual SQL permissions checking performed by + <productname>PostgreSQL</productname>. + </para> + + <para> + <productname>SELinux</productname> access control decisions are made using + security labels, which are represented by strings such as + <literal>system_u:object_r:sepgsql_table_t:s0</literal>. Each access control + decision involves two labels: the label of the subject attempting to + perform the action, and the label of the object on which the operation is + to be performed. Since these labels can be applied to any sort of object, + access control decisions for objects stored within the database can be + (and, with this module, are) subjected to the same general criteria used + for objects of any other type, such as files. This design is intended to + allow a centralized security policy to protect information assets + independent of the particulars of how those assets are stored. + </para> + + <para> + The <xref linkend="sql-security-label"/> statement allows assignment of + a security label to a database object. + </para> + + </sect2> + <sect2 id="sepgsql-installation"> + <title>Installation</title> + + <para> + <filename>sepgsql</filename> can only be used on <productname>Linux</productname> + 2.6.28 or higher with <productname>SELinux</productname> enabled. + It is not available on any other platform. You will also need + <productname>libselinux</productname> 2.1.10 or higher and + <productname>selinux-policy</productname> 3.9.13 or higher (although some + distributions may backport the necessary rules into older policy + versions). + </para> + + <para> + The <command>sestatus</command> command allows you to check the status of + <productname>SELinux</productname>. A typical display is: +<screen> +$ sestatus +SELinux status: enabled +SELinuxfs mount: /selinux +Current mode: enforcing +Mode from config file: enforcing +Policy version: 24 +Policy from config file: targeted +</screen> + If <productname>SELinux</productname> is disabled or not installed, you must set + that product up first before installing this module. + </para> + + <para> + To build this module, include the option <literal>--with-selinux</literal> in + your PostgreSQL <literal>configure</literal> command. Be sure that the + <filename>libselinux-devel</filename> RPM is installed at build time. + </para> + + <para> + To use this module, you must include <literal>sepgsql</literal> + in the <xref linkend="guc-shared-preload-libraries"/> parameter in + <filename>postgresql.conf</filename>. The module will not function correctly + if loaded in any other manner. Once the module is loaded, you + should execute <filename>sepgsql.sql</filename> in each database. + This will install functions needed for security label management, and + assign initial security labels. + </para> + + <para> + Here is an example showing how to initialize a fresh database cluster + with <filename>sepgsql</filename> functions and security labels installed. + Adjust the paths shown as appropriate for your installation: + </para> + +<screen> +$ export PGDATA=/path/to/data/directory +$ initdb +$ vi $PGDATA/postgresql.conf + change + #shared_preload_libraries = '' # (change requires restart) + to + shared_preload_libraries = 'sepgsql' # (change requires restart) +$ for DBNAME in template0 template1 postgres; do + postgres --single -F -c exit_on_error=true $DBNAME \ + </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null + done +</screen> + + <para> + Please note that you may see some or all of the following notifications + depending on the particular versions you have of + <productname>libselinux</productname> and <productname>selinux-policy</productname>: +<screen> +/etc/selinux/targeted/contexts/sepgsql_contexts: line 33 has invalid object type db_blobs +/etc/selinux/targeted/contexts/sepgsql_contexts: line 36 has invalid object type db_language +/etc/selinux/targeted/contexts/sepgsql_contexts: line 37 has invalid object type db_language +/etc/selinux/targeted/contexts/sepgsql_contexts: line 38 has invalid object type db_language +/etc/selinux/targeted/contexts/sepgsql_contexts: line 39 has invalid object type db_language +/etc/selinux/targeted/contexts/sepgsql_contexts: line 40 has invalid object type db_language +</screen> + These messages are harmless and should be ignored. + </para> + + <para> + If the installation process completes without error, you can now start the + server normally. + </para> + </sect2> + + <sect2 id="sepgsql-regression"> + <title>Regression Tests</title> + + <para> + Due to the nature of <productname>SELinux</productname>, running the + regression tests for <filename>sepgsql</filename> requires several extra + configuration steps, some of which must be done as root. + The regression tests will not be run by an ordinary + <literal>make check</literal> or <literal>make installcheck</literal> command; you must + set up the configuration and then invoke the test script manually. + The tests must be run in the <filename>contrib/sepgsql</filename> directory + of a configured PostgreSQL build tree. Although they require a build tree, + the tests are designed to be executed against an installed server, + that is they are comparable to <literal>make installcheck</literal> not + <literal>make check</literal>. + </para> + + <para> + First, set up <filename>sepgsql</filename> in a working database + according to the instructions in <xref linkend="sepgsql-installation"/>. + Note that the current operating system user must be able to connect to the + database as superuser without password authentication. + </para> + + <para> + Second, build and install the policy package for the regression test. + The <filename>sepgsql-regtest</filename> policy is a special purpose policy package + which provides a set of rules to be allowed during the regression tests. + It should be built from the policy source file + <filename>sepgsql-regtest.te</filename>, which is done using + <command>make</command> with a Makefile supplied by SELinux. + You will need to locate the appropriate + Makefile on your system; the path shown below is only an example. + (This Makefile is usually supplied by the + <filename>selinux-policy-devel</filename> or + <filename>selinux-policy</filename> RPM.) + Once built, install this policy package using the + <command>semodule</command> command, which loads supplied policy packages + into the kernel. If the package is correctly installed, + <literal><command>semodule</command> -l</literal> should list <literal>sepgsql-regtest</literal> as an + available policy package: + </para> + +<screen> +$ cd .../contrib/sepgsql +$ make -f /usr/share/selinux/devel/Makefile +$ sudo semodule -u sepgsql-regtest.pp +$ sudo semodule -l | grep sepgsql +sepgsql-regtest 1.07 +</screen> + + <para> + Third, turn on <literal>sepgsql_regression_test_mode</literal>. + For security reasons, the rules in <filename>sepgsql-regtest</filename> + are not enabled by default; + the <literal>sepgsql_regression_test_mode</literal> parameter enables + the rules needed to launch the regression tests. + It can be turned on using the <command>setsebool</command> command: + </para> + +<screen> +$ sudo setsebool sepgsql_regression_test_mode on +$ getsebool sepgsql_regression_test_mode +sepgsql_regression_test_mode --> on +</screen> + + <para> + Fourth, verify your shell is operating in the <literal>unconfined_t</literal> + domain: + </para> +<screen> +$ id -Z +unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 +</screen> + + <para> + See <xref linkend="sepgsql-resources"/> for details on adjusting your + working domain, if necessary. + </para> + + <para> + Finally, run the regression test script: + </para> +<screen> +$ ./test_sepgsql +</screen> + + <para> + This script will attempt to verify that you have done all the configuration + steps correctly, and then it will run the regression tests for the + <filename>sepgsql</filename> module. + </para> + + <para> + After completing the tests, it's recommended you disable + the <literal>sepgsql_regression_test_mode</literal> parameter: + </para> + +<screen> +$ sudo setsebool sepgsql_regression_test_mode off +</screen> + + <para> + You might prefer to remove the <filename>sepgsql-regtest</filename> policy + entirely: + </para> + +<screen> +$ sudo semodule -r sepgsql-regtest +</screen> + </sect2> + + <sect2 id="sepgsql-parameters"> + <title>GUC Parameters</title> + + <variablelist> + <varlistentry id="guc-sepgsql-permissive" xreflabel="sepgsql.permissive"> + <term> + <varname>sepgsql.permissive</varname> (<type>boolean</type>) + <indexterm> + <primary><varname>sepgsql.permissive</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + This parameter enables <filename>sepgsql</filename> to function + in permissive mode, regardless of the system setting. + The default is off. + This parameter can only be set in the <filename>postgresql.conf</filename> + file or on the server command line. + </para> + + <para> + When this parameter is on, <filename>sepgsql</filename> functions + in permissive mode, even if SELinux in general is working in enforcing + mode. This parameter is primarily useful for testing purposes. + </para> + </listitem> + + </varlistentry> + <varlistentry id="guc-sepgsql-debug-audit" xreflabel="sepgsql.debug_audit"> + <term> + <varname>sepgsql.debug_audit</varname> (<type>boolean</type>) + <indexterm> + <primary><varname>sepgsql.debug_audit</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + This parameter enables the printing of audit messages regardless of + the system policy settings. + The default is off, which means that messages will be printed according + to the system settings. + </para> + + <para> + The security policy of <productname>SELinux</productname> also has rules to + control whether or not particular accesses are logged. + By default, access violations are logged, but allowed + accesses are not. + </para> + + <para> + This parameter forces all possible logging to be turned on, regardless + of the system policy. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="sepgsql-features"> + <title>Features</title> + <sect3> + <title>Controlled Object Classes</title> + <para> + The security model of <productname>SELinux</productname> describes all the access + control rules as relationships between a subject entity (typically, + a client of the database) and an object entity (such as a database + object), each of which is + identified by a security label. If access to an unlabeled object is + attempted, the object is treated as if it were assigned the label + <literal>unlabeled_t</literal>. + </para> + + <para> + Currently, <filename>sepgsql</filename> allows security labels to be + assigned to schemas, tables, columns, sequences, views, and functions. + When <filename>sepgsql</filename> is in use, security labels are + automatically assigned to supported database objects at creation time. + This label is called a default security label, and is decided according + to the system security policy, which takes as input the creator's label, + the label assigned to the new object's parent object and optionally name + of the constructed object. + </para> + + <para> + A new database object basically inherits the security label of the parent + object, except when the security policy has special rules known as + type-transition rules, in which case a different label may be applied. + For schemas, the parent object is the current database; for tables, + sequences, views, and functions, it is the containing schema; for columns, + it is the containing table. + </para> + </sect3> + + <sect3> + <title>DML Permissions</title> + + <para> + For tables, <literal>db_table:select</literal>, <literal>db_table:insert</literal>, + <literal>db_table:update</literal> or <literal>db_table:delete</literal> are + checked for all the referenced target tables depending on the kind of + statement; in addition, <literal>db_table:select</literal> is also checked for + all the tables that contain columns referenced in the + <literal>WHERE</literal> or <literal>RETURNING</literal> clause, as a data source + for <literal>UPDATE</literal>, and so on. + </para> + + <para> + Column-level permissions will also be checked for each referenced column. + <literal>db_column:select</literal> is checked on not only the columns being + read using <literal>SELECT</literal>, but those being referenced in other DML + statements; <literal>db_column:update</literal> or <literal>db_column:insert</literal> + will also be checked for columns being modified by <literal>UPDATE</literal> or + <literal>INSERT</literal>. + </para> + + <para> + For example, consider: +<synopsis> +UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100; +</synopsis> + + Here, <literal>db_column:update</literal> will be checked for + <literal>t1.x</literal>, since it is being updated, + <literal>db_column:{select update}</literal> will be checked for + <literal>t1.y</literal>, since it is both updated and referenced, and + <literal>db_column:select</literal> will be checked for <literal>t1.z</literal>, since + it is only referenced. + <literal>db_table:{select update}</literal> will also be checked + at the table level. + </para> + + <para> + For sequences, <literal>db_sequence:get_value</literal> is checked when we + reference a sequence object using <literal>SELECT</literal>; however, note that we + do not currently check permissions on execution of corresponding functions + such as <literal>lastval()</literal>. + </para> + + <para> + For views, <literal>db_view:expand</literal> will be checked, then any other + required permissions will be checked on the objects being + expanded from the view, individually. + </para> + + <para> + For functions, <literal>db_procedure:{execute}</literal> will be checked when + user tries to execute a function as a part of query, or using fast-path + invocation. If this function is a trusted procedure, it also checks + <literal>db_procedure:{entrypoint}</literal> permission to check whether it + can perform as entry point of trusted procedure. + </para> + + <para> + In order to access any schema object, <literal>db_schema:search</literal> + permission is required on the containing schema. When an object is + referenced without schema qualification, schemas on which this + permission is not present will not be searched (just as if the user did + not have <literal>USAGE</literal> privilege on the schema). If an explicit schema + qualification is present, an error will occur if the user does not have + the requisite permission on the named schema. + </para> + + <para> + The client must be allowed to access all referenced tables and + columns, even if they originated from views which were then expanded, + so that we apply consistent access control rules independent of the manner + in which the table contents are referenced. + </para> + + <para> + The default database privilege system allows database superusers to + modify system catalogs using DML commands, and reference or modify + toast tables. These operations are prohibited when + <filename>sepgsql</filename> is enabled. + </para> + </sect3> + + <sect3> + <title>DDL Permissions</title> + <para> + <productname>SELinux</productname> defines several permissions to control common + operations for each object type; such as creation, alter, drop and + relabel of security label. In addition, several object types have + special permissions to control their characteristic operations; such as + addition or deletion of name entries within a particular schema. + </para> + <para> + Creating a new database object requires <literal>create</literal> permission. + <productname>SELinux</productname> will grant or deny this permission based on the + client's security label and the proposed security label for the new + object. In some cases, additional privileges are required: + </para> + + <itemizedlist> + <listitem> + <para> + <xref linkend="sql-createdatabase"/> additionally requires + <literal>getattr</literal> permission for the source or template database. + </para> + </listitem> + <listitem> + <para> + Creating a schema object additionally requires <literal>add_name</literal> + permission on the parent schema. + </para> + </listitem> + <listitem> + <para> + Creating a table additionally requires permission to create each + individual table column, just as if each table column were a + separate top-level object. + </para> + </listitem> + <listitem> + <para> + Creating a function marked as <literal>LEAKPROOF</literal> additionally + requires <literal>install</literal> permission. (This permission is also + checked when <literal>LEAKPROOF</literal> is set for an existing function.) + </para> + </listitem> + </itemizedlist> + + <para> + When <literal>DROP</literal> command is executed, <literal>drop</literal> will be + checked on the object being removed. Permissions will be also checked for + objects dropped indirectly via <literal>CASCADE</literal>. Deletion of objects + contained within a particular schema (tables, views, sequences and + procedures) additionally requires <literal>remove_name</literal> on the schema. + </para> + + <para> + When <literal>ALTER</literal> command is executed, <literal>setattr</literal> will be + checked on the object being modified for each object types, except for + subsidiary objects such as the indexes or triggers of a table, where + permissions are instead checked on the parent object. In some cases, + additional permissions are required: + </para> + + <itemizedlist> + <listitem> + <para> + Moving an object to a new schema additionally requires + <literal>remove_name</literal> permission on the old schema and + <literal>add_name</literal> permission on the new one. + </para> + </listitem> + <listitem> + <para> + Setting the <literal>LEAKPROOF</literal> attribute on a function requires + <literal>install</literal> permission. + </para> + </listitem> + <listitem> + <para> + Using <xref linkend="sql-security-label"/> on an object additionally + requires <literal>relabelfrom</literal> permission for the object in + conjunction with its old security label and <literal>relabelto</literal> + permission for the object in conjunction with its new security label. + (In cases where multiple label providers are installed and the user + tries to set a security label, but it is not managed by + <productname>SELinux</productname>, only <literal>setattr</literal> should be checked here. + This is currently not done due to implementation restrictions.) + </para> + </listitem> + </itemizedlist> + + </sect3> + + <sect3> + <title>Trusted Procedures</title> + <para> + Trusted procedures are similar to security definer functions or setuid + commands. <productname>SELinux</productname> provides a feature to allow trusted + code to run using a security label different from that of the client, + generally for the purpose of providing highly controlled access to + sensitive data (e.g., rows might be omitted, or the precision of stored + values might be reduced). Whether or not a function acts as a trusted + procedure is controlled by its security label and the operating system + security policy. For example: + </para> + +<screen> +postgres=# CREATE TABLE customer ( + cid int primary key, + cname text, + credit text + ); +CREATE TABLE +postgres=# SECURITY LABEL ON COLUMN customer.credit + IS 'system_u:object_r:sepgsql_secret_table_t:s0'; +SECURITY LABEL +postgres=# CREATE FUNCTION show_credit(int) RETURNS text + AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'') + FROM customer WHERE cid = $1' + LANGUAGE sql; +CREATE FUNCTION +postgres=# SECURITY LABEL ON FUNCTION show_credit(int) + IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'; +SECURITY LABEL +</screen> + + <para> + The above operations should be performed by an administrative user. + </para> + +<screen> +postgres=# SELECT * FROM customer; +ERROR: SELinux: security policy violation +postgres=# SELECT cid, cname, show_credit(cid) FROM customer; + cid | cname | show_credit +-----+--------+--------------------- + 1 | taro | 1111-2222-3333-xxxx + 2 | hanako | 5555-6666-7777-xxxx +(2 rows) +</screen> + + <para> + In this case, a regular user cannot reference <literal>customer.credit</literal> + directly, but a trusted procedure <literal>show_credit</literal> allows the user + to print the credit card numbers of customers with some of the digits + masked out. + </para> + </sect3> + + <sect3> + <title>Dynamic Domain Transitions</title> + <para> + It is possible to use SELinux's dynamic domain transition feature + to switch the security label of the client process, the client domain, + to a new context, if that is allowed by the security policy. + The client domain needs the <literal>setcurrent</literal> permission and also + <literal>dyntransition</literal> from the old to the new domain. + </para> + <para> + Dynamic domain transitions should be considered carefully, because they + allow users to switch their label, and therefore their privileges, + at their option, rather than (as in the case of a trusted procedure) + as mandated by the system. + Thus, the <literal>dyntransition</literal> permission is only considered + safe when used to switch to a domain with a smaller set of privileges than + the original one. For example: + </para> +<screen> +regression=# select sepgsql_getcon(); + sepgsql_getcon +------------------------------------------------------- + unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 +(1 row) + +regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4'); + sepgsql_setcon +---------------- + t +(1 row) + +regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023'); +ERROR: SELinux: security policy violation +</screen> + <para> + In this example above we were allowed to switch from the larger MCS + range <literal>c1.c1023</literal> to the smaller range <literal>c1.c4</literal>, but + switching back was denied. + </para> + <para> + A combination of dynamic domain transition and trusted procedure + enables an interesting use case that fits the typical process life-cycle + of connection pooling software. + Even if your connection pooling software is not allowed to run most + of SQL commands, you can allow it to switch the security label + of the client using the <literal>sepgsql_setcon()</literal> function + from within a trusted procedure; that should take some + credential to authorize the request to switch the client label. + After that, this session will have the privileges of the target user, + rather than the connection pooler. + The connection pooler can later revert the security label change by + again using <literal>sepgsql_setcon()</literal> with + <literal>NULL</literal> argument, again invoked from within a trusted + procedure with appropriate permissions checks. + The point here is that only the trusted procedure actually has permission + to change the effective security label, and only does so when given proper + credentials. Of course, for secure operation, the credential store + (table, procedure definition, or whatever) must be protected from + unauthorized access. + </para> + </sect3> + + <sect3> + <title>Miscellaneous</title> + <para> + We reject the <xref linkend="sql-load"/> command across the board, because + any module loaded could easily circumvent security policy enforcement. + </para> + + </sect3> +</sect2> + + <sect2 id="sepgsql-functions"> + <title>Sepgsql Functions</title> + <para> + <xref linkend="sepgsql-functions-table"/> shows the available functions. + </para> + + <table id="sepgsql-functions-table"> + <title>Sepgsql Functions</title> + <tgroup cols="1"> + <thead> + <row> + <entry role="func_table_entry"><para role="func_signature"> + Function + </para> + <para> + Description + </para></entry> + </row> + </thead> + + <tbody> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <function>sepgsql_getcon</function> () + <returnvalue>text</returnvalue> + </para> + <para> + Returns the client domain, the current security label of the client. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <function>sepgsql_setcon</function> ( <type>text</type> ) + <returnvalue>boolean</returnvalue> + </para> + <para> + Switches the client domain of the current session to the new domain, + if allowed by the security policy. + It also accepts <literal>NULL</literal> input as a request to transition + to the client's original domain. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <function>sepgsql_mcstrans_in</function> ( <type>text</type> ) + <returnvalue>text</returnvalue> + </para> + <para> + Translates the given qualified MLS/MCS range into raw format if + the mcstrans daemon is running. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <function>sepgsql_mcstrans_out</function> ( <type>text</type> ) + <returnvalue>text</returnvalue> + </para> + <para> + Translates the given raw MLS/MCS range into qualified format if + the mcstrans daemon is running. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <function>sepgsql_restorecon</function> ( <type>text</type> ) + <returnvalue>boolean</returnvalue> + </para> + <para> + Sets up initial security labels for all objects within the + current database. The argument may be <literal>NULL</literal>, or the + name of a specfile to be used as alternative of the system default. + </para></entry> + </row> + </tbody> + </tgroup> + </table> + </sect2> + + <sect2 id="sepgsql-limitations"> + <title>Limitations</title> + + <variablelist> + <varlistentry> + <term>Data Definition Language (DDL) Permissions</term> + <listitem> + <para> + Due to implementation restrictions, some DDL operations do not + check permissions. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Data Control Language (DCL) Permissions</term> + <listitem> + <para> + Due to implementation restrictions, DCL operations do not check + permissions. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Row-level access control</term> + <listitem> + <para> + <productname>PostgreSQL</productname> supports row-level access, but + <filename>sepgsql</filename> does not. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Covert channels</term> + <listitem> + <para> + <filename>sepgsql</filename> does not try to hide the existence of + a certain object, even if the user is not allowed to reference it. + For example, we can infer the existence of an invisible object as + a result of primary key conflicts, foreign key violations, and so on, + even if we cannot obtain the contents of the object. The existence + of a top secret table cannot be hidden; we only hope to conceal its + contents. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="sepgsql-resources"> + <title>External Resources</title> + <variablelist> + <varlistentry> + <term><ulink url="https://wiki.postgresql.org/wiki/SEPostgreSQL">SE-PostgreSQL Introduction</ulink></term> + <listitem> + <para> + This wiki page provides a brief overview, security design, architecture, + administration and upcoming features. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><ulink url="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/">SELinux User's and Administrator's Guide</ulink></term> + <listitem> + <para> + This document provides a wide spectrum of knowledge to administer + <productname>SELinux</productname> on your systems. + It focuses primarily on Red Hat operating systems, but is not limited to them. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><ulink url="https://fedoraproject.org/wiki/SELinux_FAQ">Fedora SELinux FAQ</ulink></term> + <listitem> + <para> + This document answers frequently asked questions about + <productname>SELinux</productname>. + It focuses primarily on Fedora, but is not limited to Fedora. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="sepgsql-author"> + <title>Author</title> + <para> + KaiGai Kohei <email>kaigai@ak.jp.nec.com</email> + </para> + </sect2> +</sect1> |