Re: SE-PostgreSQL Updated Revision (r1460) - Mailing list pgsql-hackers

From KaiGai Kohei
Subject Re: SE-PostgreSQL Updated Revision (r1460)
Date
Msg-id 497EDDF6.9040106@ak.jp.nec.com
Whole thread Raw
In response to Re: SE-PostgreSQL Updated Revision (r1460)  (Robert Haas <robertmhaas@gmail.com>)
List pgsql-hackers
Robert Haas wrote:
>> And, I have a question about documentation manner.
>> - You represented "getpeercon()" function as a system call.
>>  But, it is actually a wrapper function of getsockopt(2) system call,
>>  so the "getpeercon(3)" is not a system call strictly.
>>  Is it necessary to represent these stuffs strictly correct?
>>  (Thus, I wrote it as "API" in the r1460.)
>
> Oh, OK.  It sounds a little awkward to me to refer to it as an API.
> Perhaps we could just refer to it as getpeercon(3) and not call it
> either an API or a system call.

I replaced all the "getpeercon()" by "getpeercon(3)", and removed
expression both "system call" and "API".

>> About 2, SELinux community provides its default security policy,
>> and distributor's policy (including RedHat's one) is a derivative
>> of the default policy.
>> It is developed independent from distributor's cycle.
>>  http://oss.tresys.com/projects/refpolicy
>>  http://oss.tresys.com/repos/refpolicy/trunk/policy/modules/services/postgresql.te
>
> OK, I wasn't aware of that.  I think perhaps you could spell this out
> a little more in the docs so people understand that there is an
> upstream version which includes SE-PostgreSQL support from version
> <whatever>.

I noted it as:
|  The upstreamed security policy (<literal>20080702</literal>
|  or later) already has a set of rules for SE-PostgreSQL,
|  as a part of PostgreSQL policy.

The "<whatever>" is not a tag, is it?

> Actually, I think this should probably be broken up into three
> sections.  All of the stuff about how PGACE is not very interesting to
> anyone who isn't a developer, so it should be moved to someplace under
> "Internals".  I would suggest just adding a new chapter to the end of
> that section, after "How the Planner Uses Statistics".
>
> The database ACL stuff properly belongs in the "Database Roles and
> Privileges" section, and needs to be moved there, not just a
> cross-reference.
>
> The discussion of enhanced security and SE-PostgreSQL is another new
> chapter, probably immediately following "Database Roles and
> Privileges".  I would suggest calling it "Enhanced Security and
> SE-PostgreSQL".

OK, I deployed these section as you suggested.
- The "Row-level Database ACLs" section is moved to the tail of
   Chapter 20. Database Roles and Privileges.
- The new "Enhanced Security and SE-PostgreSQL" is moved to Chapter.21.
- The new "Chapter 57. PGACE Security Framework" is moved to Chapter.57,
   next to the "56. How the Planner Uses Statistics".

 > I think in general that the current
> documentation spends far too much time explaining what SE-PostgreSQL
> is and not enough time discussing the issues that are likely to come
> up when you're actually using it.  For example, it seems to me that
> anyone who has any interest in using SE-PostgreSQL to control access
> to functions will need a much more complicated policy than what you
> are proposing here, and there doesn't seem to be much discussion of
> that issue.  I'm not really looking for specific examples of how to
> build a policy so much as general considerations that you should keep
> in mind when trying to prevent information leakage via functions.

I added a new section "21.3. Making a Security Policy", but it is
still empty. I think it is not necessary to document comprehensive
information about security policy, since it is not a SELinux document.

My plan is to introduce a simple copy & pastable example and steps to
build it (with standard toolchain) and to install it as an security
policy module.

Please wait for filling up the section...

Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@ak.jp.nec.com>
diff -Nrpc base/doc/src/sgml/catalogs.sgml sepgsql/doc/src/sgml/catalogs.sgml
*** base/doc/src/sgml/catalogs.sgml    Fri Jan 23 10:23:37 2009
--- sepgsql/doc/src/sgml/catalogs.sgml    Tue Jan 27 18:48:27 2009
***************
*** 204,209 ****
--- 204,214 ----
       </row>

       <row>
+        <entry><link linkend="catalog-pg-security"><structname>pg_security</structname></link></entry>
+        <entry>text representation of security attribute</entry>
+      </row>
+
+      <row>
        <entry><link linkend="catalog-pg-shdepend"><structname>pg_shdepend</structname></link></entry>
        <entry>dependencies on shared objects</entry>
       </row>
***************
*** 977,982 ****
--- 982,996 ----
       </row>

       <row>
+       <entry><structfield>attkind</structfield></entry>
+       <entry><type>char</type></entry>
+       <entry></entry>
+       <entry>
+        A copy of <literal>pg_class.relkind</> of this columns's relation
+       </entry>
+      </row>
+
+      <row>
        <entry><structfield>attnotnull</structfield></entry>
        <entry><type>bool</type></entry>
        <entry></entry>
***************
*** 4195,4200 ****
--- 4209,4270 ----

   </sect1>

+  <sect1 id="catalog-pg-security">
+    <title><structname>pg_security</structname></title>
+
+    <indexterm zone="catalog-pg-security">
+      <primary>pg_security</primary>
+    </indexterm>
+
+    <para>
+      The catalog <structname>pg_security</structname> stores text
+      representations of security attributes managed by the PGACE framework.
+    </para>
+
+    <para>
+      Security modules managed by the PGACE framework can associate security
+      attributes with individual tuples.  Because the same security attribute
+      value is typically associated with many individual objects, all values
+      known to the system are stored here and referenced by OID.  This OID is
+      called a <literal>security id</literal> and is part of the tuple header.
+    </para>
+
+    <para>
+      When an new security attribute is given to the system, a new tuple is
+      added to <structname>pg_security</structname> and a new <literal>security
+      id</literal> is assigned by PGACE.  On output, a
+      <literal>security id</literal> can be rendered as text using this
+      system catalog as a lookup table.
+    </para>
+
+    <para>
+      See <xref linkend="pgace-security-label"> for more information.
+    </para>
+
+    <table>
+      <title><structname>pg_security</>Columns</title>
+
+      <tgroup cols=4>
+        <thead>
+      <row>
+        <entry>Name</entry>
+        <entry>Type</entry>
+        <entry>References</entry>
+        <entry>Description</entry>
+      </row>
+        </thead>
+
+        <tbody>
+      <row>
+        <entry><structfield>seclabel</structfield></entry>
+        <entry><type>text</type></entry>
+        <entry></entry>
+        <entry>Text representation of security attribute</entry>
+      </row>
+        </tbody>
+      </tgroup>
+    </table>
+  </sect1>

   <sect1 id="catalog-pg-shdepend">
    <title><structname>pg_shdepend</structname></title>
diff -Nrpc base/doc/src/sgml/config.sgml sepgsql/doc/src/sgml/config.sgml
*** base/doc/src/sgml/config.sgml    Thu Jan 22 14:34:54 2009
--- sepgsql/doc/src/sgml/config.sgml    Tue Jan 27 18:48:27 2009
*************** SET ENABLE_SEQSCAN TO OFF;
*** 706,711 ****
--- 706,784 ----
        </listitem>
       </varlistentry>

+      <varlistentry id="guc-pgace-feature" xreflabel="pgace-feature">
+       <term><varname>pgace_feature</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>pgace_feature</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+     An identifier name of current working enhanced security feature on
+     PGACE security framework.
+     (see <xref linkend="pgace-security-framework"> for more information)
+     This parameter can only be set at server start.
+        </para>
+        <para>
+     Currently, this parameter has two possible values.
+         The one is <literal>none</literal> not to enable any
+         enhanced security features, and the other is
+         <literal>selinux</literal> to enable SE-PostgreSQL
+         feature.
+        </para>
+        <para>
+     If you run <command>initdb</command> with
+         <option>--pgace-feature=selinux</option>, this parameter is
+         automatically specified to <literal>selinux</literal>.
+         Otherwise, the default is <literal>none</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry id="guc-sepostgresql" xreflabel="sepostgresql">
+       <term><varname>sepostgresql</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>sepostgresql</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+     Enables to choose the current working mode of SE-PostgreSQL.
+     This parameter has four possible values to specify working mode of
+         SE-PostgreSQL. The <literal>default</literal> is a default
+         selection. It always follows the configuration on operating
+         system. The <literal>enforcing</literal> and
+         <literal>permissive</literal> make SE-PostgreSQL work in the
+         specified mode, independent from kernel setting. Please note
+         that those configuration requires in-kernel SELinux is not
+         disabled. The <literal>disabled</literal> disables SE-PostgreSQL.
+     This parameter is available on a binary with SELinux support
+     (<literal>--enable-selinux</literal>), and can only be set at
+     server start.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry id="guc-sepostgresql-row-level" xreflabel="sepostgresql-row-level">
+        <term><varname>sepostgresql_row_level</varname> (<type>boolean</type>)</term>
+        <indexterm>
+      <primary><varname>sepostgresql_row_level</> configuration parameter</primary>
+        </indexterm>
+        <listitem>
+      <para>
+       Enables to turn on/off row-level access controls via SE-PostgreSQL.
+       The row-level access control feature requires additional 4-bytes
+       field for each tuples, so setting it <literal>off</literal> enables
+       to save the storage consumption, in return for the row-level granularity.
+       But we don't recommend it, unless you faces extremely severe requirements
+       for saving storage consumption.
+       The default is <literal>on</literal> which means row-level access
+       controls are available.
+       This parameter is available on a binary with SELinux support
+       (<literal>--enable-selinux</literal>), and can only be set at
+       server start.
+      </para>
+        </listitem>
+      </varlistentry>
+
      </variablelist>
      </sect2>
     </sect1>
