[PATCH 21/25] libsepol: checkpolicy: implement new default labeling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


   This patch looks good to me. acked.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk7vrL0ACgkQrlYvE4MpobNpzgCg1tEPt6ImYYNDg12nxn7shP8G
cFYAn3R+Xccj9MB1M7K9PLfBRL9LhI1N
=OLnC
-----END PGP SIGNATURE-----
>From 0eb2b402ce9074139bf0d98d95263690df3c93df Mon Sep 17 00:00:00 2001
From: Eric Paris <eparis@xxxxxxxxxx>
Date: Mon, 5 Dec 2011 13:28:51 -0500
Subject: [PATCH 21/25] libsepol: checkpolicy: implement new default labeling
 behaviors

We would like to be able to say that the user, role, or range of a newly
created object should be based on the user, role, or range of either the
source or the target of the creation operation.  aka, for a new file
this could be the user of the creating process or the user or the parent
directory.  This patch implements the new language and the policydb
support to give this information to the kernel.

Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>
---
 checkpolicy/policy_define.c                |   96 ++++++++++++++++++++++++++++
 checkpolicy/policy_define.h                |    3 +
 checkpolicy/policy_parse.y                 |   37 ++++++++++-
 checkpolicy/policy_scan.l                  |   12 ++++
 libsepol/include/sepol/policydb/policydb.h |   19 +++++-
 libsepol/src/expand.c                      |   35 ++++++++++
 libsepol/src/link.c                        |   33 ++++++++++
 libsepol/src/policydb.c                    |   33 ++++++++++
 libsepol/src/write.c                       |   12 ++++
 9 files changed, 277 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index d19fc61..a86c6b3 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -351,6 +351,102 @@ static int read_classes(ebitmap_t *e_classes)
 	return 0;
 }
 
+int define_default_user(int which)
+{
+	char *id;
+	class_datum_t *cladatum;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue)))
+			free(id);
+		return 0;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_CLASSES, id)) {
+			yyerror2("class %s is not within scope", id);
+			return -1;
+		}
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
+		if (!cladatum) {
+			yyerror2("unknown class %s", id);
+			return -1;
+		}
+		if (cladatum->default_user && cladatum->default_user != which) {
+			yyerror2("conflicting default user information for class %s", id);
+			return -1;
+		}
+		cladatum->default_user = which;
+		free(id);
+	}
+
+	return 0;
+}
+
+int define_default_role(int which)
+{
+	char *id;
+	class_datum_t *cladatum;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue)))
+			free(id);
+		return 0;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_CLASSES, id)) {
+			yyerror2("class %s is not within scope", id);
+			return -1;
+		}
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
+		if (!cladatum) {
+			yyerror2("unknown class %s", id);
+			return -1;
+		}
+		if (cladatum->default_role && cladatum->default_role != which) {
+			yyerror2("conflicting default role information for class %s", id);
+			return -1;
+		}
+		cladatum->default_role = which;
+		free(id);
+	}
+
+	return 0;
+}
+
+int define_default_range(int which)
+{
+	char *id;
+	class_datum_t *cladatum;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue)))
+			free(id);
+		return 0;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_CLASSES, id)) {
+			yyerror2("class %s is not within scope", id);
+			return -1;
+		}
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
+		if (!cladatum) {
+			yyerror2("unknown class %s", id);
+			return -1;
+		}
+		if (cladatum->default_range && cladatum->default_range != which) {
+			yyerror2("conflicting default range information for class %s", id);
+			return -1;
+		}
+		cladatum->default_range = which;
+		free(id);
+	}
+
+	return 0;
+}
+
 int define_common_perms(void)
 {
 	char *id = 0, *perm = 0;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 92a9be7..ccbe56f 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -24,6 +24,9 @@ int define_av_perms(int inherits);
 int define_bool_tunable(int is_tunable);
 int define_category(void);
 int define_class(void);
+int define_default_user(int which);
+int define_default_role(int which);
+int define_default_range(int which);
 int define_common_perms(void);
 int define_compute_type(int which);
 int define_conditional(cond_expr_t *expr, avrule_t *t_list, avrule_t *f_list );
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index d808111..d92cc32 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -143,6 +143,8 @@ typedef int (* require_func_t)();
 %token POLICYCAP
 %token PERMISSIVE
 %token FILESYSTEM
+%token DEFAULT_USER DEFAULT_ROLE DEFAULT_RANGE
+%token LOW_HIGH LOW HIGH
 
 %left OR
 %left XOR
@@ -157,7 +159,7 @@ base_policy             : { if (define_policy(pass, 0) == -1) return -1; }
                           classes initial_sids access_vectors
                           { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; }
                             else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1; }}
-			  opt_mls te_rbac users opt_constraints 
+			  opt_default_rules opt_mls te_rbac users opt_constraints 
                          { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
 			   else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}}
 			  initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts
@@ -195,6 +197,39 @@ av_perms_def		: CLASS identifier '{' identifier_list '}'
                         | CLASS identifier INHERITS identifier '{' identifier_list '}'
 			{if (define_av_perms(TRUE)) return -1;}
 			;
+opt_default_rules	: default_rules
+			|
+			;
+default_rules		: default_user_def
+			| default_role_def
+			| default_range_def
+			| default_rules default_user_def
+			| default_rules default_role_def
+			| default_rules default_range_def
+			;
+default_user_def	: DEFAULT_USER names SOURCE ';'
+			{if (define_default_user(DEFAULT_SOURCE)) return -1; }
+			| DEFAULT_USER names TARGET ';'
+			{if (define_default_user(DEFAULT_TARGET)) return -1; }
+			;
+default_role_def	: DEFAULT_ROLE names SOURCE ';'
+			{if (define_default_role(DEFAULT_SOURCE)) return -1; }
+			| DEFAULT_ROLE names TARGET ';'
+			{if (define_default_role(DEFAULT_TARGET)) return -1; }
+			;
+default_range_def	: DEFAULT_RANGE names SOURCE LOW ';'
+			{if (define_default_range(DEFAULT_SOURCE_LOW)) return -1; }
+			| DEFAULT_RANGE names SOURCE HIGH ';'
+			{if (define_default_range(DEFAULT_SOURCE_HIGH)) return -1; }
+			| DEFAULT_RANGE names SOURCE LOW_HIGH ';'
+			{if (define_default_range(DEFAULT_SOURCE_LOW_HIGH)) return -1; }
+			| DEFAULT_RANGE names TARGET LOW ';'
+			{if (define_default_range(DEFAULT_TARGET_LOW)) return -1; }
+			| DEFAULT_RANGE names TARGET HIGH ';'
+			{if (define_default_range(DEFAULT_TARGET_HIGH)) return -1; }
+			| DEFAULT_RANGE names TARGET LOW_HIGH ';'
+			{if (define_default_range(DEFAULT_TARGET_LOW_HIGH)) return -1; }
+			;
 opt_mls			: mls
                         | 
 			;
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index 9b24db5..e767b5f 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -221,6 +221,18 @@ policycap |
 POLICYCAP			{ return(POLICYCAP); }
 permissive |
 PERMISSIVE			{ return(PERMISSIVE); }
+default_user |
+DEFAULT_USER			{ return(DEFAULT_USER); }
+default_role |
+DEFAULT_ROLE			{ return(DEFAULT_ROLE); }
+default_range |
+DEFAULT_RANGE			{ return(DEFAULT_RANGE); }
+low-high |
+LOW-HIGH			{ return(LOW_HIGH); }
+high |
+HIGH				{ return(HIGH); }
+low |
+LOW				{ return(LOW); }
 "/"({alnum}|[_\.\-/])*	        { return(PATH); }
 \"({alnum}|[_\.\-\~])+\"	{ return(FILENAME); }
 {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))*	{ return(IDENTIFIER); }
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 1848a7b..f53a499 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -111,6 +111,19 @@ typedef struct class_datum {
 	symtab_t permissions;	/* class-specific permission symbol table */
 	constraint_node_t *constraints;	/* constraints on class permissions */
 	constraint_node_t *validatetrans;	/* special transition rules */
+/* Options how a new object user and role should be decided */
+#define DEFAULT_SOURCE		1
+#define DEFAULT_TARGET		2
+	char default_user;
+	char default_role;
+/* Options how a new object range should be decided */
+#define DEFAULT_SOURCE_LOW	1
+#define DEFAULT_SOURCE_HIGH	2
+#define DEFAULT_SOURCE_LOW_HIGH	3
+#define DEFAULT_TARGET_LOW	4
+#define DEFAULT_TARGET_HIGH	5
+#define DEFAULT_TARGET_LOW_HIGH	6
+	char default_range;
 } class_datum_t;
 
 /* Role attributes */
@@ -667,10 +680,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #define POLICYDB_VERSION_BOUNDARY	24
 #define POLICYDB_VERSION_FILENAME_TRANS	25
 #define POLICYDB_VERSION_ROLETRANS	26
