SEPostgreSQL References

From PostgreSQL wiki
Jump to navigationJump to search

SepgsqlLogo.png

This chapter gives references for SE-PostgreSQL related stuffs.

  • List of chapters
  1. Introduction
  2. Architecture
  3. Specifications
  4. SELinux Overview
  5. Administration
  6. References
  7. Development

Object classes and access vector

Overview

SELinux represents its access permissions as a combination of object class and access vectors. The object class means the kind of objects, such as file, dir, tcp_socket and so on. All the available operations on a certain object depends on the type of the object, we cannot send a packet on a directory for instance, so the security policy defines a specific set of permissions for each object classes. We call them as access vectors.

This table introduces all the object classes and access vectors for database objects, currently we have.

Object classes and access vectors
db_database db_tablespace db_schema db_schema_temp db_table db_sequence db_procedure db_column db_tuple db_blob
create create create create create create create create create
drop drop drop drop drop drop drop drop drop
getattr getattr getattr getattr getattr getattr getattr getattr getattr
setattr setattr setattr setattr setattr setattr setattr setattr setattr
relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom relabelfrom
relabelto relabelto relabelto relabelto relabelto relabelto relabelto relabelto relabelto relabelto
access createon search search select get_value execute select select read
load_module add_name add_name update next_value entrypoint update update write
superuser remove_name remove_name insert set_value install insert insert import
delete untrusted delete export
lock

common database class

Some of access vectors are universal for database objects, so they are included within these object classes commonly. We introduces them (create, drop, getattr, setattr, relabelfrom and relabelto) in this section.

create
It is required on the database objects newly created, using CREATE xxx statement typically.
When we create new database objects, SE-PostgreSQL assigns a default security context (if no explicit one is not given) on them, then checks client's privileges on them with the default security context.
For example, when a user tries to create a new table, it may assign system_u:object_r:sepgsql_table_t:s0 on the new table, and checks user's db_table:{create} permission. If not allowed, SE-PostgreSQL prevents to execute the given query any more.
drop
It is required on the database objects to be dropped, using DROP xxx statement typically.
getattr
It is required on the database objects to be referred, using SELECT ... FROM <system catalog> statement typically.
setattr
It is required on the database objects to be updated, using ALTER xxx statement typically.
relabelfrom
It is required on the database objects with older security context, when we change the security context of them.
relabelto
It is required on the database objects with newer security context, when we change the security context of them.

db_database class

The db_database class represents the database object itself, and inherits the common database object class, so it has the common six access vectors.

The default security context
A database object performs as a root of TYPE_TRANSITION for any other database object. Thus, it does not have any parent object.
When the security policy gives a default context, SE-PostgreSQL tries to assign it. Its configuration can be stored at /etc/selinux/${POLICYTYPE}/contexts/sepgsql_context.
If no configuration given, it inherits the security context of the client process. However, the default security policy has TYPE_TRANSITION rules on them, so all the new databases will be labeled as sepgsql_db_t.
access
It is required when a client connects to a certain database. It performs as an analogy of ACL_CONNECT on the database acl mechanism.
load_module
It is required when a dynamic link library is loaded to the current address space.
The current database (not a client) needs to be allowed to load the library.
Please note that it is checked when a DLL is loaded, different from the db_database:{install_module}.
superuser
It is required when a client performs as a superuser on the database.
If the permission is not allowed, the client cannot perform as superuser, but SE-PostgreSQL does not raises an error. He can just perform as a non-privileged database user.

db_tablespace class

createon
It is required when a client tries to create something on the target tablespace.

db_schema class

The db_schema class represents schema object (not a temporary one), and inherits the common database object class, so it has the common six access vectors.

The default security context
It inherits the security context of the database where the schema object deployed on.
search
It is required when a client refers a database object within a certain schema object. It performs as an analogy of ACL_USAGE on schema objects.
add_object
It is required when a client creates a database object within a certain schema object.
remove_object
It is required when a client drops a database object within a certain schema object.

db_schema_temp class

The db_schema_temp class represents temporary scheme objects, and inherits the common database object class, so it has the common six access vectors.

The default security context
same as db_schema class.
search (not implemented now)
It should be required when a client refers a database object within a certain schema object.
add_object
same as db_schema:{add_object}
remove_object
same as db_schema:{remove_object}

