Skip to contentSkip to conversation

semantic MLS representation for users

PATCH In review Darrel Goeddel 4 participants 9 messages Aug 28, 2006 – Sep 5, 2006 SELinux security module

lore
Share & tools
lore
#0 lore raw

PATCH 3/3 semantic MLS representation for users

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

checkpolicy/policy_parse.y                 |   37 +++-----------
libsepol/include/sepol/policydb/policydb.h |    9 ++-
libsepol/src/expand.c                      |   72 ++++++++++++++++++++++++-----
libsepol/src/mls.c                         |    8 +--
libsepol/src/policydb.c                    |   57 ++++++++++++++++++----
libsepol/src/users.c                       |   13 ++---
libsepol/src/write.c                       |   17 +++++-
7 files changed, 142 insertions(+), 71 deletions(-)
checkpolicy/policy_parse.y +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/checkpolicy/policy_parse.y selinux-mls-users/checkpolicy/policy_parse.y
@@ -3736,11 +3736,10 @@ static int define_user(void)
		free(id);

		usrdatum->dfltlevel.sens = levdatum->level->sens;

- ebitmap_init(&usrdatum->dfltlevel.cat);

		while ((id = queue_remove(id_queue))) {
-			if (parse_categories(id, levdatum,
-					     &usrdatum->dfltlevel.cat)) {
+			if (parse_semantic_categories(id, levdatum,
+			                            &usrdatum->dfltlevel.cat)) {
				free(id);
				return -1;
			}
@@ -3762,13 +3761,12 @@ static int define_user(void)
				return -1;
			}
			free(id);
+
			usrdatum->range.level[l].sens = levdatum->level->sens;

- ebitmap_init(&usrdatum->range.level[l].cat);

			while ((id = queue_remove(id_queue))) {

- if (parse_categories(id, levdatum,
- &usrdatum->range.level[l].
- cat)) {
+ if (parse_semantic_categories(id, levdatum,

+				               &usrdatum->range.level[l].cat)) {
					free(id);
					return -1;
				}
@@ -3781,33 +3779,14 @@ static int define_user(void)
		}

		if (l == 0) {

- usrdatum->range.level[1].sens =
- usrdatum->range.level[0].sens;
- if (ebitmap_cpy(&usrdatum->range.level[1].cat,
- &usrdatum->range.level[0].cat)) {
+ if (mls_semantic_level_cpy(&usrdatum->range.level[1],

+			                           &usrdatum->range.level[0])) {
				yyerror("out of memory");
-				goto out;
+				return -1;
			}
		}

- if (!mls_level_dom(&usrdatum->range.level[1],
- &usrdatum->range.level[0])) {
- yyerror("high level does not dominate low level");
- goto out;
- }
- if (!mls_level_between(&usrdatum->dfltlevel,
- &usrdatum->range.level[0],
- &usrdatum->range.level[1])) {
- yyerror("default level not within user range");
- goto out;
- }

	}
	return 0;

-
- out:
- ebitmap_destroy(&usrdatum->dfltlevel.cat);
- ebitmap_destroy(&usrdatum->range.level[0].cat);
- ebitmap_destroy(&usrdatum->range.level[1].cat);
- return -1;
}

static int parse_security_context(context_struct_t * c)

libsepol/include/sepol/policydb/policydb.h +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/include/sepol/policydb/policydb.h selinux-mls-users/libsepol/include/sepol/policydb/policydb.h
@@ -149,9 +149,11 @@ typedef struct type_datum {
typedef struct user_datum {
	symtab_datum_t s;
	role_set_t roles;	/* set of authorized roles for user */

- mls_range_t range; /* MLS range (min. - max.) for user */
- mls_level_t dfltlevel; /* default login MLS level for user */
+ mls_semantic_range_t range; /* MLS range (min. - max.) for user */
+ mls_semantic_level_t dfltlevel; /* default login MLS level for user */
ebitmap_t cache; /* This is an expanded set used for context validation during parsing */
+ mls_range_t exp_range; /* expanded range used for validation */
+ mls_level_t exp_dfltlevel; /* expanded range used for validation */
} user_datum_t;

/* Sensitivity attributes */
@@ -586,9 +588,10 @@ extern int policydb_write(struct policyd #define MOD_POLICYDB_VERSION_VALIDATETRANS 5
#define MOD_POLICYDB_VERSION_MLS 5
#define MOD_POLICYDB_VERSION_RANGETRANS 6
+#define MOD_POLICYDB_VERSION_MLS_USERS 6

#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS_USERS

#define POLICYDB_CONFIG_MLS 1

libsepol/src/expand.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
			return -1;
		}

- /* clone MLS stuff */
- if (mls_range_cpy(&new_user->range, &user->range) == -1
- || mls_level_cpy(&new_user->dfltlevel,
- &user->dfltlevel) == -1) {
+ /* copy semantic MLS info */

+		if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
			ERR(state->handle, "Out of memory!");
			return -1;
		}

+ if (mls_semantic_level_cpy(&new_user->dfltlevel,
+ &user->dfltlevel)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ /* expand the semantic MLS info */
+ if (mls_semantic_range_expand(&new_user->range,
+ &new_user->exp_range,
+ state->out, state->handle)) {
+ return -1;
+ }
+ if (mls_semantic_level_expand(&new_user->dfltlevel,
+ &new_user->exp_dfltlevel,
+ state->out, state->handle)) {
+ return -1;
+ }
+ if (!mls_level_between(&new_user->exp_dfltlevel,
+ &new_user->exp_range.level[0],
+ &new_user->exp_range.level[1])) {
+ ERR(state->handle, "default level not within user "
+ "range");
+ return -1;
+ }
+ } else {
+ /* require that the MLS info match */
+ mls_range_t tmp_range;
+ mls_level_t tmp_level;
+
+ if (mls_semantic_range_expand(&user->range, &tmp_range,
+ state->out, state->handle)) {
+ return -1;
+ }
+ if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
+ state->out, state->handle)) {
+ mls_range_destroy(&tmp_range);
+ return -1;
+ }
+ if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
+ !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
+ mls_range_destroy(&tmp_range);
+ mls_level_destroy(&tmp_level);
+ return -1;
+ }
+ mls_range_destroy(&tmp_range);

+		mls_level_destroy(&tmp_level);
	}

	ebitmap_init(&tmp_union);
@@ -784,7 +828,7 @@ static int sens_copy_callback(hashtab_ke
	}

	if (state->verbose)

- INFO(state->handle, "copying senitivity level %s", id);
+ INFO(state->handle, "copying sensitivity level %s", id);

	if ((new_level =
	     (level_datum_t *) calloc(1, sizeof(*new_level))) == NULL
@@ -2203,6 +2247,17 @@ int expand_module(sepol_handle_t * handl
	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
		goto cleanup;

+ /* copy MLS's sensitivity level and categories - this needs to be done
+ * before expanding users (they need to be indexed too) */
+ if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
+ goto cleanup;
+ if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
+ goto cleanup;
+ if (policydb_index_others(handle, out, verbose)) {
+ ERR(handle, "Error while indexing out symbols");
+ goto cleanup;
+ }
+

	/* copy users */
	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
		goto cleanup;
@@ -2211,13 +2266,6 @@ int expand_module(sepol_handle_t * handl
	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
		goto cleanup;

- /* now copy MLS's sensitivity level and categories */
- if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)
- || hashtab_map(state.base->p_cats.table, cats_copy_callback,
- &state)) {
- goto cleanup;
- }
-

	if (policydb_index_classes(out)) {
		ERR(handle, "Error while indexing out classes");
		goto cleanup;
libsepol/src/mls.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/mls.c selinux-mls-users/libsepol/src/mls.c
@@ -310,7 +310,7 @@ int mls_context_isvalid(const policydb_t
	if (!c->user || c->user > p->p_users.nprim)
		return 0;
	usrdatum = p->user_val_to_struct[c->user - 1];
-	if (!mls_range_contains(usrdatum->range, c->range))
+	if (!mls_range_contains(usrdatum->exp_range, c->range))
		return 0;	/* user may not be associated with range */

	return 1;
@@ -512,9 +512,9 @@ int mls_setup_user_range(context_struct_
	if (mls) {
		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);

- mls_level_t *user_low = &(user->range.level[0]);
- mls_level_t *user_clr = &(user->range.level[1]);
- mls_level_t *user_def = &(user->dfltlevel);
+ mls_level_t *user_low = &(user->exp_range.level[0]);
+ mls_level_t *user_clr = &(user->exp_range.level[1]);

+		mls_level_t *user_def = &(user->exp_dfltlevel);
		mls_level_t *usercon_sen = &(usercon->range.level[0]);
		mls_level_t *usercon_clr = &(usercon->range.level[1]);
libsepol/src/policydb.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/policydb.c selinux-mls-users/libsepol/src/policydb.c
@@ -112,7 +112,7 @@ static struct policydb_compat_info polic
	 },
	{
	 .type = POLICY_BASE,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
	 .sym_num = SYM_NUM,
	 .ocon_num = OCON_NODE6 + 1,
	 },
@@ -130,7 +130,7 @@ static struct policydb_compat_info polic
	 },
	{
	 .type = POLICY_MOD,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
	 .sym_num = SYM_NUM,
	 .ocon_num = 0},
};
@@ -233,18 +233,22 @@ void user_datum_init(user_datum_t * x)
{
	memset(x, 0, sizeof(user_datum_t));
	role_set_init(&x->roles);
-	mls_range_init(&x->range);
-	mls_level_init(&x->dfltlevel);
+	mls_semantic_range_init(&x->range);
+	mls_semantic_level_init(&x->dfltlevel);
	ebitmap_init(&x->cache);

+ mls_range_init(&x->exp_range);
+ mls_level_init(&x->exp_dfltlevel);
}

void user_datum_destroy(user_datum_t * x)

{
	if (x != NULL) {
		role_set_destroy(&x->roles);
-		mls_range_destroy(&x->range);
-		mls_level_destroy(&x->dfltlevel);
+		mls_semantic_range_destroy(&x->range);
+		mls_semantic_level_destroy(&x->dfltlevel);
		ebitmap_destroy(&x->cache);
+		mls_range_destroy(&x->exp_range);
+		mls_level_destroy(&x->exp_dfltlevel);
	}
}

@@ -498,6 +502,17 @@ int policydb_user_cache(hashtab_key_t ke

		return -1;
	}

+ mls_range_destroy(&user->exp_range);
+ if (mls_semantic_range_expand(&user->range, &user->exp_range, p, NULL)) {
+ return -1;
+ }
+
+ mls_level_destroy(&user->exp_dfltlevel);
+ if (mls_semantic_level_expand(&user->dfltlevel,
+ &user->exp_dfltlevel, p, NULL)) {
+ return -1;
+ }
+

	return 0;
}

@@ -2234,17 +2249,35 @@ static int user_read(policydb_t * p, has

			goto bad;
	}

