On Fri, 2008-06-06 at 16:11 -0400, eparis(a)redhat.com wrote:
From: Eric Paris <eparis(a)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(a)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