I believe that calling out is the better solution, at least for me. I need to
be able to install software into chroots and other "non-host" environments for
other machines to run.
If we call out, then I can intercept that and perform setup actions [or ignore
actions] based on my configuration.
Direct API calls also limit it to the running system environment.
As for the "initial install" situation, I don't believe SE Linux should be
configured during an initial install. This would be setting up contexts and
such for the installer's kernel and not the end resulting filesystem. A flag or
something to disable this type of setup for the initial install might be
necessary. [or the script/program run could be passed the install root and know
what to do, or not to do in a new system install context. Just has to run
outside of the chroot...]
--Mark
Panu Matilainen wrote:
Hi,
On Mon, 6 Jul 2009, Stephen Lawrence wrote:
RPM currently has support for security policies to be stored in an rpm
header but it doesn't currently do anything with the policies. We'd like
to get some feedback on a prototype implementation that adds support for
using those policies in an SELinux environment.
First of all thanks for looking into this!
First, a bit of background. SELinux policy is currently installed
through %post scripts. This presents several problems. First, this means
that policy for a given application may not be loaded at the time the
files are written to disk, preventing those files from being labeled
properly, because the symbols used to label files need to be in the
policy loaded into the kernel. Secondly, this means that if multiple
packages install policy, each of their %post scripts will reload the
policy, which is a very expensive operation. Consequently, policy is
generally kept in a single package to avoid this, despite containing
many application specific policy modules that would be more suited to be
included in their application package.
So, what we would like to do is to start including SELinux policy as
part of the rpm and have rpm install all policies together before files
start to hit the disk. To do this, we would like to use the already
supported %policy directive, which stores the policy in the archive
header.
We would then install the policy before pretrans. This policy load would
involve gathering all the policies to be installed from all packages,
writing them to a temporary location, and calling out to semodule to
install the SELinux policy modules.
Obviously I'm glossing over many implementation details that would need
to be worked out. The point of this email is strictly to get feedback on
our approach. Below is a patch that implements the beginnings of what I
describe above. Any and all feedback is appreciated.
Loading the policies at pre-trans stage is how it needs to be done, but
calling out to semodule is a no-go. It'd work for upgrades more or less,
but on initial installation (to an empty chroot) the pre-trans stage
happens in a complete void, there's just nothing there, not even /bin/sh.
It needs to be done through API calls, no way around it. On the surface
it doesn't look that bad, skipping over details like error handling,
rpmtsLoadPolicy() might be something like:
static int rpmtsLoadPolicies(rpmts ts)
{
int rc;
rpmte p;
semanage_handle_t *sh = NULL;
rpmtsi pi = rpmtsiInit(ts);
while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
/* If no pre/post-transaction script, then don't bother. */
if (!rpmteHavePolicies(p, stag))
continue;
/* only set up semanage transaction if we have policies */
if (sh == NULL) {
sh = semanage_handle_create();
semanage_connect(sh);
semanage_begin_transaction(sh);
}
if (rpmteOpen(p, ts, 0)) {
/* ... fish the policies from te header, b64decode ... */
semanage_module_install(sh, ...);
rpmteClose(p, ts, 0);
}
}
if (sh) {
semanage_commit(sh);
semanage_disconnect(sh);
semanage_handle_destroy(sh);
}
pi = rpmtsiFree(pi);
return rc;
}
...but I've a feeling there's more than one devil in the details. The
"base" policy seems to be a bit special as it even has a separate loader
function, which I suppose would have to be loaded first if one is
present, but how would rpm know what's a base policy and what's not? Are
there other order dependencies in the modules? I guess not but dunno.
Another open question is upgrade/remove semantics. Maybe it's sufficient
just to semanage_module_install() on install+upgrade, and
semanage_module_remove() on non-upgrade removal (direct erase or
obsoletion), all in the pre-trans stage. I'm just wondering could there
be cases where successful removal requires the package's policy to be
loaded? If so, the module removals would either have to be done at the
middle of transaction individually per package (costly) or do them all
at post-trans stage, which would seem more symmetric in a sense. And
actually quite similar to how %pre- and %posttrans happen, might even be
possible/reasonable to lump their processing to a single function (the
actual "do stuff" part obviously differs but the transaction set
iteration and header loading is the same)
And of course it must be possible to disable this functionality. Might
be sufficient to just hang it on RPMTRANS_FLAG_NOCONTEXTS, or can you
think of a case where one would want to load policies without actually
touching the contexts (or the other way around)?
- Panu -
_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint
_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint