Re: dpkg: run maintainer scripts with SELinux user system_u

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

 



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@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@tycho
> .nsa.gov.
_______________________________________________
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