[PATCH 1/2] LiveCD - Add fake /selinux so livecd can run in enforcing

Stephen Smalley sds at tycho.nsa.gov
Mon Jun 9 14:12:57 UTC 2008


On Fri, 2008-06-06 at 16:11 -0400, eparis at redhat.com wrote:
> From: Eric Paris <eparis at redhat.com>
> 
> This patch adds a /selinux directory to a newly created livecd compose which
> will allow the tools inside the chroot to interoperate with the live system
> successfully.
> 
> Signed-off-by: Eric Paris <eparis at redhat.com>
> ---
>  imgcreate/creator.py   |   55 ++++++++++++++++++++++++++++++++++++++++++++---
>  imgcreate/kickstart.py |    2 +-
>  2 files changed, 52 insertions(+), 5 deletions(-)
> 
> diff --git a/imgcreate/creator.py b/imgcreate/creator.py
> index 5d010a1..f65f7d4 100644
> --- a/imgcreate/creator.py
> +++ b/imgcreate/creator.py
> @@ -24,6 +24,7 @@ import tempfile
>  import shutil
>  import logging
>  
> +import selinux
>  import yum
>  import rpm
>  
> @@ -421,6 +422,52 @@ class ImageCreator(object):
>          os.symlink('/proc/self/fd/2', self._instroot + "/dev/stderr")
>          os.umask(origumask)
>  
> +    def __create_selinuxfs(self):
> +        # if selinux exists on the host we need to lie to the chroot
> +        if os.path.exists("/selinux/enforce"):
> +            selinux_dir = self._instroot + "/selinux"
> +
> +            # enforce=0 tells the chroot selinux is not enforcing
> +            # policyvers=999 tell the chroot to make the highest version of policy it can
> +            files = (('/enforce', '0'),
> +                     ('/policyvers', '999'))
> +            for (file, value) in files:
> +                fd = os.open(selinux_dir + file, os.O_WRONLY | os.O_TRUNC | os.O_CREAT)
> +                os.write(fd, value)
> +                os.close(fd)
> +
> +            # we steal mls from the host system for now, might be best to always set it to 1????

This might be a problem for building RHEL 4 images, since MLS wasn't
enabled there.  I'm not certain though - I believe that there were
compatibility fixes put into RHEL 4 kernel updates to allow them to
mount filesystems modified under RHEL 5, so a modern RHEL 4 kernel would
ignore any MLS component in the context.  But the policy Makefile could
be confused by /selinux/mls==1 there.

> +            files = ("/mls",)
> +            for file in files:
> +                shutil.copyfile("/selinux" + file, selinux_dir + file)
> +
> +            # make /load -> /dev/null so chroot policy loads don't hurt anything
> +            os.mknod(selinux_dir + "/load", 0666 | stat.S_IFCHR, os.makedev(1, 3))
> +
> +        # selinux is on in the kickstart, so clean up as best we can to start
> +        if kickstart.selinux_enabled(self.ks):
> +            # label the fs like it is a root before the bind mounting
> +            arglist = ["/sbin/setfiles", "-F", "-r", self._instroot, selinux.selinux_file_context_path(), self._instroot]
> +            subprocess.call(arglist, close_fds = True)
> +            # these dumb things don't get magically fixed, so make the user generic
> +            for f in ("/proc", "/sys", "/selinux"):
> +                arglist = ["/usr/bin/chcon", "-u", "system_u", self._instroot + f]
> +                subprocess.call(arglist, close_fds = True)
> +
> +    def __destroy_selinuxfs(self):
> +        # if the system was running selinux clean up our lies
> +        if os.path.exists("/selinux/enforce"):
> +            files = ('/enforce',
> +                     '/policyvers',
> +                     '/mls',
> +                     '/load')
> +            for file in files:
> +                try:
> +                    os.unlink(self._instroot + "/selinux" + file)
> +                except OSError:
> +                    pass
> +
> +
>      def mount(self, base_on = None, cachedir = None):
>          """Setup the target filesystem in preparation for an install.
>  
> @@ -446,7 +493,7 @@ class ImageCreator(object):
>  
>          self._mount_instroot(base_on)
>  
> -        for d in ("/dev/pts", "/etc", "/boot", "/var/log", "/var/cache/yum"):
> +        for d in ("/dev/pts", "/etc", "/boot", "/var/log", "/var/cache/yum", "/sys", "/proc", "/selinux"):
>              makedirs(self._instroot + d)
>  
>          cachesrc = cachedir or (self.__builddir + "/yum-cache")
> @@ -458,9 +505,7 @@ class ImageCreator(object):
>                            (cachesrc, "/var/cache/yum")]:
>              self.__bindmounts.append(BindChrootMount(f, self._instroot, dest))
>  
> -        # /selinux should only be mounted if selinux is enabled (enforcing or permissive)
> -        if kickstart.selinux_enabled(self.ks):
> -            self.__bindmounts.append(BindChrootMount("/selinux", self._instroot, None))
> +        self.__create_selinuxfs()
>  
>          self._do_bindmounts()
>  
> @@ -483,6 +528,8 @@ class ImageCreator(object):
>          except OSError:
>              pass
>  
> +        self.__destroy_selinuxfs()
> +
>          self._undo_bindmounts()
>  
>          self._unmount_instroot()
> diff --git a/imgcreate/kickstart.py b/imgcreate/kickstart.py
> index c83e795..180cea2 100644
> --- a/imgcreate/kickstart.py
> +++ b/imgcreate/kickstart.py
> @@ -389,7 +389,7 @@ class SelinuxConfig(KickstartConfig):
>          if not os.path.exists(self.path("/sbin/restorecon")):
>              return
>  
> -        self.call(["/sbin/restorecon", "-l", "-v", "-r", "/"])
> +        self.call(["/sbin/restorecon", "-l", "-v", "-r", "-F", "-e", "/proc", "-e", "/sys", "-e", "/dev", "-e", "/selinux", "/"])

I assume that this is running the restorecon program from the chroot
rather than the host restorecon program.  Any issues there with the
(potentially older) restorecon in the image not providing the same set
of options or behavior?

>      def apply(self, ksselinux):
>          if os.path.exists(self.path("/usr/sbin/lokkit")):
-- 
Stephen Smalley
National Security Agency




More information about the selinux mailing list