NB SQL

From SELinux Wiki
Revision as of 16:39, 15 January 2011 by RichardHaines (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

SELinux PostgreSQL Support

This section gives an overview of the SE-PostgreSQL (version 8.4) extensions to support SELinux in F-12 and how the database context information is managed. It assumes some basic knowledge of PostrgreSQL that can be found at the following web site:

http://wiki.postgresql.org/wiki/Main_Page

For a more in-depth overview of SE-PostgreSQL the "Security-Enhanced PostgreSQL Security Wiki" is recommended.

SE-PostgreSQL Overview

SE-PostgreSQL adds SELinux mandatory access controls (MAC) to database objects such as databases, tables, columns, rows (tuples), procedures and blobs (binary large objects)[1]. Figure 1 shows a simple database with one table, two columns and three rows, each with their object class and associated security context. The database object classes and permissions are described in the Object Classes and Permissions section.

database (db_database)
security_context = 'unconfined_u:object_r:sepgsql_db_t:s0:c999'
table (db_table)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c10'
column 1 (db_column)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c20'
column 2 (db_column)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c30'
row 1 (db_tuple)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c100'
1:1 Information
1:2 Information
row 2 (db_tuple)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c200'
2:1 Information
2:2 Information
row 3 (db_tuple)
security_context = 'unconfined_u:object_r:sepgsql_table_t:s0:c300'
3:1 Information
3:2 Information

Figure 1: Database Security Context Information - Showing the security contexts that can be associated to a database, table, columns and rows. It is also possible to associate security contexts to procedures and blobs.


SE-PostgreSQL Database Example has a walk-through on how to install SE-PostgreSQL on F-12 with setting up a database, adding tables etc. to show how the security context is used to enforce access control.

To use SE-PostgreSQL each GNU / Linux user must have a valid PostgreSQL database role (not to be confused with an SELinux role). The default installation shown in the SE-PostgreSQL Database Example section automatically adds a user called sepgsql with a suitable database role.

If a client is connecting remotely and labeled networking is required, then it is possible to use IPSec or NetLabel as discussed in the SELinux Networking Support section (the "Security-Enhanced PostgreSQL Security Wiki" also covers these methods of connectivity with examples).

Using the SE-PostgreSQL Services diagram, the database client application (that could be provided by an API for Perl/PHP or some other programming language) connects to a database and executes SQL commands. As the SQL commands are processed by PostgreSQL, each operation performed on an object managed by the object manager (OM) is checked to see if this is allowed by the security policy or not. If the internal AVC does not hold the cached decision then the SELinux kernel Security Server is asked to resolve the query, with the result being cached internally by the OM.

Because PostgreSQL (and therefore SE-PostgreSQL) handles processes, files and directories as part of database operations, the OM also handles permissions for these objects where needed (see the sepostgresql-8.4.2-2583.fc12.src rpm - perms.c source code) by re-mapping these permissions internally.

SE-PostgreSQL supports SELinux services via the libselinux library, however it does not use the libselinux AVC API functions as it provides its own services. The AVC audits are logged into the sepostgresql.log file as described in the Logging Security Events section.

The SE-PostgreSQL extensions to support MAC access control are described in the SE-PostgreSQL Extensions section below.

SE-PostgreSQL Extensions

The following sections describe the areas that have been extended to manage the security context information and enforce access control. There are a number of examples shown in the SE-PostgreSQL Database Example section that contains a walk-through of the installation, set-up and using SE-PostgreSQL to build a simple database with a single table, two columns and then adding a number of rows.

The main areas expanded are:

  • Adding an object manager that utilises SELinux support for policy enforcement via libselinux as shown in the SE-PostgreSQL Services diagram. This runs as the sepostgresql server (replacing the postgresql server).
The PostgreSQL internal tables (the system catalog) have also been enhanced to support security context information and are described in the Internal Tables section.
  • Extending SQL statements to support a security context field.
  • Adding additional SQL functions to support viewing and updating security context information.
  • Modifying utilities to support security context information.

The sections that follow give a brief overview of the extensions added to support SE-PostgreSQL.

Extended SQL Statements

The following SQL Statements have been extended to add a SECURITY_CONTEXT = 'security_context' field to support SE-PostgreSQL:

CREATE DATABASE ALTER DATABASE
CREATE TABLE ALTER TABLE
CREATE FUNCTION ALTER FUNCTION


For example to create a table with a specific security context, execute:

testdb=# CREATE TABLE info () SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c10';
CREATE TABLE

Additional SQL Functions

The following functions have been added to manage the additional security context entries (examples are shown in SE-PostgreSQL Database Example section):

sepgsql_getcon Returns the client security context.
sepgsql_server_getcon Returns security context of the sepostgresql server.
sepgsql_get_user

sepgsql_set_user

Returns or sets the user portion of the security context.
sepgsql_get_role

sepgsql_set_role

Returns or sets the role portion of the security context.
sepgsql_get_type

sepgsql_set_type

Returns or sets the type portion of the security context.
sepgsql_get_range

sepgsql_set_range

Returns or sets the range portion of the security context.
lo_get_security

lo_set_security

Returns or sets the security context of a binary large object.
security_reclaim_label Reclaims orphaned security context entries from the internal pg_security table.
security_label_to_secid Returns the secid column entry from the pg_security table for the requested security context.

Additional Utilities

The pg_dump and pg_dumpall backup and restore utilities have been made SELinux-aware so that the security context is maintained.

An additional utility called sepg_ctl is also supplied that can be used to start, stop, restart, reload configuration files and report the status of a postgresql or sepostgresql server. sepg_ctl --help will list all the options.

Additional postgresql.conf Entries

The postgresql.conf file has the following additional entries added to manage the sepostgresql process[2]:

sepostgresql SE-PostgreSQL activation option on or off. The default is on.
sepostgresql_mcstrans If on (the default) SE-PostgreSQL uses mcstrans to translate the raw security context to a readable text field. If off the context is not translated.
sepostgresql_row_level If on (the default), then row-level access controls (the db_tuple object class) will be enforced. If off row-level access control is not enforced.


Internal Tables

To support the overall database operation PostgreSQL has internal tables in the system catalog that hold information relating to user databases, tables etc. This section will only highlight the internal tables and their columns used by SE-PostgreSQL to support the object classes and security context entries using examples taken from the SE-PostgreSQL Database Example section.

Table 1 describes each of the tables used by SE-PostgreSQL to support security context relationships with example SELECT statements to retrieve the relevant information. The only internal table to actually hold security context strings is the pg_security table as all others reference these strings using identifiers as described in Table 2.

Internal Table Name Object Object Class Comments
pg_database Database db_database The datname column holds the database name.
SELECT datname, security_context FROM pg_database WHERE datname = 'testdb';

datname  | security_context
---------+-------------------------------------
testdb   | unconfined_u:object_r:sepgsql_db_t:s0
pg_class Table db_table The relname column holds the table name.

The relnatts column holds the number of columns in this table.

The relfilenode column value is that contained in the pg_security.relid entry for each row of the table (as they are related).

SELECT relname, security_context, relnatts, relfilenode FROM pg_class WHERE relname = 'info';

relname  | security_context                              | relnatts   | relfilenode
---------+-----------------------------------------------+------------+-------------
info     | unconfined_u:object_r:sepgsql_table_t:s0:c10  | 2          | 16389
pg_attribute Column db_column The attname column holds the column name.

The attnum column holds the column number.

The attrelid column value is that contained in the pg_security.relid entry for each row of the table (as they are related).

SELECT attname, security_context, attnum, attrelid FROM pg_attribute WHERE attrelid = 'info'::regclass AND
 attnum > 0;

attname      | security_context                              | attnum | attrelid
-------------+-----------------------------------------------+--------+-----------
user_name    | unconfined_u:object_r:sepgsql_table_t:s0:c20  | 1      | 16389
email_addr   | unconfined_u:object_r:sepgsql_table_t:s0:c30  | 2      | 16389
pg_security Row db_tuple The pg_security table holds the security context strings and pointers for all objects including the rows (or tuples) as described in Table 2.

Table 1: PostgreSQL Internal Tables - Note that each table has other columns containing information, however only that relevant to the overview are described.


Table 2 describes each of the columns defined in the pg_security table with example entries after the table.

pg_security Column
Comment
secid The unique identifier for this security context. The context is unique for this database (the datid column) and related OID (the relid column for the table, procedure, row etc.).
datid The OID of the database to which this entry refers. This can be obtained from the pg_stat_database table as shown in the following example (that will list all contexts used by this instance of the database):
SELECT datname, secid, relid, secattr FROM pg_security, pg_stat_database WHERE pg_security.datid = pg_stat_database.datid AND
 datname='testdb';
relid The OID of an object (table, column etc.) or the related ID of a row.

This section will only describe the table, column and row entries for relid. There are many others that relate to internal OIDs used by PostgreSQL that are beyond the scope of this Notebook[3].

For tables an OID of '1259' is assigned. These relate to table names in the pg_class internal table.

For columns an OID of '1249' is assigned. These relate to column names in the pg_attribute internal table.

For rows inserted into a table this is the related pg_class.relfilenode and pg_attribute.attrelid entry for that table / column.

seckind This is currently 'l' for label.
secattr Text string of the security context for the object (database, table etc.).

Table 2: pg_security Table Columns


The following are example entries with comments taken from the pg_security table columns that were displayed using SELECT * FROM pg_security;:

# datid '1' is for an internal PostgreSQL database.
# relid '3764' is the pg_ts_template OID
# Therefore this context is assigned to a system template object.

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
 3380 | 1     | 3764  | l       | unconfined_u:object_r:sepgsql_sysobj_t:s0
# datid '1' is for an internal PostgreSQL database.
# relid '1255' is the pg_proc (procedure) OID
# Therefore this context is assigned to a system procedure object.

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
3397  | 1     | 1255  | l       | unconfined_u:object_r:sepgsql_db_t:s0
# datid '0' is assigned to an internal database.
# relid '1262' is the pg_database (database) OID
# Therefore this context entry is assigned to database objects. 
#
# Note that datid = 0 and relid = 1262 entries define contexts assigned to 
# database instances including 'testdb' (but see next example).

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
3399  | 0     | 1262  | l       | unconfined_u:object_r:sepgsql_db_t:s0
# This example is for the 'testdb' database after altering its context from the
# above default to 'unconfined_u:object_r:sepgsql_db_t:s0:c888' using:

ALTER DATABASE testdb SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_db_t:s0:c888'

# This will insert an additional entry into the pg_security table as follows:

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
3400  | 0     | 1262  | l       | unconfined_u:object_r:sepgsql_db_t:s0:c888
# datid '16384' is assigned by the system as the identifier for testdb database.
# relid '1259' is the pg_class (table) OID
# Therefore this entry is for a table in the testdb database.

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
16385 | 16384 | 1259 | l        | unconfined_u:object_r:sepgsql_table_t:s0:c10
# datid '16384' is assigned by the system as the identifier for testdb database.
# relid '1249' is the pg_attribute (column) OID
# Therefore this entry is for a column in a table in the testdb database.

secid | datid | relid | seckind | secattr 
------+-------+-------+---------+--------------------------------------------
16386 | 16384 | 1249  | l       | unconfined_u:object_r:sepgsql_table_t:s0
# datid '16384' is assigned by the system as the identifier for testdb database.
# relid '16389' is a system pointer back to the table (pg_class.relfilenode) and
# column (pg_attribute.attrelid) in testdb database for a row of data.
# Therefore this entry represents the context for a row (tuple) of data in a
# table of the testdb database.

 secid | datid | relid | seckind | secattr 
-------+-------+-------+---------+--------------------------------------------
16393  | 16384 | 16389 | l       | unconfined_u:object_r:sepgsql_table_t:s0:c110

Logging Security Events

SE-PostgreSQL manages its own AVC audit entries in the /var/log/sepostgresql.log file and by default only errors are logged (i.e. it does not add AVC entries into the standard audit.log). To be able to see greater detail then the boolean sepgsql_enable_audit_allow can be enabled (although this does show much gory detail). A pre-requisite is that the sepostgresql-devel policy module is installed. If the SE-PostgreSQL package has been installed as shown in the SE-PostgreSQL Database Example section, then the policy module would have been installed but not activated. To activate the module:

semodule -i /usr/share/selinux/packages/sepostgresql-devel.pp

Once installed, the boolean can be enabled by:

setsebool -P sepgsql_enable_audit_allow on

The following examples show an sepostgresql.log sequence when the sepgsql_enable_audit_allow boolean has been enabled and a user connects to a database and then performs a SELECT statement.

The following commands are executed:

# Connect to a database with the psql client:
psql testdb

# Issue a SELECT statement to retrieve information:
testdb=# SELECT user_name, email_addr, security_context FROM info;

user_name | email_addr         | security_context 
----------+--------------------+-------------------------------------------
fred      | fred@yahoo.com     | unconfined_u:object_r:sepgsql_table_t:s0:c100
derf      | derf@hotmail.com   | unconfined_u:object_r:sepgsql_table_t:s0:c110
george    | george@hotmail.com | unconfined_u:object_r:sepgsql_table_t:s0:c120
(3 rows)

And the resulting sepostgresql.log entries would be:

# This is the 'psql testdb' sequence:
LOG: SELinux: granted { access } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name=testdb

# This is the 'SELECT user_name, email_addr, security_context FROM info;' sequence of events.
LOG: SELinux: granted { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c10 tclass=db_table name=info
STATEMENT: SELECT user_name, email_addr, security_context FROM info;

LOG: SELinux: granted { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name=info.security_context
STATEMENT: SELECT user_name, email_addr, security_context FROM info;

LOG: SELinux: granted { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c20 tclass=db_column name=info.user_name
STATEMENT: SELECT user_name, email_addr, security_context FROM info;

LOG: SELinux: granted { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c30 tclass=db_column name=info.email_addr
STATEMENT: SELECT user_name, email_addr, security_context FROM info;

SE-PostgreSQL Database Example

Introduction

This section gives a run through installing and running a very simple database to show some of the SE-PostgreSQL features. The "Security-Enhanced PostgreSQL Security Wiki" contains a more complete coverage of the principles, however it does not have a simple walk-through.

The areas covered are:

  • Install sepostgresql using yum. It assumes that postgresql or sepostgresql are not installed.
  • Initialise a database cluster so that sepostgresql can be started.
  • Create a database called testdb.
  • Using the PostgreSQL terminal client psql create a simple table with two columns and insert 4 rows (or tuples) of data demonstrating how to add and show the security context information associated with these objects. To enable the security context information to be distinguished between the various objects the following will be used:
Name Object Context used
Database (testdb) db_database unconfined_u:object_r:sepgsql_db_t:s0
Table (info) db_table unconfined_u:object_r:sepgsql_table_t:s0:c10
Column 1 (user_name) db_column unconfined_u:object_r:sepgsql_table_t:s0:c20
Column 2 (email_addr) db_column unconfined_u:object_r:sepgsql_table_t:s0:c30
Row 1 db_tuple unconfined_u:object_r:sepgsql_table_t:s0:c100
Row 2 db_tuple unconfined_u:object_r:sepgsql_table_t:s0:c110
Row 3 db_tuple unconfined_u:object_r:sepgsql_table_t:s0:c120
Row 4 db_tuple unconfined_u:object_r::unconfined_t:s0:c130
  • Finally run some sepostgresql specific functions and explain their results.


The following assumptions have been made:

  1. The user has a basic knowledge of databases and the SQL language.
  2. SE-PostgreSQL or PostgreSQL are not installed.
  3. The system used is Fedora 12 with the targeted policy (selinux-policy-targeted-3.6.32-103.fc12.noarch). This would have installed the postgresql policy modules by default.
  4. Generally when adding entries to a database SE-PostgreSQL will use a default security context, however in this walk-through all entries will have specific security context defined for them (except the database (testdb) that will use the SE-PostgreSQL default).

SE-PostgreSQL Walk-through

Install sepostgresql using yum. This will install all the required components including postgresql:

yum install sepostgresql

On the authors machine, the following were installed:

rpm -qa | grep postgresql

sepostgresql-8.4.2-2583.fc12.i686
postgresql-libs-8.4.3-1.fc12.i686
postgresql-8.4.3-1.fc12.i686
postgresql-server-8.4.3-1.fc12.i686

Ensure SELinux is in enforcing mode:

setenforce 1

Once sepostgresql is installed a database cluster needs to be initialised. As part of the sepostgresql installation an init script (/etc/init.d/sepostgresql) was added that will manage this process:

service sepostgresql initdb
Initializing database:

For information, the database cluster will be built by the above process in /var/lib/sepgsql/data. Note that an sepgsql user and group were also added as a part of the installation process:

ls -lZ /var/lib/sepgsql
drwx------. 2 sepgsql sepgsql system_u:object_r:postgresql_db_t:s0 backups
drwx------. 2 sepgsql sepgsql unconfined_u:object_r:postgresql_db_t:s0 data

Once the database cluster has been initialised it can be started by:

service sepostgresql start
Starting sepostgresql service: [ OK ]

This demo will create the test database and tables etc. as the sepgsql user:

su - sepgsql

Optionally, once logged on as the sepgsql user, the PostgreSQL createuser command can be used to allow other GNU / Linux users to access PostgreSQL by:

createuser [login_name]

# for example:
createuser root
Shall the new role be a superuser? (y/n) y
# This would allow root to use the PostgreSQL commands to manage
# the database as a superuser.

Now the testdb database itself needs to be created by the PostgreSQL createdb command:

createdb testdb

Once created, the PostgreSQL interactive terminal (psql) needs to be loaded so that SQL statements can be run against the database:

# This command will load psql and connect it to the testdb database:
psql testdb

Now that psql is active and connected to the testdb database SQL statements can be run. The first one is to display the security context of the database that requires some knowledge of how SE-PostgreSQL holds its internal parameters. As explained in the SELinux PostgreSQL Support section the main internal tables of interest are pg_database, pg_class, pg_attribute and pg_security, with pg_database holding the database name. Therefore if the following SQL statement is executed, the security context of the testdb database will be returned:

testdb=# SELECT datname, security_context FROM pg_database 
WHERE datname = 'testdb';

datname  | security_context 
---------+---------------------------------------
testdb   | unconfined_u:object_r:sepgsql_db_t:s0
(1 row)

Now a table (info) will be created that will have two columns (user_name and email_addr). A unique security context will be given to each object created as follows:

testdb=# CREATE TABLE info (user_name CHAR(10) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c20', 
email_addr CHAR(20) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c30'
) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c10';
CREATE TABLE

Now that the table has been created, the security context of each object can be displayed by querying SE-PostgreSQL internal tables.

The SQL statement to retrieve the table object info security context is as follows, note that the pg_class internal table holds the table name:

testdb=# SELECT relname, security_context FROM pg_class WHERE relname = 'info'; 

relname  | security_context 
---------+----------------------------------------------
info     | unconfined_u:object_r:sepgsql_table_t:s0:c10
(1 row)

The SQL statement to retrieve the column object user_name is as follows, note that the pg_attribute internal table holds the column name:

testdb=# SELECT attname, security_context FROM pg_attribute WHERE attname = 'user_name';

attname    | security_context 
-----------+----------------------------------------------
user_name  | unconfined_u:object_r:sepgsql_table_t:s0:c20
(1 row)

And the SQL statement to retrieve the column object email_addr is as follows:

testdb=# SELECT attname, security_context FROM pg_attribute WHERE attname = 'email_addr';

attname     | security_context 
------------+----------------------------------------------
email_addr  | unconfined_u:object_r:sepgsql_table_t:s0:c30
(1 row)

Now that the table and its columns have been created, it is now possible to insert information into the database. Each row (or tuple) will now be added with its own unique security context.

Insert Row 1:

testdb=# INSERT INTO info (security_context, user_name, email_addr) 
 VALUES ('unconfined_u:object_r:sepgsql_table_t:s0:c100', 'fred', 'fred@yahoo.com');
INSERT 0 1

Show Row 1 security context, note that only the table name info is specified (i.e. no internal table name required):

testdb=# SELECT user_name, email_addr, security_context FROM info;

user_name  | email_addr      | security_context 
-----------+-----------------+-------------------------------------------
fred       | fred@yahoo.com  | unconfined_u:object_r:sepgsql_table_t:s0:c100
(1 row)

Insert Rows 2 and 3 each with a unique security context:

testdb=# INSERT INTO info (security_context, user_name, email_addr) VALUES 
 ('unconfined_u:object_r:sepgsql_table_t:s0:c110', 'derf', 'derf@hotmail.com');
INSERT 0 1

testdb=# INSERT INTO info (security_context, user_name, email_addr) VALUES
 ('unconfined_u:object_r:sepgsql_table_t:s0:c120', 'george', 'george@hotmail.com');
INSERT 0 1

Show Rows 1, 2 and 3 security context:

testdb=# SELECT user_name, email_addr, security_context FROM info;

user_name | email_addr         | security_context 
----------+--------------------+--------------------------------------------
fred      | fred@yahoo.com     | unconfined_u:object_r:sepgsql_table_t:s0:c100
derf      | derf@hotmail.com   | unconfined_u:object_r:sepgsql_table_t:s0:c110
george    | george@hotmail.com | unconfined_u:object_r:sepgsql_table_t:s0:c120
(3 rows)

To demonstrate that SE-PostgreSQL will not allow entries to be entered unless the security context is valid, an entry will be made with a type of unconfined_t as this is not valid for the standard targeted policy. It is assumed that SELinux is in enforcing mode:

testdb=# INSERT INTO info (security_context, user_name, email_addr) VALUES 'unconfined_u:object_r:unconfined_t:s0:c130', 'hidden', 'hidden@hotmail.com');
ERROR: SELinux: security policy violation

Now to demonstrate that SE-PostgreSQL will not display information that is not allowed by the policy, set SELinux to permissive mode:

setenforce 0

Now insert the row again:

testdb=# INSERT INTO info (security_context, user_name, email_addr)
 VALUES 'unconfined_u:object_r:unconfined_t:s0:c130', 'hidden', 'hidden@hotmail.com');
INSERT 0 1

And then display the information:

testdb=# SELECT user_name, email_addr, security_context FROM info;

user_name | email_addr         | security_context 
----------+--------------------+-----------------------------------------
fred      | fred@yahoo.com     | unconfined_u:object_r:sepgsql_table_t:s0:c100
derf      | derf@hotmail.com   | unconfined_u:object_r:sepgsql_table_t:s0:c110
george    | george@hotmail.com | unconfined_u:object_r:sepgsql_table_t:s0:c120
hidden    | hidden@hotmail.com | unconfined_u:object_r:unconfined_t:s0:c130
(4 rows)

Now set SELinux to enforcing mode:

setenforce 1

And then display the information, note that the 4th row is not displayed:

testdb=# SELECT user_name, email_addr, security_context FROM info;

user_name | email_addr         | security_context 
----------+--------------------+-------------------------------------------
fred      | fred@yahoo.com     | unconfined_u:object_r:sepgsql_table_t:s0:c100
derf      | derf@hotmail.com   | unconfined_u:object_r:sepgsql_table_t:s0:c110
george    | george@hotmail.com | unconfined_u:object_r:sepgsql_table_t:s0:c120
(3 rows)


SE-PostgreSQL Functions

This section will demonstrate some of the additional SE-PostgreSQL functions using the example database 'testdb'.

Get / Set Security Context Components

There are functions to get/set the security context components and this example shows the sepgsql_get/set_range function.

Show the range component:

testdb=# SELECT sepgsql_get_range(security_context), user_name, email_addr FROM info;

sepgsql_getrange | user_name | email_addr 
-----------------+-----------+----------------------
s0:c100          | fred      | fred@yahoo.com
s0:c110          | derf      | derf@hotmail.com 
s0:c120          | george    | george@hotmail.com
(3 rows)

Now change the range for the row that contains the user name of 'fred':

testdb=# UPDATE info SET security_context = sepgsql_set_range(security_context, 's0:c999') WHERE user_name = 'fred';
UPDATE 1

Now show the updated range component:

testdb=# SELECT sepgsql_get_range(security_context), user_name, email_addr FROM info;

sepgsql_getrange | user_name | email_addr 
-----------------+-----------+----------------------
s0:c110          | derf      | derf@hotmail.com 
s0:c120          | george    | george@hotmail.com
s0:c999          | fred      | fred@yahoo.com
(3 rows)


Get Connection Information

There are two functions to retrieve client and server context information and are shown below.

Get client context:

testdb=# SELECT sepgsql_getcon();

sepgsql_getcon 
-------------------------------------------------------
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

Get SE-PostgreSQL server context:

testdb=# SELECT sepgsql_server_getcon();

sepgsql_server_getcon 
---------------------------------------
unconfined_u:system_r:postgresql_t:s0
(1 row)

Reclaiming Unused Labels

When security contexts (labels) are no longer used, they are left in the pg_security table until they are reused or the space reclaimed. The following example runs the security_reclaim_label function that first returns 0, a row is then deleted (remember each row in the example database has a unique label) and the unused label space is then reclaimed.

Run function to check there whether there are labels to reclaim:

SELECT security_reclaim_label();

security_reclaim_label
----------------------------
                        1
(1 row)

The function claimed one label as the entry:

user_name  | email_addr     | security_context 
-----------+----------------+-------------------------------------------
fred       | fred@yahoo.com | unconfined_u:object_r:sepgsql_table_t:s0:c100

Was changed to:

user_name  | email_addr     | security_context 
-----------+----------------+-------------------------------------------
fred       | fred@yahoo.com | unconfined_u:object_r:sepgsql_table_t:s0:c999



  1. Version 8.5 will support additional database objects.
  2. For the default installation described in the SE-PostgreSQL Database Example section, the configuration file is located at /var/lib/sepgsql/data/postgresql.conf.
  3. Note that the database context (OID = 1262 in the relid column) is listed as being under the datid of database '0'. The best way to retrieve the actual database context is by: SELECT security_context FROM pg_database WHERE datname = '...';