diff -Nrpc base/doc/src/sgml/errcodes.sgml sepgsql/doc/src/sgml/errcodes.sgml
*** base/doc/src/sgml/errcodes.sgml    Mon Dec 29 20:19:56 2008
--- sepgsql/doc/src/sgml/errcodes.sgml    Sat Jan  3 16:58:53 2009
***************
*** 1420,1425 ****
--- 1420,1458 ----
  <entry>too_many_rows</entry>
  </row>

+ <row>
+ <entry spanname="span13"><emphasis role="bold">Class SE — Enhanced Security Error</></entry>
+ </row>
+
+ <row>
+ <entry><literal>SE000</literal></entry>
+ <entry>PGACE ERROR</entry>
+ <entry>pgace_framework_error</entry>
+ </row>
+
+ <row>
+ <entry><literal>SE011</literal></entry>
+ <entry>ROWACL ERROR</entry>
+ <entry>errors_in_row_level_acls</entry>
+ </row>
+
+ <row>
+ <entry><literal>SE021</literal></entry>
+ <entry>SELINUX ERROR</entry>
+ <entry>errors_in_sepostgresql</entry>
+ </row>
+
+ <row>
+ <entry><literal>SE022</literal></entry>
+ <entry>SELINUX AUDIT</entry>
+ <entry>audit_records_of_sepostgresql</entry>
+ </row>
+
+ <row>
+ <entry><literal>SE023</literal></entry>
+ <entry>SELINUX INFO</entry>
+ <entry>information_from_sepostgresql</entry>
+ </row>

  <row>
  <entry spanname="span13"><emphasis role="bold">Class XX — Internal Error</></entry>
diff -Nrpc base/doc/src/sgml/filelist.sgml sepgsql/doc/src/sgml/filelist.sgml
*** base/doc/src/sgml/filelist.sgml    Mon Jan  5 17:36:07 2009
--- sepgsql/doc/src/sgml/filelist.sgml    Tue Jan 27 18:48:27 2009
***************
*** 45,50 ****
--- 45,51 ----
  <!entity runtime       SYSTEM "runtime.sgml">
  <!entity config        SYSTEM "config.sgml">
  <!entity user-manag    SYSTEM "user-manag.sgml">
+ <!entity sepgsql       SYSTEM "sepgsql.sgml">
  <!entity wal           SYSTEM "wal.sgml">

  <!-- programmer's guide -->
***************
*** 84,89 ****
--- 85,91 ----
  <!entity planstats    SYSTEM "planstats.sgml">
  <!entity indexam    SYSTEM "indexam.sgml">
  <!entity nls        SYSTEM "nls.sgml">
+ <!entity pgace      SYSTEM "pgace.sgml">
  <!entity plhandler  SYSTEM "plhandler.sgml">
  <!entity protocol   SYSTEM "protocol.sgml">
  <!entity sources    SYSTEM "sources.sgml">
