[DSE-Dev] SELinux progress

cgzones cgzones at googlemail.com
Thu Jan 12 11:39:06 UTC 2017


I have some items on my agenda:

Are there any updates on the patches I proposed here:
https://lists.alioth.debian.org/pipermail/selinux-devel/2017-January/002167.html?
Additionally, there are some lintian issues fixed with:
================================================
diff --git a/debian/control b/debian/control
index 3638c23..96ed067 100644
--- a/debian/control
+++ b/debian/control
@@ -98,7 +98,9 @@ Depends: checkpolicy (>= 2.4),
          policycoreutils (>= 2.4),
          policycoreutils-dev (>= 2.4),
          policycoreutils-python-utils (>= 2.4),
+# for refpolicy's segenxml.py
          python,
+         python3,
          selinux-utils (>= 2.4),
          ${misc:Depends}
 Recommends: setools
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
deleted file mode 100644
index 029e20a..0000000
--- a/debian/source/lintian-overrides
+++ /dev/null
@@ -1,3 +0,0 @@
-# These is scripts are Perl scripts, the debhelper token cannot be
added to them
-refpolicy source: maintainer-script-lacks-debhelper-token
debian/selinux-policy-default.postrm
-refpolicy source: maintainer-script-lacks-debhelper-token
debian/selinux-policy-mls.postrm
================================================


Next item is dpkg:
Currently, dpkg runs its maintainer tasks in the context type
dpkg_script_t without changing user or role.
So when running in sysadm_u:sysadm_r:sysadm_t, the tasks will be run
in sysadm_u:sysadm_r:dpkg_script_t.
The problem are the postinst scripts: The might create files and run binaries.
Almost all the files created in this way do not have the correct file
context system_u:object_r:*.
e.g.: Would relabel /var/cache/man/pt/index.db from
unconfined_u:object_r:man_cache_t:s0 to
system_u:object_r:man_cache_t:s0
Also for example, the exim4 postinst script does some work leading to
run sendmail in system_mail_t, which is not allowed to run under
sysadm_r/unconfined_r.
So this can cause issues upgrading packages in enforced mode even as
unconfined user.
I am using a dpkg patch to run the mainter task in the context (may be
altered in the selinux policy) system_u:system_r:dpkg_script_t:
================================================
>From d864662073e66800ac724ba6d20369b8fbb9ae8f Mon Sep 17 00:00:00 2001
From: root <root at debianSE>
Date: Mon, 9 Jan 2017 22:42:03 +0100
Subject: [PATCH] selinux fix

---
 src/script.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 85 insertions(+), 6 deletions(-)

diff --git a/src/script.c b/src/script.c
index 2f252ae..ae81e2c 100644
--- a/src/script.c
+++ b/src/script.c
@@ -32,6 +32,7 @@
 #include <stdlib.h>

 #ifdef WITH_LIBSELINUX
+#include <ctype.h> // isspace
 #include <selinux/selinux.h>
 #endif

@@ -141,6 +142,63 @@ maintscript_pre_exec(struct command *cmd)
        return cmd->filename + instdirlen;
 }

+#ifdef WITH_LIBSELINUX
+/*
+ * derived from get_init_context()
+ * https://github.com/SELinuxProject/selinux/blob/master/policycoreutils/run_init/run_init.c
+ *
+ * Get the CONTEXT associated with the context for the dpkg maint scripts.
+ *
+ * in:          nothing
+ * out:         The CONTEXT associated with the context.
+ * return:      0 on success, -1 on failure.
+ */
+static int
+get_dpkg_context(char **context)
+{
+       FILE *fp;
+       char buf[255], *bufp;
+       size_t buf_len;
+       char context_file[4096];
+       snprintf(context_file, sizeof(context_file) - 1, "%s/%s",
selinux_contexts_path(), "dpkg_context");
+       fp = fopen(context_file, "r");
+       if (!fp) {
+               ohshite(_("Could not open file %s\n"), context_file);
+               return -1;
+       }
+
+       while (1) {             /* loop until we find a non-empty line */
+
+               if (!fgets(buf, sizeof buf, fp)) {
+                       break;
+               }
+
+               buf_len = strlen(buf);
+               if (buf[buf_len - 1] == '\n') {
+                        buf[buf_len - 1] = 0;
+               }
+
+               bufp = buf;
+               while (*bufp && isspace(*bufp)) {
+                        bufp++;
+               }
+
+               if (*bufp) {
+                       *context = strdup(bufp);
+                       if (!(*context)) {
+                               goto out;
+                       }
+                       fclose(fp);
+                       return 0;
+               }
+       }
+      out:
+       fclose(fp);
+       ohshit(_("No context in file %s\n"), context_file);
+       return -1;
+}
+#endif
+
 /**
  * Set a new security execution context for the maintainer script.
  *
@@ -149,15 +207,36 @@ maintscript_pre_exec(struct command *cmd)
  * one, use the given fallback.
  */
 static int
-maintscript_set_exec_context(struct command *cmd, const char *fallback)
+maintscript_set_exec_context(const struct command *cmd)
 {
+#ifdef WITH_LIBSELINUX
        int rc = 0;
+       char *dpkg_context = NULL;

-#ifdef WITH_LIBSELINUX
-       rc = setexecfilecon(cmd->filename, fallback);
-#endif
+       if (is_selinux_enabled() < 1) {
+               return 0;
+       }

-       return rc < 0 ? rc : 0;
+       if ((rc = get_dpkg_context(&dpkg_context)) < 0) {
+               ohshit(_("Can not get dpkg_context"));
+               goto out;
+       }
+
+       if ((rc = setexeccon(dpkg_context)) < 0) {
+               ohshite(_("Can not set exec content to %s"), dpkg_context);
+               goto out;;
+       }
+
+      out:
+       if (rc < 0 && security_getenforce() == 0) {
+               rc = 0;
+       }
+
+       free(dpkg_context);
+       return rc;
+#else
+       return 0;
+#endif
 }

 static int
@@ -190,7 +269,7 @@ maintscript_exec(struct pkginfo *pkg, struct pkgbin *pkgbin,

                cmd->filename = cmd->argv[0] = maintscript_pre_exec(cmd);

-               if (maintscript_set_exec_context(cmd, "dpkg_script_t") < 0)
+               if (maintscript_set_exec_context(cmd) < 0)
                        ohshite(_("cannot set security execution context for "
                                  "maintainer script"));

--
2.11.0
================================================
From: cgzones <cgzones at googlemail.com>
Date: Tue, 10 Jan 2017 14:19:54 +0100
Subject: add dpkg_context appcontext

---
 Makefile                               | 2 +-
 config/appconfig-mcs/dpkg_context      | 1 +
 config/appconfig-mls/dpkg_context      | 1 +
 config/appconfig-standard/dpkg_context | 1 +
 4 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 config/appconfig-mcs/dpkg_context
 create mode 100644 config/appconfig-mls/dpkg_context
 create mode 100644 config/appconfig-standard/dpkg_context

diff --git a/Makefile b/Makefile
index 154beb57c..1ad9e079f 100644
--- a/Makefile
+++ b/Makefile
@@ -250,7 +250,7 @@ seusers := $(appconf)/seusers
 appdir := $(contextpath)
 user_default_contexts := $(wildcard
config/appconfig-$(TYPE)/*_default_contexts)
 user_default_contexts_names := $(addprefix
$(contextpath)/users/,$(subst _default_contexts,,$(notdir
$(user_default_contexts))))
-appfiles := $(addprefix $(appdir)/,default_contexts default_type
initrc_context failsafe_context userhelper_context removable_context
dbus_contexts sepgsql_contexts x_contexts customizable_types
securetty_types lxc_contexts virtual_domain_context
virtual_image_context) $(contextpath)/files/media $(fcsubspath)
$(user_default_contexts_names)
+appfiles := $(addprefix $(appdir)/,default_contexts default_type
initrc_context dpkg_context failsafe_context userhelper_context
removable_context dbus_contexts sepgsql_contexts x_contexts
customizable_types securetty_types lxc_contexts virtual_domain_context
virtual_image_context) $(contextpath)/files/media $(fcsubspath)
$(user_default_contexts_names)
 net_contexts := $(builddir)net_contexts

 all_layers := $(shell find $(wildcard $(moddir)/*) -maxdepth 0 -type d)
diff --git a/config/appconfig-mcs/dpkg_context
b/config/appconfig-mcs/dpkg_context
new file mode 100644
index 000000000..f7ed03c8c
--- /dev/null
+++ b/config/appconfig-mcs/dpkg_context
@@ -0,0 +1 @@
+system_u:system_r:dpkg_script_t:s0
diff --git a/config/appconfig-mls/dpkg_context
b/config/appconfig-mls/dpkg_context
new file mode 100644
index 000000000..555917148
--- /dev/null
+++ b/config/appconfig-mls/dpkg_context
@@ -0,0 +1 @@
+system_u:system_r:dpkg_script_t:s0-mls_systemhigh
diff --git a/config/appconfig-standard/dpkg_context
b/config/appconfig-standard/dpkg_context
new file mode 100644
index 000000000..7c56bf1f5
--- /dev/null
+++ b/config/appconfig-standard/dpkg_context
@@ -0,0 +1 @@
+system_u:system_r:dpkg_script_t
================================================

What are your thoughts on this change?


Last item is sddm:
I saw that you, Russel, fixed sddm in the Debian policy, but I missed
any sddm related changes. I could not get sddm to transition in the
proper contexts for the login windows process and the user sessions.
How did you achieve it?
On my systems I added a pam_selinux option to transition into different contexts

================================================
>From bdacb32d6fbb2d77ef93e91e07234cf2120a22a0 Mon Sep 17 00:00:00 2001
From: cgzones <cgzones at googlemail.com>
Date: Tue, 3 Jan 2017 12:04:20 +0100
Subject: [PATCH] pam fix

---
modules/pam_selinux/pam_selinux.c | 46 ++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/modules/pam_selinux/pam_selinux.c
b/modules/pam_selinux/pam_selinux.c
index b96cc23..446b4fb 100644
--- a/modules/pam_selinux/pam_selinux.c
+++ b/modules/pam_selinux/pam_selinux.c
@@ -63,8 +63,6 @@

#include <selinux/selinux.h>
#include <selinux/get_context_list.h>
-#include <selinux/flask.h>
-#include <selinux/av_permissions.h>
#include <selinux/selinux.h>
#include <selinux/context.h>
#include <selinux/get_default_type.h>
@@ -480,7 +478,8 @@ set_file_context(const pam_handle_t *pamh,
security_context_t context,
static int
compute_exec_context(pam_handle_t *pamh, module_data_t *data,
                    int select_context, int use_current_range,
-                    int env_params, int debug)
+                    int env_params, int debug,
+                    const char *select_default_context)
{
  const char *username;

@@ -491,6 +490,7 @@ compute_exec_context(pam_handle_t *pamh,
module_data_t *data,
  char *level = NULL;
  security_context_t *contextlist = NULL;
  int num_contexts = 0;
+  int selected_context;

  if (!(username = get_item(pamh, PAM_USER))) {
    pam_syslog(pamh, LOG_ERR, "Cannot obtain the user name");
@@ -516,7 +516,27 @@ compute_exec_context(pam_handle_t *pamh,
module_data_t *data,
  }
  if (num_contexts > 0) {
    free(seuser);
-    data->default_user_context = strdup(contextlist[0]);
+    if (select_default_context) {
+      pam_syslog(pamh, LOG_DEBUG,
+                  "Selecting default context based on %s from %d contexts",
+                  select_default_context, num_contexts);
+      if (num_contexts == 1) {
+        data->default_user_context = strdup(contextlist[0]);
+      } else if (strcmp(select_default_context, "last") == 0) {
+        data->default_user_context = strdup(contextlist[num_contexts - 1]);
+      } else {
+        selected_context = atoi(select_default_context);
+        if (selected_context <= 0 || selected_context > num_contexts) {
+          pam_syslog(pamh, LOG_ERR,
+                "Invalid select option %s for %d contexts, fallback
to default",
+                select_default_context, num_contexts);
+          selected_context = 1;
+        }
+        data->default_user_context = strdup(contextlist[selected_context - 1]);
+      }
+    } else {
+      data->default_user_context = strdup(contextlist[0]);
+    }
     freeconary(contextlist);
    if (!data->default_user_context) {
      pam_syslog(pamh, LOG_ERR, "Out of memory");
@@ -549,6 +569,7 @@ static int
compute_tty_context(const pam_handle_t *pamh, module_data_t *data)
{
  const char *tty = get_item(pamh, PAM_TTY);
+  security_class_t tclass;

  if (!tty || !*tty || !strcmp(tty, "ssh") || !strncmp(tty, "NODEV", 5)) {
    tty = ttyname(STDIN_FILENO);
@@ -584,8 +605,13 @@ compute_tty_context(const pam_handle_t *pamh,
module_data_t *data)
    return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS;
  }

+  tclass = string_to_security_class("chr_file");
+  if (!tclass) {
+    pam_syslog(pamh, LOG_ERR, "Failed to translate security class
context. %m");
+    return PAM_SESSION_ERR;
+  }
  if (security_compute_relabel(data->exec_context, data->prev_tty_context,
-                              SECCLASS_CHR_FILE, &data->tty_context)) {
+                              tclass, &data->tty_context)) {
    data->tty_context = NULL;
    pam_syslog(pamh, LOG_ERR, "Failed to compute new context for %s: %m",
              data->tty_path);
@@ -691,6 +717,9 @@ create_context(pam_handle_t *pamh, int argc, const
char **argv,
  int select_context = 0;
  int use_current_range = 0;
  int env_params = 0;
+  const char *select_default_context = NULL;
+  const char *select_default_context_str = "select_default_context";
+  const size_t select_default_context_len = strlen(select_default_context_str);
  module_data_t *data;

  /* Parse arguments. */
@@ -707,6 +736,11 @@ create_context(pam_handle_t *pamh, int argc,
const char **argv,
    if (strcmp(argv[i], "env_params") == 0) {
      env_params = 1;
    }
+    if (strncmp(argv[i], select_default_context_str,
+          select_default_context_len) == 0
+        && argv[i][select_default_context_len] == '=') {
+      select_default_context = argv[i] + select_default_context_len + 1;
+    }
  }

  if (is_selinux_enabled() <= 0) {
@@ -727,7 +761,7 @@ create_context(pam_handle_t *pamh, int argc, const
char **argv,
  }

  i = compute_exec_context(pamh, data, select_context, use_current_range,
-                          env_params, debug);
+                          env_params, debug, select_default_context);
  if (i != PAM_SUCCESS) {
    free_module_data(data);
    return i;
--
2.11.0
================================================


Best Regards,
       Christian Göttsche



More information about the SELinux-devel mailing list