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.