diff -Nrpc base/doc/src/sgml/pgace.sgml sepgsql/doc/src/sgml/pgace.sgml
*** base/doc/src/sgml/pgace.sgml    Thu Jan  1 09:00:00 1970
--- sepgsql/doc/src/sgml/pgace.sgml    Tue Jan 27 18:48:27 2009
***************
*** 0 ****
--- 1,234 ----
+ <chapter id="pgace-security-framework">
+   <title>PGACE Security Framework</title>
+
+   <para>
+     This chapter introduces the design of PGACE (PostgreSQL Access
+     Control Extension) security framework.
+   </para>
+   <para>
+     It enables to host various kind of enhanced security features
+     based on individual security design, granularity and platforms
+     with minimum impact toward the core PostgreSQL implementation.
+   </para>
+   <para>
+     Currently, it hosts two security features.
+
+     The one is Row-level ACLs feature. It is always enabled as an
+     enhancement of common database ACLs in row-level granularity,
+     as a hardwired DAC (Discretionary Access Control) feature.
+
+     It also allows users to choose a MAC (Mandatory Access Control)
+     via a GUC option <literal>pgace_feature</literal> on the startup
+     time. Its default is <literal>none</literal>, but currently we
+     have <literal>selinux</literal> option as a candidate.
+   </para>
+   <para>
+      PGACE consists of two major facilities.
+
+      The one is a set of security hooks deployed on some of strategic
+      points in the core PostgreSQL. It enables to implement new enhanced
+      security features with minimum impact to the core code.
+      The other is facilities to manage security attribute which can be
+      used to make a decision in access controls.
+   </para>
+
+   <sect1 id="pgace-security-hooks">
+     <title>PGACE Security Hooks</title>
+     <para>
+       This section introduces the overview of security hooks and
+       the way to invoke your security feature via the hooks.
+     </para>
+     <para>
+       All the security hooks are defined at
+       <filename>src/backend/security/pgaceHooks.c</filename>.
+
+       The security hooks are entry point of any enhanced security
+       feature chosen by users, so invoked ones can return its
+       decision on the given strategic point.
+     </para>
+     <para>
+       For example, the following <literal>pgaceHeapTupleInsert</literal>
+       is invoked just before inserting a new tuple into a relation.
+
+       If the hook returns <literal>false</literal> to the caller,
+       this insertion will be skipped. Otherwise, rest of steps will be
+       done normally.
+
+       The enhanced security feature can make its decision based on the
+       given arguments which shows context in the invocation of hook.
+       The <literal>rel</literal> and <literal>tuple</literal> show
+       the target relation and tuple in this example.
+     </para>
+ <programlisting>
+ bool
+ pgaceHeapTupleInsert(Relation rel, HeapTuple tuple,
+                      bool is_internal, bool with_returning)
+ {
+     /* A wired DAC check */
+     if (!rowaclHeapTupleInsert(rel, tuple,
+                                is_internal,
+                                with_returning))
+         return false;
+
+     switch (pgace_feature)
+     {
+ #ifdef HAVE_SELINUX
+     case PGACE_FEATURE_SELINUX:
+         if (sepgsqlIsEnabled())
+             return sepgsqlHeapTupleInsert(rel, tuple,
+                                           is_internal,
+                                           with_returning);
+         break;
+ #endif
+     default:
+         break;
+     }
+     return true;
+ }
+ </programlisting>
+     <para>
+       This example shows a hard-wired security feature (Row-level ACLs)
+       and one or no selectable feature can be invoked on a tuple insertion.
+
+       Is allows users to shoose an enhanced security feature from the
+       candidates via <literal>pgace_feature</literal> GUC option.
+       An integer variable of <literal>pgace_feature</literal> reflects
+       the configuration.
+     </para>
+     <para>
+       In this example, SE-PostgreSQL is an only candidate when the binary
+       is compiled with <option>--enable-selinux</option> option.
+     </para>
+     <para>
+       If you add a new security feature, you should add a new case
+       branch in the <literal>switch</literal> statement and an option
+       to the GUC parameter, for users selection.
+
+       The following example shows a case when someone add a new security
+       feature compiled when <literal>HAVE_FOO_SECURITY</literal> is
+       defined on build-time.
+     </para>
+ <programlisting>
+ bool
+ pgaceHeapTupleInsert(Relation rel, HeapTuple tuple,
+                      bool is_internal, bool with_returning)
+ {
+     /* A wired DAC check */
+     if (!rowaclHeapTupleInsert(rel, tuple,
+                                is_internal,
+                                with_returning))
+         return false;
+
+     switch (pgace_feature)
+     {
+ #ifdef HAVE_SELINUX
+     case PGACE_FEATURE_SELINUX:
+         if (sepgsqlIsEnabled())
+             return sepgsqlHeapTupleInsert(rel, tuple,
+                                           is_internal,
+                                           with_returning);
+         break;
+ #endif
+ #ifdef HAVE_FOO_SECURITY
+     case PGACE_FEATURE_FOO_SECURITY:
+         return fooSecurityHeapTupleInsert(rel, tuple,
+                                           is_internal,
+                                           with_returning);
+         break;
+ #endif
+     default:
+         break;
+     }
+     return true;
+ }
+ </programlisting>
+     <para>
+       Please note that individual specifications of security hooks are
+       described in <filename>src/backend/security/pgaceHooks.c</filename>
+       as a source code comment.
+       It will help you to understand.
+
+       If a part of given hooks are unnecessary for your security design,
+       keep it as is.
+     </para>
+   </sect1>
+
+   <sect1 id="pgace-security-label">
+     <title>Management of Security Label</title>
+     <para>
+       A security label is a human readable security attribute which can
+       be exported/imported via <literal>security_label</literal> system
+       column
+
+       PGACE provides a common facility to manage the security label of
+       tuples for various kind of security features.
+       It enables an enhanced security feature chosen to store and featch
+       a security label of tuples, and allows it to make a decision in
+       access controls based on the label.
+     </para>
+     <para>
+       It enables us to handle security labels in text form, but they
+       are internally handled as an alternative identifier.
+
+       We call it as a <literal>security id</literal>.
+       It is an object identifier (oid) of <literal>pg_security</literal>
+       system catalog which holds human readable text form of security labels.
+
+       So, we can mutually translate security id and security label via
+       <literal>pg_security</literal> system catalog.
+     </para>
+     <para>
+       The <literal>security id</literal> of tuple is stored within the
+       padding field of <literal>HeapTupleHeader</literal>, as if oid doing.
+
+       We can fetch it via <literal>HeapTupleGetSecLabel()</literal>
+       macro. If <literal>pgaceTupleDescHasSecLabel()</literal> security
+       hook returns <literal>true</literal> for the given relation, it
+       means a new tuple within the relation should have a field to store
+       its <literal>security id</literal>.
+
+       We can set it via <literal>HeapTupleSetSecLabel()</literal> macro.
+     </para>
+     <para>
+       A few utility functions are provided.
+
+       <literal>pgaceLookupSecurityId()</literal> returns a security id
+       towards given security label in text format. If it is not on
+       <literal>pg_security</literal>, it automatically inserts a new
+       entry and returns its security id.
+
+       <literal>pgaceLookupSecurityLabel()</literal> returns a security
+       label for the given sid.
+       If it is not on <literal>pg_security</literal>, it returns
+       <literal>NULL</literal>, so the guest should handle it as a
+       something like default or unlabeled.
+     </para>
+     <para>
+       The <literal>security_label</literal> system column allows users
+       to input a security label in text format on <command>INSERT</command>,
+       <command>UPDATE</command>, <command>COPY</command> and so on.
+
+       The given security label is translated into security id automatically,
+       and put on the security field of tuples. If user provides nothing as
+       a security label, it is initialized as <literal>InvalidOid</literal>.
+
+       The <literal>pgaceHeapTupleInsert()</literal> or others are invoked
+       later, so the enhanced security feature can know whether user gives
+       a proper security label or not. If no security label is given, it
+       can assign a default security label. If violated security label is
+       given, it can raise an error.
+
+       Vice versa, when user refers <literal>security_label</literal>,
+       the sid of tuples are automatically translated into text format.
+       If the sid is invalid, the enhanced security feature can return
+       an alternative string using
+       <literal>pgaceUnlabeledSecurityLabel()</literal> hook.
+     </para>
+     <para>
+       The Row-level Database ACLs uses this facility to manage security
+       labels to store its ACLs. Tuples have a capability to store both types
+       of security ids simultaneously, but enhanced security features should
+       not touch the row-level ACLs.
+     </para>
+   </sect1>
+ </chapter>
diff -Nrpc base/doc/src/sgml/postgres.sgml sepgsql/doc/src/sgml/postgres.sgml
*** base/doc/src/sgml/postgres.sgml    Tue May 13 14:48:54 2008
--- sepgsql/doc/src/sgml/postgres.sgml    Tue Jan 27 18:48:27 2009
***************
*** 148,153 ****
--- 148,154 ----
    &config;
    &client-auth;
    &user-manag;
+   &sepgsql;
    &manage-ag;
    &charset;
    &maintenance;
***************
*** 242,247 ****
--- 243,249 ----
    &storage;
    &bki;
    &planstats;
+   &pgace;

   </part>

diff -Nrpc base/doc/src/sgml/ref/initdb.sgml sepgsql/doc/src/sgml/ref/initdb.sgml
*** base/doc/src/sgml/ref/initdb.sgml    Wed Oct  1 14:42:02 2008
--- sepgsql/doc/src/sgml/ref/initdb.sgml    Sun Jan 25 21:01:21 2009
*************** PostgreSQL documentation
*** 234,239 ****
--- 234,252 ----
         </para>
        </listitem>
       </varlistentry>
+
+      <varlistentry>
+       <term><option>--pgace-feature=<replaceable>FEATURE</></option></term>
+       <listitem>
+        <para>
+         Selects an enhanced security feature, and writes it to
+         <filename>postgresql.conf</filename>.
+         The default is <literal>none</literal> which means no enhanced
+         security feature is activated.  Currently, the only available
+         enhanced security feature is <literal>selinux</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>

diff -Nrpc base/doc/src/sgml/ref/pg_dump.sgml sepgsql/doc/src/sgml/ref/pg_dump.sgml
*** base/doc/src/sgml/ref/pg_dump.sgml    Tue Jan  6 14:45:31 2009
--- sepgsql/doc/src/sgml/ref/pg_dump.sgml    Sun Jan 25 21:01:21 2009
*************** PostgreSQL documentation
*** 634,639 ****
--- 634,662 ----
         </para>
        </listitem>
       </varlistentry>
+
+      <varlistentry>
+       <term><option>--security-acl</option></term>
+       <listitem>
+        <para>
+         Dumps row-level ACLs with table contents.
+         ACLs can be restored via writable system column
+         <literal>security_acl</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>--security-label</option></term>
+       <listitem>
+        <para>
+         Dumps security labels managed by available enhanced security feature
+         with table contents.
+         Labels can be restored via writable system column
+         <literal>security_label</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>

diff -Nrpc base/doc/src/sgml/ref/pg_dumpall.sgml sepgsql/doc/src/sgml/ref/pg_dumpall.sgml
*** base/doc/src/sgml/ref/pg_dumpall.sgml    Tue Jan  6 14:45:31 2009
--- sepgsql/doc/src/sgml/ref/pg_dumpall.sgml    Sun Jan 25 21:01:21 2009
*************** PostgreSQL documentation
*** 334,339 ****
--- 334,361 ----
        </listitem>
       </varlistentry>

+      <varlistentry>
+       <term><option>--security-acl</option></term>
+       <listitem>
+        <para>
+         Dumps row-level ACLs with table contents.
+         ACLs can be restored via writable system column
+         <literal>security_acl</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>--security-label</option></term>
+       <listitem>
+        <para>
+         Dumps security labels managed by available enhanced security feature
+         with table contents.
+         Labels can be restored via writable system column
+         <literal>security_label</literal>.
+        </para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>