db_table class

The db_table class represents regular table objects, and inherits the common database object class, so it has the common six access vectors.

The default security context
It inherits the security context of the schema where the table object deployed on.
The default policy has a few TYPE_TRANSITION rules on db_table class, so a new table will be labeled as sepgsql_table_t, user_sepgsql_table_t or unpriv_sepgsql_table_t.
select
It is required on the table to be refered via SELECT or COPY TO statement and others which contains any references such as RETURNING clause.
Please note that we can consider a reference within WHERE, ORDER BY and other clauses also require db_table:{select} permission, although it does not return the contents directly.
update
It is required on the table to be updated via UPDATE statement.
insert
It is required on the table to be inserted via INSERT or COPY FROM statement.
delete
It is required on the table to be deleted via DELETE or TRUNCATE statement.
lock
It is required on the table to be locked explicitly via LOCK statement, or SELECT ... FOR UPDATE/SHARE statement.
Please note that it is not required on implicit table locks.

db_procedure class

The db_procedure class represents SQL functions, and inherits the common database object class, so it has the common six access vectors.

The default security context
It inherits the security context of the schema where the SQL functions deployed on.
The default policy has a few TYPE_TRANSITION rules on db_procedure class, so a new table will be labeled as sepgsql_proc_exec_t, user_sepgsql_proc_exec_t or unpriv_sepgsql_proc_exec_t.
execute
It is required on the procedure to be executed. It performs as an analogy of ACL_EXECUTE on the database acl mechanism.
entrypoint
It is required on the procedure to be executed as a trusted procedure.
See the PUT HERE A PROPER URL for more details.
Trusted procedures causes a domain transition, so the process:{transition} also needs to be allowed.
The following policies are necessary when a client (staff_t) invokes a trusted procedure (sepgsql_trusted_proc_exec_t) that causes domain transition to sepgsql_trusted_proc_t.
Please note that we don't support to use built-in functions as trusted procedures due to implementation reason.
allow staff_t sepgsql_trusted_proc_exec_t : db_procedure { execute entrypoint };
allow staff_t sepgsql_trusted_proc_t : process { transition };
type_transition staff_t sepgsql_trusted_proc_exec_t : db_procedure sepgsql_proc_t;
install
It is required on the procedures to be installed as a part of system internal stuffs.
PostgreSQL invokes user defined functions as a part of server internal stuffs, so SE-PostgreSQL checks its correctness on its installation time.
untrusted
It is required on the creation of procedures which uses untrusted language, in addition to db_procedure:{create}

db_sequence class

The db_sequence class represents sequence objects, and inherits the common database object class, so it has the common six access vectors.

The default security context
It inherits the security context of the schema where the sequence object deployed on.
get_value
It is required on the sequence to be referred without any changes.
next_value
It is required on the sequence to be referred with an increment of the value.
set_value
It is required on the sequence to be set a given value.

db_column class

The db_column class represents table column objects, and inherits the common database object class, so it has the common six access vectors.

The default security context.
It inherits the security context of the table which contains the column.
select
It is required on the column which is referred via SELECT or COPY TO statement and others which contains any references such as RETURNING clause.
update
It is required on the column which is listed on UPDATE statement.
insert
It is required on the column which is listed on INSERT or COPY FROM statement.

db_tuple class

The db_tuple class represents tuples within a regular tables, and it contains six access vectors.

The default security context
It inherits the security context of the table which contains the tuple.
relabelfrom
It is required on the tuple with older context when it is relabeled.
relabelto
It is required on the tuple with newer context when it is relabeled.
select
It is required on the tuple to be selected.
update
It is required on the tuple to be updated.
insert
It is required on the tuple to be inserted.
delete
It is required on the tuple to be deleted.

db_blob class

The db_blob class represents binary large objects, and inherits the common database object class, so it has the common six access vectors.

The default security context
It inherits the security context of the database.
The default policy has a few TYPE_TRANSITION rules on db_blob class, so a new largeobject will be labeled as sepgsql_blob_t, user_sepgsql_blob_t or unpriv_sepgsql_blob_t.
read
It is required on the largeobject to be read with loread() or lo_export().
write
It is required on the largeobject to be written with lowrite(), lo_truncate() or lo_import().
import
It is required on the largeobject to be imported with lo_import() function, not only db_blob:{write}.
Please note that a largeobject is created with a default security context, so this permission is checked on the default one.
export
It is required on the largeobject to be exported with lo_export() function, not only db_blob:{read}.

