Still ongoing selinux policy and toolchain work in this area is needed and I should do more testing on a host machine with selinux disabled but this is the livecd patch I've got working as of today. I think that I want to make my print >> sys.stderr message actually be fatal. The reason for this is because setting selinux --disabled in the kickstart and not having /usr/sbin/lokkit results in an enabled livecd which doesn't work... No reason to just print a message and not stop the work if we know for sure the results are useless...
This patch also has the f.close() fix that I sent yesterday, so it might not apply if you already applied that one...
-Eric
diff -Naupr imgcreate.orig/creator.py imgcreate/creator.py --- imgcreate.orig/creator.py 2008-05-06 12:16:08.000000000 -0400 +++ imgcreate/creator.py 2008-06-05 17:10:36.561313078 -0400 @@ -23,6 +23,7 @@ import sys import tempfile import shutil
+import selinux import yum import rpm
@@ -402,6 +403,52 @@ class ImageCreator(object): fstab.write(self._get_fstab()) fstab.close()
+ 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???? + 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.
@@ -427,7 +474,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") @@ -439,10 +486,6 @@ 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)) - # Create minimum /dev origumask = os.umask(0000) devices = [('null', 1, 3, 0666), @@ -460,6 +503,8 @@ class ImageCreator(object): os.symlink('/proc/self/fd/2', self._instroot + "/dev/stderr") os.umask(origumask)
+ self.__create_selinuxfs() + self._do_bindmounts()
os.symlink("../proc/mounts", self._instroot + "/etc/mtab") @@ -479,6 +524,8 @@ class ImageCreator(object): except OSError: pass
+ self.__destroy_selinuxfs() + self._undo_bindmounts()
self._unmount_instroot() @@ -543,7 +590,17 @@ class ImageCreator(object): for pkg in kickstart.get_excluded(self.ks, self._get_excluded_packages()): ayum.deselectPackage(pkg) - + + # if the system is running selinux and the kickstart wants it disabled + # we need /usr/sbin/lokkit + def __can_handle_selinux(self, ayum): + has_req = 1 + file = "/usr/sbin/lokkit" + if not kickstart.selinux_enabled(self.ks) and os.path.exists("/selinux/enforce"): + has_req = ayum.installHasFile(file) + if not has_req: + print >> sys.stderr, "Dude, you need a package which provides %s for your selinux setup to work" %(file) + def install(self, repo_urls = {}): """Install packages into the install root.
@@ -579,6 +636,9 @@ class ImageCreator(object): self.__select_packages(ayum) self.__select_groups(ayum) self.__deselect_packages(ayum) + + self.__can_handle_selinux(ayum) + ayum.runInstall() except yum.Errors.RepoError, e: raise CreatorError("Unable to download from repo : %s" % (e,)) diff -Naupr imgcreate.orig/kickstart.py imgcreate/kickstart.py --- imgcreate.orig/kickstart.py 2008-05-06 12:16:08.000000000 -0400 +++ imgcreate/kickstart.py 2008-06-04 14:56:35.033603440 -0400 @@ -369,14 +369,15 @@ class SelinuxConfig(KickstartConfig): path = self.path(fn) f = file(path, "w+") os.chmod(path, 0644) + f.close()
if ksselinux.selinux == ksconstants.SELINUX_DISABLED: return - if not os.path.exists(self.path("/sbin/restorecon")): + if os.path.exists(self.path("/sbin/restorecon")): + self.call(["/sbin/restorecon", "-l", "-v", "-r", "-F", "-e", "/proc", "-e", "/sys", "-e", "/dev", "-e", "/selinux", "/"]) + else: return
- self.call(["/sbin/restorecon", "-l", "-v", "-r", "/"]) - def apply(self, ksselinux): if os.path.exists(self.path("/usr/sbin/lokkit")): args = ["/usr/sbin/lokkit", "-f", "--quiet", "--nostart"] diff -Naupr imgcreate.orig/yuminst.py imgcreate/yuminst.py --- imgcreate.orig/yuminst.py 2008-05-06 12:16:08.000000000 -0400 +++ imgcreate/yuminst.py 2008-06-05 17:00:00.574631892 -0400 @@ -79,7 +79,7 @@ class LiveCDYum(yum.YumBase): def selectPackage(self, pkg): """Select a given package. Can be specified with name.arch or name*""" return self.install(pattern = pkg) - + def deselectPackage(self, pkg): """Deselect package. Can be specified as name.arch or name*""" sp = pkg.rsplit(".", 2) @@ -138,6 +138,20 @@ class LiveCDYum(yum.YumBase): repo.setCallback(TextProgress()) self.repos.add(repo) return repo + + def installHasFile(self, file): + has_file = 0 + provides_pkg = self.whatProvides(file, None, None) + dlpkgs = map(lambda x: x.po, filter(lambda txmbr: txmbr.ts_state in ("i", "u"), self.tsInfo.getMembers())) + for p in dlpkgs: + for q in provides_pkg: + if (p == q): + has_file = 1 + if has_file: + return True + else: + return False +
def runInstall(self): os.environ["HOME"] = "/"
On Wed, Jun 04, 2008 at 03:13:08PM -0400, Daniel J Walsh wrote:
You might need to check your user database
semanage user -l semanage login -l
Thank you for this hint.
I tracked the issue to a manifestation of the following bug:
https://bugzilla.redhat.com/show_bug.cgi?id=443852
The fix was to do as one of the comments in the bug report suggested. First, I downloaded both the F7 and F9 selinux-policy* packages. Then, I did as follows:
1) mv /etc/selinux /etc/selinux.old
2) rpm --oldpackage -Uvh selinux-policy*fc7*
3) boot into the F9 rescue mode
4) chroot /mnt/sysimage
5) rpm -Uvh selinux-policy*fc9* (this last step took a long time, but the upgrade fixed the user_u issues while operating in a sane SELinux environment)
6) Reboot
Thanks a lot for the pointer!
Best regards,
---Kayvan
This looks good. Just a couple of (minor) tweaks/questions
* Doesn't want to apply cleanly to current tip of git. Should be straight-forward to fix, if you don't have the time, I can * Any chance of splitting it into two chunks (one for the main bit, a second for the "selinux --enforcing request, but no lokkit in the package list)? Again, I can if not
On Thu, 2008-06-05 at 17:35 -0400, Eric Paris wrote:
Still ongoing selinux policy and toolchain work in this area is needed and I should do more testing on a host machine with selinux disabled but this is the livecd patch I've got working as of today. I think that I want to make my print >> sys.stderr message actually be fatal. The reason for this is because setting selinux --disabled in the kickstart and not having /usr/sbin/lokkit results in an enabled livecd which doesn't work... No reason to just print a message and not stop the work if we know for sure the results are useless...
Sure, and it's early enough to be reasonable. Just switch the print to raise CreatorError and things will get torn down correctly too
This patch also has the f.close() fix that I sent yesterday, so it might not apply if you already applied that one...
Yeah, I pushed it right after you sent it
In any case, I can fix those little things up tomorrow if you want to move on to something else and just get this committed, pushed and the relevant bug closed. And then we can hopefully get some more testing than just the two of us
Jeremy
selinux@lists.fedoraproject.org