[Rpm-maint] [RFC PATCH] install selinux policies from package header
Mark Hatle
mark.hatle at windriver.com
Tue Jul 7 13:18:53 UTC 2009
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 at lists.rpm.org
> http://lists.rpm.org/mailman/listinfo/rpm-maint
More information about the Rpm-maint
mailing list