Hello, The latest SE-PostgreSQL patches are updated here:
[1/4] http://sepgsql.googlecode.com/files/sepostgresql-sepgsql-8.4devel-3-r1005.patch [2/4] http://sepgsql.googlecode.com/files/sepostgresql-pg_dump-8.4devel-3-r1005.patch [3/4] http://sepgsql.googlecode.com/files/sepostgresql-policy-8.4devel-3-r1005.patch [4/4] http://sepgsql.googlecode.com/files/sepostgresql-docs-8.4devel-3-r1005.patch They contains rebasing to the CVS HEAD, because we cannot apply the previous ones correctly due to progress in the base version. Rest of changes are here: - A new PGACE hook: pgaceIsAllowExecutorRunHook(). It enables to control overriding ExecutorRun_hook, because several important hooks are invoked from standard_ExecutorRun(). - T_SEvalItem related equalXXXX() functions are added to nodes/equalfuncs.c. # I've left for implement them. - Fix typo in src/include/security/pgace.h BTW, I thought I have to show the overview of the patch to help reviwers. The main patch ([1/4]) is especially big and contains new concepts. The following explanation shows several key concept of SE-PostgreSQL. I'm happy if it can reduce the load of reviwers. No need to say, please feel free to ask me anything. :-) Thanks, Security hooks -------------- We called it as PostgreSQL Access Control Extention (PGACE). The "src/include/security/pgace.h" newly added declares these hooks as inline functions. If HAVE_SELINUX is available at build time, they have a valid implementation to invoke functions to make access control decision. When the SE-PostgreSQL feature is disabled at build time or run time, it does not change any existing behavior. These hooks have a prefix of "pgace", like pgaceHeapTupleInsert(). This hook is invoked just before inserting a new tuple into a relation, and the SE-PostgreSQL subsystem can make its decision. Its argument provides information to make a decision. The pgaceHeapTupleInsert() has four arguments like the target Relation object and newly inserted HeapTuple. Specifications of each hooks are described in the "src/include/security/pgace.h". Security attribute management ----------------------------- We need a security attribute of tuple to use it as a basic of access control decision. SELinux calls it as "security context", and most of security aware operating system has similar idea called as label. It is represented as a text format like "system_u:object_r:etc_t:s0", and has its characteristic that many objects tend to share a single security context. We stores text represented security attribute into "pg_security" system catalog and put an alternate key (oid of pg_security) on each tuples, because it is unacceptable approach to put a raw string data on individual tuples. The alternate key is stored in the tail of HeapTupleHeader, as "oid" doing. This field is valid when t_infomask has HEAP_HASSECURITY bit. HeapTupleHeader +-----------------+ | : | +-----------------+ | t_infomask | +-----------------+ pg_security system catalog | t_hoff o-------+ +-------+---------------------------------------------+ +-----------------+ | | oid | seclabel | | : | | +-------+---------------------------------------------+ | : | | | 16389 | system_u:object_r:sepgsql_table_t:s0 | +-----------------+ | | 16401 | system_u:object_r:sepgsql_proc_t:s0 | |*Oid security_id*|---------> | 16402 | system_u:object_r:sepgsql_secret_table_t:s0 | +-----------------+ | | : | : | | Oid object_id | | +-----------------+ <--+ | Data field | | : | The alternate key is just a internal representation, so we have to translate it to/from text format when communicating to in-kernel SELinux, or export/import them. Note that the security attribute is also assigned to tuples within system catalogs. A security attribute of a tuple within pg_attribute means column's security attribute, and used to column-level access controls, for example. The src/backend/security/pgaceCommon.c have functions to traslate them: char *pgaceLookupSecurityLabel(Oid security_id); Oid pgaceLookupSecurityId(char *security_label); When a new security_label is given and not found on pg_security, pgaceLookupSecurityId() tries to insert a new tuple into pg_security and returns its object id as an alternate key. Two more similar functions are also declared: char *pgaceSidToSecurityLabel(Oid security_id) Oid pgaceSecurityLabelToSid(char *security_label) It also enables to translate between a cosmetic text format and an internal security identifier. An example of cosmetic format is: unconfined_u:unconfined_r:unconfined_t:SystemLow-SystemHigh ^^^^^^^^^^^^^^^^^^^^ We have a case when `pg_security` system catalog is not available because initdb does not complete to initialize system catalogs yet. In early phase, this facility caches the pairs of identifier and text representations, then it writes out to `pg_security` after initial set up completed. earlySecurityLabelToSid() and earlySidToSecurityLabel() are used while we are in bootstraping mode, and pgacePostBootstrapingMode() write out them. Making access control decision ------------------------------ SE-PostgreSQL makes its decision with three steps in major path. The first step picks up any database objects accessed with the given queries. For example, the following UPDATE statement contains accesses to 6 objects. UPDATE t SET a = 5, b = b * 2 WHERE c > 10; - table t is updated and refered. - column a is updated. - column b is updated and refered. - column c is refered without leaking its contents. - function int4mul and int4gt are executed. The sepgsqlProxyQuery() defined at "src/backend/security/sepgsql/proxy.c" walks on the given Query trees to pick up database objects accessed, and makes a list of them. This list is chained to Query->pgaceItem which is a private field of security subsystem, and delivered to private member of PlannedStmt structure. In same time, it marks a kind of accesses on RangeTblEntry->pgaceTuplePerms. This value is copied to Scan->pgaceTuplePerms, and sepgsqlExecScan() hook refers to identify what is the purpose of this scan. The second step is evaluations of permission for picked up database objects. The sepgsqlVerifyQuery() is invoked at the head of ExecutorStart(), to check whether the client has enough permission It walk on the list chained to PlannedStmt->pgaceItem which is created at the first step, and checks whether the client has enough permissions, or not. If the security policy does not allow the required accesses, SE-PostgreSQL makes an error to abort query execution. Tuple-level access controls are not done in this step. The last step is evaluations of permission for scanned tuples. The sepgsqlExecScan() defined at "src/baskend/security/sepgsql/hooks.c" is invoked from ExecScan(). This hook can return bool value, and modified logic skips a tuple scanned if it returns 'false'. Other topics ------------ * Default security context The security policy also contains rules to decide a security context of newly inserted tuples. If client does not specify any explicit one, the default one is applied. We can specify explicit security context with the following Enhanced SQL statement or writable system column. * Enhanced SQL statement It helps to define a new table, column, function and database with specific security context. We can use the facility as follows: CREATE TABLE t ( a integer primary key, b text, ) SECURITY_CONTEXT = 'system_u:object_r:sepgsql_ro_t:s0'; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The above token is represented as DefElem objects in gram.y, and saved on private member of CreateStmt structure. Then, these are translated to List of DefElem and delivered to heap_create_with_catalog() with its fifteenth argument. pgaceCreateRelationCommon() and pgaceCreateAttributeCommon() are invoked just before inserting a new tuple into pg_class/pg_attribute. These are defined at "src/backend/security/pgaceCommon.c", and they invokes PGACE hooks if the security context of new objects are explicitly specified. At the next, sepgsqlHeapTupleInsert() is invoked for the new tuple. It skips to assign default security context, because explicit security context is already set. Permissions to create table/column is evaluated for explicitly specified one. * Writable system column Security contexts can be exported via "security_context" system column. In the previous version, system column is read only, so we cannot specify in an element of INSERT or UPDATE. SE-PostgreSQL allows to set an explicit value to "security_context" system column to utilize it as an interface to change security context of tuples. An example) UPDATE t SET security_context = security_context || ':c0' WHERE a = 10; The TargetEntry->resjunk for "security_context" is always turned on for INSERT, UPDATE and SELECT INTO statement. In the result, its new value is computed but removed at ExecFilterJunk(). The patched ExecutePlan() fetches the value and stores it on the tail of HeapTupleHeader with HeapTupleSetSecurity() macro. This patch changes transformInsertStmt() and updateTargetListEntry() to turn on TargetEntry->resjunk when attribute number is negative. Its purpose is to enable writable system column. Same logic can be applied to writable "oid" system column as a possibility. * userspace Access vector cache The "src/backend/security/sepgsql/avc.c" is an implementation of userspace access vector cache. SE-PostgreSQL ask in-kernel SELinux to check whether the given access should be allowed, or not. However, it requires system call invocation which is a bit heavy step. The userspace AVC caches recently asked access patterns, and enables to reduce the number of system call invocation. -- OSS Platform Development Division, NEC KaiGai Kohei <[EMAIL PROTECTED]> -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers