First round of cleanup of sepgsql code and documentation.

Robert Haas, with a few suggestions from Thom Brown
This commit is contained in:
Robert Haas 2011-01-23 22:47:16 -05:00
parent 968bc6fac9
commit 194c8f713a
5 changed files with 231 additions and 275 deletions

View File

@ -1 +1,5 @@
/sepgsql.sql /sepgsql.sql
/sepgsql-regtest.fc
/sepgsql-regtest.if
/sepgsql-regtest.pp
/tmp

View File

@ -171,12 +171,12 @@ check_relation_privileges(Oid relOid,
SEPG_DB_TABLE__DELETE)) != 0) SEPG_DB_TABLE__DELETE)) != 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("selinux: hardwired security policy violation"))); errmsg("SELinux: hardwired security policy violation")));
if (relkind == RELKIND_TOASTVALUE) if (relkind == RELKIND_TOASTVALUE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("selinux: hardwired security policy violation"))); errmsg("SELinux: hardwired security policy violation")));
} }
/* /*

View File

@ -91,7 +91,7 @@ sepgsql_client_auth(Port *port, int status)
if (getpeercon_raw(port->sock, &context) < 0) if (getpeercon_raw(port->sock, &context) < 0)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("selinux: failed to get the peer label"))); errmsg("SELinux: unable to get peer label")));
sepgsql_set_client_label(context); sepgsql_set_client_label(context);
@ -318,7 +318,7 @@ sepgsql_utility_command(Node *parsetree,
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("SELinux: LOAD is not allowed anyway."))); errmsg("SELinux: LOAD is not permitted")));
} }
break; break;
default: default:
@ -352,8 +352,8 @@ _PG_init(void)
*/ */
if (IsUnderPostmaster) if (IsUnderPostmaster)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("Not allowed to load SE-PostgreSQL now"))); errmsg("sepgsql must be loaded via shared_preload_libraries")));
/* /*
* Check availability of SELinux on the platform. * Check availability of SELinux on the platform.
@ -414,7 +414,7 @@ _PG_init(void)
if (getcon_raw(&context) < 0) if (getcon_raw(&context) < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("selinux: unable to get security label of server"))); errmsg("SELinux: failed to get server security label")));
sepgsql_set_client_label(context); sepgsql_set_client_label(context);
/* Security label provider hook */ /* Security label provider hook */

View File

