Message ID | CAJ2a_DcVJVogztwh7Wx88W8tDv0L4GmrsaCr-hYd1GND25w56Q@mail.gmail.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
On Wed, 2017-01-25 at 18:29 +0100, cgzones wrote: > 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): This only supports running all maintainer tasks in a single, fixed security context that is not based in any way on the context in which dpkg itself runs. Whereas the setexecfilecon() approach allows for different scripts to run in different roles or domains via policy transitions, and for the user identity and range to be preserved from the dpkg instance. I understand the motivation but not sure this is a general approach. I'm not clear anymore on why ubac even exists, since if you truly want that type of separation, you are better off using roles given that modern SELinux supports fine-grained role transitions and roles on files (originally UBAC was a fallback I believe due to the lack of support for roles on files). > > 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/policycoreu > tils/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@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 > > > > Best Regards, > Christian Göttsche > > _______________________________________________ > Selinux mailing list > Selinux@tycho.nsa.gov > To unsubscribe, send email to Selinux-leave@tycho.nsa.gov. > To get help, send an email containing "help" to Selinux-request@tycho > .nsa.gov.
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@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
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(-) Best Regards, Christian Göttsche