The default security policy

Overview

This section introduces the list of pre-defined object types and booleans on the default security policy and sepostgresql-devel policy modules. In most cases, we don't need to write our own security policy module from the scratch. Please consider a possibility to achieve your security design with customization of the default security policy.

The default security policy defines various kind of domains. Some of them are called as unconfined domain, such as unconfined_t, on which widespread permissions are allowed. The default security policy also allows the unconfined domains anything on database objects with a few exceptions. Please note that the introductions in this section is intended to the domains except for unconfined domains, such as user_t and httpd_t.

Some of SELinux roles has its prefix (it is a conventional rule to write security policy), such as user, staff and so on. They has types related to the prefix like user_home_t. It enables role level separation, and the default security policy also defines the prefix'ed types for database objects. In this document, it is shown as (PREFIX) which can be replaced by user or others in actually.

Pre-defined types

Types for Databases

sepgsql_db_t
It is the only type we can assign on databases in the default security policy.
It allows confined domains to connect, but disallow to create, drop, alter the databases and to perform as a superuser on the databases.

Types for Tablespaces

sepgsql_tablespace_t
It is the only type we can assign on tablespace in the default security policy.
Currently, it does not provide a certain protection.

Types for Shemas

sepgsql_schema_t
sepgsql_schema_temp_t

Types for Tables