- /* users aren't allowed in mls modules but they can be required, the mls fields will be empty,
- * user declarations in non-mls modules will also have empty mls fields */
+ /* users were not allowed in mls modules before version
+ * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
+ * required - the mls fields will be empty. user declarations in
+ * non-mls modules will also have empty mls fields */

	if ((p->policy_type == POLICY_KERN
	     && p->policyvers >= POLICYDB_VERSION_MLS)
	    || (p->policy_type == POLICY_MOD
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
	    || (p->policy_type == POLICY_BASE

- && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
- if (mls_read_range_helper(&usrdatum->range, fp))
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS
+ && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
+ if (mls_read_range_helper(&usrdatum->exp_range, fp))
+ goto bad;
+ if (mls_range_to_semantic(&usrdatum->exp_range,
+ &usrdatum->range))
+ goto bad;
+ if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
+ goto bad;
+ if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
+ &usrdatum->dfltlevel))
+ goto bad;
+ } else if ((p->policy_type == POLICY_MOD
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
+ || (p->policy_type == POLICY_BASE
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
+ if (mls_read_semantic_range_helper(&usrdatum->range, fp))

			goto bad;
-		if (mls_read_level(&usrdatum->dfltlevel, fp))
+		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
			goto bad;
	}
libsepol/src/users.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/users.c selinux-mls-users/libsepol/src/users.c
@@ -47,13 +47,13 @@ static int user_to_record(sepol_handle_t
 
		context_init(&context);
		if (mls_level_cpy(&context.range.level[0],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
			ERR(handle, "could not copy MLS level");
			context_destroy(&context);
			goto err;
		}
		if (mls_level_cpy(&context.range.level[1],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
			ERR(handle, "could not copy MLS level");
			context_destroy(&context);
			goto err;
@@ -71,7 +71,7 @@ static int user_to_record(sepol_handle_t
		free(str);

		context_init(&context);
-		if (mls_range_cpy(&context.range, &usrdatum->range) < 0) {
+		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
			ERR(handle, "could not copy MLS range");
			context_destroy(&context);
			goto err;
@@ -191,8 +191,8 @@ int sepol_user_modify(sepol_handle_t * h
			context_destroy(&context);
			goto err;
		}
-		if (mls_level_cpy(&usrdatum->dfltlevel, &context.range.level[0])
-		    < 0) {
+		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
+				  &context.range.level[0]) < 0) {
			ERR(handle, "could not copy MLS level %s", cmls_level);
			context_destroy(&context);
			goto err;
@@ -211,13 +211,12 @@ int sepol_user_modify(sepol_handle_t * h
			context_destroy(&context);
			goto err;
		}
-		if (mls_range_cpy(&usrdatum->range, &context.range) < 0) {
+		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
			ERR(handle, "could not copy MLS range %s", cmls_range);
			context_destroy(&context);
			goto err;
		}
		context_destroy(&context);
-
	} else if (cmls_level != NULL || cmls_range != NULL) {
		ERR(handle, "MLS is disabled, but MLS level/range "
		    "was found for user %s", cname);
libsepol/src/write.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/write.c selinux-mls-users/libsepol/src/write.c
@@ -1005,18 +1005,27 @@ static int user_write(hashtab_key_t key,
		if (role_set_write(&usrdatum->roles, fp))
			return POLICYDB_ERROR;
	}
-	/* Users are allowed in non-mls modules, so the empty field will be present
-	   in modules with users >= MOD_POLICYDB_VERSION_MLS */
+
	if ((p->policyvers >= POLICYDB_VERSION_MLS
	     && p->policy_type == POLICY_KERN)
	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
		&& p->policy_type == POLICY_MOD)
	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
		&& p->policy_type == POLICY_BASE)) {
-		if (mls_write_range_helper(&usrdatum->range, fp))
+		if (mls_write_range_helper(&usrdatum->exp_range, fp))
			return POLICYDB_ERROR;
-		if (mls_write_level(&usrdatum->dfltlevel, fp))
+		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
			return POLICYDB_ERROR;

+ } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+ && p->policy_type == POLICY_MOD)
+ || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+ && p->policy_type == POLICY_BASE)) {
+ if (mls_write_semantic_range_helper(&usrdatum->range, fp))
+ return -1;
+ if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))

+			return -1;
	}

	return POLICYDB_SUCCESS;

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

Acked-by on v1 3/3
#1 lore raw
Quoted 11 lines · Darrel Goeddel

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Quoted 6 lines

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

Quoted 440 lines
 checkpolicy/policy_parse.y                 |   37 +++-----------
 libsepol/include/sepol/policydb/policydb.h |    9 ++-
 libsepol/src/expand.c                      |   72 ++++++++++++++++++++++++-----
 libsepol/src/mls.c                         |    8 +--
 libsepol/src/policydb.c                    |   57 ++++++++++++++++++----
 libsepol/src/users.c                       |   13 ++---
 libsepol/src/write.c                       |   17 +++++-
 7 files changed, 142 insertions(+), 71 deletions(-)

diff --exclude=.svn -ruNp selinux-rangetrans/checkpolicy/policy_parse.y selinux-mls-users/checkpolicy/policy_parse.y

checkpolicy/policy_parse.y +8 -29
@@ -3736,11 +3736,10 @@ static int define_user(void)
 		free(id);
 
 		usrdatum->dfltlevel.sens = levdatum->level->sens;
-		ebitmap_init(&usrdatum->dfltlevel.cat);
 
 		while ((id = queue_remove(id_queue))) {
-			if (parse_categories(id, levdatum,
-					     &usrdatum->dfltlevel.cat)) {
+			if (parse_semantic_categories(id, levdatum,
+			                            &usrdatum->dfltlevel.cat)) {
 				free(id);
 				return -1;
 			}
@@ -3762,13 +3761,12 @@ static int define_user(void)
 				return -1;
 			}
 			free(id);
+
 			usrdatum->range.level[l].sens = levdatum->level->sens;
-			ebitmap_init(&usrdatum->range.level[l].cat);
 
 			while ((id = queue_remove(id_queue))) {
-				if (parse_categories(id, levdatum,
-						     &usrdatum->range.level[l].
-						     cat)) {
+				if (parse_semantic_categories(id, levdatum,
+				               &usrdatum->range.level[l].cat)) {
 					free(id);
 					return -1;
 				}
@@ -3781,33 +3779,14 @@ static int define_user(void)
 		}
 
 		if (l == 0) {
-			usrdatum->range.level[1].sens =
-			    usrdatum->range.level[0].sens;
-			if (ebitmap_cpy(&usrdatum->range.level[1].cat,
-					&usrdatum->range.level[0].cat)) {
+			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
+			                           &usrdatum->range.level[0])) {
 				yyerror("out of memory");
-				goto out;
+				return -1;
 			}
 		}
-		if (!mls_level_dom(&usrdatum->range.level[1],
-				   &usrdatum->range.level[0])) {
-			yyerror("high level does not dominate low level");
-			goto out;
-		}
-		if (!mls_level_between(&usrdatum->dfltlevel,
-				       &usrdatum->range.level[0],
-				       &usrdatum->range.level[1])) {
-			yyerror("default level not within user range");
-			goto out;
-		}
 	}
 	return 0;
-
-      out:
-	ebitmap_destroy(&usrdatum->dfltlevel.cat);
-	ebitmap_destroy(&usrdatum->range.level[0].cat);
-	ebitmap_destroy(&usrdatum->range.level[1].cat);
-	return -1;
 }
 
 static int parse_security_context(context_struct_t * c)

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/include/sepol/policydb/policydb.h selinux-mls-users/libsepol/include/sepol/policydb/policydb.h

