libsemanage: patch for MCS/MLS in user files
The attached patch makes the
/etc/selinux/default/contexts/files/file_contexts.homedirs generation process
include the MCS/MLS level.
This means that if you have a user with a MCS/MLS level that isn't SystemLow
then their home directory will be labeled such that they can have read/write
access to it by default.
Unless anyone has any better ideas for how to solve this problem I will upload
this to Debian shortly.
What do the MLS users do in this situation? Just relabel home directories
manually?
Finally it seems that when you run "semanage user -m" the
file_contexts.homedirs doesn't get updated, it's only when you run
"semanage login -m" that it takes affect.
Signed-off-by: Eric Paris <[email protected]>
Acked-by: Russell Coker <[email protected]>
Acked-by: Dan Walsh <[email protected]>
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 8b29c2e..847d87e 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -76,9 +76,11 @@
#define TEMPLATE_USER "USER"
#define TEMPLATE_ROLE "ROLE"
#define TEMPLATE_SEUSER "system_u"
+#define TEMPLATE_LEVEL "s0"
#define FALLBACK_USER "user_u"
#define FALLBACK_USER_PREFIX "user"
+#define FALLBACK_USER_LEVEL "s0"
#define DEFAULT_LOGIN "__default__"
typedef struct {
@@ -87,6 +89,7 @@
const char *homedir_template_path;
char *fallback_user;
char *fallback_user_prefix;
+ char *fallback_user_level;
semanage_handle_t *h_semanage;
sepol_policydb_t *policydb;
} genhomedircon_settings_t;
@@ -96,6 +99,7 @@
char *sename;
char *prefix;
char *home;
+ char *level;
struct user_entry *next;
} genhomedircon_user_entry_t;
@@ -487,12 +491,13 @@
static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out,
semanage_list_t * tpl, const char *user,
const char *seuser, const char *home,
- const char *role_prefix)
+ const char *role_prefix, const char *level)
{
replacement_pair_t repl[] = {
{.search_for = TEMPLATE_SEUSER,.replace_with = seuser},
{.search_for = TEMPLATE_HOME_DIR,.replace_with = home},
{.search_for = TEMPLATE_ROLE,.replace_with = role_prefix},
+ {.search_for = TEMPLATE_LEVEL,.replace_with = level},
{NULL, NULL}
};
Ustr *line = USTR_NULL;
@@ -584,13 +589,15 @@
}
static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
- const char *sen, const char *pre, const char *h)
+ const char *sen, const char *pre, const char *h,
+ const char *l)
{
genhomedircon_user_entry_t *temp = NULL;
char *name = NULL;
char *sename = NULL;
char *prefix = NULL;
char *home = NULL;
+ char *level = NULL;
temp = malloc(sizeof(genhomedircon_user_entry_t));
if (!temp)
@@ -607,11 +614,15 @@
home = strdup(h);
if (!home)
goto cleanup;
+ level = strdup(l);
+ if (!level)
+ goto cleanup;
temp->name = name;
temp->sename = sename;
temp->prefix = prefix;
temp->home = home;
+ temp->level = level;
temp->next = (*list);
(*list) = temp;
@@ -622,6 +633,7 @@
free(sename);
free(prefix);
free(home);
+ free(level);
free(temp);
return STATUS_ERR;
}
@@ -639,25 +651,30 @@
free(temp->sename);
free(temp->prefix);
free(temp->home);
+ free(temp->level);
free(temp);
}
-static int set_fallback_user(genhomedircon_settings_t *s,
- const char *user, const char *prefix)
+static int set_fallback_user(genhomedircon_settings_t *s, const char *user,
+ const char *prefix, const char *level)
{
char *fallback_user = strdup(user);
char *fallback_user_prefix = strdup(prefix);
+ char *fallback_user_level = strdup(level);
- if (fallback_user == NULL || fallback_user_prefix == NULL) {
+ if (fallback_user == NULL || fallback_user_prefix == NULL || fallback_user_level == NULL) {
free(fallback_user);
free(fallback_user_prefix);
+ free(fallback_user_level);
return STATUS_ERR;
}
free(s->fallback_user);
free(s->fallback_user_prefix);
+ free(s->fallback_user_level);
s->fallback_user = fallback_user;
s->fallback_user_prefix = fallback_user_prefix;
+ s->fallback_user_level = fallback_user_level;
return STATUS_SUCCESS;
}
@@ -670,6 +687,7 @@
const char *name = NULL;
const char *seuname = NULL;
const char *prefix = NULL;
+ const char *level = NULL;
unsigned int i;
int retval;
int errors = 0;
@@ -692,11 +710,17 @@
break;
}
if (semanage_user_query(s->h_semanage, key, &u) < 0)
+ {
prefix = name;
+ level = "s0";
+ }
else
+ {
prefix = semanage_user_get_prefix(u);
+ level = semanage_user_get_mlslevel(u);
+ }
- if (set_fallback_user(s, seuname, prefix) != 0)
+ if (set_fallback_user(s, seuname, prefix, level) != 0)
errors = STATUS_ERR;
semanage_user_key_free(key);
if (u)
@@ -724,6 +748,7 @@
const char *name = NULL;
const char *seuname = NULL;
const char *prefix = NULL;
+ const char *level = NULL;
struct passwd pwstorage, *pwent = NULL;
unsigned int i;
long rbuflen;
@@ -775,8 +800,10 @@
&name_user_cmp);
if (u) {
prefix = semanage_user_get_prefix(*u);
+ level = semanage_user_get_mlslevel(*u);
} else {
prefix = name;
+ level = "s0";
}
retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
@@ -803,7 +830,7 @@
continue;
}
if (push_user_entry(&head, name, seuname,
- prefix, pwent->pw_dir) != STATUS_SUCCESS) {
+ prefix, pwent->pw_dir, level) != STATUS_SUCCESS) {
*errors = STATUS_ERR;
break;
}
@@ -846,7 +873,7 @@
if (write_home_dir_context(s, out, homedir_context_tpl,
users->name,
users->sename, users->home,
- users->prefix)) {
+ users->prefix, users->level)) {
return STATUS_ERR;
}
if (write_user_context(s, out, user_context_tpl, users->name,
@@ -910,7 +937,7 @@
homedir_context_tpl,
s->fallback_user, s->fallback_user,
ustr_cstr(temp),
- s->fallback_user_prefix) !=
+ s->fallback_user_prefix, s->fallback_user_level) !=
STATUS_SUCCESS) {
ustr_sc_free(&temp);
retval = STATUS_ERR;
@@ -967,7 +994,8 @@
s.fallback_user = strdup(FALLBACK_USER);
s.fallback_user_prefix = strdup(FALLBACK_USER_PREFIX);
- if (s.fallback_user == NULL || s.fallback_user_prefix == NULL)
+ s.fallback_user_level = strdup(FALLBACK_USER_LEVEL);
+ if (s.fallback_user == NULL || s.fallback_user_prefix == NULL || s.fallback_user_level == NULL)
return STATUS_ERR;
s.usepasswd = usepasswd;