Re: handling locally-modified policy and upgrades with ostree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 02/29/2016 03:53 PM, Colin Walters wrote:
Hi,

Currently there's a conflict between the way OSTree handles
config files (modified version in /etc wins, see https://ostree.readthedocs.org/en/latest/manual/deployment/ )
and SELinux, because the policy lives in /etc.

The core problem is that right now, as soon as one modifies
the policy, that binary version is propagated forwards until
the admin reruns `semodule -B` (and really you want to
run it for the *new* chroot)

I'm not sure what the above problem statement means.  Can you elaborate?


A few of us from Red Hat talked about this at Devconf.cz,
and I filed:

https://bugzilla.gnome.org/show_bug.cgi?id=761620

The first question from the bug is:

  - Can we detect "is the policy changed"?  Probably cmp /{usr/,}etc/selinux/targeted/policy/policy.29 - but is there an API for that?

Is this really only an issue for the policy.N file or is it an issue for all of the /etc/selinux files that are regenerated by libsemanage on a policy transaction (e.g. file_contexts, seusers, ...).

The only real support for comparing two policies is sediff from setools. cmp would likely work for your purposes but technically could provide a false-positive (i.e. two kernel binary policies might differ on a byte-for-byte basis but be semantically equivalent, differing only in ordering).


I was briefly looking at this again today, started by reading the semodule
code.

The first question is most important to me - right now by nature
of having the immutable copy in /etc, OSTree itself can help
me know whether policy is modified.  But, I have to know the
policy path and version.

I started reading the code in selinux/libselinux/src/load_policy.c
around finding out "what is the current policy version", and
while selinux_binary_policy_path() will tell me the prefix,
the code around detecting the version number is rather
nontrivial[1].

Indeed, it is complicated by the need to support arbitrary kernel/userspace combinations and by the need to provide backward compatibility. However, in practice, it should just be the highest version for which a policy file exists. Normally this will be the same as sepol_policy_kern_vers_max(), but it is technically possible for libsepol to be updated to a newer version without triggering a policy rebuild, and thus there might not yet be a policy file with that version, so you need to scan downwards until you find a file that exists (but you can stop at sepol_policy_kern_vers_min()). Even if the libsepol-supported version exceeds the version supported by the kernel, libselinux will downgrade the policy via libsepol in memory to a version supported by the kernel before loading it into the kernel.

The libsemanage code has some layers here that seem to
ultimately boil down to picking the largest version known to libsemanage,
but here I need logic more like what load_policy is doing (I want
to know the current binary version, not generate a new one).

Maybe we could add a public API for this?  Alternatively, have
`semodule -B --only-if-modified` or something that would immediately
exit if there's nothing to do?

At the moment, we have the APIs mentioned above, which I think suffice even if they are a bit clumsy to use. semodule -B by definition is "force a rebuild", so I don't know what --only-if-modified would mean or how one would implement it. semodule -B is only used when one manually populates the policy store (i.e. directly copies files into it rather than creating them via semodule -i and semanage commands) and then needs to trigger a rebuild, or when one is stripping or restoring dontaudit rules (i.e. semodule -DB, semodule -B).


The above text covers the first question, the second one from the bug is:

  - Can we efficiently detect the case where on upgrade, the base policy version didn't change, so we don't need to recompile, and just propagate forward our modified policy from /etc?

This one is actually a different "policy version", I should have written
"policy RPM package version" or so.  This one is probably relatively
simple to do in rpm-ostree, just compare the EVRs of the policy package,
but is there some sort of package-system independent version (like
a checksum of the .pp files) that I could use?

That seems sane, but I don't know for sure.

[1] What is up with the dlopen?  It'd be nice to have a comment in this code;
the git commit message just says "initial import from svn trunk revision 2950"
and I'm too lazy right now to install Subversion in the hopes
that contains a useful log message.

It's to avoid a hard dependency on libsepol and to avoid requiring all users of libselinux to link against libsepol. Technically one can load policy just fine without libsepol as long as the policy version is supported by the kernel. I think it originated from the early embedded SELinux folks.

In Android, for comparison, the policy version is wired to one supported by all supported kernels, there is only ever a single policy file (and thus no version suffix), and the policy loading logic is very simple.
_______________________________________________
Selinux mailing list
Selinux@xxxxxxxxxxxxx
To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx.
To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux