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-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)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("selinux: hardwired security policy violation")));
errmsg("SELinux: hardwired security policy violation")));
if (relkind == RELKIND_TOASTVALUE)
ereport(ERROR,
(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)
ereport(FATAL,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("selinux: failed to get the peer label")));
errmsg("SELinux: unable to get peer label")));
sepgsql_set_client_label(context);
@ -318,7 +318,7 @@ sepgsql_utility_command(Node *parsetree,
{
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("SELinux: LOAD is not allowed anyway.")));
errmsg("SELinux: LOAD is not permitted")));
}
break;
default:
@ -352,8 +352,8 @@ _PG_init(void)
*/
if (IsUnderPostmaster)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Not allowed to load SE-PostgreSQL now")));
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("sepgsql must be loaded via shared_preload_libraries")));
/*
* Check availability of SELinux on the platform.
@ -414,7 +414,7 @@ _PG_init(void)
if (getcon_raw(&context) < 0)
ereport(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);
/* 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)
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("selinux: unable to get initial security label")));
errmsg("SELinux: failed to get initial security label")));
PG_TRY();
{
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)
ereport(ERROR,
(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
*/
@ -154,13 +154,11 @@ sepgsql_getcon(PG_FUNCTION_ARGS)
char *client_label;
if (!sepgsql_is_enabled())
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELinux: now disabled")));
PG_RETURN_NULL();
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())
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELinux: now disabled")));
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("sepgsql is not enabled")));
if (selinux_trans_to_raw_context(text_to_cstring(label),
&raw_label) < 0)
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux: internal error on mcstrans")));
errmsg("SELinux: could not translate security label")));
PG_TRY();
{
@ -200,7 +198,7 @@ sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
PG_END_TRY();
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())
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELinux: now disabled")));
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("sepgsql is not currently enabled")));
if (selinux_raw_to_trans_context(text_to_cstring(label),
&qual_label) < 0)
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux: internal error on mcstrans")));
errmsg("SELinux: could not translate security label")));
PG_TRY();
{
@ -240,7 +238,7 @@ sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
PG_END_TRY();
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;
default:
elog(ERROR, "Bug? %u is not supported to set initial labels",
catalogId);
elog(ERROR, "unexpected catalog id: %u", catalogId);
break;
}
@ -387,12 +384,12 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
}
else if (errno == ENOENT)
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)));
else
ereport(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);
@ -422,8 +419,8 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
*/
if (!sepgsql_is_enabled())
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELinux: now disabled")));
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("sepgsql is not currently enabled")));
/*
* Check DAC permission. Only superuser can set up initial
* security labels, like root-user in filesystems
@ -431,7 +428,7 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
if (!superuser())
ereport(ERROR,
(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
@ -452,7 +449,7 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
if (!sehnd)
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux internal error")));
errmsg("SELinux: failed to initialize labeling handle")));
PG_TRY();
{
/*

View File

@ -8,9 +8,12 @@
</indexterm>
<para>
The <filename>sepgsql</> is a module which performs as an external
security provider; to support label based mandatory access control
(MAC) base on <productname>SELinux</> policy.
<filename>sepgsql</> is a loadable module which supports label-based
mandatory access control (MAC) based on <productname>SELinux</> security
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>
This extension won't build at all unless the installation was configured
@ -21,59 +24,44 @@
<title>Overview</title>
<para>
<productname>PostgreSQL</> provides various kind of hooks. Some of these
hooks can be utilized to make access control decision on the supplied
users' accesses on database objects.
We call plug-in modules making access control decision based on its own
security model as an external security provider.
This module integrates with <productname>SELinux</> to provide an
additional layer of security checking above and beyond what is normaly
provided by <productname>PostgreSQL</productname>. From the perspective of
<productname>SELinux</>, 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 an additional to
the usual permissions checking performed by
<productname>PostgreSQL</productname>.
</para>
<para>
This module acquires control on these strategic points, then it asks
<productname>SELinux</> to check whether the supplied access shall be
allowed, or not. Then, it returns its access control decision.
If violated, this module prevents this access with rising an error for
example.
<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</>. 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 (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>
A series of making decision is done independently from the default
database privilege mechanism. Users must be allowed with both of access
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.
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>
The <filename>sepgsql</> module requires the following packages to install.
Please check it at first.
This module has several prerequisites.
</para>
<variablelist>
<varlistentry>
<term><productname>Linux kernel</productname></term>
@ -103,14 +91,14 @@
</para>
<para>
The default security policy provides a set of access control rules.
Some of distribution may backports necessary rules, even if base
policy was older than above version.
Some distributions may backport necessary rules to older policy versions.
</para>
</listitem>
</varlistentry>
</variablelist>
<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
<command>sestatus</>.
<screen>
@ -122,38 +110,41 @@ Mode from config file: enforcing
Policy version: 24
Policy from config file: targeted
</screen>
If disabled or not-installed, you need to set up <productname>SELinux</>
prior to all the installation step of <productname>SE-PostgreSQL</>.
If <productname>SELinux</> is disabled or not installed, you must set
that product up first before installing this module.
</para>
<para>
On the compile time, add <literal>--with-selinux</> option to
the <command>configure</> script to check existence of
the <productname>libselinux</>, and to set a flag whether
we build this contrib module, or not.
At compile time, pass the <literal>--with-selinux</> option to
the <command>configure</> script to enable this module.
<screen>
$ ./configure --enable-debug --enable-cassert --with-selinux
$ make
$ make install
</screen>
</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>
Then, load the <filename>sepgsql.sql</filename> script for each databases.
It installs functions corresponding to security label management, and
tries to assign initial labels on the target objects.
Following <command>initdb</>, add <literal>'$libdir/sepgsql'</>
to <xref linkend="guc-shared-preload-libraries"> in
the <filename>postgresql.conf</>. Note that <productname>sepgsql</>
must be loaded at server startup.
</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>
The following instruction assumes your installation is under the
<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>
<screen>
$ initdb -D $PGDATA
$ vi $PGDATA/postgresql.conf
@ -162,34 +153,32 @@ $ for DBNAME in template0 template1 postgres; do
< /usr/local/pgsql/share/contrib/sepgsql.sql > /dev/null
done
</screen>
<para>
If all the installation process was done with no errors, start postmaster
process. <productname>SE-PostgreSQL</> shall prevent violated accesses
according to the security policy of <productname>SELinux</>.
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>
The regression test of this module requires a few more configurations
on the platform system, in addition to the above installation process.
See the following steps.
Due to the nature of <productname>SELinux</productname>, running the
regression tests for this module requires several additional configuration
steps.
</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
that provides a set of rules to be allowed during the regression test
cases. It shall be installed at <filename>/usr/local/pgsql/share/contrib</>
directory in the default setup.
</para>
<para>
You need to install this policy package using <command>semodule</>
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.
which provides a set of rules to be allowed during the regression tests.
You need to install this policy package using the <command>semodule</>
command, which links supplied policy packages and loads them
into the kernel space. If this packages is correctly installed,
<literal><command>semodule</> -l</> should list sepgsql-regtest as an
available policy package.
</para>
<screen>
$ su
# semodule -u /usr/local/pgsql/share/contrib/sepgsql-regtest.pp
@ -198,78 +187,50 @@ $ su
sepgsql-regtest 1.03
:
</screen>
<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</>
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
with rules to launch regression test.
It can be turned on using <command>setsebool</> command.
</para>
<screen>
$ su
# setsebool sepgsql_regression_test_mode on
# getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on
</screen>
<para>
Last, kick the regression test from the <literal>unconfined_t</> domain.
</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>
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.
</para>
<screen>
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
</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>
If <command>pg_regress</> failed to launch <command>psql</> command,
here is a hint to fix up the matter.
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.
See <xref linkend="sepgsql-resources"> for details on adjusting your
working domain, if necessary.
</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>
$ restorecon -R /usr/local/pgsql/
</screen>
@ -286,28 +247,20 @@ $ restorecon -R /usr/local/pgsql/
</indexterm>
<listitem>
<para>
This parameter enables to perform <productname>SE-PostgreSQL</>
in permissive mode independent from the system setting.
The default is off (according to the system setting).
This parameter enables <productname>SE-PostgreSQL</> 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</>
file or on the server command line.
</para>
<para>
We have two performing mode except for disabled; The one is enforcing
mode that checks the security policy on references and actually prevents
violated accesses. The other is permissive mode that only checks
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.
When this parameter is on, <productname>SE-PostgreSQL</> functions
in permissive mode, even if the platform system 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</> (<type>boolean</>)</>
@ -316,21 +269,21 @@ $ restorecon -R /usr/local/pgsql/
</indexterm>
<listitem>
<para>
This parameter enables to print audit messages independent from
This parameter enables the printing of audit messages independent from
the policy setting.
The default is off (according to the security policy setting).
</para>
<para>
The security policy of <productname>SELinux</> also has rules to
control what accesses shall be logged, or not.
In the default, any access violations are logged, but any allowed
accesses are not logged.
control whether or not particular accesses are logged.
By default, access violations are logged, but allowed
accesses are not.
</para>
<para>
When this parameter is on, all the possible logs shall be printed
independently from the policy settings.
We recommend to keep the variable turned off in normal cases to
avoid noisy messages.
This parameter forces all possible logging to be turned on, regardless
of the system policy.
</para>
</listitem>
</varlistentry>
@ -344,48 +297,35 @@ $ restorecon -R /usr/local/pgsql/
<para>
The security model of <productname>SELinux</> describes all the access
control rules as a relationship between a subject entity (typically,
it is a client of database) and an object entity.
And, these entities are identified by a security label.
it is a client of database) and an object entity, each of which is
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>
We call a set of these rules as security policy.
All the access control decision shall be made according to the security
policy, when we ask SELinux whether the required action shall be allowed
or not.
Thus, we have no way to control accesses on any sort of objects without
security labels.
(<productname>SELinux</> assumes <literal>unlabeled_t</> is assigned,
if no valid security label is assigned on the target object.)
Currently, <productname>sepgsql</productname> allows security labels to be
assigned to schemas, tables, columns, sequences, views, and functions.
When <productname>sepgsql</productname> is in use, security labels are
automatically assigned to suppoted database objects at creation time.
This label is called as a default security label, being decided according
to the system security policy, which takes as input the creator's label
and the label assigned to the new object's parent object.
</para>
<para>
This version of <productname>SE-PostgreSQL</> supports to assign
a security label on these database object classes: schema, table, column,
sequence, view and procedure.
Other database object classes are not supported to assign security label
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.
A new database object basically inherits 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.
The meaning of the term "parent object" varies by object class, as follows.
</para>
<variablelist>
<varlistentry>
<term>schema</term>
<listitem>
<para>
Its upper object is the current database.
The parent object is the current database.
</para>
</listitem>
</varlistentry>
@ -393,7 +333,7 @@ $ restorecon -R /usr/local/pgsql/
<term>table</term>
<listitem>
<para>
Its upper object is the schema object which owns the new table.
The parent object is the containing schema.
</para>
</listitem>
</varlistentry>
@ -401,7 +341,7 @@ $ restorecon -R /usr/local/pgsql/
<term>column</term>
<listitem>
<para>
Its upper object is the table object which owns the new column.
The parent object is the table.
</para>
</listitem>
</varlistentry>
@ -409,7 +349,7 @@ $ restorecon -R /usr/local/pgsql/
<term>sequence</term>
<listitem>
<para>
Its upper object is the schema object which owns the new sequence.
The parent object is the containing schema.
</para>
</listitem>
</varlistentry>
@ -417,15 +357,15 @@ $ restorecon -R /usr/local/pgsql/
<term>view</term>
<listitem>
<para>
Its upper object is the schema object which owns the new view.
The parent object is the containing schema.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>procedure</term>
<term>function</term>
<listitem>
<para>
Its upper object is the schema object which owns the new procedure.
Its parent object is the containing schema.
</para>
</listitem>
</varlistentry>
@ -433,56 +373,62 @@ $ restorecon -R /usr/local/pgsql/
</sect3>
<sect3>
<title>DML Permissions</title>
<para>
This section introduces what permissions shall be checked on DML;
<literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</> and
<literal>DELETE</>.
</para>
<para>
DML statements are used to reference or modify contents within
the specified database objects; such as tables or columns.
We basically checks access rights of the client on all the appeared
objects in the given statement, and kind of privileges depend on
class of object and sort of accesses.
We basically checks access rights of the client on all the objects
mentioned in the given statement, and the kind of privileges checked
depend on the class of the object and the type of access.
</para>
<para>
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
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
<literal>WHERE</> or <literal>RETURNING</> clause, as a data source
of <literal>UPDATE</>, and so on.
</para>
<para>
<synopsis>
UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
</synopsis>
In this case, we must have <literal>db_table:select</>, not only
<literal>db_table:update</>, because <literal>t1.a</> is referenced
within <literal>WHERE</> clause.
Also note that column-level permission shall be checked individually.
within <literal>WHERE</> clause. Column-level permissions will be
checked as well, for each referenced column.
</para>
<para>
The client must be allowed to reference all the appeared tables and
columns, even if they are originated from views then expanded, unlike
the default database privileges, because we intend to apply consistent
access control rules independent from the route to reference contents
of the tables.
columns, even if they are originated from views then expanded, because we
intend to apply consistent access control rules independent from the
manner in which the table contents are referenced.
</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
referenced in other DML statement.
</para>
<para>
Of course, it also checks <literal>db_column:update</> or
<literal>db_column:insert</> on the column being modified by
<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>
<synopsis>
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
in the table-level granularity.
</para>
<para>
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
such as <literal>lastval()</> right now, although they performs same
job, because here is no object access hook to acquire controls.
</para>
<para>
For views, <literal>db_view:expand</> shall be checked, then any other
corresponding permissions shall be also checked on the objects being
expanded from the view, individually.
Note that both of permissions have to be allowed.
</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.
</para>
<para>
Here is a few more corner cases.
The default database privilege system allows database superusers to
modify system catalogs using DML commands, and reference or modify
toast tables, however, both of the cases shall be denied when
<productname>SE-PostgreSQL</> is enabled.
toast tables. These operations are prohibited when
<productname>sepgsql</> is enabled.
</para>
</sect3>
<sect3>
<title>DDL Permissions</title>
<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
new security label.
</para>
<para>
In a case when multiple label providers are installed and user tries
to set a security label, but is not managed by <productname>SELinux</>,
only <literal>setattr</> should be checked here.
However, it is not unavailable because of limitation of the hook.
</para>
<para>
As we will describe in <xref linkend="sepgsql-limitations"> section,
<productname>SE-PostgreSQL</> does not control any other DDL operations.
This is currently not done due to implementation restrictions.
</para>
</sect3>
<sect3>
<title>Trusted Procedure</title>
<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
called as trusted procedures.
</para>
<para>
A trusted function is a function with a special security label being
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.
See the following example.
</para>
<screen>
postgres=# CREATE TABLE customer (
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';
SECURITY LABEL
</screen>
<para>
Above operations shall be done by administrative users.
</para>
<screen>
postgres=# SELECT * FROM customer;
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 rows)
</screen>
<para>
In this case, a regular user cannot reference <literal>customer.credit</>
directly, but a trusted procedure <literal>show_credit</> enables us
to print credit number of customers with a bit modification.
</para>
</sect3>
<sect3>
<title>Miscellaneous</title>
<para>
In this version, we reject <xref linkend="sql-load"> command across
the board, because the binary module can override security hooks to
make access control decision. It means a risk to invalidate all the
control by security providers.
the board, because any module loaded could easily circumvent security
policy enforcement.
</para>
</sect3>
</sect2>
<sect2 id="sepgsql-limitations">
<title>Limitations</title>
<para>
This section introduces limitations of <productname>SE-PostgreSQL</>
in this version.
</para>
<variablelist>
<varlistentry>
<term>Userspace access vector cache</term>
<listitem>
<para>
<productname>SE-PostgreSQL</> tells <productname>SELinux</> its access
control decision. It takes system call invocation being heavy, however,
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.
<productname>sepgsql</> does not yet support an access vector cache.
This would likely improve performance.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>DDL Permissions</term>
<term>Data Definition Language (DDL) Permissions</term>
<listitem>
<para>
Now <productname>PostgreSQL</> does not provide a set of hooks on
the DDL routines.
It means plugin modules cannot acquire control here,
so <productname>SE-PostgreSQL</> does not check DDL Permissions
right now.
Due to implementation restrictions, DDL permissions are not checked.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Data Control Language (DCL) Permissions</term>
<listitem>
<para>
Due to implementation restrictions, DCL permissions are not checked.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Row-level access control</term>
<listitem>
<para>
Now <productname>SE-PostgreSQL</> does not support row-level access
control, because a few needed facilities are not supported yet.
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.
<productname>PostgreSQL</> does not support row-level access; therefore,
<productname>sepgsql</productname> does not support it either.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Covert channels</term>
<listitem>
<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.
For example, we can infer an existence of invisible object using
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>
</variablelist>
</sect2>
<sect2 id="sepgsql-resources">
<title>External Resources</title>
<variablelist>
@ -669,7 +622,7 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
<term><ulink url="http://wiki.postgresql.org/wiki/SEPostgreSQL">SE-PostgreSQL Introduction</ulink></term>
<listitem>
<para>
This wikipage provides a brief-overview, security design, architecture,
This wiki page provides a brief-overview, security design, architecture,
administration and upcoming feature for more details.
</para>
</listitem>
@ -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>
<listitem>
<para>
This document provides wide spectrum of knowledge to administrate
SELinux on your systems.
It primary focuses on Fedora, but not limited to Fedora.
This document provides wide spectrum of knowledge to administer
<productname>SELinux</> on your systems.
It primary focuses on Fedora, but is not limited to Fedora.
</para>
</listitem>
</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>
<listitem>
<para>
This document provides FAQs about SELinux.
It primary focuses on Fedora, but not limited to Fedora.
This document answers frequently asked questins about
<productname>SELinux</productname>.
It primary focuses on Fedora, but is not limited to Fedora.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="sepgsql-author">
<title>Author</title>
<para>