@ -81,7 +81,7 @@ sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0) if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("selinux: unable to get initial security label"))); errmsg("SELinux: failed to get initial security label")));
PG_TRY(); PG_TRY();
{ {
label = pstrdup(unlabeled); label = pstrdup(unlabeled);
@ -114,7 +114,7 @@ sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
security_check_context_raw((security_context_t) seclabel) < 0) security_check_context_raw((security_context_t) seclabel) < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME), (errcode(ERRCODE_INVALID_NAME),
errmsg("invalid security label: \"%s\"", seclabel))); errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
/* /*
* Do actual permission checks for each object classes * Do actual permission checks for each object classes
*/ */
@ -154,13 +154,11 @@ sepgsql_getcon(PG_FUNCTION_ARGS)
char *client_label; char *client_label;
if (!sepgsql_is_enabled()) if (!sepgsql_is_enabled())
ereport(ERROR, PG_RETURN_NULL();
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELinux: now disabled")));
client_label = sepgsql_get_client_label(); client_label = sepgsql_get_client_label();
PG_RETURN_POINTER(cstring_to_text(client_label)); PG_RETURN_TEXT_P(cstring_to_text(client_label));
} }
/* /*
@ -179,14 +177,14 @@ sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
if (!sepgsql_is_enabled()) if (!sepgsql_is_enabled())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("SELinux: now disabled"))); errmsg("sepgsql is not enabled")));
if (selinux_trans_to_raw_context(text_to_cstring(label), if (selinux_trans_to_raw_context(text_to_cstring(label),
&raw_label) < 0) &raw_label) < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux: internal error on mcstrans"))); errmsg("SELinux: could not translate security label")));
PG_TRY(); PG_TRY();
{ {
@ -200,7 +198,7 @@ sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
PG_END_TRY(); PG_END_TRY();
freecon(raw_label); freecon(raw_label);
PG_RETURN_POINTER(cstring_to_text(result)); PG_RETURN_TEXT_P(cstring_to_text(result));
} }
/* /*
@ -219,14 +217,14 @@ sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
if (!sepgsql_is_enabled()) if (!sepgsql_is_enabled())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("SELinux: now disabled"))); errmsg("sepgsql is not currently enabled")));
if (selinux_raw_to_trans_context(text_to_cstring(label), if (selinux_raw_to_trans_context(text_to_cstring(label),
&qual_label) < 0) &qual_label) < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux: internal error on mcstrans"))); errmsg("SELinux: could not translate security label")));
PG_TRY(); PG_TRY();
{ {
@ -240,7 +238,7 @@ sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
PG_END_TRY(); PG_END_TRY();
freecon(qual_label); freecon(qual_label);
PG_RETURN_POINTER(cstring_to_text(result)); PG_RETURN_TEXT_P(cstring_to_text(result));
} }
/* /*
@ -360,8 +358,7 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
break; break;
default: default:
elog(ERROR, "Bug? %u is not supported to set initial labels", elog(ERROR, "unexpected catalog id: %u", catalogId);
catalogId);
break; break;
} }
@ -387,12 +384,12 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
} }
else if (errno == ENOENT) else if (errno == ENOENT)
ereport(WARNING, ereport(WARNING,
(errmsg("no valid initial label on %s (type=%d), skipped", (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
objname, objtype))); objname, objtype)));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("libselinux: internal error"))); errmsg("SELinux: could not determine initial security label for %s (type=%d)", objname, objtype)));
} }
systable_endscan(sscan); systable_endscan(sscan);
@ -422,8 +419,8 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
*/ */
if (!sepgsql_is_enabled()) if (!sepgsql_is_enabled())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("SELinux: now disabled"))); errmsg("sepgsql is not currently enabled")));
/* /*
* Check DAC permission. Only superuser can set up initial * Check DAC permission. Only superuser can set up initial
* security labels, like root-user in filesystems * security labels, like root-user in filesystems
@ -431,7 +428,7 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to restore initial contexts"))); errmsg("SELinux: must be superuser to restore initial contexts")));
/* /*
* Open selabel_lookup(3) stuff. It provides a set of mapping * Open selabel_lookup(3) stuff. It provides a set of mapping
@ -452,7 +449,7 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
if (!sehnd) if (!sehnd)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux internal error"))); errmsg("SELinux: failed to initialize labeling handle")));
PG_TRY(); PG_TRY();
{ {
/* /*

View File

@ -8,9 +8,12 @@
</indexterm> </indexterm>
<para> <para>
The <filename>sepgsql</> is a module which performs as an external <filename>sepgsql</> is a loadable module which supports label-based
security provider; to support label based mandatory access control mandatory access control (MAC) based on <productname>SELinux</> security
(MAC) base on <productname>SELinux</> policy. policy. This implementation is not complete, and primarily provides
protection for Data Manipulation Language statements (DML). Support for
fine-grained access control of Data Definition Language (DDL) and Data
Control Language (DCL) statements may be added in a future release.
</para> </para>
<para> <para>
This extension won't build at all unless the installation was configured This extension won't build at all unless the installation was configured
@ -21,59 +24,44 @@
<title>Overview</title> <title>Overview</title>
<para> <para>
<productname>PostgreSQL</> provides various kind of hooks. Some of these This module integrates with <productname>SELinux</> to provide an
hooks can be utilized to make access control decision on the supplied additional layer of security checking above and beyond what is normaly
users' accesses on database objects. provided by <productname>PostgreSQL</productname>. From the perspective of
We call plug-in modules making access control decision based on its own <productname>SELinux</>, this module allows
security model as an external security provider. <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 an additional to
the usual permissions checking performed by
<productname>PostgreSQL</productname>.
</para> </para>
<para> <para>
This module acquires control on these strategic points, then it asks <productname>SELinux</productname> access control decisions are made using
<productname>SELinux</> to check whether the supplied access shall be security labels, which are represented by strings such as
allowed, or not. Then, it returns its access control decision. <literal>system_u:object_r:sepgsql_table_t:s0</>. Each access control
If violated, this module prevents this access with rising an error for decision involves two labels: the label of the subject attempting to
example. 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 (e.g. 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>
<para> <para>
A series of making decision is done independently from the default The <xref linkend="sql-security-label"> statement allows assignment of
database privilege mechanism. Users must be allowed with both of access a security label to a database object.
control models, whenever they try to access something.
</para>
<para>
We can see <productname>SELinux</> as a function which takes two arguments
then returns a bool value; allowed or denied. The first argument in this
analogy is label of subject which tries to reference a certain obejct.
The other one is label of the object being referenced in this operation.
</para>
<para>
Label is a formatted string,
like <literal>system_u:object_r:sepgsql_table_t:s0</>.
It is not a property depending on characteristics of a certain kind of
object, so we can apply common credentials on either database objects
or others.
</para>
<para>
<productname>PostgreSQL</> 9.1 or later supports
<xref linkend="sql-security-label"> statement that allows to assign
a security label on specified database objects, if user wants to change
label from the creation default.
Also <productname>SELinux</> provides an interface to obtain security
label of the peer process that connected to.
</para>
<para>
These facilities enable to integrate <productname>SELinux</> model within
access controls to database objects. Because it makes access control
decision according to a common centralized security policy (a set of rules),
its decision will be always consistent independent from the way to store
information assets.
</para> </para>
</sect2> </sect2>
<sect2 id="sepgsql-installation"> <sect2 id="sepgsql-installation">
<title>Installation</title> <title>Installation</title>
<para> <para>
The <filename>sepgsql</> module requires the following packages to install. This module has several prerequisites.
Please check it at first.
</para> </para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><productname>Linux kernel</productname></term> <term><productname>Linux kernel</productname></term>
@ -103,14 +91,14 @@
</para> </para>
<para> <para>
The default security policy provides a set of access control rules. The default security policy provides a set of access control rules.
Some of distribution may backports necessary rules, even if base Some distributions may backport necessary rules to older policy versions.
policy was older than above version.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<para> <para>
<productname>SE-PostgreSQL</> needs <productname>SELinux</> being
<productname>sepgsql</> needs <productname>SELinux</> being
available on the platform. You can check the current setting using available on the platform. You can check the current setting using
<command>sestatus</>. <command>sestatus</>.
<screen> <screen>
@ -122,38 +110,41 @@ Mode from config file: enforcing
Policy version: 24 Policy version: 24
Policy from config file: targeted Policy from config file: targeted
</screen> </screen>
If disabled or not-installed, you need to set up <productname>SELinux</> If <productname>SELinux</> is disabled or not installed, you must set
prior to all the installation step of <productname>SE-PostgreSQL</>. that product up first before installing this module.
</para> </para>
<para> <para>
On the compile time, add <literal>--with-selinux</> option to At compile time, pass the <literal>--with-selinux</> option to
the <command>configure</> script to check existence of the <command>configure</> script to enable this module.
the <productname>libselinux</>, and to set a flag whether
we build this contrib module, or not.
<screen> <screen>
$ ./configure --enable-debug --enable-cassert --with-selinux $ ./configure --enable-debug --enable-cassert --with-selinux
$ make $ make
$ make install $ make install
</screen> </screen>
</para> </para>
<para>
Next to the <command>initdb</>, add <literal>'$libdir/sepgsql'</>
to <xref linkend="guc-shared-preload-libraries"> in
the <filename>postgresql.conf</>.
It enables to load <filename>sepgsql</> on the starting up of
postmaster process.
</para>
<para> <para>
Then, load the <filename>sepgsql.sql</filename> script for each databases. Following <command>initdb</>, add <literal>'$libdir/sepgsql'</>
It installs functions corresponding to security label management, and to <xref linkend="guc-shared-preload-libraries"> in
tries to assign initial labels on the target objects. the <filename>postgresql.conf</>. Note that <productname>sepgsql</>
must be loaded at server startup.
</para> </para>
<para>
Next, load the <filename>sepgsql.sql</filename> script for each database.
It installs functions for security label management, and attempts to assign
initial labels to the target objects.
</para>
<para> <para>
The following instruction assumes your installation is under the The following instruction assumes your installation is under the
<filename>/usr/local/pgsql</> directory, and the database cluster is in <filename>/usr/local/pgsql</> directory, and the database cluster is in
<filename>/usr/local/pgsql/data</>. Substitute your paths appropriately. <filename>/usr/local/pgsql/data</>. Adjust the paths shown below as
appropriate for your installaton.
</para> </para>
<screen> <screen>
$ initdb -D $PGDATA $ initdb -D $PGDATA
$ vi $PGDATA/postgresql.conf $ vi $PGDATA/postgresql.conf
@ -162,34 +153,32 @@ $ for DBNAME in template0 template1 postgres; do
< /usr/local/pgsql/share/contrib/sepgsql.sql > /dev/null < /usr/local/pgsql/share/contrib/sepgsql.sql > /dev/null
done done
</screen> </screen>
<para> <para>
If all the installation process was done with no errors, start postmaster If the installation process completes without error, you can now start the
process. <productname>SE-PostgreSQL</> shall prevent violated accesses server normally.
according to the security policy of <productname>SELinux</>.
</para> </para>
</sect2> </sect2>
<sect2 id="sepgsql-regression"> <sect2 id="sepgsql-regression">
<title>Regression Tests</title> <title>Regression Tests</title>
<para> <para>
The regression test of this module requires a few more configurations Due to the nature of <productname>SELinux</productname>, running the
on the platform system, in addition to the above installation process. regression tests for this module requires several additional configuration
See the following steps. steps.
</para> </para>
<para> <para>
First, install the policy package for regression test. First, install the policy package for the regression test.
The <filename>sepgsql-regtest.pp</> is a special purpose policy package The <filename>sepgsql-regtest.pp</> is a special purpose policy package
that provides a set of rules to be allowed during the regression test which provides a set of rules to be allowed during the regression tests.
cases. It shall be installed at <filename>/usr/local/pgsql/share/contrib</> You need to install this policy package using the <command>semodule</>
directory in the default setup. command, which links supplied policy packages and loads them
</para> into the kernel space. If this packages is correctly installed,
<para> <literal><command>semodule</> -l</> should list sepgsql-regtest as an
You need to install this policy package using <command>semodule</> available policy package.
command which enables to link supplied policy packages and load them
into the kernel space. If you could install the pakage correctly,
<literal><command>semodule</> -l</> prints sepgsql-regtest as a part
of policy packages currently available.
</para> </para>
<screen> <screen>
$ su $ su
# semodule -u /usr/local/pgsql/share/contrib/sepgsql-regtest.pp # semodule -u /usr/local/pgsql/share/contrib/sepgsql-regtest.pp
@ -198,78 +187,50 @@ $ su
sepgsql-regtest 1.03 sepgsql-regtest 1.03
: :
</screen> </screen>
<para> <para>
Second, turn on the <literal>sepgsql_regression_test_mode</>. Second, turn on <literal>sepgsql_regression_test_mode</>.
We don't enable all the rules in the <filename>sepgsql-regtest.pp</> We don't enable all the rules in the <filename>sepgsql-regtest.pp</>
in the default, for your system's safety. by default, for your system's safety.
The <literal>sepgsql_regression_test_mode</literal> parameter is associated The <literal>sepgsql_regression_test_mode</literal> parameter is associated
with rules to launch regression test. with rules to launch regression test.
It can be turned on using <command>setsebool</> command. It can be turned on using <command>setsebool</> command.
</para> </para>
<screen> <screen>
$ su $ su
# setsebool sepgsql_regression_test_mode on # setsebool sepgsql_regression_test_mode on
# getsebool sepgsql_regression_test_mode # getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on sepgsql_regression_test_mode --> on
</screen> </screen>
<para> <para>
Last, kick the regression test from the <literal>unconfined_t</> domain. Last, kick the regression test from the <literal>unconfined_t</> domain.
</para> </para>
<para>
This test policy is designed to kick each test cases from the
<literal>unconfined_t</> domain that is a default choice in most of
the known <literal>SELinux</> installation base.
So, you don't need to set up anything special, as long as you didn't
change default configuration of SELinux before.
</para>
<para> <para>
The <command>id</> command tells us the current working domain. The <command>id</> command tells us the current working domain.
Confirm your shell is now performing with <literal>unconfined_t</> Confirm your shell is now performing with the <literal>unconfined_t</>
domain as follows. domain as follows.
</para> </para>
<screen> <screen>
$ id -Z $ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
</screen> </screen>
<para>
If not an expected one, you should revert this configuration.
The <xref linkend="sepgsql-resources"> section will give you
some useful hints.
</para>
<para>
Then, you will see the all-green result of regression test,
if we have no problem here.
</para>
<screen>
$ make -C contrib/sepgsql/ installcheck
:
../../src/test/regress/pg_regress --inputdir=. --psqldir=/usr/local/pgsql/bin \
--dbname=contrib_regression --launcher ../../contrib/sepgsql/launcher \
label dml
(using postmaster on Unix socket, default port)
============== dropping database "contrib_regression" ==============
DROP DATABASE
============== creating database "contrib_regression" ==============
CREATE DATABASE
ALTER DATABASE
============== running regression test queries ==============
test label ... ok
test dml ... ok
test misc ... ok
=====================
All 3 tests passed.
=====================
</screen>
<para> <para>
If <command>pg_regress</> failed to launch <command>psql</> command, See <xref linkend="sepgsql-resources"> for details on adjusting your
here is a hint to fix up the matter. working domain, if necessary.
When we try to launch <command>psql</> command with restrictive
privileges, the <command>psql</> must eb labeled as <literal>bin_t</>.
If not, try to run <command>restorecon</> to fix up security label of
the commands as expected.
</para> </para>
<para>
If <command>pg_regress</> fails to launch the <command>psql</> command,
you may need to ensure that the <command>psql</> command is labeled
as <literal>bin_t</>. If it is not, the <command>restorecon</> command can
often be used to fix up security labels within the
<productname>PostgreSQL</productname> installation directory.
</para>
<screen> <screen>
$ restorecon -R /usr/local/pgsql/ $ restorecon -R /usr/local/pgsql/
</screen> </screen>
@ -286,28 +247,20 @@ $ restorecon -R /usr/local/pgsql/
</indexterm> </indexterm>
<listitem> <listitem>
<para> <para>
This parameter enables to perform <productname>SE-PostgreSQL</> This parameter enables <productname>SE-PostgreSQL</> to function
in permissive mode independent from the system setting. in permissive mode, regardless of the system setting.
The default is off (according to the system setting). The default is off.
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
</para> </para>
<para> <para>
We have two performing mode except for disabled; The one is enforcing When this parameter is on, <productname>SE-PostgreSQL</> functions
mode that checks the security policy on references and actually prevents in permissive mode, even if the platform system is working in enforcing
violated accesses. The other is permissive mode that only checks mode. This parameter is primarily useful for testing purposes.
the security policy, but does not prevents anything except for log
generation.
This log shall be utilized for debugging of the security policy itself.
</para>
<para>
When this parameter is on, <productname>SE-PostgreSQL</> performs
in permissive mode, even if the platform system is working on enforcing
mode.
We recommend users to keep the default setting, except for the case
when we develop security policy by ourself.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-sepgsql-debug-audit" xreflabel="sepgsql.debug_audit"> <varlistentry id="guc-sepgsql-debug-audit" xreflabel="sepgsql.debug_audit">
<term><varname>sepgsql.debug_audit</> (<type>boolean</>)</> <term><varname>sepgsql.debug_audit</> (<type>boolean</>)</>
@ -316,21 +269,21 @@ $ restorecon -R /usr/local/pgsql/
</indexterm> </indexterm>
<listitem> <listitem>
<para> <para>
This parameter enables to print audit messages independent from This parameter enables the printing of audit messages independent from
the policy setting. the policy setting.
The default is off (according to the security policy setting). The default is off (according to the security policy setting).
</para> </para>
<para> <para>
The security policy of <productname>SELinux</> also has rules to The security policy of <productname>SELinux</> also has rules to
control what accesses shall be logged, or not. control whether or not particular accesses are logged.
In the default, any access violations are logged, but any allowed By default, access violations are logged, but allowed
accesses are not logged. accesses are not.
</para> </para>
<para> <para>
When this parameter is on, all the possible logs shall be printed This parameter forces all possible logging to be turned on, regardless
independently from the policy settings. of the system policy.
We recommend to keep the variable turned off in normal cases to
avoid noisy messages.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -344,48 +297,35 @@ $ restorecon -R /usr/local/pgsql/
<para> <para>
The security model of <productname>SELinux</> describes all the access The security model of <productname>SELinux</> describes all the access
control rules as a relationship between a subject entity (typically, control rules as a relationship between a subject entity (typically,
it is a client of database) and an object entity. it is a client of database) and an object entity, each of which is
And, these entities are identified by a security label. identified by a security label. If access to an unlabelled object is
attempted, the object is treated as if it were assigned the label
<literal>unlabeled_t</>.
</para> </para>
<para> <para>
We call a set of these rules as security policy. Currently, <productname>sepgsql</productname> allows security labels to be
All the access control decision shall be made according to the security assigned to schemas, tables, columns, sequences, views, and functions.
policy, when we ask SELinux whether the required action shall be allowed When <productname>sepgsql</productname> is in use, security labels are
or not. automatically assigned to suppoted database objects at creation time.
Thus, we have no way to control accesses on any sort of objects without This label is called as a default security label, being decided according
security labels. to the system security policy, which takes as input the creator's label
(<productname>SELinux</> assumes <literal>unlabeled_t</> is assigned, and the label assigned to the new object's parent object.
if no valid security label is assigned on the target object.)
</para> </para>
<para> <para>
This version of <productname>SE-PostgreSQL</> supports to assign A new database object basically inherits security label of the parent
a security label on these database object classes: schema, table, column, object, except when the security policy has special rules known as
sequence, view and procedure. type-transition rules, in which case a different label may be applied.
Other database object classes are not supported to assign security label The meaning of the term "parent object" varies by object class, as follows.
on, right now.
</para>
<para>
A security label shall be automatically assigned to the supported
database objects on their creation time.
This label is called as a default security label; being decided according
to the security policy, or a pair of security label of the client and
upper object for more correctly.
</para>
<para>
A new database object basically inherits security label of the upper
object. A new column inherits security label of its parent table for
instance.
If and when the security policy has special rules called as
type-transition on a pair of the client and upper object, we can assign
an individual label as a default. The upper object depends on sort of
object classes as follows.
</para> </para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term>schema</term> <term>schema</term>
<listitem> <listitem>
<para> <para>
Its upper object is the current database. The parent object is the current database.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -393,7 +333,7 @@ $ restorecon -R /usr/local/pgsql/
<term>table</term> <term>table</term>
<listitem> <listitem>
<para> <para>
Its upper object is the schema object which owns the new table. The parent object is the containing schema.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -401,7 +341,7 @@ $ restorecon -R /usr/local/pgsql/
<term>column</term> <term>column</term>
<listitem> <listitem>
<para> <para>
Its upper object is the table object which owns the new column. The parent object is the table.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -409,7 +349,7 @@ $ restorecon -R /usr/local/pgsql/
<term>sequence</term> <term>sequence</term>
<listitem> <listitem>
<para> <para>
Its upper object is the schema object which owns the new sequence. The parent object is the containing schema.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -417,15 +357,15 @@ $ restorecon -R /usr/local/pgsql/
<term>view</term> <term>view</term>
<listitem> <listitem>
<para> <para>
Its upper object is the schema object which owns the new view. The parent object is the containing schema.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>procedure</term> <term>function</term>
<listitem> <listitem>
<para> <para>
Its upper object is the schema object which owns the new procedure. Its parent object is the containing schema.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -433,56 +373,62 @@ $ restorecon -R /usr/local/pgsql/
</sect3> </sect3>
<sect3> <sect3>
<title>DML Permissions</title> <title>DML Permissions</title>
<para> <para>
This section introduces what permissions shall be checked on DML; This section introduces what permissions shall be checked on DML;
<literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</> and <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</> and
<literal>DELETE</>. <literal>DELETE</>.
</para> </para>
<para> <para>
DML statements are used to reference or modify contents within DML statements are used to reference or modify contents within
the specified database objects; such as tables or columns. the specified database objects; such as tables or columns.
We basically checks access rights of the client on all the appeared We basically checks access rights of the client on all the objects
objects in the given statement, and kind of privileges depend on mentioned in the given statement, and the kind of privileges checked
class of object and sort of accesses. depend on the class of the object and the type of access.
</para> </para>
<para> <para>
For tables, <literal>db_table:select</>, <literal>db_table:insert</>, For tables, <literal>db_table:select</>, <literal>db_table:insert</>,
<literal>db_table:update</> or <literal>db_table:delete</> shall be <literal>db_table:update</> or <literal>db_table:delete</> is
checked for all the appeared target tables depending on the sort of checked for all the appeared target tables depending on the sort of
statement; statement;
In addition, <literal>db_table:select</> shall be also checked for in addition, <literal>db_table:select</> is also checked for
all the tables that containin the columns to be referenced in all the tables that containin the columns to be referenced in
<literal>WHERE</> or <literal>RETURNING</> clause, as a data source <literal>WHERE</> or <literal>RETURNING</> clause, as a data source
of <literal>UPDATE</>, and so on. of <literal>UPDATE</>, and so on.
</para> </para>
<para> <para>
<synopsis> <synopsis>
UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100; UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
</synopsis> </synopsis>
In this case, we must have <literal>db_table:select</>, not only In this case, we must have <literal>db_table:select</>, not only
<literal>db_table:update</>, because <literal>t1.a</> is referenced <literal>db_table:update</>, because <literal>t1.a</> is referenced
within <literal>WHERE</> clause. within <literal>WHERE</> clause. Column-level permissions will be
Also note that column-level permission shall be checked individually. checked as well, for each referenced column.
</para> </para>
<para> <para>
The client must be allowed to reference all the appeared tables and The client must be allowed to reference all the appeared tables and
columns, even if they are originated from views then expanded, unlike columns, even if they are originated from views then expanded, because we
the default database privileges, because we intend to apply consistent intend to apply consistent access control rules independent from the
access control rules independent from the route to reference contents manner in which the table contents are referenced.
of the tables.
</para> </para>
<para> <para>
For columns, <literal>db_column:select</> shall be also checked on For columns, <literal>db_column:select</> is checked on
not only the columns being read using <literal>SELECT</>, but being not only the columns being read using <literal>SELECT</>, but being
referenced in other DML statement. referenced in other DML statement.
</para> </para>
<para> <para>
Of course, it also checks <literal>db_column:update</> or Of course, it also checks <literal>db_column:update</> or
<literal>db_column:insert</> on the column being modified by <literal>db_column:insert</> on the column being modified by
<literal>UPDATE</> or <literal>INSERT</>. <literal>UPDATE</> or <literal>INSERT</>.
Note that we have no definition of column-level delete permission,
like as the default database privilege doing.
</para> </para>
<para> <para>
<synopsis> <synopsis>
UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100; UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
@ -495,31 +441,35 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
Also note that <literal>db_table:{select update}</> shall be checked Also note that <literal>db_table:{select update}</> shall be checked
in the table-level granularity. in the table-level granularity.
</para> </para>
<para> <para>
For sequences, <literal>db_sequence:get_value</> when we reference For sequences, <literal>db_sequence:get_value</> when we reference
a sequence object using <literal>SELECT</>, however, note that we a sequence object using <literal>SELECT</>; however, note that we
cannot check permissions on execution of corresponding functions cannot check permissions on execution of corresponding functions
such as <literal>lastval()</> right now, although they performs same such as <literal>lastval()</> right now, although they performs same
job, because here is no object access hook to acquire controls. job, because here is no object access hook to acquire controls.
</para> </para>
<para> <para>
For views, <literal>db_view:expand</> shall be checked, then any other For views, <literal>db_view:expand</> shall be checked, then any other
corresponding permissions shall be also checked on the objects being corresponding permissions shall be also checked on the objects being
expanded from the view, individually. expanded from the view, individually.
Note that both of permissions have to be allowed.
</para> </para>
<para> <para>
For procedures, <literal>db_procedure:{execute}</> is defined, but not For functions, <literal>db_procedure:{execute}</> is defined, but not
checked in this version. checked in this version.
</para> </para>
<para> <para>
Here is a few more corner cases. Here is a few more corner cases.
The default database privilege system allows database superusers to The default database privilege system allows database superusers to
modify system catalogs using DML commands, and reference or modify modify system catalogs using DML commands, and reference or modify
toast tables, however, both of the cases shall be denied when toast tables. These operations are prohibited when
<productname>SE-PostgreSQL</> is enabled. <productname>sepgsql</> is enabled.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title>DDL Permissions</title> <title>DDL Permissions</title>
<para> <para>
@ -528,17 +478,15 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
with an old security label, then <literal>relabelto</> on the supplied with an old security label, then <literal>relabelto</> on the supplied
new security label. new security label.
</para> </para>
<para> <para>
In a case when multiple label providers are installed and user tries In a case when multiple label providers are installed and user tries
to set a security label, but is not managed by <productname>SELinux</>, to set a security label, but is not managed by <productname>SELinux</>,
only <literal>setattr</> should be checked here. only <literal>setattr</> should be checked here.
However, it is not unavailable because of limitation of the hook. This is currently not done due to implementation restrictions.
</para>
<para>
As we will describe in <xref linkend="sepgsql-limitations"> section,
<productname>SE-PostgreSQL</> does not control any other DDL operations.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title>Trusted Procedure</title> <title>Trusted Procedure</title>
<para> <para>
@ -548,6 +496,7 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
for more correctness) during execution of certain functions; being for more correctness) during execution of certain functions; being
called as trusted procedures. called as trusted procedures.
</para> </para>
<para> <para>
A trusted function is a function with a special security label being A trusted function is a function with a special security label being
set up as a trusted procedure. set up as a trusted procedure.
@ -556,6 +505,7 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
The default security policy also provides this special security label. The default security policy also provides this special security label.
See the following example. See the following example.
</para> </para>
<screen> <screen>
postgres=# CREATE TABLE customer ( postgres=# CREATE TABLE customer (
cid int primary key, cid int primary key,
@ -575,9 +525,11 @@ postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'; IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL SECURITY LABEL
</screen> </screen>
<para> <para>
Above operations shall be done by administrative users. Above operations shall be done by administrative users.
</para> </para>
<screen> <screen>
postgres=# SELECT * FROM customer; postgres=# SELECT * FROM customer;
ERROR: SELinux: security policy violation ERROR: SELinux: security policy violation
@ -588,71 +540,71 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
2 | hanako | 5555-6666-7777-xxxx 2 | hanako | 5555-6666-7777-xxxx
(2 rows) (2 rows)
</screen> </screen>
<para> <para>
In this case, a regular user cannot reference <literal>customer.credit</> In this case, a regular user cannot reference <literal>customer.credit</>
directly, but a trusted procedure <literal>show_credit</> enables us directly, but a trusted procedure <literal>show_credit</> enables us
to print credit number of customers with a bit modification. to print credit number of customers with a bit modification.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title>Miscellaneous</title> <title>Miscellaneous</title>
<para> <para>
In this version, we reject <xref linkend="sql-load"> command across In this version, we reject <xref linkend="sql-load"> command across
the board, because the binary module can override security hooks to the board, because any module loaded could easily circumvent security
make access control decision. It means a risk to invalidate all the policy enforcement.
control by security providers.
</para> </para>
</sect3> </sect3>
</sect2> </sect2>
<sect2 id="sepgsql-limitations"> <sect2 id="sepgsql-limitations">
<title>Limitations</title> <title>Limitations</title>
<para>
This section introduces limitations of <productname>SE-PostgreSQL</>
in this version.
</para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term>Userspace access vector cache</term> <term>Userspace access vector cache</term>
<listitem> <listitem>
<para> <para>
<productname>SE-PostgreSQL</> tells <productname>SELinux</> its access <productname>sepgsql</> does not yet support an access vector cache.
control decision. It takes system call invocation being heavy, however, This would likely improve performance.
we can reduce number of the invocations using caching mechanism; called
as access vector cache in <productname>SELinux</>.
Because of code size, <productname>SE-PostgreSQL</> does not support
this mechanism yet.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>DDL Permissions</term> <term>Data Definition Language (DDL) Permissions</term>
<listitem> <listitem>
<para> <para>
Now <productname>PostgreSQL</> does not provide a set of hooks on Due to implementation restrictions, DDL permissions are not checked.
the DDL routines.
It means plugin modules cannot acquire control here,
so <productname>SE-PostgreSQL</> does not check DDL Permissions
right now.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>Data Control Language (DCL) Permissions</term>
<listitem>
<para>
Due to implementation restrictions, DCL permissions are not checked.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>Row-level access control</term> <term>Row-level access control</term>
<listitem> <listitem>
<para> <para>
Now <productname>SE-PostgreSQL</> does not support row-level access <productname>PostgreSQL</> does not support row-level access; therefore,
control, because a few needed facilities are not supported yet. <productname>sepgsql</productname> does not support it either.
The one is security labels on users' tables. The other is behavior of
optimizer. Also see <xref linkend="rules-privileges"> for more details.
We know similar issue on VIEW.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>Covert channels</term> <term>Covert channels</term>
<listitem> <listitem>
<para> <para>
<productname>SE-PostgreSQL</> never tries to hide existence of <productname>sepgsql</> never tries to hide existence of
a certain object, even if user is not allowed to reference. a certain object, even if user is not allowed to reference.
For example, we can infer an existence of invisible object using For example, we can infer an existence of invisible object using
primary-key confliction, foreign-key violation, and so on, even if primary-key confliction, foreign-key violation, and so on, even if
@ -662,6 +614,7 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>
<sect2 id="sepgsql-resources"> <sect2 id="sepgsql-resources">
<title>External Resources</title> <title>External Resources</title>
<variablelist> <variablelist>
@ -678,9 +631,9 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
<term><ulink url="http://docs.fedoraproject.org/selinux-user-guide/">Fedora SELinux User Guide</ulink></term> <term><ulink url="http://docs.fedoraproject.org/selinux-user-guide/">Fedora SELinux User Guide</ulink></term>
<listitem> <listitem>
<para> <para>
This document provides wide spectrum of knowledge to administrate This document provides wide spectrum of knowledge to administer
SELinux on your systems. <productname>SELinux</> on your systems.
It primary focuses on Fedora, but not limited to Fedora. It primary focuses on Fedora, but is not limited to Fedora.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -688,13 +641,15 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
<term><ulink url="http://docs.fedoraproject.org/selinux-faq">Fedora SELinux FAQ</ulink></term> <term><ulink url="http://docs.fedoraproject.org/selinux-faq">Fedora SELinux FAQ</ulink></term>
<listitem> <listitem>
<para> <para>
This document provides FAQs about SELinux. This document answers frequently asked questins about
It primary focuses on Fedora, but not limited to Fedora. <productname>SELinux</productname>.
It primary focuses on Fedora, but is not limited to Fedora.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>
<sect2 id="sepgsql-author"> <sect2 id="sepgsql-author">
<title>Author</title> <title>Author</title>
<para> <para>