diff -Nrpc base/doc/src/sgml/sepgsql.sgml sepgsql/doc/src/sgml/sepgsql.sgml
*** base/doc/src/sgml/sepgsql.sgml    Thu Jan  1 09:00:00 1970
--- sepgsql/doc/src/sgml/sepgsql.sgml    Tue Jan 27 18:48:27 2009
***************
*** 0 ****
--- 1,1018 ----
+ <chapter id="enhanced-security-and-sepostgresql">
+   <title>Enhanced Security and SE-PostgreSQL</title>
+   <para>
+     This chapter introduces enhanced security features which enable
+     <productname>PostgreSQL</productname> to provide mandatory
+     access controls, fine-grained access controls, and integration
+     of security policy between the operating system and
+     <productname>PostgreSQL</productname>.
+   </para>
+   <para>
+     The current version of <productname>PostgreSQL</productname>
+     has two enhanced security features: Row-level Database ACLs and
+     SE-PostgreSQL (Security Enhanced PostgreSQL).
+
+     Both are implemented using a common security framework called
+     PGACE (PostgreSQL Access Control Extensions), which provides basic
+     facilities to manage security attributes for database objects and
+     hooks to take control at strategic points within the core code.
+
+     See, <xref linkend="pgace-security-framework"> for more details.
+   </para>
+
+   <para>
+     The Row-level Database ACLs feature enables
+     <productname>PostgreSQL</productname> to apply existing DAC
+     (Discretionary Access Control) policy down to the level of individual
+     database rows.
+
+     Permissions can be set individually for <command>SELECT</command>,
+     <command>UPDATE</command> and <command>DELETE</command>.
+     Tuples for which permission is denied are silently filtered from the
+     result set.
+
+     It is also introduced at <xref linkend="row-level-database-acls">.
+   </para>
+
+   <para>
+     SE-PostgreSQL provides additional fine-grained mandatory access
+     controls on accesses to database objects via SQL. It makes a
+     decision whether a given client request should be
+     allowed, or not, by communicating with in-kernel SELinux.
+
+     SELinux holds its security policy which is a set of white listed
+     rules, and provides its access control decisions to the kernel
+     and userspace object manager.
+
+     The key concept of SE-PostgreSQL is integration of access controls
+     between operating system and database management systems.
+     It makes and applies its access control decision based on a single
+     unified security policy of operating system. It applies the security
+     context of peer process as privileges of client, independent from
+     database authentication.
+
+     The access controls implemented by SE-PostgrSQL may not be bypassed even
+     by privileged database users, making it an implementation of
+     MAC (Mandatory Access Control).  This enables it to prevent information
+     leaks and manipulation from a hypothetical malicious insider and reduced
+     the risks posed by SQL injection or other application-level bugs.
+   </para>
+
+   <para>
+     The PGACE security framework can host two security
+     features simultaneously.  Row-level Database ACLs are always provided as
+     a Discretionary Access Control (DAC) feature.  Mandatory Access Control
+     (MAC) must be explicitly enabled, and the only current implementation is
+     SE-PostgreSQL.
+
+     To enable SE-PostgreSQL, specify <option>--enable-selinux</option> option
+     at <command>configure</command> time,
+     and use the <option>--pgace-feature=selinux</option> option to
+     <command>initdb</command>.
+ <screen>
+ <prompt>$ </prompt><userinput>./configure --enable-selinux</userinput>
+ <prompt>$ </prompt><userinput>make install</userinput>
+ <prompt>$ </prompt><userinput>initdb --pgace-feature=selinux</userinput>
+ </screen>
+   </para>
+
+   <sect1 id="sepostgresql-features">
+     <title>SE-PostgreSQL Features</title>
+
+     <sect2 id="sepostgresql-single-unified-security-policy">
+       <title>Single unified security policy</title>
+
+       <para>
+     Because files and databases have similar capabilities to store
+     information assets, similar access controls are needed to maintain
+     confidentiality and data integrity.  Information stored in the
+     filesystem is accessed through system calls, such as
+     <command>write(2)</command>, while database objects are accessed
+     via SQL queries.
+       </para>
+       <para>
+     Without specific support from the database, there is no way for a
+     system-level mandatory access control policy to also apply to database
+     objects.  While access to the database files themselves could be
+     controlled, selective access to the contents of the database would
+     be forced to rely on whatever set of discretionary access controls
+     the database system provided.
+       </para>
+       <para>
+     SE-PostgreSQL overcomes this problem by making its access control
+     decision based on the security policy of SELinux.  This means that
+     the same security contexts and policies which are applied to filesystem
+     objects can also be applied to database objects, providing a
+     reliable foundation for comprehensive and integrated
+     security.
+       </para>
+       <para>
+     For example, when we store information labeled as
+     <literal>Classified</literal>, it cannot be accesed by users without
+     proper privileges regardless of whether it is stored in the filesystem
+     or within the database.  Because the decision to allow or deny access
+     is based only on the kernel's mandatory access control policy, and
+     not on PostgreSQL's existing Discretionary Access Control (DAC)
+     mechanisms, it cannot be subverted even by a database superuser.
+     (Similarly, SELinux in general can restrict privileges of any system
+     user, including <literal>root</literal>.)
+       </para>
+
+       <sect3 id="sepostgresql-security-context">
+     <title>Security Context</title>
+     <para>
+       The SELinux security policy is a set of access controls
+       rules which define who is allowed to perform which operations
+       on which objects.
+
+       These rules are described as a relationship of two entities
+       identified by common format called a security context.
+     </para>
+     <para>
+       The security context is a formatted string independent of
+       the type of object being labeled, such as:
+       <synopsis>system_u:object_r:postgresql_db_t:SystemHigh</synopsis>.
+
+       Security contexts are used to label files, sockets, and other
+       resources, and access decisions are made by testing whether
+       a particular relationship between two labels is permitted by
+       the access control rules.
+     </para>
+     <para>
+       For example, when a process labeled as
+       <literal>system_u:system_r:postgresql_t:s0</literal> tries to
+       write a log message to <filename>/var/log/postgresql.log</filename>
+       labeled as <literal>system_u:object_r:postgresql_log_t:s0</literal>,
+       it issues a <literal>write(2)</literal> system call; SELinux searches
+       its security policy database to determine the relationship between
+       the two security contexts.
+
+       If the entry found entry allows the operation, SELinux takes no
+       action;
+       otherwise, SELinux blocks the write.
+     </para>
+     <para>
+       Any object managers which want a decision come from SELinux
+       (including kernel) should have the capability to manage the security
+       contexts of their objects.
+
+       For example, most of major filesystems support xattr (Extended
+       Attributes) facilities which allows to store individual security
+       context of files.
+
+       SE-PostgreSQL also provides a facility to manage security context
+       of database objects. We can import/export them via
+       <literal>security_label</literal> system column.
+     </para>
+       </sect3>
+
+       <sect3 id="sepostgresql-client-privileges">
+     <title>Client Privileges</title>
+     <para>
+       In order to properly apply SELinux access controls, SE-PostgreSQL
+       needs to know the security context of each connected client.
+       It does this using the SELinux-supplied
+       <literal>getpeercon(3)</literal>, which provides the security
+       context of the process connected to the remote end of a particular
+       socket.
+
+       Note that the peer's security context is unrelated to the database
+       role used to authenticate, although the role-based permissions are
+       still applied and can deny access to database objects independently
+       of SE-PostgreSQL.
+     </para>
+
+     <para>
+       The security context of the connected client can be fetched using
+       the <literal>sepgsql_getcon()</literal> function, like this:
+ <screen>
+ <prompt>$ </prompt><userinput>id -Z</userinput>
+ unconfined_u:unconfined_r:unconfined_t:Classified
+ <prompt>$ </prompt><userinput>psql -q</userinput>
+ <prompt>postgres=# </prompt><userinput>SELECT sepgsql_getcon();</userinput>
+                   sepgsql_getcon
+ ---------------------------------------------------
+  unconfined_u:unconfined_r:unconfined_t:Classified
+ (1 row)
+ </screen>
+     </para>
+
+     <para>
+       When connecting to SE-PostgreSQL via a TCP/IP socket, labeled
+       networking must be set up to ensure that
+       <literal>getpeercon(3)</literal> returns the correct security
+       context.
+       See <xref linkend="sepostgresql-labeled-networks"> for more
+       defails.
+     </para>
+       </sect3>
+
+       <sect3 id="sepostgresql-mac">
+        <title>Mandatory Access Controls</title>
+        <para>
+      MAC (Mandatory Access Controls) a system of security controls that
+      is significantly different from DAC (Discretionary Access Controls)
+      such as filesystem permissions and database ACLs.
+
+      The major difference is that MAC requires that access controls be
+      applied to all managed objects without exception, including,
+      for example, the <literal>root</literal> user.
+
+      Every subject and object must be identified by security
+      labels, and MAC policy is described as a set of relationships
+      between pairs of labels. The security context of SELinux is a
+      sort of label, but includes more identifiers than
+      traditional trusted-operating system.
+
+      Finally, MAC should not allow resource owners to change its
+      access control rights arbitrarily. DAC design allows us
+      to change them using <command>chmod</command> or
+      <command>GRANT</command>. But in a MAC design, security policy
+      restricts these types of changes.
+        </para>
+        <para>
+      SELinux is a MAC feature in operating system, so it applies
+      MAC policy for accesses to resources managed by operating
+      system like files, sockets and so on.
+        </para>
+        <para>
+      SE-PostgreSQL is a symmetric feature in database management
+      system. It also applies MAC policy for accesses to any
+      database objects, managed by database management system
+      as a literal.
+        </para>
+       </sect3>
+     </sect2>
+
+     <sect2 id="sepostgresql-functionality">
+       <title>The functionality of SE-PostgreSQL</title>
+
+       <sect3 id="sepostgresql-security-label">
+        <title>security_label system column</title>
+        <para>
+      SE-PostgreSQL enables to import/export security context of
+      tuples via <literal>security_label</literal> system column
+      which is available v8.4, or later.
+        </para>
+        <para>
+      The following example shows a case when we export security
+      context of tuples and its data via <command>SELECT</command>.
+        </para>
+ <screen>
+ <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput>
+                 security_label                | id | name  | price
+ ----------------------------------------------+----+-------+-------
+  system_u:object_r:sepgsql_table_t            |  1 | water |   100
+  system_u:object_r:sepgsql_table_t            |  2 | coke  |   120
+  system_u:object_r:sepgsql_table_t            |  3 | juice |   130
+  system_u:object_r:sepgsql_table_t            |  4 | cofee |   180
+  system_u:object_r:sepgsql_table_t:Classified |  5 | beer  |   240
+  system_u:object_r:sepgsql_table_t:Classified |  6 | sake  |   320
+ (6 rows)
+ </screen>
+        <para>
+      The security policy has rules to determine what security context
+      should be applied on newly inserted tuples.  SE-PostgreSQL applies
+      these rules unless a different context is explicitly specified by
+      including the <literal>security_label</literal> system column as
+      a target.
+        </para>
+ <screen>
+ <prompt># </prompt><userinput>INSERT INTO drink (security_label, id, name, price)
+      VALUES('system_u:object_r:sepgsql_ro_table_t', 7, 'tea', 130);</userinput>
+ </screen>
+        <para>
+      We can also change security context of tuples using
+      <literal>UPDATE</literal> statement.
+        </para>
+ <screen>
+ <prompt># </prompt><userinput>UPDATE drink SET security_label = 'system_u:object_r:sepgsql_ro_table_t' WHERE id <
4;</userinput>
+ </screen>
+        <para>
+      To use this feature, the client must have privileges to insert or
+      update the security context of tuples.  Otherwise, SE-PostgreSQL
+      will block any attempt to change them.
+        </para>
+        <para>
+      <command>SELECT INTO</command> or <command>CREATE TABLE AS</command>
+      including <literal>security_label</literal> system column as a target
+      is handled like a series of <literal>INSERT</literal> statements with
+      explicit security contexts.
+        </para>
+ <screen>
+ <prompt># </prompt><userinput>SELECT security_label, id, name, price / 2 AS price INTO discount FROM
drink;</userinput>
+ SELECT
+ postgres=# SELECT security_label, * FROM discount;
+                 security_label                | id | name  | price
+ ----------------------------------------------+----+-------+-------
+  system_u:object_r:sepgsql_table_t            |  1 | water |    50
+  system_u:object_r:sepgsql_table_t            |  2 | coke  |    60
+  system_u:object_r:sepgsql_table_t            |  3 | juice |    65
+  system_u:object_r:sepgsql_table_t            |  4 | cofee |    90
+  system_u:object_r:sepgsql_table_t:Classified |  5 | beer  |   120
+  system_u:object_r:sepgsql_table_t:Classified |  6 | sake  |   160
+ (6 rows)
+ </screen>
+        <para>
+      Please note that PostgreSQL uses system catalogs to represent
+      metadata of tables, columns and so on.
+      SE-PostgreSQL considers tuples within the system catalogs
+      show the security context of them.
+      For example, security context of tuples within
+      <literal>pg_class</literal> is considered as the one of table.
+        </para>
+      </sect3>
+
+      <sect3>
+        <title>Access controls on Tuples</title>
+        <para>
+      SE-PostgreSQL applies its access controls for each tuple.
+
+      If client tries to select, update or delete violated tuples,
+      these tuples are filtered from the result set or ignored from
+      the target of updates/deletions, as if they are not exist
+      on the table.
+        </para>
+        <para>
+      The following example shows the case when two users with different
+      security contexts try to <command>SELECT</command> the same table
+      with same SQL.
+      A <literal>Classified</literal> user can whole of the table.
+      But <literal>Classified</literal> tuples are invisible from
+      other users.
+        </para>
+ <screen>
+ <prompt>$ </prompt><userinput>id -Z</userinput>
+ unconfined_u:unconfined_r:unconfined_t:Classified
+ <prompt>$ </prompt><userinput>psql -q postgres</userinput>
+ <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput>
+                 security_label                | id | name  | price
+ ----------------------------------------------+----+-------+-------
+  system_u:object_r:sepgsql_table_t            |  1 | water |   100
+  system_u:object_r:sepgsql_table_t            |  2 | coke  |   120
+  system_u:object_r:sepgsql_table_t            |  3 | juice |   130
+  system_u:object_r:sepgsql_table_t            |  4 | cofee |   180
+  system_u:object_r:sepgsql_table_t:Classified |  5 | beer  |   240
+  system_u:object_r:sepgsql_table_t:Classified |  6 | sake  |   320
+ (6 rows)
+ </screen>
+        <para>
+      It shows the <literal>Classified</literal> user got 6 tuples
+      with unconditional <command>SELECT</command> on drink table.
+
+      However, the unclassified (not labeled) user got 4 tuples
+      with same SQL, because 2 tuples were filtered out by SE-PostgreSQL.
+        </para>
+ <screen>
+ <prompt>$ </prompt><userinput>id -Z</userinput>
+ unconfined_u:unconfined_r:unconfined_t
+ <prompt>$ </prompt><userinput>psql -q postgres</userinput>
+ <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput>
+ postgres=# SELECT security_label, * FROM drink;
+           security_label           | id | name  | price
+ -----------------------------------+----+-------+-------
+  system_u:object_r:sepgsql_table_t |  1 | water |   100
+  system_u:object_r:sepgsql_table_t |  2 | coke  |   120
+  system_u:object_r:sepgsql_table_t |  3 | juice |   130
+  system_u:object_r:sepgsql_table_t |  4 | cofee |   180
+ (4 rows)
+ </screen>
+      </sect3>
+
+      <sect3>
+        <title>Access controls on Tables and Columns</title>
+        <para>
+      SE-PostgreSQL also applies access controls to
+      tables and columns, but these are handled differently than row-level
+      security.
+        </para>
+        <para>
+      SE-PostgreSQL walks each query and considers the security contexts
+      of all tables and columns which appeare therin.  If any of those
+      tables or columns are ones which the client is not permitted to
+      access, SE-PostgreSQL aborts query execution and returns an error
+      to the client.
+        </para>
+        <para>
+      The following example shows a case when we declared a
+      <literal>ccredit</literal> column to store credit card numbers
+      as a secret column, hidden from unclassified users.
+        </para>
+ <screen>
+ CREATE TABLE customer (
+     cid     integer primary key,
+     cname   varchar(32),
+     credit  varchar(32)
+         SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t'
+ );
+ GRANT ALL ON customer TO PUBLIC;
+
+ INSERT INTO customer (cid, cname, credit)
+     VALUES ( 10, 'jack', '1111-2222-3333-4444'),
+            ( 13, 'adam', '5555-6666-7777-8888'),
+            ( 14, 'liza', '9876-5432-1098-7654');
+ </screen>
+
+ <screen>
+ $ id -Z
+ staff_u:staff_r:staff_t
+ $ psql -q postgres
+ postgres=# SELECT * FROM customer;
+ ERROR:  SELinux: denied { select } \
+     scontext=staff_u:staff_r:staff_t \
+     tcontext=system_u:object_r:sepgsql_secret_table_t \
+     tclass=db_column name=customer.credit
+ postgres=# SELECT cid, cname FROM customer;
+  cid | cname
+ -----+-------
+   10 | jack
+   13 | adam
+   14 | liza
+ (3 rows)
+ </screen>
+        <para>
+      In the first query, the user tried to refer all the columns;
+      SE-PostgreSQL prevents query execution because it contains
+      a reference to <literal>ccredit</literal> column which is
+      labeled as <literal>sepgsql_secret_table_t</literal>.
+
+      Then, the user tried to refer to all columns except the
+      <literal>ccredit</literal> column, so SE-PostgreSQL allowed the user
+      to execute the query, because no access control rules were violated.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Access Controls on Functions</title>
+        <para>
+      SE-PostgreSQL also prevents clients from invoking functions for
+      which they do not have the necessary privileges.
+        </para>
+        <para>
+      In the current default security policy, a function declared by
+      administrative users (like <literal>unconfined_t</literal> domain)
+      is labeled as <literal>sepgsql_proc_t</literal>. Those declared
+      by normal users (like <literal>staff_t</literal> domain) are labeled
+      as <literal>staff_sepgsql_proc_exec_t</literal> and therefore can't
+      be invoked by administrative users.
+
+      This system prevents administrative users from invoking malicious
+      function by mistake. They have to confirm its declaration and
+      relabel its security context to <literal>sepgsql_proc_t</literal>.
+        </para>
+        <para>
+      SE-PostgreSQL allows clients to change privileges during
+      execution of specific functions called as trusted procedures.
+      These are similar to security definer functions, but for security
+      contexts rather than database roles.
+
+      In the current default security policy, trusted procedures are
+      functions labeled as <literal>sepgsql_trusted_proc_exec_t</literal>.
+      This enables users to execute these functions with administrative
+      privileges, providing a secure method for accessing confidential
+      objects.
+
+      This provides a simple all or nothing policy, but more complex
+      controls are possible if you install your own security policy module.
+        </para>
+        <para>
+      The following example declares a trusted procedure
+      <literal>show_credit</literal> to expose some, but not all, of the
+      information stored in <literal>customer.credit</literal>.
+
+      Assume that a client within <literal>staff_t</literal> domain
+      cannot access the <literal>credit</literal> column.  A trusted
+      trusted procedure can provide access, because the sub-queries
+      from the procedure are handled as an administrative domain.
+        </para>
+ <screen>
+ # CREATE OR REPLACE FUNCTION show_credit (integer) RETURNS text
+     LANGUAGE 'sql'
+     SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t'
+     AS 'SELECT substring(credit from ''^[0-9]+-'') || ''xxxx-xxxx-xxxx''
+             FROM customer WHERE CID = $1';
+ CREATE FUNCTION
+ # \q
+ </screen>
+ <screen>
+ $ id -Z
+ staff_u:staff_r:staff_t
+ $ psql postgres
+ postgres=# SELECT * FROM customer;
+ ERROR:  SELinux: denied { select }      \
+     scontext=staff_u:staff_r:staff_t    \
+     tcontext=system_u:object_r:sepgsql_secret_table_t   \
+     tclass=db_column name=customer.credit
+ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
+  cid | cname |     show_credit
+ -----+-------+---------------------
+   10 | jack  | 1111-xxxx-xxxx-xxxx
+   13 | adam  | 5555-xxxx-xxxx-xxxx
+   14 | liza  | 9876-xxxx-xxxx-xxxx
+ (3 rows)
+
+ postgres=#
+ </screen>
+      </sect3>
+     </sect2>
+
+     <sect2>
+       <title>Limitations</title>
+       <para>
+     SE-PostgreSQL does not prevent information leaks via covert channels.
+     In other words, clients may be able to infer information about data
+     they cannot directly access.
+
+     If your requirements include elimination of covert channels,
+     SE-PostgreSQL may not be an adequate solution.  Covert channel
+     analysis was required by the upper B2 class of TCSEC and by
+     ISO/IEC15408 now, also known as CC (Common Criteria).
+       </para>
+       <para>
+     Covert channels are possible when, for example, a client attempts
+     to update or delete a tuple with primary key refered by
+     one or more invisible foreign keys. SE-PostgreSQL will prevent the
+     action to preserve reference integrity, even though the client
+     cannot see the key.
+
+     From this, the client can infer the existence of the invisible foreign
+     key, an inference to which he is not entitled.
+
+     As a practical matter, this scenario can sometimes be avoided by using
+     non-natural primary and foreign keys, such as UUIDs.  This may make it
+     impossible to infer any meaningful data.
+       </para>
+     </sect2>
+   </sect1>
+
+   <sect1 id="sepostgresql-administration">
+     <title>SE-PostgreSQL Administration</title>
+
+     <sect2>
+       <title>Build and Installation</title>
+       <sect3>
+     <title>Requirement</title>
+     <para>
+       We need the following packages to build and install
+       SE-PostgreSQL properly. Please check it at first.
+     </para>
+
+     <variablelist>
+       <varlistentry>
+         <term><literal>Linux kernel</literal></term>
+         <listitem>
+           <para>
+         Linux kernel has to support SELinux feature, at least.
+         In addition, it is necessary to provide an interface to
+         obtain a list of supported object classes and permissions
+         via <filename>/selinux/class</filename>, which is available
+         on the Linux kernel 2.6.23 or later.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><literal>Security policy</literal></term>
+         <listitem>
+           <para>
+         The security policy of SELinux is neccesary to contain access
+         control rules related to database objects.
+         The upstreamed security policy (<literal>20080702</literal>
+         or later) already has a set of rules for SE-PostgreSQL,
+         as a part of PostgreSQL policy.
+           </para>
+           <para>
+         In <literal>Red Hat EL</literal> or <literal>Fedora</literal>,
+         check the version number of <literal>selinux-policy</literal>
+         rpm package is <literal>3.4.2</literal>, or later.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><literal>libselinux</literal></term>
+         <listitem>
+           <para>
+         <literal>libselinux</literal> is a library to communicate
+         between applications and in-kernel SELinux, so it provides
+         us various kind of APIs and header definitions.
+         It is necessary to provide header definitions of object
+         classes and permissions related to database. Rest of
+         requirements are already included in older version.
+           </para>
+           <para>
+         In <literal>Red Hat EL</literal> or <literal>Fedora</literal>,
+         check the version number of <literal>libselinux</literal>
+         and <literal>libselinux-devel</literal> rpm packages are
+         <literal>2.0.46</literal>, or later.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><command>checkmodule</command></term>
+         <listitem>
+           <para>
+         The <command>checkmodule</command> is a policy compiler
+         for a modular policy package, such as
+         <literal>sepostgresql-devel.pp</literal> we provided.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><command>semodule</command></term>
+         <listitem>
+           <para>
+         The <command>semodule</command> is a command to manage
+         modular policy packages. It enables to link/unlink,
+         upgrade or load/unload modular policy packages, such as
+         <literal>sepostgresql-devel.pp</literal> we provided.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><command>restorecon</command></term>
+         <listitem>
+           <para>
+         The <command>restorecon</command> enables to assign
+         correct security context for files, directories and
+         any other objects on filesystem, based on the security
+         policy configuration.
+         It helps to assign correct security context on
+         installed files by hand.
+           </para>
+         </listitem>
+       </varlistentry>
+     </variablelist>
+       </sect3>
+
+       <sect3>
+     <title>Build</title>
+     <para>
+       SE-PostgreSQL feature is disabled in the default build.
+       So, we have to add <option>--enable-selinux</option> option
+       to configure script. It enables to build your PostgreSQL
+       with a feature to suppor SELinux.
+     </para>
+ <screen>
+ <prompt>$ </prompt><userinput>./configure --enable-selinux</userinput>
+ <prompt>$ </prompt><userinput>make</userinput>
+ <prompt>$ </prompt><userinput>make -C src/backend/security/sepgsql/policy</userinput>
+ </screen>
+         <para>
+       Please note that the recent upstreamed security policy of SELinux
+       contains a set of rules for SE-PostgreSQL, so we are not always
+       necessary to build security policy module.
+     </para>
+     <para>
+       However, SE-PostgreSQL also provides an optinal policy module
+       for development Purpose. It enables several operations like
+       regression test, toggle audit logs and so on.
+     </para>
+     <para>
+       It is stored in
+       <filename>src/backend/security/sepgsql/policy</filename>,
+       and can be also build and installed as a binary security policy
+       module.
+     </para>
+       </sect3>
+
+       <sect3>
+     <title>Installation</title>
+     <para>
+       Please note that SELinux requires installed files, directories and
+       others should be labeled properly. RPM installation do it implicitly.
+
+       But, when you install PostgreSQL from a tarball, you should assign
+       proper security context for them. The development policy module
+       has a list that shows what security context should be assigned to
+       what files, and will help you to manage them, so we recommend to
+       install the <filename>sepostgresql-devel.pp</filename> also.
+     </para>
+ <screen>
+ <prompt># </prompt><userinput>make install</userinput>
+ <prompt># </prompt><userinput>/usr/sbin/semodule -i
src/backend/security/sepgsql/policy/sepostgresql-devel.pp</userinput>
+ <prompt># </prompt><userinput>/sbin/restorecon -R /usr/local/pgsql</userinput>
+ </screen>
+         <para>
+       <command>semodule</command> is a command to install and uninstall
+       a security policy module. <command>restorecon</command> is a command
+       to assign given directories its default security context recursively.
+     </para>
+
+     <para>
+       As we note later, all the files and directories to store database
+       cluster should be labeled as <literal>postgresql_db_t</literal>.
+       The default security policy assumes it is constructed at
+       <filename>/var/lib/pgsql/data</filename> as RPM doing.
+
+       If you want to set up it on another directory, you need to label
+       it by hand.
+     </para>
+ <screen>
+ <prompt># </prompt><userinput>mkdir -p $PGDATA</userinput>
+ <prompt># </prompt><userinput>chcon -t postgresql_db_t -R $PGDATA</userinput>
+ </screen>
+         <para>
+       Then, we need to run <command>initdb</command> to initialize
+       the database cluster. It is necessary to specify an option of
+       <option>--pgace-feature=selinux</option> which enables to initialize
+       database cluster with proper security context.
+
+       Without this option, no enhanced security feature will be activated
+       for the database cluster.
+     </para>
+ <screen>
+ <prompt>$ </prompt><userinput>initdb --pgace-feature=selinux</userinput>
+ <prompt>$ </prompt><userinput>pg_ctl start</userinput>
+ </screen>
+       </sect3>
+     </sect2>
+
+     <sect2>
+       <title>Backup and Restore</title>
+       <para>
+     When we restore a database from backups, we have to restore
+     its security context correctly as GRANT statement doing on
+     the restored table.
+       </para>
+
+       <para>
+     The <command>pg_dump</command> and <command>pg_dumpall</command>
+     have <option>--security-label</option> option to dump databases
+     with its security context.
+
+     The dumped image can be restored with proper security context.
+       </para>
+
+       <para>
+     Needless to say, a process which invokes <command>pg_dump</command>
+     must be allowed to refer whole of the database,
+     because SE-PostgreSQL filters all inaccessible tuples from the result
+     set, or aborts query execution if it references inaccessible
+     columns, tables, or functions.
+
+     These requirements are same when we restore the image.
+     A process which invokes <command>pg_restore</command> has to have
+     enough permission to create/insert these objects with the specified
+     security context.
+       </para>
+ <screen>
+ <prompt>$ </prompt><userinput>pg_dump --security-label postgres</userinput>
+     :
+       (snip)
+     :
+ --
+ -- Name: drink; Type: TABLE; Schema: public; Owner: kaigai; Tablespace:
+ --
+
+ CREATE TABLE drink (
+     id integer NOT NULL,
+     name character varying(48),
+     price integer
+ ) SECURITY_LABEL = 'system_u:object_r:sepgsql_table_t';
+     :
+       (snip)
+     :
+ --
+ -- Data for Name: drink; Type: TABLE DATA; Schema: public; Owner: kaigai
+ --
+
+ COPY drink (security_label, id, name, price) FROM stdin;
+ system_u:object_r:sepgsql_table_t       1       water   100
+ system_u:object_r:sepgsql_table_t       2       coke    120
+ system_u:object_r:sepgsql_table_t       3       juice   130
+ system_u:object_r:sepgsql_table_t       4       cofee   180
+ system_u:object_r:sepgsql_table_t:Classified    5       beer    240
+ system_u:object_r:sepgsql_table_t:Classified    6       sake    320
+ \.
+     :
+       (snip)
+     :
+ </screen>
+       <para>
+     This example shows a backup image with explicitly specified security
+     context on tables and tuples.
+
+     If a column has different security context from that of the table, it
+     must be specified explicitly in the <command>CREATE TABLE</command>
+     statement.
+       </para>
+     </sect2>
+
+     <sect2 id="sepostgresql-labeled-networks">
+       <title>Labeled Networks</title>
+       <para>
+     Labeled Networks is a technology which makes it possible to
+     obtain the security context of peer process communicating
+     via a TCP/IP connection.
+       </para>
+
+       <para>
+     This technology contains two facilities.
+     One is <literal>Labeled IPsec</literal>,
+     and the other is <literal>Static Fallback Context</literal>.
+
+     This section shows the way to set up both labeled networks
+     technology.
+       </para>
+
+       <sect3>
+     <title>Labeled IPsec</title>
+     <para>
+       When communicating using an encrypted channel
+       with IPsec, the key-exchange daemon <command>racoon</command>
+       on each machine exchanges encryption keys with its peer.
+
+       In addition, the security context of the connecting process is
+       delivered to the peer.
+
+       The delivered security context is cached on the kernel, and
+       it is exported into applications via the
+       <command>getpeercon(3)</command>.
+     </para>
+
+     <para>
+       This section introduces the steps to set up labeled ipsec,
+       but it is necessity minimum configuration, so we recommend
+       you to refer external technical documents related to ipsec
+       for more details.
+     </para>
+
+     <sect4>
+       <title>Example Environment</title>
+       <para>
+         In this introduction, we assume the server host where SE-PostgreSQL
+         works has an IP address of <literal>192.168.1.10</literal> and
+         the client host has IP address of <literal>192.168.1.200</literal>.
+
+         They are wired to same network, and can communicate each other
+         directly, without any router.
+       </para>
+
+       <para>
+         The purpose of the following configuration is to obtain
+         the security context of the process working on the client host
+         (<literal>192.168.1.200</literal>) from SE-PostgreSQL daemon
+         working on the server host (<literal>192.168.1.10</literal>),
+         when a connection is established.
+       </para>
+     </sect4>
+
+     <sect4>
+       <title>Adding a SPD entry</title>
+       <para>
+         It is needed to add an SPD (Security Policy Database) entry
+         to indicate applying IPsec on channels between two host.
+
+         Note that SPD is not a term of SELinux, it is a configuration
+         parameter of IPsec, although it's a bit confusable.
+       </para>
+
+       <para>
+         This example shows esp/transport mode should be applied on
+         outbounding packets from <literal>192.168.1.10</literal>
+         to <literal>192.168.1.200</literal>, and inbounding packets
+         from <literal>192.168.1.200</literal> to
+         <literal>192.168.1.10</literal>.
+ <programlisting>
+ spdadd 192.168.1.10 192.168.1.200 any
+ -ctx 1 1 "system_u:object_r:ipsec_spd_t:s0"
+ -P out ipsec
+ esp/transport//require;
+
+ spdadd 192.168.1.200 192.168.1.10 any
+ -ctx 1 1 "system_u:object_r:ipsec_spd_t:s0"
+ -P in ipsec
+ esp/transport//require;
+ </programlisting>
+             In addition, the second line of each entries enables to
+             turn on security context delivery during key exchanging.
+       </para>
+       <para>
+         You can load the above configuration using
+         <command>setkey</command> command.
+
+         Save your configuration into a temporary file,
+         and invoke <command>setkey</command> with the file
+         as an argument.
+ <screen>
+ <prompt># </prompt><userinput>/sbin/setkey -f <your configuration file></userinput>
+ </screen>
+       </para>
+       <para>
+         It is necessary to do this on both server side and client side.
+
+         Note that you have to switch the IP addreses on the client side.
+       </para>
+     </sect4>
+
+     <sect4>
+       <title>Racoon configuration</title>
+       <para>
+         In the next, we have to edit a configuration file of
+         <command>racoon</command> to specify encryption algorithm,
+         authentication method and so on.
+
+         This example uses pre shared key to authenticate the peer
+         host (<literal>192.168.1.200</literal>) for simplification.
+
+         Note that you have to switch the IP addresses on the client side.
+       </para>
+
+       <para>
+         An additional entry to
+         <filename>/etc/racoon/racoon.conf</filename>.
+ <programlisting>
+ remote 192.168.1.200
+ {
+     exchange_mode aggressive, main;
+     my_identifier address;
+     proposal {
+         encryption_algorithm 3des;
+         hash_algorithm sha1;
+         authentication_method pre_shared_key;
+         dh_group 2 ;
+     }
+ }
+ </programlisting>
+       </para>
+       <para>
+         We have to put a set of key string and IP address of destination
+         in <filename>/etc/racoon/psk.txt</filename>.
+
+         The key string has also to be same in the client side.
+ <programlisting>
+ # file for pre-shared keys used for IKE authentication
+ # format is: 'identifier' 'key'
+ # For example:
+ #
+ # 10.1.1.1 flibbertigibbet
+ # www.example.com 12345
+ # foo@www.example.com micropachycephalosaurus
+ 192.168.1.200    somethingsecrettext
+ </programlisting>
+           </para>
+     </sect4>
+
+     <sect4>
+       <title>Restart Racoon</title>
+       <para>
+         Restart racoon daemon in both peers.
+       </para>
+ <screen>
+ <prompt># </prompt><userinput>service racoon restart</userinput>
+ </screen>
+     </sect4>
+       </sect3>
+
+       <sect3>
+     <title>Static Fallback Context</title>
+     <para>
+       We cannot apply labeled IPsec for any situation.
+
+       It requires both server and cliets being SElinux'ed and IPsec is
+       available on their communication channel.
+     </para>
+     <para>
+       SELinux provides an alternative method to identify a security
+       context of peer process inside the <literal>getpeercon(3)</literal>,
+       when a connection come from unlabeled networks.
+
+       This facility is called as static fallback context.
+       It enables to return a security context associated with IP address
+       or network interfaces, as if a new connection come from labeled
+       networks.
+     </para>
+     <para>
+       <command>netlabelctl</command> within
+       <literal>netlabel_tools</literal>
+       package can be used to set up static fallback context.
+     </para>
+     <para>
+       The following example shows a case when we associate a security
+       context with connections come from <literal>192.168.1.0/24</literal>
+       via all network interfaces.
+ <screen>
+ <prompt># </prompt><userinput>/sbin/netlabelctl unlbl add default address:192.168.1.0/24
label:user_u:user_r:user_t:s0</userinput>
+ </screen>
+           The following example shows a case when we associate a security
+           context with connections come from <literal>192.168.2.0/24</literal>
+           via <literal>eth0</literal>.
+ <screen>
+ <prompt># </prompt><userinput>/sbin/netlabelctl unlbl add dev:eth0 address:192.168.2.0/24
label:staff_u:staff_r:staff_t:s0:c0</userinput>
+ </screen>
+     </para>
+       </sect3>
+     </sect2>
+   </sect1>
+
+   <sect1 id="sepostgresql-policy">
+     <title>Making a Security Policy</title>
+     <para>
+       This section introduces steps to make your own security policy
+       modules, and to install them.
+     </para>
+   </sect1>
+ </chapter>
diff -Nrpc base/doc/src/sgml/user-manag.sgml sepgsql/doc/src/sgml/user-manag.sgml
*** base/doc/src/sgml/user-manag.sgml    Wed Oct 29 13:39:02 2008
--- sepgsql/doc/src/sgml/user-manag.sgml    Tue Jan 27 18:48:27 2009
*************** DROP ROLE <replaceable>name</replaceable
*** 502,505 ****
--- 502,655 ----
    </para>
   </sect1>

