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

Reply via email to