sepgsql_table_t
It is the default type for a new tables created by unconfined domain.
It allows confined domains all the DML operations (db_table:{select update insert delete}), but DDL operations are not disallowed.
sepgsql_fixed_table_t
It allows confined domains db_table:{select insert} only.
The purpose of the type is to protect information once inserted from unexpected manipulation or deletion.
An example usage is to store a document which have to be kept for a certain period for legal reasons.
sepgsql_ro_table_t
It allows confined domains db_table:{select} only.
The purpose of the type is to set up read-only table.
An example usage is to set up a master table of commodities which is not updatable.
sepgsql_secret_table_t
It allows confined domains nothing, so they need to access the type via trusted procedures, if provided.
An example usage is to store confidential information like credit card numbers.
sepgsql_sysobj_t
It is the default type of system catalogs.
It allows confined domains db_table:{select} only.
(PREFIX)_sepgsql_table_t
It is the default type for a new table created by prefixed domain.
It allows prefixed domains all the DML operations (db_table:{select update insert delete}), and it also allows them DDL operations (db_table:{create drop setattr} when sepgsql_enable_users_ddl is turned on.
An example usage is role based separation.
(PREFIX)_sepgsql_sysobj_t
It is the default type of tuples within system catalogs by prefixed domains.
It always allows prefixed domains db_tuple:{select}, and it also allows db_tuple:{update insert delete} when sepgsql_enable_users_ddl is turned on.
unpriv_sepgsql_table_t
It is the default type for a new table created by confined domain without prefixes.
It allows confined domains all the DML operations (db_table:{select update insert delete}), and it also allows them DDL operations (db_table:{create drop setattr} when sepgsql_enable_users_ddl is turned on.
unpriv_sepgsql_sysobj_t
It is the default type of tuples within system catalogs by confined domains without prefixes.
It always allows confined domains db_tuple:{select}, and it also allows db_tuple:{update insert delete} when sepgsql_enable_users_ddl is turned on.

Types for Sequences

sepgsql_seq_t
(PREFIX)_sepgsql_seq_t
unpriv_sepgsql_seq_t

Types for Procedures

sepgsql_proc_exec_t
It is the default type for a new functions defined by unconfined domains and initial setups.
It allows any domains to execute and install the functions, but disallows confined domains db_procedure:{create drop setattr}.
sepgsql_trusted_proc_exec_t
It is the type for trusted procedures.
It allows any domains to execute the function, then confined domains transit to an unconfined domain (sepgsql_trusted_proc_t). Because we don't need trusted procedures as a system internal stuff, db_procedure:{install} is not allowed.
The purpose of the type is to provide secure ways to access confidential information. Needless to say, only unconfined domains are allowed to set up trusted procedures, but should be done carefully.
(PREFIX)_sepgsql_proc_exec_t
It is the default type for a new functions defined by prefixed domains.
It allows prefixed domains db_procedure:{execute} and db_procedure:{create drop setattr} when sepgsql_enable_users_ddl is turned on.
But it disallow unconfined domains to execute the functions with this type, because we consider unconfined domains should not invoke user defined functions without validation of its safeness. If unconfined domains needs to invoke user defined functions, verify its declaration and relabel it to sepgsql_proc_t at first.
unpriv_sepgsql_proc_exec_t
It is the default type for a new functions defined by confined domains without prefixes.
It allows confined domains db_procedure:{execute} and db_procedure:{create drop setattr} when sepgsql_enable_users_ddl is turned on.
But it disallow unconfined domains to execute the functions with this type, because we consider unconfined domains should not invoke user defined functions without validation of its safeness. If unconfined domains needs to invoke user defined functions, verify its declaration and relabel it to sepgsql_proc_t at first.

Types for Large objects

sepgsql_blob_t
It is the default type for a new large object created by unconfined domains.
It allows confined domains to read and wrote, but does not allow to create, drop and so on.
sepgsql_ro_blob_t
It allows confined domains to read large object.
sepgsql_secret_blob_t
It dose not allow confined domains anything. So, they need to access them via trusted procedures, if provided.
(PREFIX)_sepgsql_blob_t
It is the default type for a new large object created by prefixed domains.
It allows them anything except for relabeling.
unpriv_sepgsql_blob_t
It is the default type for a new large object created by confined domains withing prefixes.
It allows them anything except for relabeling.

Pre-defined booleans

sepgsql_enable_users_ddl
default = true
It enables to control the capability of confined domains to execute DDL statement (CREATE/ALTER/DROP).
When it is turned off, SE-PostgreSQL prevents confined domains to invoke DDLs.
sepgsql_enable_auditallow (sepostgresql-devel.pp)
default = false
It enables to turn on/off audit messages for access allowed.
When it is turned on, SE-PostgreSQL generates audit messages for access allowed events, except for db_tuple object class to avoid flood of audit logs because massive number of tuples can be accessed in a single query.
sepgsql_enable_auditdeny (sepostgresql-devel.pp)
default = true
It enables to turn on/off audit messages for access denied.
When it is turned on, SE-PostgreSQL generates audit messages for access denied events, except for db_tuple object class to avoid flood of audit logs because massive number of tuples can be accessed in a single query.
sepgsql_regression_test_mode (sepostgresql-devel.pp)
default = false
It enables to run regression test correctly.
When it is turned on, it allows to load dynamic link libraries deployed on user's home directly.
Please note that it should not be turned on except for regression test phase since it is fundamentally dangerous.

Enhanced SQL statements

This section introduces new extensions of SQL statements to support explicit security context.

CREATE DATABASE
CREATE DATABASE dbname SECURITY_LABEL = 'context of database';
The enhanced CREATE DATABASE statement enables to create a new database with explicit security context.
db_database:{create} permission needs to be allowed on the explicitly specified security context.
Example:
postgres=# CREATE DATABASE testdb SECURITY_LABEL =
'system_u:object_r:sepgsql_db_t:Classified';
CREATE DATABASE
postgres=#
ALTER DATABASE
ALTER DATABASE dbname SECURITY_LABEL = 'context of database';
The enhanced ALTER DATABASE statement enables to change the security context of an existing database.
db_database:{setattr relabelfrom} permission needs to be allows on the database, and db_database:{relabelto} permission needs to be allowed on the explicitly specified security context.
Example:
postgres=# ALTER DATABASE testdb SECURITY_LABEL =
'system_u:object_r:sepgsql_db_t:Secret';
ALTER DATABASE
CREATE TABLE
CREATE TABLE table_name (
column_name <TYPE> [<CONSTRAINT>] SECURITY_CONTEXT = 'context of column',
:
) [<table options>] SECURITY_LABEL = 'context of table';
The enhanced CREATE TABLE statement enables to create a new table and columns with explicit security context.
db_table:{create} or db_column:{create} permission needs to be allowed on the explicitly specified security context.
Please note that newly created columns inherit the security context of the relation, so when you omit the SECURITY_LABEL = '...' option for columns, all the columns are labeled as the explicitly specified one for the table.
Example:
postgres=# CREATE TABLE testtbl (
x int PRIMARY KEY,
y text SECURITY_LABEL = 'system_u:object_r:sepgsql_ro_table_t', z date
) SECURITY_LABEL = 'system_u:object_r:sepgsql_fixed_table_t';
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "testtbl_pkey" for table "testtbl"
CREATE TABLE
ALTER TABLE
ALTER TABLE table_name [ALTER column_name] SECURITY_LABEL = 'context of table/column'
The enhanced ALTER TABLE statement enables to change the security context of an existing table or column.
db_table:{setattr relabelfrom} or db_column:{setattr relabelfrom} permissions need to be allowed on the current table or columns, and db_table:{relabelto} or db_column:{relabelto} permissions need to be allowed on the explicitly specified security context.
Example:
postgres=# ALTER TABLE testtbl ALTER x SECURITY_LABEL =
'system_u:object_r:sepgsql_table_t:Classified';
ALTER TABLE
CREATE FUNCTION
CREATE [OR REPLACE] FUNCTION function_name (<type>,...) RETURNS <type> [<options> ...]
SECURITY_LABEL = 'context of function'
[AS ‘<definition>’]
The enhanced CREATE FUNCTION statement enables to create a new function with explicit security context.
db_procedure:{create} permission needs to be allowed on the explicitly specified security context.
Example
postgres=# CREATE or REPLACE function less_than (integer, integer)
RETURNS bool LANGUAGE 'sql'
SECURITY_LABEL = 'system_u:object_r:user_sepgsql_proc_exec_t'
AS 'SELECT $1 < $2';
CREATE FUNCTION
ALTER FUNCTION
ALTER FUNCTION function_name SECURITY_LABEL = 'context of function'
The enhanced ALTER FUNCTION statement enables to change the security context of an existing function.
db_procedure:{setattr relabelfrom} permission needs to be allowed on the current procedure, and db_procedure:{relabelto} permission needs to be allowed on the explicitly specified security context.
Example
postgres=# ALTER FUNCTION less_than (integer, integer)
SECURITY_LABEL = 'system_u:object_r:sepgsql_proc_t';
ALTER FUNCTION

Enhanced SQL functions

This section introduces several new functions to utilize SE-PostgreSQL's security features.

text lo_get_security(oid loid)
This function returns a security attribute of the given large object.
Example:
postgres=# SELECT lo_get_security(16454);
lo_get_security
--------------------------------------
unconfined_u:object_r:sepgsql_blob_t
(1 row)
bool lo_set_security(oid loid, text context)
This function enables to set a new security attribute to the given large object. It returns true, if succeeded.
Example:
postgres=# SELECT lo_set_security(16454, 'unconfined_u:object_r:sepgsql_ro_blob_t');
lo_set_security
-----------------
t
(1 row)
postgres=# SELECT lo_get_security(16454);
lo_get_security
-----------------------------------------
unconfined_u:object_r:sepgsql_ro_blob_t
(1 row)
text sepgsql_getcon()
This function returns the current security policy of the client.
It is delivered via labeled networking facility, and SE-PostgreSQL applies it as privileges of the client when it makes access control decision. In other word, we can see the current privileges as a result of the function.
Example:
postgres=# SELECT sepgsql_getcon();
sepgsql_getcon
-------------------------------------------------------------
unconfined_u:unconfined_r:unconfined_t:SystemLow-SystemHigh
(1 row)
text sepgsql_server_getcon()
This function returns the current security policy of the server process.
Example:
postgres=# select sepgsql_server_getcon();
sepgsql_server_getcon
-----------------------------------
system_u:system_r:postgresql_t:s0
(1 row)
text sepgsql_get_user(text context)
This function returns user field of the given security context.
Example:
postgres=# SELECT sepgsql_get_user(security_context), * FROM drink;
sepgsql_get_user | id | name | price
------------------+----+-------+-------
unconfined_u | 1 | water | 100
unconfined_u | 2 | coke | 120
unconfined_u | 3 | juice | 130
unconfined_u | 4 | cofee | 180
(4 rows)
text sepgsql_set_user(text context, text new_user)
This function returns a modified security context whose user field is replace by the given new_user. It can be used as a new value on relabeling.
Example:
postgres=# UPDATE drink SET security_context =
sepgsql_set_user(security_context, 'system_u') WHERE id in (3,4);
UPDATE 2
postgres=# SELECT security_context, * FROM drink ORDER BY id;
security_context | id | name | price
--------------------------------------------------+----+-------+-------
unconfined_u:object_r:sepgsql_table_t | 1 | water | 100
unconfined_u:object_r:sepgsql_table_t:Classified | 2 | coke | 120
system_u:object_r:sepgsql_table_t:Classified | 3 | juice | 130
system_u:object_r:sepgsql_table_t | 4 | cofee | 180
(4 rows)
text sepgsql_get_role(text context)
This function returns role field of the given security context.
Example:
postgres=# SELECT sepgsql_get_role(security_context), * FROM drink;
sepgsql_get_role | id | name | price
------------------+----+-------+-------
object_r | 1 | water | 100
object_r | 2 | coke | 120
object_r | 3 | juice | 130
object_r | 4 | cofee | 180
(4 rows)
text sepgsql_set_role(text context, text new_role)
This function returns a modified security context whose role field is replace by the given new_role. It can be used as a new value on relabeling.
Example:
postgres=# UPDATE drink SET security_context =
sepgsql_set_role(security_context, 'system_r') WHERE id in (1,4);
ERROR: unconfined_u:system_r:sepgsql_ro_table_t:s0: invalid security attribute
Note that the default security policy does not allow to change role field of security context within any objects, so above example got an error, but this function generates a security context string correctly.
text sepgsql_get_type(text context)
This function returns type/domain field of the given security context.
Example:
postgres=# SELECT sepgsql_get_type(security_context), * FROM drink;
sepgsql_get_type | id | name | price
------------------+----+-------+-------
sepgsql_table_t | 1 | water | 100
sepgsql_table_t | 2 | coke | 120
sepgsql_table_t | 3 | juice | 130
sepgsql_table_t | 4 | cofee | 180
(4 rows)
text sepgsql_set_type(text context, text new_type)
This function returns a modified security context whose type/domain field is replace by the given new_type. It can be used as a new value on relabeling.
Example:
postgres=# UPDATE drink SET security_context =
sepgsql_set_type(security_context, 'sepgsql_ro_table_t') WHERE id in (1,4);
UPDATE 2
postgres=# SELECT security_context, * FROM drink ORDER BY id;
security_context | id | name | price
--------------------------------------------------+----+-------+-------
unconfined_u:object_r:sepgsql_ro_table_t | 1 | water | 100
unconfined_u:object_r:sepgsql_table_t:Classified | 2 | coke | 120
unconfined_u:object_r:sepgsql_table_t:Classified | 3 | juice | 130
unconfined_u:object_r:sepgsql_ro_table_t | 4 | cofee | 180
(4 rows)
text sepgsql_get_range(text context)
This function returns range field of the given security context.
Example:
postgres=# SELECT sepgsql_get_range(security_context), * FROM drink ORDER BY id;
sepgsql_get_range | id | name | price
-------------------+----+-------+-------
s0 | 1 | water | 100
s0:c0 | 2 | coke | 120
s0:c0 | 3 | juice | 130
s0 | 4 | cofee | 180
(4 rows)
text sepgsql_set_range(text context, text new_range)
This function returns a modified security context whose range field is replace by the given new_range. It can be used as a new value on relabeling.
Example:
postgres=# UPDATE drink SET security_context =
sepgsql_set_range(security_context, 'Classified') WHERE id in (2,3);
UPDATE 2
postgres=# SELECT security_context, * FROM drink ORDER BY id;
security_context | id | name | price
--------------------------------------------------+----+-------+-------
unconfined_u:object_r:sepgsql_table_t | 1 | water | 100
unconfined_u:object_r:sepgsql_table_t:Classified | 2 | coke | 120
unconfined_u:object_r:sepgsql_table_t:Classified | 3 | juice | 130
unconfined_u:object_r:sepgsql_table_t | 4 | cofee | 180
(4 rows)