Skip to content

Commit

Permalink
Allow sepgsql labels to depend on object name.
Browse files Browse the repository at this point in the history
The main change here is to call security_compute_create_name_raw()
rather than security_compute_create_raw().  This ups the minimum
requirement for libselinux from 2.0.99 to 2.1.10, but it looks
like most distributions will have picked that up before 9.3 is out.

KaiGai Kohei
  • Loading branch information
robertmhaas committed Mar 28, 2013
1 parent ae7f1c3 commit 0f05840
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 40 deletions.
24 changes: 12 additions & 12 deletions configure
Expand Up @@ -9710,9 +9710,9 @@ fi
# for contrib/sepgsql
if test "$with_selinux" = yes; then

{ $as_echo "$as_me:$LINENO: checking for selinux_status_open in -lselinux" >&5
$as_echo_n "checking for selinux_status_open in -lselinux... " >&6; }
if test "${ac_cv_lib_selinux_selinux_status_open+set}" = set; then
{ $as_echo "$as_me:$LINENO: checking for security_compute_create_name in -lselinux" >&5
$as_echo_n "checking for security_compute_create_name in -lselinux... " >&6; }
if test "${ac_cv_lib_selinux_security_compute_create_name+set}" = set; then
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
Expand All @@ -9730,11 +9730,11 @@ cat >>conftest.$ac_ext <<_ACEOF
#ifdef __cplusplus
extern "C"
#endif
char selinux_status_open ();
char security_compute_create_name ();
int
main ()
{
return selinux_status_open ();
return security_compute_create_name ();
;
return 0;
}
Expand All @@ -9760,31 +9760,31 @@ $as_echo "$ac_try_echo") >&5
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
ac_cv_lib_selinux_selinux_status_open=yes
ac_cv_lib_selinux_security_compute_create_name=yes
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_lib_selinux_selinux_status_open=no
ac_cv_lib_selinux_security_compute_create_name=no
fi

rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_selinux_status_open" >&5
$as_echo "$ac_cv_lib_selinux_selinux_status_open" >&6; }
if test "x$ac_cv_lib_selinux_selinux_status_open" = x""yes; then
{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_security_compute_create_name" >&5
$as_echo "$ac_cv_lib_selinux_security_compute_create_name" >&6; }
if test "x$ac_cv_lib_selinux_security_compute_create_name" = x""yes; then
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBSELINUX 1
_ACEOF

LIBS="-lselinux $LIBS"

else
{ { $as_echo "$as_me:$LINENO: error: library 'libselinux', version 2.0.99 or newer, is required for SELinux support" >&5
$as_echo "$as_me: error: library 'libselinux', version 2.0.99 or newer, is required for SELinux support" >&2;}
{ { $as_echo "$as_me:$LINENO: error: library 'libselinux', version 2.1.10 or newer, is required for SELinux support" >&5
$as_echo "$as_me: error: library 'libselinux', version 2.1.10 or newer, is required for SELinux support" >&2;}
{ (exit 1); exit 1; }; }
fi

Expand Down
4 changes: 2 additions & 2 deletions configure.in
Expand Up @@ -952,8 +952,8 @@ fi

# for contrib/sepgsql
if test "$with_selinux" = yes; then
AC_CHECK_LIB(selinux, selinux_status_open, [],
[AC_MSG_ERROR([library 'libselinux', version 2.0.99 or newer, is required for SELinux support])])
AC_CHECK_LIB(selinux, security_compute_create_name, [],
[AC_MSG_ERROR([library 'libselinux', version 2.1.10 or newer, is required for SELinux support])])
fi

# for contrib/uuid-ossp
Expand Down
3 changes: 2 additions & 1 deletion contrib/sepgsql/database.c
Expand Up @@ -92,7 +92,8 @@ sepgsql_database_post_create(Oid databaseId, const char *dtemplate)

ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
tcontext,
SEPG_CLASS_DB_DATABASE);
SEPG_CLASS_DB_DATABASE,
NameStr(datForm->datname));

/*
* check db_database:{create} permission
Expand Down
35 changes: 32 additions & 3 deletions contrib/sepgsql/expected/label.out
Expand Up @@ -64,17 +64,45 @@ SELECT sepgsql_getcon(); -- confirm client privilege

CREATE TABLE t3 (s int, t text);
INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
SELECT sepgsql_getcon(); -- confirm client privilege
sepgsql_getcon
----------------------------------------------------
unconfined_u:unconfined_r:sepgsql_regtest_dba_t:s0
(1 row)

CREATE TABLE t4 (m int, n text);
INSERT INTO t4 VALUES (1,'mmm'), (2,'nnn'), (3,'ooo');
SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux'
AND objtype in ('table', 'column')
AND objname in ('t1', 't2', 't3');
WHERE provider = 'selinux' AND objtype = 'table' AND objname in ('t1', 't2', 't3');
objtype | objname | label
---------+---------+-----------------------------------------------
table | t1 | unconfined_u:object_r:sepgsql_table_t:s0
table | t2 | unconfined_u:object_r:sepgsql_table_t:s0
table | t3 | unconfined_u:object_r:user_sepgsql_table_t:s0
(3 rows)

SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux' AND objtype = 'column' AND (objname like 't3.%' OR objname like 't4.%');
objtype | objname | label
---------+-------------+-----------------------------------------------
column | t3.t | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.s | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.ctid | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.xmin | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.cmin | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.xmax | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.cmax | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t3.tableoid | unconfined_u:object_r:user_sepgsql_table_t:s0
column | t4.n | unconfined_u:object_r:sepgsql_table_t:s0
column | t4.m | unconfined_u:object_r:sepgsql_table_t:s0
column | t4.ctid | unconfined_u:object_r:sepgsql_sysobj_t:s0
column | t4.xmin | unconfined_u:object_r:sepgsql_sysobj_t:s0
column | t4.cmin | unconfined_u:object_r:sepgsql_sysobj_t:s0
column | t4.xmax | unconfined_u:object_r:sepgsql_sysobj_t:s0
column | t4.cmax | unconfined_u:object_r:sepgsql_sysobj_t:s0
column | t4.tableoid | unconfined_u:object_r:sepgsql_sysobj_t:s0
(16 rows)

--
-- Tests for SECURITY LABEL
--
Expand Down Expand Up @@ -456,6 +484,7 @@ SELECT sepgsql_getcon(); -- confirm client privilege
DROP TABLE IF EXISTS t1 CASCADE;
DROP TABLE IF EXISTS t2 CASCADE;
DROP TABLE IF EXISTS t3 CASCADE;
DROP TABLE IF EXISTS t4 CASCADE;
DROP FUNCTION IF EXISTS f1() CASCADE;
DROP FUNCTION IF EXISTS f2() CASCADE;
DROP FUNCTION IF EXISTS f3() CASCADE;
Expand Down
3 changes: 2 additions & 1 deletion contrib/sepgsql/proc.c
Expand Up @@ -95,7 +95,8 @@ sepgsql_proc_post_create(Oid functionId)
tcontext = sepgsql_get_label(NamespaceRelationId,
proForm->pronamespace, 0);
ncontext = sepgsql_compute_create(scontext, tcontext,
SEPG_CLASS_DB_PROCEDURE);
SEPG_CLASS_DB_PROCEDURE,
NameStr(proForm->proname));

/*
* check db_procedure:{create (install)} permission
Expand Down
9 changes: 6 additions & 3 deletions contrib/sepgsql/relation.c
Expand Up @@ -88,7 +88,8 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
scontext = sepgsql_get_client_label();
tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
ncontext = sepgsql_compute_create(scontext, tcontext,
SEPG_CLASS_DB_COLUMN);
SEPG_CLASS_DB_COLUMN,
NameStr(attForm->attname));

/*
* check db_column:{create} permission
Expand Down Expand Up @@ -309,7 +310,8 @@ sepgsql_relation_post_create(Oid relOid)
scontext = sepgsql_get_client_label();
tcontext = sepgsql_get_label(NamespaceRelationId,
classForm->relnamespace, 0);
rcontext = sepgsql_compute_create(scontext, tcontext, tclass);
rcontext = sepgsql_compute_create(scontext, tcontext, tclass,
NameStr(classForm->relname));

/*
* check db_xxx:{create} permission
Expand Down Expand Up @@ -363,7 +365,8 @@ sepgsql_relation_post_create(Oid relOid)

ccontext = sepgsql_compute_create(scontext,
rcontext,
SEPG_CLASS_DB_COLUMN);
SEPG_CLASS_DB_COLUMN,
NameStr(attForm->attname));

/*
* check db_column:{create} permission
Expand Down
13 changes: 9 additions & 4 deletions contrib/sepgsql/schema.c
Expand Up @@ -42,6 +42,7 @@ sepgsql_schema_post_create(Oid namespaceId)
char *tcontext;
char *ncontext;
char audit_name[NAMEDATALEN + 20];
const char *nsp_name;
ObjectAddress object;
Form_pg_namespace nspForm;

Expand All @@ -67,17 +68,21 @@ sepgsql_schema_post_create(Oid namespaceId)
elog(ERROR, "catalog lookup failed for namespace %u", namespaceId);

nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
nsp_name = NameStr(nspForm->nspname);
if (strncmp(nsp_name, "pg_temp_", 8) == 0)
nsp_name = "pg_temp";
else if (strncmp(nsp_name, "pg_toast_temp_", 14) == 0)
nsp_name = "pg_toast_temp";

tcontext = sepgsql_get_label(DatabaseRelationId, MyDatabaseId, 0);
ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
tcontext,
SEPG_CLASS_DB_SCHEMA);

SEPG_CLASS_DB_SCHEMA,
nsp_name);
/*
* check db_schema:{create}
*/
snprintf(audit_name, sizeof(audit_name),
"schema %s", NameStr(nspForm->nspname));
snprintf(audit_name, sizeof(audit_name), "schema %s", nsp_name);
sepgsql_avc_check_perms_label(ncontext,
SEPG_CLASS_DB_SCHEMA,
SEPG_DB_SCHEMA__CREATE,
Expand Down
11 changes: 7 additions & 4 deletions contrib/sepgsql/selinux.c
Expand Up @@ -836,7 +836,8 @@ sepgsql_compute_avd(const char *scontext,
char *
sepgsql_compute_create(const char *scontext,
const char *tcontext,
uint16 tclass)
uint16 tclass,
const char *objname)
{
security_context_t ncontext;
security_class_t tclass_ex;
Expand All @@ -853,9 +854,11 @@ sepgsql_compute_create(const char *scontext,
* Ask SELinux what is the default context for the given object class on a
* pair of security contexts
*/
if (security_compute_create_raw((security_context_t) scontext,
(security_context_t) tcontext,
tclass_ex, &ncontext) < 0)
if (security_compute_create_name_raw((security_context_t) scontext,
(security_context_t) tcontext,
tclass_ex,
objname,
&ncontext) < 0)
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("SELinux could not compute a new context: "
Expand Down
17 changes: 16 additions & 1 deletion contrib/sepgsql/sepgsql-regtest.te
@@ -1,4 +1,4 @@
policy_module(sepgsql-regtest, 1.04)
policy_module(sepgsql-regtest, 1.05)

gen_require(`
all_userspace_class_perms
Expand Down Expand Up @@ -43,6 +43,21 @@ allow sepgsql_regtest_dba_t sepgsql_regtest_user_t : process { dyntransition };
allow sepgsql_regtest_dba_t sepgsql_regtest_foo_t : process { dyntransition };
allow sepgsql_regtest_dba_t sepgsql_regtest_var_t : process { dyntransition };

# special rule for system columns
optional_policy(`
gen_require(`
attribute sepgsql_table_type;
type sepgsql_sysobj_t;
')
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "ctid";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "oid";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "xmin";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "xmax";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "cmin";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "cmax";
type_transition sepgsql_regtest_dba_t sepgsql_table_type:db_column sepgsql_sysobj_t "tableoid";
')

#
# Dummy domain for unpriv users
#
Expand Down
3 changes: 2 additions & 1 deletion contrib/sepgsql/sepgsql.h
Expand Up @@ -239,7 +239,8 @@ extern void sepgsql_compute_avd(const char *scontext,

extern char *sepgsql_compute_create(const char *scontext,
const char *tcontext,
uint16 tclass);
uint16 tclass,
const char *objname);

extern bool sepgsql_check_perms(const char *scontext,
const char *tcontext,
Expand Down
11 changes: 8 additions & 3 deletions contrib/sepgsql/sql/label.sql
Expand Up @@ -71,10 +71,14 @@ SECURITY LABEL ON TABLE var_tbl
CREATE TABLE t3 (s int, t text);
INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');

-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_dba_t:s0
CREATE TABLE t4 (m int, n text);
INSERT INTO t4 VALUES (1,'mmm'), (2,'nnn'), (3,'ooo');

SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux' AND objtype = 'table' AND objname in ('t1', 't2', 't3');
SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux'
AND objtype in ('table', 'column')
AND objname in ('t1', 't2', 't3');
WHERE provider = 'selinux' AND objtype = 'column' AND (objname like 't3.%' OR objname like 't4.%');

--
-- Tests for SECURITY LABEL
Expand Down Expand Up @@ -229,6 +233,7 @@ SELECT sepgsql_getcon();
DROP TABLE IF EXISTS t1 CASCADE;
DROP TABLE IF EXISTS t2 CASCADE;
DROP TABLE IF EXISTS t3 CASCADE;
DROP TABLE IF EXISTS t4 CASCADE;
DROP FUNCTION IF EXISTS f1() CASCADE;
DROP FUNCTION IF EXISTS f2() CASCADE;
DROP FUNCTION IF EXISTS f3() CASCADE;
Expand Down
4 changes: 2 additions & 2 deletions contrib/sepgsql/uavc.c
Expand Up @@ -250,10 +250,10 @@ sepgsql_avc_compute(const char *scontext, const char *tcontext, uint16 tclass)
{
if (!ucontext)
ncontext = sepgsql_compute_create(scontext, tcontext,
SEPG_CLASS_PROCESS);
SEPG_CLASS_PROCESS, NULL);
else
ncontext = sepgsql_compute_create(scontext, ucontext,
SEPG_CLASS_PROCESS);
SEPG_CLASS_PROCESS, NULL);
if (strcmp(scontext, ncontext) == 0)
{
pfree(ncontext);
Expand Down
7 changes: 4 additions & 3 deletions doc/src/sgml/sepgsql.sgml
Expand Up @@ -63,7 +63,7 @@
<filename>sepgsql</> can only be used on <productname>Linux</productname>
2.6.28 or higher with <productname>SELinux</productname> enabled.
It is not available on any other platform. You will also need
<productname>libselinux</> 2.0.99 or higher and
<productname>libselinux</> 2.1.10 or higher and
<productname>selinux-policy</> 3.9.13 or higher (although some
distributions may backport the necessary rules into older policy
versions).
Expand Down Expand Up @@ -326,8 +326,9 @@ $ sudo semodule -r sepgsql-regtest
When <filename>sepgsql</filename> is in use, security labels are
automatically assigned to supported database objects at creation time.
This label is called a default security label, and is decided according
to the system security policy, which takes as input the creator's label
and the label assigned to the new object's parent object.
to the system security policy, which takes as input the creator's label,
the label assigned to the new object's parent object and optionally name
of the constructed object.
</para>

<para>
Expand Down

0 comments on commit 0f05840

Please sign in to comment.