+  <sect1 id="row-level-database-acls">
+    <title>Row-level Database ACLs</title>
+    <para>
+      This section introduces design and implementation of the Row-level
+      Database ACLs in PostgreSQL. It makes it possible to assign ACLs
+      to each individual tuple, and works as a supplemental facility to
+      existing database ACLs applied to tables and columns.
+    </para>
+
+    <sect2>
+      <title>Design</title>
+      <para>
+        The design of Row-level Database ACLs feature inherits many things
+        from existing access control mechanism. For example, it is a sort
+        of discretionary access control mechanism, so it allows the owner of
+        a resource to change its access control rights, and does not affect
+        database superusers.
+      </para>
+      <para>
+        This feature is implemented as a guest of PGACE security framework,
+        but wired feature, not a selectable one.
+      </para>
+      <para>
+        It works as if there is a filter to drop inaccessible tuples on scanning
+        the relation. Just before the executor scans relation, tables and
+        columns level ACLs are also checked, and the feature makes a decision
+        as to whether the tuple should be returned, ot not.
+      </para>
+      <para>
+        We provides four kind of permissions on tuples.
+        These are <literal>SELECT</literal>, <literal>UPDATE</literal>,
+        <literal>DELETE</literal> and <literal>REFERENCES</literal>.
+
+        An <literal>INSERT</literal> permission would not make sense,
+        because the target does not exist when it should be checked.
+
+        You should control insertion of tuples via table-level ACLs.
+      </para>
+      <para>
+        PostgreSQL implements foreign key constraints as built-in trigger
+        functions, and it invokes another query to maintain referential
+        integrity.
+
+        It is an exception case of the filtering. In this case, it raises
+        an error to abort current transation, if the query tries to fetch
+        an inaccessible tuple.
+
+        As with SE-PostgreSQL, unprivileged users may be able to infer
+        information about tuples they cannot access directly.
+      </para>
+      <para>
+        This feature is activated via table option of
+        <literal>row_level_acl</literal>. It can heve either of
+        <literal>on</literal> or <literal>off</literal> in the default.
+
+        It enables us to refer or set per-tuple ACLs via the
+        <literal>security_acl</literal> system column.
+        We can modify it via <literal>UPDATE</literal>,
+        <literal>INSERT</literal> with explict ACLs on the system column.
+
+        A feature to set default ACLs is also available.
+        A new table option of <literal>default_row_acl</literal> enables to
+        specify a default ACLs of for newly inserted tuples.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Administration</title>
+      <sect3>
+        <title>Setup Row-level ACLs</title>
+        <para>
+      The <literal>row_level_acl</literal> table option on
+      <literal>CREATE TABLE</literal> or <literal>ALTER TABLE</literal>
+      is used to activate the Row-level Database ACLs.
+        </para>
+ <screen>
+ <prompt># </prompt><userinput>CREATE TABLE drink (
+       id      int primary key,
+       name    text,
+       price   int
+   ) WITH (row_level_acl=on);</userinput>
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "drink_pkey" for table "drink"
+ CREATE TABLE
+ </screen>
+        <para>
+      We can set Row-level ACLs via <literal>security_acl</literal>
+      system column.  For example:
+        </para>
+ <screen>
+ <prompt># </prompt><userinput>UPDATE drink SET security_acl = '{=r/postgres}' WHERE id in (3,4,5);</userinput>
+ UPDATE 3
+ <prompt># </prompt><userinput>SELECT security_acl, * FROM drink order by id;</userinput>
+          security_acl           | id | name  | price
+ --------------------------------+----+-------+-------
+  {kaigai=rwd/kaigai}            |  1 | water |   100
+  {kaigai=rwd/kaigai}            |  2 | coke  |   120
+  {=r/kaigai}                    |  3 | juice |   130
+  {=r/kaigai}                    |  4 | cofee |   180
+  {=r/kaigai}                    |  5 | beer  |   240
+  {kaigai=r/kaigai,ymj=r/kaigai} |  6 | sake  |   320
+ (6 rows)
+ </screen>
+        <para>
+      The database user must have ownership of the relation or privileges
+      of database superuser in order to update
+      <literal>security_acl</literal>.
+
+      Please note that this feature considers the owner of a tuple to be
+      the owner of the table in which they are stored, rather than the
+      client who inserted the tuple.
+        </para>
+      </sect3>
+
+      <sect3>
+        <title>Backup and Restore</title>
+        <para>
+      The <literal>--security-acl</literal> option to
+      <command>pg_dump</command> and <command>pg_dumpall</command>
+      can be used to dump tables with row-level ACLs.  With this option,
+      the output will contain the <literal>security_acl</literal> system
+      column if the row-level ACLs feature is enabled on the target
+      table.
+        </para>
+ <screen>
+ <prompt>$ </prompt><userinput>pg_dump --security-acl postgres</userinput>
+           :
+ CREATE TABLE drink (
+     id integer NOT NULL,
+     name text,
+     price integer
+ )
+ WITH (row_level_acl=on);
+           :
+ --
+ -- Data for Name: drink; Type: TABLE DATA; Schema: public; Owner: kaigai
+ --
+
+ COPY drink (security_acl, id, name, price) FROM stdin;
+ {kaigai=rwd/kaigai}     1       water   100
+ {kaigai=rwd/kaigai}     2       coke    120
+ {=r/kaigai}     3       juice   130
+ {=r/kaigai}     4       coffee  180
+ {=r/kaigai}     5       beer    240
+ {kaigai=r/kaigai,ymj=rw/kaigai} 6       sake    320
+ \.
+           :
+ </screen>
+      </sect3>
+    </sect2>
+  </sect1>
  </chapter>

pgsql-hackers by date:

Previous
From: Mark Kirkwood
Date:
Subject: Re: 8.4 release planning
Next
From: Bernd Helmle
Date:
Subject: Re: [COMMITTERS] pgsql: Automatic view update rules Bernd Helmle