Re: [Rpm-maint] [RFC PATCH] install selinux policies from package header

2009-07-07 Thread Panu Matilainen


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


Re: [Rpm-maint] [RFC PATCH] install selinux policies from package header

2009-07-07 Thread Mark Hatle
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