+#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	27
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN	POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_ROLETRANS
+#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
 
 /* Module versions and specific changes*/
 #define MOD_POLICYDB_VERSION_BASE		4
@@ -686,9 +700,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #define MOD_POLICYDB_VERSION_ROLETRANS		12
 #define MOD_POLICYDB_VERSION_ROLEATTRIB		13
 #define MOD_POLICYDB_VERSION_TUNABLE_SEP	14
+#define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	15
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_TUNABLE_SEP
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
 
 #define POLICYDB_CONFIG_MLS    1
 
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 493e478..73b9107 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -358,6 +358,35 @@ static int constraint_node_clone(constraint_node_t ** dst,
 	return -1;
 }
 
+static int class_copy_default_new_object(expand_state_t *state,
+					 class_datum_t *olddatum,
+					 class_datum_t *newdatum)
+{
+	if (olddatum->default_user) {
+		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
+			ERR(state->handle, "Found conflicting default user definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_user = olddatum->default_user;
+
+	}
+	if (olddatum->default_role) {
+		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
+			ERR(state->handle, "Found conflicting default role definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_role = olddatum->default_role;
+	}
+	if (olddatum->default_range) {
+		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
+			ERR(state->handle, "Found conflicting default range definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_range = olddatum->default_range;
+	}
+	return 0;
+}
+
 static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			       void *data)
 {
@@ -393,6 +422,12 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 	new_class->s.value = class->s.value;
 	state->out->p_classes.nprim++;
 
+	ret = class_copy_default_new_object(state, class, new_class);
+	if (ret) {
+		free(new_class);
+		return ret;
+	}
+	
 	new_id = strdup(id);
 	if (!new_id) {
 		ERR(state->handle, "Out of memory!");
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index ee9675b..01d3231 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -205,6 +205,34 @@ static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 	return ret;
 }
 
+static int class_copy_default_new_object(link_state_t *state,
+					 class_datum_t *olddatum,
+					 class_datum_t *newdatum)
+{
+	if (olddatum->default_user) {
+		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
+			ERR(state->handle, "Found conflicting default user definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_user = olddatum->default_user;
+	}
+	if (olddatum->default_role) {
+		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
+			ERR(state->handle, "Found conflicting default role definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_role = olddatum->default_role;
+	}
+	if (olddatum->default_range) {
+		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
+			ERR(state->handle, "Found conflicting default range definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_range = olddatum->default_range;
+	}
+	return 0;
+}
+
 static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			       void *data)
 {
@@ -287,6 +315,11 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 	state->dest_class = new_class;
 	state->dest_class_name = (char *)key;
 
+	/* copy default new object rules */
+	ret = class_copy_default_new_object(state, cladatum, new_class);
+	if (ret)
+		return ret;
+
 	ret =
 	    hashtab_map(cladatum->permissions.table, permission_copy_callback,
 			state);
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 136b450..a84de2f 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -151,6 +151,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_KERN,
+	 .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_NODE6 + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_BASE,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -228,6 +235,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_NODE6 + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_MOD,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -304,6 +318,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .ocon_num = 0,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 };
 
 #if 0
@@ -2064,6 +2085,18 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
 			goto bad;
 	}
 
+	if ((p->policy_type == POLICY_KERN &&
+	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
+	    (p->policy_type == POLICY_BASE &&
+	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
+		rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
+		if (rc < 0)
+			goto bad;
+		cladatum->default_user = le32_to_cpu(buf[0]);
+		cladatum->default_role = le32_to_cpu(buf[1]);
+		cladatum->default_range = le32_to_cpu(buf[2]);
+	}
+
 	if (hashtab_insert(h, key, cladatum))
 		goto bad;
 
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index e34ab52..22e6143 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -976,6 +976,18 @@ static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
 			return POLICYDB_ERROR;
 	}
 
+	if ((p->policy_type == POLICY_KERN &&
+	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
+	    (p->policy_type == POLICY_BASE &&
+	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
+		buf[0] = cpu_to_le32(cladatum->default_user);
+		buf[1] = cpu_to_le32(cladatum->default_role);
+		buf[2] = cpu_to_le32(cladatum->default_range);
+		items = put_entry(buf, sizeof(uint32_t), 3, fp);
+		if (items != 3)
+			return POLICYDB_ERROR;
+	}
+
 	return POLICYDB_SUCCESS;
 }
 
-- 
1.7.8


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux