[Rpm-maint] whitelisting/wrapping script execution

Colin Walters walters at verbum.org
Wed Apr 23 13:13:10 UTC 2014


Hi,

For the rpm-ostree project, I need the ability to whitelist scriptlets. 
 There are a few reasons for this, but the most critical is that due to 
the way OSTree uses hardlinks, and because I can't assume I have 
copy-on-write links, I need to know that scriptlets will cleanly break 
hardlinks instead of edit-in-place.

For example, suppose I'm layering a package on top of a base tree that 
contains a shared library.  We need to update /etc/ld.so.cache.  In the 
traditional RPM model, that package will contain a scriptlet to run 
/sbin/ldconfig.

I happen to know that /sbin/ldconfig is safe - it creates 
/etc/ld.so.cache~ and rename()s into place, so I can just run it.  But 
if the package happens to do something I haven't whitelisted as safe, I 
need to error out and refuse to install it.

(Note an important side benefit here of moving away from the "whatever 
arbitrary code you want that runs as root" aspect of scripts)

Now related to this, I'd like to have rpm-ostree take care of executing 
any subprocesses (and even Lua code potentially).  The reason for this 
is because *every* rpm-ostree install will be in a chroot.  In the 
OSTree model, you running system is immutable - so to "upgrade" a 
package, we make a hardlink farm of the current tree, and re-unpack the 
new version of of a package on top, then set it up for the next boot.

If you look at software like mock, it does a complex dance to set up 
things like /proc in the target root and then run yum --installroot.  
But if we were in control over all subprocesses launched, we could use 
systemd to put each scriptlet inside a container, with its own private 
/proc and such, inside its own mount namespace.  There are a huge 
number of advantages to this - systemd is very good at isolation, 
logging, etc.  For example, we could cut off scriptlets from access to 
physical devices using 
https://fedoraproject.org/wiki/Changes/PrivateDevicesAndPrivateNetwork

So, a few ways to accomplish this:

1) Add rpmtsSetScriptCallback() - This would allow me to set a callback 
which would be used instead of the fork()/exec() bits in rpmScriptRun.  
I could analyze the script content, and exec it myself using something 
like "systemd-run".

2) Have rpm-ostree extract the scripts manually *before* the 
transaction, analyze them, unpack all of the rpms, then run all of the 
scripts as if they were %posttrans anyways

I need to do a bit more evaluation, but the more I think about it the 
more I like #2 as it maximizes control.  If we go that route though 
there's a detail - Lua-based scripts.  In order to implement these it's 
a bit harder as I'd need to exec a new RPM process inside the root and 
run the script inside that process.  Maybe I could get away with just 
ignoring Lua scripts, I suspect many of them are there to work around 
things like "can't replace directory with symlink" problem that OSTree 
itself fixes.

Thoughts?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20140423/6994db63/attachment.html>


More information about the Rpm-maint mailing list