Description of problem: Heck, you can't even list the active modules. Looks like, among other things, it's trying to create lock files in /etc. This can be worked around in stateless by 'installing' the module first. But it's still awfully odd.
Steven, shouldn't load_policy succeed if /etc read only?
load_policy works fine in that case. The problem is that semodule -> libsemanage manages the module store under /etc/selinux/$SELINUXTYPE/modules, and that includes lock files plus the modules themselves and the generated policy. /etc has to be writable for policy updates (which is what installing a policy module is). Or we have to the policy module store elsewhere, but that is a big PITA at this point.
So, I suspect part of this was my unfamiliarity with the module process; semodule -i is actually the combination of 'install the policy in the place where it's loaded from, and load it'; the loading itself can be done read-only, provided it's already there. So, what I'd suggest is: 1) is there a way to load the binary policy module without copying it to /etc/XXXX? 2) semodule -l should at least still work when read-only.
"Loading" a policy module requires linking it with all other policy modules (including the base module) and then expanding the linked policy to a kernel binary policy file, then loading that kernel binary policy file. At present, that requires going through libsemanage (which is what semodule does) and manipulating the module store, yielding a final generated kernel policy in the standard location which is then loaded by load_policy. There are development tools included in policycoreutils (semodule_link, semodule_expand) that can be used to manually link and expand modular policy to kernel policy in a separate location, but that is really just for development/debug purposes, and load_policy presently will only load policy from the standard location under /etc/selinux/... (see prior discussions about moving policy loading logic into libselinux and selinux_mkload_policy interface used by load_policy these days). So the short answer is no. If /etc is going to be rdonly (and we can't get a separate rw mount on /etc/selinux), then /etc/selinux likely needs to be relocated or at least transparently relocatable for the tools, which suggests a patch to libselinux to use an alternate location if defined, e.g. via environment variable. Although you'd likely want that scrubbed if libc secure mode was enabled.
1) No, the modules must be protected and preserved in the store. If the modules are elsewhere they could get replaced outside of semodule and the next policy change would pull in a different policy. 2) We need reader locks on the store to prevent a reader from getting a new policy in mid-read. My suggestion would be to move the whole /etc/selinux directory somewhere else and bind mount to /etc/selinux. Be sure the labels are correct afterward. (semanage fcontext to make sure they are preserved)
Did we decide what we want to do here? I pointed out in email that checking the filesystem for EROFS isn't totally safe (since the filesystem can be remounted rw in the middle of an operation and the lock won't be held) but if that is an acceptable risk we can put the check in there..
Can't we just use the readonly lock?
IIRC flock works fine on a readonly filesystem so we just need to make sure we aren't trying to open files O_RW if the connection is read only. I'll take a look at this as soon as I can, unless someone else gets around to it first.
This is fixed in upstream libsemanage svn revision 33
Fixed in libsemanage-1.6.12-1