libsepol/include/sepol/policydb/policydb.h +6 -3
@@ -149,9 +149,11 @@ typedef struct type_datum {
 typedef struct user_datum {
 	symtab_datum_t s;
 	role_set_t roles;	/* set of authorized roles for user */
-	mls_range_t range;	/* MLS range (min. - max.) for user */
-	mls_level_t dfltlevel;	/* default login MLS level for user */
+	mls_semantic_range_t range;	/* MLS range (min. - max.) for user */
+	mls_semantic_level_t dfltlevel;	/* default login MLS level for user */
 	ebitmap_t cache;	/* This is an expanded set used for context validation during parsing */
+	mls_range_t exp_range;     /* expanded range used for validation */
+	mls_level_t exp_dfltlevel; /* expanded range used for validation */
 } user_datum_t;
 
 /* Sensitivity attributes */
@@ -586,9 +588,10 @@ extern int policydb_write(struct policyd
 #define MOD_POLICYDB_VERSION_VALIDATETRANS 5
 #define MOD_POLICYDB_VERSION_MLS	   5
 #define MOD_POLICYDB_VERSION_RANGETRANS	   6
+#define MOD_POLICYDB_VERSION_MLS_USERS	   6
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS_USERS
 
 #define POLICYDB_CONFIG_MLS    1
 

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c

libsepol/src/expand.c +60 -12
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
 			return -1;
 		}
 
-		/* clone MLS stuff */
-		if (mls_range_cpy(&new_user->range, &user->range) == -1
-		    || mls_level_cpy(&new_user->dfltlevel,
-				     &user->dfltlevel) == -1) {
+		/* copy semantic MLS info */
+		if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
+		if (mls_semantic_level_cpy(&new_user->dfltlevel,
+					   &user->dfltlevel)) {
+			ERR(state->handle, "Out of memory!");
+			return -1;
+		}
+
+		/* expand the semantic MLS info */
+		if (mls_semantic_range_expand(&new_user->range,
+					      &new_user->exp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&new_user->dfltlevel,
+					      &new_user->exp_dfltlevel,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (!mls_level_between(&new_user->exp_dfltlevel,
+				       &new_user->exp_range.level[0],
+				       &new_user->exp_range.level[1])) {
+			ERR(state->handle, "default level not within user "
+			    "range");
+			return -1;
+		}
+	} else {
+		/* require that the MLS info match */
+		mls_range_t tmp_range;
+		mls_level_t tmp_level;
+
+		if (mls_semantic_range_expand(&user->range, &tmp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
+					      state->out, state->handle)) {
+			mls_range_destroy(&tmp_range);
+			return -1;
+		}
+		if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
+		    !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
+			mls_range_destroy(&tmp_range);
+			mls_level_destroy(&tmp_level);
+			return -1;
+		}
+		mls_range_destroy(&tmp_range);
+		mls_level_destroy(&tmp_level);
 	}
 
 	ebitmap_init(&tmp_union);
@@ -784,7 +828,7 @@ static int sens_copy_callback(hashtab_ke
 	}
 
 	if (state->verbose)
-		INFO(state->handle, "copying senitivity level %s", id);
+		INFO(state->handle, "copying sensitivity level %s", id);
 
 	if ((new_level =
 	     (level_datum_t *) calloc(1, sizeof(*new_level))) == NULL
@@ -2203,6 +2247,17 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
 		goto cleanup;
 
+	/* copy MLS's sensitivity level and categories - this needs to be done
+	 * before expanding users (they need to be indexed too) */
+	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
+		goto cleanup;
+	if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
+		goto cleanup;
+	if (policydb_index_others(handle, out, verbose)) {
+		ERR(handle, "Error while indexing out symbols");
+		goto cleanup;
+	}
+
 	/* copy users */
 	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
 		goto cleanup;
@@ -2211,13 +2266,6 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
 		goto cleanup;
 
-	/* now copy MLS's sensitivity level and categories */
-	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)
-	    || hashtab_map(state.base->p_cats.table, cats_copy_callback,
-			   &state)) {
-		goto cleanup;
-	}
-
 	if (policydb_index_classes(out)) {
 		ERR(handle, "Error while indexing out classes");
 		goto cleanup;

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/mls.c selinux-mls-users/libsepol/src/mls.c

libsepol/src/mls.c +4 -4
@@ -310,7 +310,7 @@ int mls_context_isvalid(const policydb_t
 	if (!c->user || c->user > p->p_users.nprim)
 		return 0;
 	usrdatum = p->user_val_to_struct[c->user - 1];
-	if (!mls_range_contains(usrdatum->range, c->range))
+	if (!mls_range_contains(usrdatum->exp_range, c->range))
 		return 0;	/* user may not be associated with range */
 
 	return 1;
@@ -512,9 +512,9 @@ int mls_setup_user_range(context_struct_
 	if (mls) {
 		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
 		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);
-		mls_level_t *user_low = &(user->range.level[0]);
-		mls_level_t *user_clr = &(user->range.level[1]);
-		mls_level_t *user_def = &(user->dfltlevel);
+		mls_level_t *user_low = &(user->exp_range.level[0]);
+		mls_level_t *user_clr = &(user->exp_range.level[1]);
+		mls_level_t *user_def = &(user->exp_dfltlevel);
 		mls_level_t *usercon_sen = &(usercon->range.level[0]);
 		mls_level_t *usercon_clr = &(usercon->range.level[1]);
 

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/policydb.c selinux-mls-users/libsepol/src/policydb.c

libsepol/src/policydb.c +45 -12
@@ -112,7 +112,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_BASE,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = OCON_NODE6 + 1,
 	 },
@@ -130,7 +130,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_MOD,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = 0},
 };
@@ -233,18 +233,22 @@ void user_datum_init(user_datum_t * x)
 {
 	memset(x, 0, sizeof(user_datum_t));
 	role_set_init(&x->roles);
-	mls_range_init(&x->range);
-	mls_level_init(&x->dfltlevel);
+	mls_semantic_range_init(&x->range);
+	mls_semantic_level_init(&x->dfltlevel);
 	ebitmap_init(&x->cache);
+	mls_range_init(&x->exp_range);
+	mls_level_init(&x->exp_dfltlevel);
 }
 
 void user_datum_destroy(user_datum_t * x)
 {
 	if (x != NULL) {
 		role_set_destroy(&x->roles);
-		mls_range_destroy(&x->range);
-		mls_level_destroy(&x->dfltlevel);
+		mls_semantic_range_destroy(&x->range);
+		mls_semantic_level_destroy(&x->dfltlevel);
 		ebitmap_destroy(&x->cache);
+		mls_range_destroy(&x->exp_range);
+		mls_level_destroy(&x->exp_dfltlevel);
 	}
 }
 
@@ -498,6 +502,17 @@ int policydb_user_cache(hashtab_key_t ke
 		return -1;
 	}
 
+	mls_range_destroy(&user->exp_range);
+	if (mls_semantic_range_expand(&user->range, &user->exp_range, p, NULL)) {
+		return -1;
+	}
+
+	mls_level_destroy(&user->exp_dfltlevel);
+	if (mls_semantic_level_expand(&user->dfltlevel,
+				      &user->exp_dfltlevel, p, NULL)) {
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -2234,17 +2249,35 @@ static int user_read(policydb_t * p, has
 			goto bad;
 	}
 
-	/* users aren't allowed in mls modules but they can be required, the mls fields will be empty,
-	 * user declarations in non-mls modules will also have empty mls fields */
+	/* users were not allowed in mls modules before version
+	 * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
+	 * required - the mls fields will be empty.  user declarations in
+	 * non-mls modules will also have empty mls fields */
 	if ((p->policy_type == POLICY_KERN
 	     && p->policyvers >= POLICYDB_VERSION_MLS)
 	    || (p->policy_type == POLICY_MOD
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
 	    || (p->policy_type == POLICY_BASE
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
-		if (mls_read_range_helper(&usrdatum->range, fp))
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_range_helper(&usrdatum->exp_range, fp))
+			goto bad;
+		if (mls_range_to_semantic(&usrdatum->exp_range,
+					  &usrdatum->range))
+			goto bad;
+		if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
+			goto bad;
+		if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
+					  &usrdatum->dfltlevel))
+			goto bad;
+	} else if ((p->policy_type == POLICY_MOD
+		    && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
+		   || (p->policy_type == POLICY_BASE
+		       && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_semantic_range_helper(&usrdatum->range, fp))
 			goto bad;
-		if (mls_read_level(&usrdatum->dfltlevel, fp))
+		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
 			goto bad;
 	}
 

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/users.c selinux-mls-users/libsepol/src/users.c

libsepol/src/users.c +6 -7
@@ -47,13 +47,13 @@ static int user_to_record(sepol_handle_t
 
 		context_init(&context);
 		if (mls_level_cpy(&context.range.level[0],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
 		}
 		if (mls_level_cpy(&context.range.level[1],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
@@ -71,7 +71,7 @@ static int user_to_record(sepol_handle_t
 		free(str);
 
 		context_init(&context);
-		if (mls_range_cpy(&context.range, &usrdatum->range) < 0) {
+		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
 			ERR(handle, "could not copy MLS range");
 			context_destroy(&context);
 			goto err;
@@ -191,8 +191,8 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_level_cpy(&usrdatum->dfltlevel, &context.range.level[0])
-		    < 0) {
+		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
+				  &context.range.level[0]) < 0) {
 			ERR(handle, "could not copy MLS level %s", cmls_level);
 			context_destroy(&context);
 			goto err;
@@ -211,13 +211,12 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_range_cpy(&usrdatum->range, &context.range) < 0) {
+		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
 			ERR(handle, "could not copy MLS range %s", cmls_range);
 			context_destroy(&context);
 			goto err;
 		}
 		context_destroy(&context);
-
 	} else if (cmls_level != NULL || cmls_range != NULL) {
 		ERR(handle, "MLS is disabled, but MLS level/range "
 		    "was found for user %s", cname);

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/write.c selinux-mls-users/libsepol/src/write.c

libsepol/src/write.c +13 -5
@@ -1005,18 +1005,27 @@ static int user_write(hashtab_key_t key,
 		if (role_set_write(&usrdatum->roles, fp))
 			return POLICYDB_ERROR;
 	}
-	/* Users are allowed in non-mls modules, so the empty field will be present
-	   in modules with users >= MOD_POLICYDB_VERSION_MLS */
+
 	if ((p->policyvers >= POLICYDB_VERSION_MLS
 	     && p->policy_type == POLICY_KERN)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_MOD)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_BASE)) {
-		if (mls_write_range_helper(&usrdatum->range, fp))
+		if (mls_write_range_helper(&usrdatum->exp_range, fp))
 			return POLICYDB_ERROR;
-		if (mls_write_level(&usrdatum->dfltlevel, fp))
+		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
 			return POLICYDB_ERROR;
+	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+		    && p->policy_type == POLICY_MOD)
+		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+		       && p->policy_type == POLICY_BASE)) {
+		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
+			return -1;
+		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
+			return -1;
 	}
 
 	return POLICYDB_SUCCESS;
 
--
Quoted 3 lines

This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#2 lore raw
In reply to Darrel Goeddel
Quoted 17 lines · Darrel Goeddel

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

<snip>

Quoted 29 lines

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c

libsepol/src/expand.c +15 -4
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
 			return -1;
 		}
 
-		/* clone MLS stuff */
-		if (mls_range_cpy(&new_user->range, &user->range) == -1
-		    || mls_level_cpy(&new_user->dfltlevel,
-				     &user->dfltlevel) == -1) {
+		/* copy semantic MLS info */
+		if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
+		if (mls_semantic_level_cpy(&new_user->dfltlevel,
+					   &user->dfltlevel)) {
+			ERR(state->handle, "Out of memory!");
+			return -1;
+		}
+
+		/* expand the semantic MLS info */
+		if (mls_semantic_range_expand(&new_user->range,
+					      &new_user->exp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&new_user->dfltlevel,

libsepol/src/expand.c static int user_copy_callback(hashtab_ke · line 718

Quoted 10 lines
libsepol/src/expand.c +10 -0
+					      &new_user->exp_dfltlevel,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (!mls_level_between(&new_user->exp_dfltlevel,
+				       &new_user->exp_range.level[0],
+				       &new_user->exp_range.level[1])) {
+			ERR(state->handle, "default level not within user "
+			    "range");
+			return -1;

not sure here, we normally outright expand into the new datum in the copy_callbacks. Is there a reason you need to keep the semantic copy around? Is there a problem moving user copying to after level copying if that is the issue.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#3 lore raw
Quoted 57 lines · Joshua Brindle
Quoted 17 lines · Darrel Goeddel

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

<snip>

Quoted 36 lines

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c

libsepol/src/expand.c +22 -4
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
 			return -1;
 		}
 
-		/* clone MLS stuff */
-		if (mls_range_cpy(&new_user->range, &user->range) == -1
-		    || mls_level_cpy(&new_user->dfltlevel,
-				     &user->dfltlevel) == -1) {
+		/* copy semantic MLS info */
+		if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
+		if (mls_semantic_level_cpy(&new_user->dfltlevel,
+					   &user->dfltlevel)) {
+			ERR(state->handle, "Out of memory!");
+			return -1;
+		}
+
+		/* expand the semantic MLS info */
+		if (mls_semantic_range_expand(&new_user->range,
+					      &new_user->exp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&new_user->dfltlevel,
+					      &new_user->exp_dfltlevel,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (!mls_level_between(&new_user->exp_dfltlevel,
+				       &new_user->exp_range.level[0],
+				       &new_user->exp_range.level[1])) {
Quoted 8 lines

libsepol/src/expand.c static int user_copy_callback(hashtab_ke · line 718

Quoted 3 lines
libsepol/src/expand.c +3 -0
+			ERR(state->handle, "default level not within user "
+			    "range");
+			return -1;

not sure here, we normally outright expand into the new datum in the copy_callbacks. Is there a reason you need to keep the semantic copy around?

I was trying to keep both representation in sync while I was developing this code. Removing the copies of the semantic representation seems feasible - I'll test.

Is there a problem moving user copying to after level copying if

Quoted 1 line

that is the issue.

There should be no problems.

Signature · 6 lines
Darrel

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
#4 lore raw
Quoted 76 lines · Darrel Goeddel
Quoted 60 lines · Joshua Brindle
Quoted 17 lines · Darrel Goeddel

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

<snip>

Quoted 39 lines

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c
--- selinux-rangetrans/libsepol/src/expand.c 2006-08-25
07:37:42.000000000 -0500
+++ selinux-mls-users/libsepol/src/expand.c 2006-08-25
07:50:48.000000000 -0500

(quoted diff) +23 -4
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
            return -1;
        }
 
-        /* clone MLS stuff */
-        if (mls_range_cpy(&new_user->range, &user->range) == -1
-            || mls_level_cpy(&new_user->dfltlevel,
-                     &user->dfltlevel) == -1) {
+        /* copy semantic MLS info */
+        if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
            ERR(state->handle, "Out of memory!");
            return -1;
        }
+        if (mls_semantic_level_cpy(&new_user->dfltlevel,
+                       &user->dfltlevel)) {
+            ERR(state->handle, "Out of memory!");
+            return -1;
+        }
+
+        /* expand the semantic MLS info */
+        if (mls_semantic_range_expand(&new_user->range,
+                          &new_user->exp_range,
+                          state->out, state->handle)) {
+            return -1;
+        }
+        if (mls_semantic_level_expand(&new_user->dfltlevel,
+                          &new_user->exp_dfltlevel,
+                          state->out, state->handle)) {
+            return -1;
+        }
+        if (!mls_level_between(&new_user->exp_dfltlevel,
+                       &new_user->exp_range.level[0],
+                       &new_user->exp_range.level[1])) {
+            ERR(state->handle, "default level not within user "
Quoted 8 lines

Review static int user_copy_callback(hashtab_ke · line 718

Quoted 2 lines
(quoted diff) +2 -0
+                "range");
+            return -1;

not sure here, we normally outright expand into the new datum in the copy_callbacks. Is there a reason you need to keep the semantic copy around?

I was trying to keep both representation in sync while I was developing this code. Removing the copies of the semantic representation seems feasible - I'll test.

Quoted 6 lines

Is there a problem moving user copying to after level copying if

Quoted 1 line

that is the issue.

There should be no problems.

So... there can be problems. Re-indexing will cause a re-expansion of the user's MLS fields. This is similar to the caching of roles using the currently available information. If we do not copy the semantic versions over, a re-indexing of a kernel policy will wipe out all MLS info for users - not good.

We could:
- just leave it in there and allow re-indexing to work as-is
- get fancy and put in a flag to keep track of which representation is valid
- only expand the MLS info during a policydb_user_cache call if we are not dealing with a kernel policy

The first option is easiest ;) The third option also seems reasonable to me. That would basically say that kernel policies rely on the expanded MLS, while other policies rely on the semantic MLS.

In a related note, what type of policies can be used with functions like sepol_user_*() and sepol_context_isvalid(). With the current patch, those functions assume that the expanded MLS is there, so they expect a kernel policy or modular policy that has been expanded (or at least has the user MLS fields expanded through indexing).

Signature · 6 lines
Darrel

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
#5 lore raw
Quoted 104 lines · Darrel Goeddel
Quoted 85 lines · Darrel Goeddel
Quoted 69 lines · Joshua Brindle
Quoted 25 lines · Darrel Goeddel

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS
range and dfltlevel. There is also the possibility of having an expanded
version of that data also present in the user_datum. This is used much like
the role cache in the user_datum. When the user are indexed, the MLS info is
expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion
is performed again to ensure that the data it is present and in sync with the
rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have
their MLS data converted to the new semantic structs.

<snip>

Quoted 40 lines

diff --exclude=.svn -ruNp selinux-rangetrans/libsepol/src/expand.c selinux-mls-users/libsepol/src/expand.c
--- selinux-rangetrans/libsepol/src/expand.c 2006-08-25
07:37:42.000000000 -0500
+++ selinux-mls-users/libsepol/src/expand.c 2006-08-25
07:50:48.000000000 -0500

(quoted diff) +23 -4
@@ -688,13 +688,57 @@ static int user_copy_callback(hashtab_ke
            return -1;
        }
 
-        /* clone MLS stuff */
-        if (mls_range_cpy(&new_user->range, &user->range) == -1
-            || mls_level_cpy(&new_user->dfltlevel,
-                     &user->dfltlevel) == -1) {
+        /* copy semantic MLS info */
+        if (mls_semantic_range_cpy(&new_user->range, &user->range)) {
            ERR(state->handle, "Out of memory!");
            return -1;
        }
+        if (mls_semantic_level_cpy(&new_user->dfltlevel,
+                       &user->dfltlevel)) {
+            ERR(state->handle, "Out of memory!");
+            return -1;
+        }
+
+        /* expand the semantic MLS info */
+        if (mls_semantic_range_expand(&new_user->range,
+                          &new_user->exp_range,
+                          state->out, state->handle)) {
+            return -1;
+        }
+        if (mls_semantic_level_expand(&new_user->dfltlevel,
+                          &new_user->exp_dfltlevel,
+                          state->out, state->handle)) {
+            return -1;
+        }
+        if (!mls_level_between(&new_user->exp_dfltlevel,
+                       &new_user->exp_range.level[0],
+                       &new_user->exp_range.level[1])) {
+            ERR(state->handle, "default level not within user "
Quoted 8 lines

Review static int user_copy_callback(hashtab_ke · line 718

Quoted 2 lines
(quoted diff) +2 -0
+                "range");
+            return -1;

not sure here, we normally outright expand into the new datum in the copy_callbacks. Is there a reason you need to keep the semantic copy around?

I was trying to keep both representation in sync while I was developing this code. Removing the copies of the semantic representation seems feasible - I'll test.

Quoted 6 lines

Is there a problem moving user copying to after level copying if

Quoted 1 line

that is the issue.

There should be no problems.

So... there can be problems. Re-indexing will cause a re-expansion of the user's MLS fields. This is similar to the caching of roles using the currently available information. If we do not copy the semantic versions over, a re-indexing of a kernel policy will wipe out all MLS info for users - not good.

We could:
- just leave it in there and allow re-indexing to work as-is
- get fancy and put in a flag to keep track of which representation is valid
- only expand the MLS info during a policydb_user_cache call if we are not dealing with a kernel policy

Quoted 3 lines

The first option is easiest ;) The third option also seems reasonable to me. That would basically say that kernel policies rely on the expanded MLS, while other policies rely on the semantic MLS.

I agree, the third option should be how we handle everything else .

Quoted 7 lines

In a related note, what type of policies can be used with functions like sepol_user_*() and sepol_context_isvalid(). With the current patch, those functions assume that the expanded MLS is there, so they expect a kernel policy or modular policy that has been expanded (or at least has the user MLS fields expanded through indexing).

the _isvalid function should only work after users and roles have their cache filled up which should be the same for mls.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#6 lore raw

PATCH v2 3/3 semantic MLS representation for users

In reply to Darrel Goeddel

Here is a second take on the previous patch. The changes are:
- no longer create semantic representation of user MLS fields when reading in a kernel format policy
- no longer copy the semantic representation of user MLS fields when expanding users
- no longer deal attempt to expand the semantic MLS components when caching user information if the policy is already in kernel format (the semantic info is no longer there)

---

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

checkpolicy/policy_parse.y                 |   37 +++--------------
libsepol/include/sepol/policydb/policydb.h |    9 ++--
libsepol/src/expand.c                      |   63 +++++++++++++++++++++++------
libsepol/src/mls.c                         |    8 +--
libsepol/src/policydb.c                    |   62 +++++++++++++++++++++++-----
libsepol/src/users.c                       |   13 ++---
libsepol/src/write.c                       |   17 +++++--
7 files changed, 137 insertions(+), 72 deletions(-)
checkpolicy/policy_parse.y +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/checkpolicy/policy_parse.y selinux-mls-users-2/checkpolicy/policy_parse.y
@@ -3737,11 +3737,10 @@ static int define_user(void)
		free(id);

		usrdatum->dfltlevel.sens = levdatum->level->sens;

- ebitmap_init(&usrdatum->dfltlevel.cat);

		while ((id = queue_remove(id_queue))) {
-			if (parse_categories(id, levdatum,
-					     &usrdatum->dfltlevel.cat)) {
+			if (parse_semantic_categories(id, levdatum,
+			                            &usrdatum->dfltlevel.cat)) {
				free(id);
				return -1;
			}
@@ -3763,13 +3762,12 @@ static int define_user(void)
				return -1;
			}
			free(id);
+
			usrdatum->range.level[l].sens = levdatum->level->sens;

- ebitmap_init(&usrdatum->range.level[l].cat);

			while ((id = queue_remove(id_queue))) {

- if (parse_categories(id, levdatum,
- &usrdatum->range.level[l].
- cat)) {
+ if (parse_semantic_categories(id, levdatum,

+				               &usrdatum->range.level[l].cat)) {
					free(id);
					return -1;
				}
@@ -3782,33 +3780,14 @@ static int define_user(void)
		}

		if (l == 0) {

- usrdatum->range.level[1].sens =
- usrdatum->range.level[0].sens;
- if (ebitmap_cpy(&usrdatum->range.level[1].cat,
- &usrdatum->range.level[0].cat)) {
+ if (mls_semantic_level_cpy(&usrdatum->range.level[1],

+			                           &usrdatum->range.level[0])) {
				yyerror("out of memory");
-				goto out;
+				return -1;
			}
		}

- if (!mls_level_dom(&usrdatum->range.level[1],
- &usrdatum->range.level[0])) {
- yyerror("high level does not dominate low level");
- goto out;
- }
- if (!mls_level_between(&usrdatum->dfltlevel,
- &usrdatum->range.level[0],
- &usrdatum->range.level[1])) {
- yyerror("default level not within user range");
- goto out;
- }

	}
	return 0;

-
- out:
- ebitmap_destroy(&usrdatum->dfltlevel.cat);
- ebitmap_destroy(&usrdatum->range.level[0].cat);
- ebitmap_destroy(&usrdatum->range.level[1].cat);
- return -1;
}

static int parse_security_context(context_struct_t * c)

libsepol/include/sepol/policydb/policydb.h +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/include/sepol/policydb/policydb.h selinux-mls-users-2/libsepol/include/sepol/policydb/policydb.h
@@ -149,9 +149,11 @@ typedef struct type_datum {
typedef struct user_datum {
	symtab_datum_t s;
	role_set_t roles;	/* set of authorized roles for user */

- mls_range_t range; /* MLS range (min. - max.) for user */
- mls_level_t dfltlevel; /* default login MLS level for user */
+ mls_semantic_range_t range; /* MLS range (min. - max.) for user */
+ mls_semantic_level_t dfltlevel; /* default login MLS level for user */
ebitmap_t cache; /* This is an expanded set used for context validation during parsing */
+ mls_range_t exp_range; /* expanded range used for validation */
+ mls_level_t exp_dfltlevel; /* expanded range used for validation */
} user_datum_t;

/* Sensitivity attributes */
@@ -586,9 +588,10 @@ extern int policydb_write(struct policyd #define MOD_POLICYDB_VERSION_VALIDATETRANS 5
#define MOD_POLICYDB_VERSION_MLS 5
#define MOD_POLICYDB_VERSION_RANGETRANS 6
+#define MOD_POLICYDB_VERSION_MLS_USERS 6

#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS_USERS

#define POLICYDB_CONFIG_MLS 1

libsepol/src/expand.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/expand.c selinux-mls-users-2/libsepol/src/expand.c
@@ -692,13 +692,46 @@ static int user_copy_callback(hashtab_ke
			return -1;
		}

- /* clone MLS stuff */
- if (mls_range_cpy(&new_user->range, &user->range) == -1
- || mls_level_cpy(&new_user->dfltlevel,
- &user->dfltlevel) == -1) {
- ERR(state->handle, "Out of memory!");
+ /* expand the semantic MLS info */
+ if (mls_semantic_range_expand(&user->range,
+ &new_user->exp_range,
+ state->out, state->handle)) {
+ return -1;
+ }
+ if (mls_semantic_level_expand(&user->dfltlevel,
+ &new_user->exp_dfltlevel,
+ state->out, state->handle)) {
+ return -1;
+ }
+ if (!mls_level_between(&new_user->exp_dfltlevel,
+ &new_user->exp_range.level[0],
+ &new_user->exp_range.level[1])) {
+ ERR(state->handle, "default level not within user "
+ "range");
+ return -1;
+ }
+ } else {
+ /* require that the MLS info match */
+ mls_range_t tmp_range;
+ mls_level_t tmp_level;
+
+ if (mls_semantic_range_expand(&user->range, &tmp_range,

+					      state->out, state->handle)) {
			return -1;
		}

+ if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
+ state->out, state->handle)) {
+ mls_range_destroy(&tmp_range);
+ return -1;
+ }
+ if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
+ !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
+ mls_range_destroy(&tmp_range);
+ mls_level_destroy(&tmp_level);
+ return -1;
+ }
+ mls_range_destroy(&tmp_range);

+		mls_level_destroy(&tmp_level);
	}

	ebitmap_init(&tmp_union);
@@ -788,7 +821,7 @@ static int sens_copy_callback(hashtab_ke
	}

	if (state->verbose)

- INFO(state->handle, "copying senitivity level %s", id);
+ INFO(state->handle, "copying sensitivity level %s", id);

	if ((new_level =
	     (level_datum_t *) calloc(1, sizeof(*new_level))) == NULL
@@ -2207,6 +2240,17 @@ int expand_module(sepol_handle_t * handl
	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
		goto cleanup;

+ /* copy MLS's sensitivity level and categories - this needs to be done
+ * before expanding users (they need to be indexed too) */
+ if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
+ goto cleanup;
+ if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
+ goto cleanup;
+ if (policydb_index_others(handle, out, verbose)) {
+ ERR(handle, "Error while indexing out symbols");
+ goto cleanup;
+ }
+

	/* copy users */
	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
		goto cleanup;
@@ -2215,13 +2259,6 @@ int expand_module(sepol_handle_t * handl
	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
		goto cleanup;

- /* now copy MLS's sensitivity level and categories */
- if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)
- || hashtab_map(state.base->p_cats.table, cats_copy_callback,
- &state)) {
- goto cleanup;
- }
-

	if (policydb_index_classes(out)) {
		ERR(handle, "Error while indexing out classes");
		goto cleanup;
libsepol/src/mls.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/mls.c selinux-mls-users-2/libsepol/src/mls.c
@@ -310,7 +310,7 @@ int mls_context_isvalid(const policydb_t
	if (!c->user || c->user > p->p_users.nprim)
		return 0;
	usrdatum = p->user_val_to_struct[c->user - 1];
-	if (!mls_range_contains(usrdatum->range, c->range))
+	if (!mls_range_contains(usrdatum->exp_range, c->range))
		return 0;	/* user may not be associated with range */

	return 1;
@@ -512,9 +512,9 @@ int mls_setup_user_range(context_struct_
	if (mls) {
		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);

- mls_level_t *user_low = &(user->range.level[0]);
- mls_level_t *user_clr = &(user->range.level[1]);
- mls_level_t *user_def = &(user->dfltlevel);
+ mls_level_t *user_low = &(user->exp_range.level[0]);
+ mls_level_t *user_clr = &(user->exp_range.level[1]);

+		mls_level_t *user_def = &(user->exp_dfltlevel);
		mls_level_t *usercon_sen = &(usercon->range.level[0]);
		mls_level_t *usercon_clr = &(usercon->range.level[1]);
libsepol/src/policydb.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/policydb.c selinux-mls-users-2/libsepol/src/policydb.c
@@ -112,7 +112,7 @@ static struct policydb_compat_info polic
	 },
	{
	 .type = POLICY_BASE,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
	 .sym_num = SYM_NUM,
	 .ocon_num = OCON_NODE6 + 1,
	 },
@@ -130,7 +130,7 @@ static struct policydb_compat_info polic
	 },
	{
	 .type = POLICY_MOD,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
	 .sym_num = SYM_NUM,
	 .ocon_num = 0},
};
@@ -233,18 +233,22 @@ void user_datum_init(user_datum_t * x)
{
	memset(x, 0, sizeof(user_datum_t));
	role_set_init(&x->roles);
-	mls_range_init(&x->range);
-	mls_level_init(&x->dfltlevel);
+	mls_semantic_range_init(&x->range);
+	mls_semantic_level_init(&x->dfltlevel);
	ebitmap_init(&x->cache);

+ mls_range_init(&x->exp_range);
+ mls_level_init(&x->exp_dfltlevel);
}

void user_datum_destroy(user_datum_t * x)

{
	if (x != NULL) {
		role_set_destroy(&x->roles);
-		mls_range_destroy(&x->range);
-		mls_level_destroy(&x->dfltlevel);
+		mls_semantic_range_destroy(&x->range);
+		mls_semantic_level_destroy(&x->dfltlevel);
		ebitmap_destroy(&x->cache);
+		mls_range_destroy(&x->exp_range);
+		mls_level_destroy(&x->exp_dfltlevel);
	}
}

@@ -498,6 +502,20 @@ int policydb_user_cache(hashtab_key_t ke

		return -1;
	}

+ if (p->policy_type != POLICY_KERN) {
+ mls_range_destroy(&user->exp_range);
+ if (mls_semantic_range_expand(&user->range,
+ &user->exp_range, p, NULL)) {
+ return -1;
+ }
+
+ mls_level_destroy(&user->exp_dfltlevel);
+ if (mls_semantic_level_expand(&user->dfltlevel,
+ &user->exp_dfltlevel, p, NULL)) {
+ return -1;
+ }
+ }
+

	return 0;
}

@@ -2235,17 +2253,37 @@ static int user_read(policydb_t * p, has

			goto bad;
	}

- /* users aren't allowed in mls modules but they can be required, the mls fields will be empty,
- * user declarations in non-mls modules will also have empty mls fields */
+ /* users were not allowed in mls modules before version
+ * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
+ * required - the mls fields will be empty. user declarations in
+ * non-mls modules will also have empty mls fields */

	if ((p->policy_type == POLICY_KERN
	     && p->policyvers >= POLICYDB_VERSION_MLS)
	    || (p->policy_type == POLICY_MOD
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
	    || (p->policy_type == POLICY_BASE

- && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
- if (mls_read_range_helper(&usrdatum->range, fp))
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS
+ && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
+ if (mls_read_range_helper(&usrdatum->exp_range, fp))
+ goto bad;
+ if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
+ goto bad;
+ if (p->policy_type != POLICY_KERN) {
+ if (mls_range_to_semantic(&usrdatum->exp_range,
+ &usrdatum->range))
+ goto bad;
+ if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
+ &usrdatum->dfltlevel))
+ goto bad;
+ }
+ } else if ((p->policy_type == POLICY_MOD
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
+ || (p->policy_type == POLICY_BASE
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
+ if (mls_read_semantic_range_helper(&usrdatum->range, fp))

			goto bad;
-		if (mls_read_level(&usrdatum->dfltlevel, fp))
+		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
			goto bad;
	}
libsepol/src/users.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/users.c selinux-mls-users-2/libsepol/src/users.c
@@ -47,13 +47,13 @@ static int user_to_record(sepol_handle_t
 
		context_init(&context);
		if (mls_level_cpy(&context.range.level[0],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
			ERR(handle, "could not copy MLS level");
			context_destroy(&context);
			goto err;
		}
		if (mls_level_cpy(&context.range.level[1],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
			ERR(handle, "could not copy MLS level");
			context_destroy(&context);
			goto err;
@@ -71,7 +71,7 @@ static int user_to_record(sepol_handle_t
		free(str);

		context_init(&context);
-		if (mls_range_cpy(&context.range, &usrdatum->range) < 0) {
+		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
			ERR(handle, "could not copy MLS range");
			context_destroy(&context);
			goto err;
@@ -191,8 +191,8 @@ int sepol_user_modify(sepol_handle_t * h
			context_destroy(&context);
			goto err;
		}
-		if (mls_level_cpy(&usrdatum->dfltlevel, &context.range.level[0])
-		    < 0) {
+		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
+				  &context.range.level[0]) < 0) {
			ERR(handle, "could not copy MLS level %s", cmls_level);
			context_destroy(&context);
			goto err;
@@ -211,13 +211,12 @@ int sepol_user_modify(sepol_handle_t * h
			context_destroy(&context);
			goto err;
		}
-		if (mls_range_cpy(&usrdatum->range, &context.range) < 0) {
+		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
			ERR(handle, "could not copy MLS range %s", cmls_range);
			context_destroy(&context);
			goto err;
		}
		context_destroy(&context);
-
	} else if (cmls_level != NULL || cmls_range != NULL) {
		ERR(handle, "MLS is disabled, but MLS level/range "
		    "was found for user %s", cname);
libsepol/src/write.c +0 -0
diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/write.c selinux-mls-users-2/libsepol/src/write.c
@@ -1005,18 +1005,27 @@ static int user_write(hashtab_key_t key,
		if (role_set_write(&usrdatum->roles, fp))
			return POLICYDB_ERROR;
	}
-	/* Users are allowed in non-mls modules, so the empty field will be present
-	   in modules with users >= MOD_POLICYDB_VERSION_MLS */
+
	if ((p->policyvers >= POLICYDB_VERSION_MLS
	     && p->policy_type == POLICY_KERN)
	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
		&& p->policy_type == POLICY_MOD)
	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
		&& p->policy_type == POLICY_BASE)) {
-		if (mls_write_range_helper(&usrdatum->range, fp))
+		if (mls_write_range_helper(&usrdatum->exp_range, fp))
			return POLICYDB_ERROR;
-		if (mls_write_level(&usrdatum->dfltlevel, fp))
+		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
			return POLICYDB_ERROR;

+ } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+ && p->policy_type == POLICY_MOD)
+ || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+ && p->policy_type == POLICY_BASE)) {
+ if (mls_write_semantic_range_helper(&usrdatum->range, fp))
+ return -1;
+ if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))

+			return -1;
	}

	return POLICYDB_SUCCESS;

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

Acked-by on v2 3/3
#7 lore raw
Quoted 452 lines · Darrel Goeddel

Here is a second take on the previous patch. The changes are:
- no longer create semantic representation of user MLS fields when reading in a kernel format policy
- no longer copy the semantic representation of user MLS fields when expanding users
- no longer deal attempt to expand the semantic MLS components when caching user information if the policy is already in kernel format (the semantic info is no longer there)

---

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

 checkpolicy/policy_parse.y                 |   37 +++--------------
 libsepol/include/sepol/policydb/policydb.h |    9 ++--
 libsepol/src/expand.c                      |   63 +++++++++++++++++++++++------
 libsepol/src/mls.c                         |    8 +--
 libsepol/src/policydb.c                    |   62 +++++++++++++++++++++++-----
 libsepol/src/users.c                       |   13 ++---
 libsepol/src/write.c                       |   17 +++++--
 7 files changed, 137 insertions(+), 72 deletions(-)

diff --exclude=.svn -ruNp selinux-rangetrans-2/checkpolicy/policy_parse.y selinux-mls-users-2/checkpolicy/policy_parse.y

checkpolicy/policy_parse.y +8 -29
@@ -3737,11 +3737,10 @@ static int define_user(void)
 		free(id);
 
 		usrdatum->dfltlevel.sens = levdatum->level->sens;
-		ebitmap_init(&usrdatum->dfltlevel.cat);
 
 		while ((id = queue_remove(id_queue))) {
-			if (parse_categories(id, levdatum,
-					     &usrdatum->dfltlevel.cat)) {
+			if (parse_semantic_categories(id, levdatum,
+			                            &usrdatum->dfltlevel.cat)) {
 				free(id);
 				return -1;
 			}
@@ -3763,13 +3762,12 @@ static int define_user(void)
 				return -1;
 			}
 			free(id);
+
 			usrdatum->range.level[l].sens = levdatum->level->sens;
-			ebitmap_init(&usrdatum->range.level[l].cat);
 
 			while ((id = queue_remove(id_queue))) {
-				if (parse_categories(id, levdatum,
-						     &usrdatum->range.level[l].
-						     cat)) {
+				if (parse_semantic_categories(id, levdatum,
+				               &usrdatum->range.level[l].cat)) {
 					free(id);
 					return -1;
 				}
@@ -3782,33 +3780,14 @@ static int define_user(void)
 		}
 
 		if (l == 0) {
-			usrdatum->range.level[1].sens =
-			    usrdatum->range.level[0].sens;
-			if (ebitmap_cpy(&usrdatum->range.level[1].cat,
-					&usrdatum->range.level[0].cat)) {
+			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
+			                           &usrdatum->range.level[0])) {
 				yyerror("out of memory");
-				goto out;
+				return -1;
 			}
 		}
-		if (!mls_level_dom(&usrdatum->range.level[1],
-				   &usrdatum->range.level[0])) {
-			yyerror("high level does not dominate low level");
-			goto out;
-		}
-		if (!mls_level_between(&usrdatum->dfltlevel,
-				       &usrdatum->range.level[0],
-				       &usrdatum->range.level[1])) {
-			yyerror("default level not within user range");
-			goto out;
-		}
 	}
 	return 0;
-
-      out:
-	ebitmap_destroy(&usrdatum->dfltlevel.cat);
-	ebitmap_destroy(&usrdatum->range.level[0].cat);
-	ebitmap_destroy(&usrdatum->range.level[1].cat);
-	return -1;
 }
 
 static int parse_security_context(context_struct_t * c)

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/include/sepol/policydb/policydb.h selinux-mls-users-2/libsepol/include/sepol/policydb/policydb.h

libsepol/include/sepol/policydb/policydb.h +6 -3
@@ -149,9 +149,11 @@ typedef struct type_datum {
 typedef struct user_datum {
 	symtab_datum_t s;
 	role_set_t roles;	/* set of authorized roles for user */
-	mls_range_t range;	/* MLS range (min. - max.) for user */
-	mls_level_t dfltlevel;	/* default login MLS level for user */
+	mls_semantic_range_t range;	/* MLS range (min. - max.) for user */
+	mls_semantic_level_t dfltlevel;	/* default login MLS level for user */
 	ebitmap_t cache;	/* This is an expanded set used for context validation during parsing */
+	mls_range_t exp_range;     /* expanded range used for validation */
+	mls_level_t exp_dfltlevel; /* expanded range used for validation */
 } user_datum_t;
 
 /* Sensitivity attributes */
@@ -586,9 +588,10 @@ extern int policydb_write(struct policyd
 #define MOD_POLICYDB_VERSION_VALIDATETRANS 5
 #define MOD_POLICYDB_VERSION_MLS	   5
 #define MOD_POLICYDB_VERSION_RANGETRANS	   6
+#define MOD_POLICYDB_VERSION_MLS_USERS	   6
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS_USERS
 
 #define POLICYDB_CONFIG_MLS    1
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/expand.c selinux-mls-users-2/libsepol/src/expand.c

libsepol/src/expand.c +50 -13
@@ -692,13 +692,46 @@ static int user_copy_callback(hashtab_ke
 			return -1;
 		}
 
-		/* clone MLS stuff */
-		if (mls_range_cpy(&new_user->range, &user->range) == -1
-		    || mls_level_cpy(&new_user->dfltlevel,
-				     &user->dfltlevel) == -1) {
-			ERR(state->handle, "Out of memory!");
+		/* expand the semantic MLS info */
+		if (mls_semantic_range_expand(&user->range,
+					      &new_user->exp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&user->dfltlevel,
+					      &new_user->exp_dfltlevel,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (!mls_level_between(&new_user->exp_dfltlevel,
+				       &new_user->exp_range.level[0],
+				       &new_user->exp_range.level[1])) {
+			ERR(state->handle, "default level not within user "
+			    "range");
+			return -1;
+		}
+	} else {
+		/* require that the MLS info match */
+		mls_range_t tmp_range;
+		mls_level_t tmp_level;
+
+		if (mls_semantic_range_expand(&user->range, &tmp_range,
+					      state->out, state->handle)) {
 			return -1;
 		}
+		if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
+					      state->out, state->handle)) {
+			mls_range_destroy(&tmp_range);
+			return -1;
+		}
+		if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
+		    !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
+			mls_range_destroy(&tmp_range);
+			mls_level_destroy(&tmp_level);
+			return -1;
+		}
+		mls_range_destroy(&tmp_range);
+		mls_level_destroy(&tmp_level);
 	}
 
 	ebitmap_init(&tmp_union);
@@ -788,7 +821,7 @@ static int sens_copy_callback(hashtab_ke
 	}
 
 	if (state->verbose)
-		INFO(state->handle, "copying senitivity level %s", id);
+		INFO(state->handle, "copying sensitivity level %s", id);
 
 	if ((new_level =
 	     (level_datum_t *) calloc(1, sizeof(*new_level))) == NULL
@@ -2207,6 +2240,17 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
 		goto cleanup;
 
+	/* copy MLS's sensitivity level and categories - this needs to be done
+	 * before expanding users (they need to be indexed too) */
+	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
+		goto cleanup;
+	if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
+		goto cleanup;
+	if (policydb_index_others(handle, out, verbose)) {
+		ERR(handle, "Error while indexing out symbols");
+		goto cleanup;
+	}
+
 	/* copy users */
 	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
 		goto cleanup;
@@ -2215,13 +2259,6 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
 		goto cleanup;
 
-	/* now copy MLS's sensitivity level and categories */
-	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)
-	    || hashtab_map(state.base->p_cats.table, cats_copy_callback,
-			   &state)) {
-		goto cleanup;
-	}
-
 	if (policydb_index_classes(out)) {
 		ERR(handle, "Error while indexing out classes");
 		goto cleanup;

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/mls.c selinux-mls-users-2/libsepol/src/mls.c

libsepol/src/mls.c +4 -4
@@ -310,7 +310,7 @@ int mls_context_isvalid(const policydb_t
 	if (!c->user || c->user > p->p_users.nprim)
 		return 0;
 	usrdatum = p->user_val_to_struct[c->user - 1];
-	if (!mls_range_contains(usrdatum->range, c->range))
+	if (!mls_range_contains(usrdatum->exp_range, c->range))
 		return 0;	/* user may not be associated with range */
 
 	return 1;
@@ -512,9 +512,9 @@ int mls_setup_user_range(context_struct_
 	if (mls) {
 		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
 		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);
-		mls_level_t *user_low = &(user->range.level[0]);
-		mls_level_t *user_clr = &(user->range.level[1]);
-		mls_level_t *user_def = &(user->dfltlevel);
+		mls_level_t *user_low = &(user->exp_range.level[0]);
+		mls_level_t *user_clr = &(user->exp_range.level[1]);
+		mls_level_t *user_def = &(user->exp_dfltlevel);
 		mls_level_t *usercon_sen = &(usercon->range.level[0]);
 		mls_level_t *usercon_clr = &(usercon->range.level[1]);
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/policydb.c selinux-mls-users-2/libsepol/src/policydb.c

libsepol/src/policydb.c +50 -12
@@ -112,7 +112,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_BASE,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = OCON_NODE6 + 1,
 	 },
@@ -130,7 +130,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_MOD,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = 0},
 };
@@ -233,18 +233,22 @@ void user_datum_init(user_datum_t * x)
 {
 	memset(x, 0, sizeof(user_datum_t));
 	role_set_init(&x->roles);
-	mls_range_init(&x->range);
-	mls_level_init(&x->dfltlevel);
+	mls_semantic_range_init(&x->range);
+	mls_semantic_level_init(&x->dfltlevel);
 	ebitmap_init(&x->cache);
+	mls_range_init(&x->exp_range);
+	mls_level_init(&x->exp_dfltlevel);
 }
 
 void user_datum_destroy(user_datum_t * x)
 {
 	if (x != NULL) {
 		role_set_destroy(&x->roles);
-		mls_range_destroy(&x->range);
-		mls_level_destroy(&x->dfltlevel);
+		mls_semantic_range_destroy(&x->range);
+		mls_semantic_level_destroy(&x->dfltlevel);
 		ebitmap_destroy(&x->cache);
+		mls_range_destroy(&x->exp_range);
+		mls_level_destroy(&x->exp_dfltlevel);
 	}
 }
 
@@ -498,6 +502,20 @@ int policydb_user_cache(hashtab_key_t ke
 		return -1;
 	}
 
+	if (p->policy_type != POLICY_KERN) {
+		mls_range_destroy(&user->exp_range);
+		if (mls_semantic_range_expand(&user->range,
+					      &user->exp_range, p, NULL)) {
+			return -1;
+		}
+
+		mls_level_destroy(&user->exp_dfltlevel);
+		if (mls_semantic_level_expand(&user->dfltlevel,
+					      &user->exp_dfltlevel, p, NULL)) {
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -2235,17 +2253,37 @@ static int user_read(policydb_t * p, has
 			goto bad;
 	}
 
-	/* users aren't allowed in mls modules but they can be required, the mls fields will be empty,
-	 * user declarations in non-mls modules will also have empty mls fields */
+	/* users were not allowed in mls modules before version
+	 * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
+	 * required - the mls fields will be empty.  user declarations in
+	 * non-mls modules will also have empty mls fields */
 	if ((p->policy_type == POLICY_KERN
 	     && p->policyvers >= POLICYDB_VERSION_MLS)
 	    || (p->policy_type == POLICY_MOD
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
 	    || (p->policy_type == POLICY_BASE
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
-		if (mls_read_range_helper(&usrdatum->range, fp))
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_range_helper(&usrdatum->exp_range, fp))
+			goto bad;
+		if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
+			goto bad;
+		if (p->policy_type != POLICY_KERN) {
+			if (mls_range_to_semantic(&usrdatum->exp_range,
+						  &usrdatum->range))
+				goto bad;
+			if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
+						  &usrdatum->dfltlevel))
+				goto bad;
+		}
+	} else if ((p->policy_type == POLICY_MOD
+		    && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
+		   || (p->policy_type == POLICY_BASE
+		       && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_semantic_range_helper(&usrdatum->range, fp))
 			goto bad;
-		if (mls_read_level(&usrdatum->dfltlevel, fp))
+		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
 			goto bad;
 	}
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/users.c selinux-mls-users-2/libsepol/src/users.c

libsepol/src/users.c +6 -7
@@ -47,13 +47,13 @@ static int user_to_record(sepol_handle_t
 
 		context_init(&context);
 		if (mls_level_cpy(&context.range.level[0],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
 		}
 		if (mls_level_cpy(&context.range.level[1],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
@@ -71,7 +71,7 @@ static int user_to_record(sepol_handle_t
 		free(str);
 
 		context_init(&context);
-		if (mls_range_cpy(&context.range, &usrdatum->range) < 0) {
+		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
 			ERR(handle, "could not copy MLS range");
 			context_destroy(&context);
 			goto err;
@@ -191,8 +191,8 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_level_cpy(&usrdatum->dfltlevel, &context.range.level[0])
-		    < 0) {
+		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
+				  &context.range.level[0]) < 0) {
 			ERR(handle, "could not copy MLS level %s", cmls_level);
 			context_destroy(&context);
 			goto err;
@@ -211,13 +211,12 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_range_cpy(&usrdatum->range, &context.range) < 0) {
+		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
 			ERR(handle, "could not copy MLS range %s", cmls_range);
 			context_destroy(&context);
 			goto err;
 		}
 		context_destroy(&context);
-
 	} else if (cmls_level != NULL || cmls_range != NULL) {
 		ERR(handle, "MLS is disabled, but MLS level/range "
 		    "was found for user %s", cname);

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/write.c selinux-mls-users-2/libsepol/src/write.c

libsepol/src/write.c +6 -4
@@ -1005,18 +1005,27 @@ static int user_write(hashtab_key_t key,
 		if (role_set_write(&usrdatum->roles, fp))
 			return POLICYDB_ERROR;
 	}
-	/* Users are allowed in non-mls modules, so the empty field will be present
-	   in modules with users >= MOD_POLICYDB_VERSION_MLS */
+
 	if ((p->policyvers >= POLICYDB_VERSION_MLS
 	     && p->policy_type == POLICY_KERN)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_MOD)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_BASE)) {
-		if (mls_write_range_helper(&usrdatum->range, fp))
+		if (mls_write_range_helper(&usrdatum->exp_range, fp))
 			return POLICYDB_ERROR;
-		if (mls_write_level(&usrdatum->dfltlevel, fp))
+		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
 			return POLICYDB_ERROR;
+	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS

libsepol/src/write.c static int user_write(hashtab_key_t key, · line 1031

Quoted 10 lines
libsepol/src/write.c +7 -0
+		    && p->policy_type == POLICY_MOD)
+		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+		       && p->policy_type == POLICY_BASE)) {
+		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
+			return -1;
+		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
+			return -1;
 	}
 
 	return POLICYDB_SUCCESS;

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#8 lore raw
Quoted 462 lines · Joshua Brindle
Quoted 461 lines · Darrel Goeddel

Here is a second take on the previous patch. The changes are:
- no longer create semantic representation of user MLS fields when reading in a kernel format policy
- no longer copy the semantic representation of user MLS fields when expanding users
- no longer deal attempt to expand the semantic MLS components when caching user information if the policy is already in kernel format (the semantic info is no longer there)

---

Use the semantic representation for user_datums in modular policy formats.

All user_datums in a modular format use the semantic representation of the MLS range and dfltlevel. There is also the possibility of having an expanded version of that data also present in the user_datum. This is used much like the role cache in the user_datum. When the user are indexed, the MLS info is expanded. This info may be used to check the validity of context. This expansion is not used when writing out a kernel format policy - the expansion is performed again to ensure that the data it is present and in sync with the rest of the policy.

Like the range_trans structs, user_datums from older modular formats will have their MLS data converted to the new semantic structs.

 checkpolicy/policy_parse.y                 |   37 +++--------------
 libsepol/include/sepol/policydb/policydb.h |    9 ++--
 libsepol/src/expand.c                      |   63 +++++++++++++++++++++++------
 libsepol/src/mls.c                         |    8 +--
 libsepol/src/policydb.c                    |   62 +++++++++++++++++++++++-----
 libsepol/src/users.c                       |   13 ++---
 libsepol/src/write.c                       |   17 +++++--
 7 files changed, 137 insertions(+), 72 deletions(-)

diff --exclude=.svn -ruNp selinux-rangetrans-2/checkpolicy/policy_parse.y selinux-mls-users-2/checkpolicy/policy_parse.y

checkpolicy/policy_parse.y +8 -29
@@ -3737,11 +3737,10 @@ static int define_user(void)
 		free(id);
 
 		usrdatum->dfltlevel.sens = levdatum->level->sens;
-		ebitmap_init(&usrdatum->dfltlevel.cat);
 
 		while ((id = queue_remove(id_queue))) {
-			if (parse_categories(id, levdatum,
-					     &usrdatum->dfltlevel.cat)) {
+			if (parse_semantic_categories(id, levdatum,
+			                            &usrdatum->dfltlevel.cat)) {
 				free(id);
 				return -1;
 			}
@@ -3763,13 +3762,12 @@ static int define_user(void)
 				return -1;
 			}
 			free(id);
+
 			usrdatum->range.level[l].sens = levdatum->level->sens;
-			ebitmap_init(&usrdatum->range.level[l].cat);
 
 			while ((id = queue_remove(id_queue))) {
-				if (parse_categories(id, levdatum,
-						     &usrdatum->range.level[l].
-						     cat)) {
+				if (parse_semantic_categories(id, levdatum,
+				               &usrdatum->range.level[l].cat)) {
 					free(id);
 					return -1;
 				}
@@ -3782,33 +3780,14 @@ static int define_user(void)
 		}
 
 		if (l == 0) {
-			usrdatum->range.level[1].sens =
-			    usrdatum->range.level[0].sens;
-			if (ebitmap_cpy(&usrdatum->range.level[1].cat,
-					&usrdatum->range.level[0].cat)) {
+			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
+			                           &usrdatum->range.level[0])) {
 				yyerror("out of memory");
-				goto out;
+				return -1;
 			}
 		}
-		if (!mls_level_dom(&usrdatum->range.level[1],
-				   &usrdatum->range.level[0])) {
-			yyerror("high level does not dominate low level");
-			goto out;
-		}
-		if (!mls_level_between(&usrdatum->dfltlevel,
-				       &usrdatum->range.level[0],
-				       &usrdatum->range.level[1])) {
-			yyerror("default level not within user range");
-			goto out;
-		}
 	}
 	return 0;
-
-      out:
-	ebitmap_destroy(&usrdatum->dfltlevel.cat);
-	ebitmap_destroy(&usrdatum->range.level[0].cat);
-	ebitmap_destroy(&usrdatum->range.level[1].cat);
-	return -1;
 }
 
 static int parse_security_context(context_struct_t * c)

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/include/sepol/policydb/policydb.h selinux-mls-users-2/libsepol/include/sepol/policydb/policydb.h

libsepol/include/sepol/policydb/policydb.h +6 -3
@@ -149,9 +149,11 @@ typedef struct type_datum {
 typedef struct user_datum {
 	symtab_datum_t s;
 	role_set_t roles;	/* set of authorized roles for user */
-	mls_range_t range;	/* MLS range (min. - max.) for user */
-	mls_level_t dfltlevel;	/* default login MLS level for user */
+	mls_semantic_range_t range;	/* MLS range (min. - max.) for user */
+	mls_semantic_level_t dfltlevel;	/* default login MLS level for user */
 	ebitmap_t cache;	/* This is an expanded set used for context validation during parsing */
+	mls_range_t exp_range;     /* expanded range used for validation */
+	mls_level_t exp_dfltlevel; /* expanded range used for validation */
 } user_datum_t;
 
 /* Sensitivity attributes */
@@ -586,9 +588,10 @@ extern int policydb_write(struct policyd
 #define MOD_POLICYDB_VERSION_VALIDATETRANS 5
 #define MOD_POLICYDB_VERSION_MLS	   5
 #define MOD_POLICYDB_VERSION_RANGETRANS	   6
+#define MOD_POLICYDB_VERSION_MLS_USERS	   6
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS_USERS
 
 #define POLICYDB_CONFIG_MLS    1
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/expand.c selinux-mls-users-2/libsepol/src/expand.c

libsepol/src/expand.c +50 -13
@@ -692,13 +692,46 @@ static int user_copy_callback(hashtab_ke
 			return -1;
 		}
 
-		/* clone MLS stuff */
-		if (mls_range_cpy(&new_user->range, &user->range) == -1
-		    || mls_level_cpy(&new_user->dfltlevel,
-				     &user->dfltlevel) == -1) {
-			ERR(state->handle, "Out of memory!");
+		/* expand the semantic MLS info */
+		if (mls_semantic_range_expand(&user->range,
+					      &new_user->exp_range,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (mls_semantic_level_expand(&user->dfltlevel,
+					      &new_user->exp_dfltlevel,
+					      state->out, state->handle)) {
+			return -1;
+		}
+		if (!mls_level_between(&new_user->exp_dfltlevel,
+				       &new_user->exp_range.level[0],
+				       &new_user->exp_range.level[1])) {
+			ERR(state->handle, "default level not within user "
+			    "range");
+			return -1;
+		}
+	} else {
+		/* require that the MLS info match */
+		mls_range_t tmp_range;
+		mls_level_t tmp_level;
+
+		if (mls_semantic_range_expand(&user->range, &tmp_range,
+					      state->out, state->handle)) {
 			return -1;
 		}
+		if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level,
+					      state->out, state->handle)) {
+			mls_range_destroy(&tmp_range);
+			return -1;
+		}
+		if (!mls_range_eq(&new_user->exp_range, &tmp_range) ||
+		    !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) {
+			mls_range_destroy(&tmp_range);
+			mls_level_destroy(&tmp_level);
+			return -1;
+		}
+		mls_range_destroy(&tmp_range);
+		mls_level_destroy(&tmp_level);
 	}
 
 	ebitmap_init(&tmp_union);
@@ -788,7 +821,7 @@ static int sens_copy_callback(hashtab_ke
 	}
 
 	if (state->verbose)
-		INFO(state->handle, "copying senitivity level %s", id);
+		INFO(state->handle, "copying sensitivity level %s", id);
 
 	if ((new_level =
 	     (level_datum_t *) calloc(1, sizeof(*new_level))) == NULL
@@ -2207,6 +2240,17 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state))
 		goto cleanup;
 
+	/* copy MLS's sensitivity level and categories - this needs to be done
+	 * before expanding users (they need to be indexed too) */
+	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state))
+		goto cleanup;
+	if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state))
+		goto cleanup;
+	if (policydb_index_others(handle, out, verbose)) {
+		ERR(handle, "Error while indexing out symbols");
+		goto cleanup;
+	}
+
 	/* copy users */
 	if (hashtab_map(state.base->p_users.table, user_copy_callback, &state))
 		goto cleanup;
@@ -2215,13 +2259,6 @@ int expand_module(sepol_handle_t * handl
 	if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state))
 		goto cleanup;
 
-	/* now copy MLS's sensitivity level and categories */
-	if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)
-	    || hashtab_map(state.base->p_cats.table, cats_copy_callback,
-			   &state)) {
-		goto cleanup;
-	}
-
 	if (policydb_index_classes(out)) {
 		ERR(handle, "Error while indexing out classes");
 		goto cleanup;

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/mls.c selinux-mls-users-2/libsepol/src/mls.c

libsepol/src/mls.c +4 -4
@@ -310,7 +310,7 @@ int mls_context_isvalid(const policydb_t
 	if (!c->user || c->user > p->p_users.nprim)
 		return 0;
 	usrdatum = p->user_val_to_struct[c->user - 1];
-	if (!mls_range_contains(usrdatum->range, c->range))
+	if (!mls_range_contains(usrdatum->exp_range, c->range))
 		return 0;	/* user may not be associated with range */
 
 	return 1;
@@ -512,9 +512,9 @@ int mls_setup_user_range(context_struct_
 	if (mls) {
 		mls_level_t *fromcon_sen = &(fromcon->range.level[0]);
 		mls_level_t *fromcon_clr = &(fromcon->range.level[1]);
-		mls_level_t *user_low = &(user->range.level[0]);
-		mls_level_t *user_clr = &(user->range.level[1]);
-		mls_level_t *user_def = &(user->dfltlevel);
+		mls_level_t *user_low = &(user->exp_range.level[0]);
+		mls_level_t *user_clr = &(user->exp_range.level[1]);
+		mls_level_t *user_def = &(user->exp_dfltlevel);
 		mls_level_t *usercon_sen = &(usercon->range.level[0]);
 		mls_level_t *usercon_clr = &(usercon->range.level[1]);
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/policydb.c selinux-mls-users-2/libsepol/src/policydb.c

libsepol/src/policydb.c +50 -12
@@ -112,7 +112,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_BASE,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = OCON_NODE6 + 1,
 	 },
@@ -130,7 +130,7 @@ static struct policydb_compat_info polic
 	 },
 	{
 	 .type = POLICY_MOD,
-	 .version = MOD_POLICYDB_VERSION_RANGETRANS,
+	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
 	 .sym_num = SYM_NUM,
 	 .ocon_num = 0},
 };
@@ -233,18 +233,22 @@ void user_datum_init(user_datum_t * x)
 {
 	memset(x, 0, sizeof(user_datum_t));
 	role_set_init(&x->roles);
-	mls_range_init(&x->range);
-	mls_level_init(&x->dfltlevel);
+	mls_semantic_range_init(&x->range);
+	mls_semantic_level_init(&x->dfltlevel);
 	ebitmap_init(&x->cache);
+	mls_range_init(&x->exp_range);
+	mls_level_init(&x->exp_dfltlevel);
 }
 
 void user_datum_destroy(user_datum_t * x)
 {
 	if (x != NULL) {
 		role_set_destroy(&x->roles);
-		mls_range_destroy(&x->range);
-		mls_level_destroy(&x->dfltlevel);
+		mls_semantic_range_destroy(&x->range);
+		mls_semantic_level_destroy(&x->dfltlevel);
 		ebitmap_destroy(&x->cache);
+		mls_range_destroy(&x->exp_range);
+		mls_level_destroy(&x->exp_dfltlevel);
 	}
 }
 
@@ -498,6 +502,20 @@ int policydb_user_cache(hashtab_key_t ke
 		return -1;
 	}
 
+	if (p->policy_type != POLICY_KERN) {
+		mls_range_destroy(&user->exp_range);
+		if (mls_semantic_range_expand(&user->range,
+					      &user->exp_range, p, NULL)) {
+			return -1;
+		}
+
+		mls_level_destroy(&user->exp_dfltlevel);
+		if (mls_semantic_level_expand(&user->dfltlevel,
+					      &user->exp_dfltlevel, p, NULL)) {
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -2235,17 +2253,37 @@ static int user_read(policydb_t * p, has
 			goto bad;
 	}
 
-	/* users aren't allowed in mls modules but they can be required, the mls fields will be empty,
-	 * user declarations in non-mls modules will also have empty mls fields */
+	/* users were not allowed in mls modules before version
+	 * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
+	 * required - the mls fields will be empty.  user declarations in
+	 * non-mls modules will also have empty mls fields */
 	if ((p->policy_type == POLICY_KERN
 	     && p->policyvers >= POLICYDB_VERSION_MLS)
 	    || (p->policy_type == POLICY_MOD
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
 	    || (p->policy_type == POLICY_BASE
-		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
-		if (mls_read_range_helper(&usrdatum->range, fp))
+		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_range_helper(&usrdatum->exp_range, fp))
+			goto bad;
+		if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
+			goto bad;
+		if (p->policy_type != POLICY_KERN) {
+			if (mls_range_to_semantic(&usrdatum->exp_range,
+						  &usrdatum->range))
+				goto bad;
+			if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
+						  &usrdatum->dfltlevel))
+				goto bad;
+		}
+	} else if ((p->policy_type == POLICY_MOD
+		    && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
+		   || (p->policy_type == POLICY_BASE
+		       && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
+		if (mls_read_semantic_range_helper(&usrdatum->range, fp))
 			goto bad;
-		if (mls_read_level(&usrdatum->dfltlevel, fp))
+		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
 			goto bad;
 	}
 

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/users.c selinux-mls-users-2/libsepol/src/users.c

libsepol/src/users.c +6 -7
@@ -47,13 +47,13 @@ static int user_to_record(sepol_handle_t
 
 		context_init(&context);
 		if (mls_level_cpy(&context.range.level[0],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
 		}
 		if (mls_level_cpy(&context.range.level[1],
-				  &usrdatum->dfltlevel) < 0) {
+				  &usrdatum->exp_dfltlevel) < 0) {
 			ERR(handle, "could not copy MLS level");
 			context_destroy(&context);
 			goto err;
@@ -71,7 +71,7 @@ static int user_to_record(sepol_handle_t
 		free(str);
 
 		context_init(&context);
-		if (mls_range_cpy(&context.range, &usrdatum->range) < 0) {
+		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
 			ERR(handle, "could not copy MLS range");
 			context_destroy(&context);
 			goto err;
@@ -191,8 +191,8 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_level_cpy(&usrdatum->dfltlevel, &context.range.level[0])
-		    < 0) {
+		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
+				  &context.range.level[0]) < 0) {
 			ERR(handle, "could not copy MLS level %s", cmls_level);
 			context_destroy(&context);
 			goto err;
@@ -211,13 +211,12 @@ int sepol_user_modify(sepol_handle_t * h
 			context_destroy(&context);
 			goto err;
 		}
-		if (mls_range_cpy(&usrdatum->range, &context.range) < 0) {
+		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
 			ERR(handle, "could not copy MLS range %s", cmls_range);
 			context_destroy(&context);
 			goto err;
 		}
 		context_destroy(&context);
-
 	} else if (cmls_level != NULL || cmls_range != NULL) {
 		ERR(handle, "MLS is disabled, but MLS level/range "
 		    "was found for user %s", cname);

diff --exclude=.svn -ruNp selinux-rangetrans-2/libsepol/src/write.c selinux-mls-users-2/libsepol/src/write.c

libsepol/src/write.c +13 -4
@@ -1005,18 +1005,27 @@ static int user_write(hashtab_key_t key,
 		if (role_set_write(&usrdatum->roles, fp))
 			return POLICYDB_ERROR;
 	}
-	/* Users are allowed in non-mls modules, so the empty field will be present
-	   in modules with users >= MOD_POLICYDB_VERSION_MLS */
+
 	if ((p->policyvers >= POLICYDB_VERSION_MLS
 	     && p->policy_type == POLICY_KERN)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_MOD)
 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
+		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
 		&& p->policy_type == POLICY_BASE)) {
-		if (mls_write_range_helper(&usrdatum->range, fp))
+		if (mls_write_range_helper(&usrdatum->exp_range, fp))
 			return POLICYDB_ERROR;
-		if (mls_write_level(&usrdatum->dfltlevel, fp))
+		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
 			return POLICYDB_ERROR;
+	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+		    && p->policy_type == POLICY_MOD)
+		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
+		       && p->policy_type == POLICY_BASE)) {
+		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
+			return -1;
+		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
+			return -1;
 	}
 
Quoted 3 lines

libsepol/src/write.c static int user_write(hashtab_key_t key, · line 1031

Quoted 1 line
libsepol/src/write.c +0 -0
 	return POLICYDB_SUCCESS;
Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.