dpkg: run maintainer scripts with SELinux user system_u

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

 



Hi list,
I created patch against dpkg, which is reported here:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=852539
Laurent suggested to post it also on this ML for discussion.


Currently, dpkg runs its maintainer tasks in the SELinux type
dpkg_script_t without changing the SELinux user or role.
So when running root as sysadm_u:sysadm_r:sysadm_t, the tasks will be
run in unconfined_u:unconfined_r:dpkg_script_t.
The problem are the postinst scripts: They create files and run binaries.
Almost all the files created in this way do not have the correct file
context system_u:object_r:*, which can break a ubac enabled system.
e.g.:

Would relabel /usr/share/info/dir.old from staff_u:object_r:usr_t:s0
to system_u:object_r:usr_t:s0
Would relabel /usr/share/info/dir from staff_u:object_r:usr_t:s0 to
system_u:object_r:usr_t:s0
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 post install script does some work
leading to run exim in system_mail_t, which is not allowed to run
under the roles sysadm_r/unconfined_r.

type=PROCTITLE msg=audit(01/24/17 15:51:28.963:2602) :
proctitle=/usr/sbin/exim4 -C /var/lib/exim4/config.autogenerated.tmp
-bV
type=SYSCALL msg=audit(01/24/17 15:51:28.963:2602) : arch=armeb
syscall=socket per=PER_LINUX_32BIT success=yes exit=4 a0=local
a1=SOCK_STREAM a2=ip a3=0x0 items=0 ppid=22511 pid=22748
auid=christian uid=root gid=root euid=root suid=root fsuid=root
egid=root sgid=root fsgid=root tty=pts1 ses=359 comm=exim4
exe=/usr/sbin/exim4 subj=staff_u:sysadm_r:system_mail_t:s0 key=(null)
type=SELINUX_ERR msg=audit(01/24/17 15:51:28.963:2602) :
op=security_compute_sid
invalid_context=staff_u:sysadm_r:system_mail_t:s0
scontext=staff_u:sysadm_r:system_mail_t:s0
tcontext=staff_u:sysadm_r:system_mail_t:s0 tclass=unix_stream_socket

This can cause issues when upgrading packages in enforced mode even as
unconfined user.

The following dpkg patch runs the maintainer tasks in the context
system_u:system_r:dpkg_script_t (may be altered inside the SELinux
policy):

Note: The patch does not touch the SELinux detection in the build
logic and the SELinux policy has to be updated beforehand.

From: root <root@debianSE>
Date: Mon, 9 Jan 2017 22:42:03 +0100
Subject: [PATCH] dpkg: fix maintainer SELinux context

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

diff --git a/src/script.c b/src/script.c
index 2f252ae..72b92cf 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,23 +142,97 @@ 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.
- *
- * Try to create a new execution context based on the current one and the
- * specific maintainer script filename. If it's the same as the current
- * one, use the given fallback.
 */
static int
-maintscript_set_exec_context(struct command *cmd, const char *fallback)
+maintscript_set_exec_context(void)
{
+#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 +265,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() < 0)
                       ohshite(_("cannot set security execution context for "
                                 "maintainer script"));

--
2.11.0


The policy patch would look like this:

From: cgzones <cgzones@xxxxxxxxxxxxxx>
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



Best Regards,
       Christian Göttsche

_______________________________________________
Selinux mailing list
Selinux@xxxxxxxxxxxxx
To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx.
To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.




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

  Powered by Linux