We checked for libintl in the top-level CMakeLists.txt but then never
used it for anything. This only ever worked on glibc where this all
is bundled in. Unfortunately Intl only becomes an importable target
in cmake >= 3.20 which is too new for us to rely on for now.
Python bindings are omitted here because we don't have any translated
messages in there. Whether we should is another topic.
A plugin is a convenient place to hide Linux-specific functionality.
Implemented in this initial version are:
- Optional private mounts during scriptlet execution, useful for
protecting the system from scriptlets (eg /home) and the scriptlets
from themselves (eg insecure /tmp usage)
- Optionally disable network access during scriptlet execution
Note that at this time, scriplets executed with the embedded Lua
interpreter are not covered by this because they run inside the main rpm
process instead of forking (#2635).
Add a testcase for private /tmp
Suggested-by: Johannes Segitz <jsegitz@suse.de>
Fixes: #2632Fixes: #2665
Rpm is probably the only software in existence that uses a prefix
instead of a suffix for detecting it's own macro files. Commit
ce7210d584 got it exactly wrong.
Too many meetings must have melted my brains.
The great irony here is that this breakage occurs while developing a
test-case for plugin-development. Oh well.
Carrying the plugin config in the main macros file for plugins that
might not even have been built+installed seems dumb, but considering
that we didn't even *have* macros.d back then, more excusable. It no
longer is, though. Split the macros to their own files, to be installed
only along with a built plugin.
We've procrastinated on making this API public for about ten years now,
and in the meanwhile there has been exactly one disruptive change to
the API. As in, it might've just as well been public all along.
There will always be more things to improve wrt any API, but we're not
going to hold this hostage to one more thing or another anymore. Some
of them we'd like to do before this goes to a stable release (ie 4.20)
but doing this now to kinda enforce this actually happens this time
around, through come hell or high water.
Fixes: #1536
Having everything accessible to everything encourages fast and loose
includes from places one shouldn't be using, and makes it easy for
those cases to hide in plain sight as well. There were reasons for
the top-level include back in 2007 but our codebase is a rather
different beast these days. Limiting access through per-target
include directories on everything nicely highlights the exceptions
and makes the whole more controllable and manageable.
This change looks huge, but it's just due to stripping no longer valid
prefixes from all the gazillion internal includes. No rpm-side
functionality is affected, this is just source-level hygiene operation.
A declaration immediately following a label is not valid C99, as crazy
as it is in a language that otherwise allows free placement of declarations.
It looks like something people forgot to update in the standard, first
in C99 and apparently C11 too. Recent gcc doesn't complain about it
but it doesn't make it right.
Suggested-by: Dmitry Mikushin <dmitry@kernelgen.org>
Make systemd_inhibit plugin behave identically to dbus_announce in the
previous commit: when DBus service isn't available, emit a debug level
message rather than completely suppressing the message to keep things
troubleshootable.
Same as commit 708e61307b, this message
will just annoy and confuse users in situations where DBus service is
not running at all, such as single-user mode and minimal container type
environments. Like our own test-suite. Rather than entirely suppress
the error, issue a debug log though.
Users are not supposed to meddle with this. So it really should not go
into /etc.
Use the DATADIR from dbus-1 and not our own install prefix.
Resolves: #2474
Another bit lost in the cmake transition: plugin linkage to librpm and
librpmio. In rpm itself this doesn't really matter because the running
process supplies the necessary symbols but it's a different story when eg
a Python process uses dlopen()'ed bindings.
Abort the build if imaevm enabled but header+library not present, use
detected values. Check for lsetxattr() availability. Drop unnecessary
imaevm linkage from the plugin, the plugin only manipulates xattrs and
does not need the IMA library.
These imported targets passed to target_link_library() are supposed to
handle all the pesky compilation, linkage etc details behind the scenes.
I was pretty sure I was missing a trick with this, but this sure isn't
exactly underlined in the documentation.
Unroll the supposedly helpful loop for handling plugins: turns out doing
this cmake native way is plenty shorter and more obvious too. The unroll
kinda belongs to a separate commit but that'd be rather painful for very
little if any gain.
Fixes: #2269 and a whole class of similar cases, allegedly
There are some missing bits and pieces still to be done for cmake build,
but that is so much easier if you don't have to worry about keeping
compatibility with the system you're about to remove that it doesn't
make sense to drag this on any further. The sooner this is over, the
sooner it is over and we can start making use of cmake's advantages
instead of just trying to bend over backwards to maintain compatibility
with the autotools build.
libselinux logs to stderr by default, which up to now has been just fine
with us. However somewhere around libselinux 3.2 it begun issuing
log messages for events discovered in selinux_status_updated().
We only call that to see whether the status *was* updated behind our
back and are not interested in these audit-style messages for our
functionality, but to suppress them while preserving actually relevant
errors and warnings, we need to have a log callback of our own. Might as
well forward them to rpmlog then.
SELINUX_ERROR and SELINUX_WARNING are pretty obvious, of SELINUX_AVC
selinux_set_callback(3) says it should be treated as SELINUX_ERROR if
not audited. The rest we suppress to debug messages, they may be handy
for diagnostics some day.
Note that this intentionally avoids explicit SELINUX_POLICYLOAD and
SELINUX_SETENFORCE cases in the switch: we don't want to introduce
libselinux >= 3.2 dependency just because of this silly thing.
- switch to read only and non blocking mode for pipe
- add 1 minute loop to wait for pipe to reappear
Sometimes during the system update/upgrade fapolicyd
get restarted e.g. when systemd gets updated.
That can lead to the situation where fapolicyd pipe
has been removed and created again.
In such cases rpm-plugin-fapolicyd gets stuck on
write() to the pipe which does not exist anymore.
After switching to non blocking file descriptor
we can try to reopen the pipe if there is an error
from write(). Assuming that a new pipe should appear
when fapolicyd daemon starts again.
If not then after 1 minute of waiting we expect
fapolicyd daemon to be not active and we let the
transaction continue.
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
This is an incomplete release-early version, NOT intended or
suitable for production use. It is intended to replace the autotools
based buildsystem in rpm 4.20, until then it'll be developed alongside
it. This causes some extra complications of course, but then we avoid
a huge flag-day, and that matters more.
To those wondering why cmake and not ${myfavorite}: the community around
us effectively made that choice for us. We've made a lot of noise about
bootstrap dependencies. When libsolv, dnf and all the related stack is
powered by cmake build, it'd be just foolish to go with anything else.
This way people working on the rpm stack have only one build system to
learn, there's peer support available nearby and bootstrap dependencies
are reduced, not increased. It also doesn't hurt that cmake is actually
and actively maintained.
setexecfilecon() is in libselinux version 2.3 in 2014, we don't need to
worry about it's availability anymore. Instead, use it to determine
libselinux suitability in the configure check, eliminating another
redundant check and a bunch of unused code.
Introduced back in 2007 in 5831404601 the
point was to fake up a sane public header structure with minimal
internal disruption, TEMPORARILY. I think 15 years is temporary enough.
The machinery has worked rather well for what it is, but having the
headers appear in multiple locations is weird and confusing to people,
plus this "physical" separation makes it far more clearer what is
a public header and what isn't.
If an RPM contains IMA signed digests and rpm-plugin-ima is installed,
then any attempt to install to a filesystem that doesn't support
extended attributes will cause the RPM installation to fail.
This can be seen, for example, if installing a file /boot, which is
usually a vFAT filesystem.
The rpm-plugin for selinux fixed this some time back, and that same
logic can be applied to IMA too - where, if a failure to set an extended
attribute results in an errno that is set to EOPNOTSUPP, then this
should not cause a complete failure, but should instead just be logged
at a debug level.
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Sadly the thing that allegedly makes things better mostly just makes
things more complicated as symlinks can't be opened, so we'll now have
to deal with both cases in plugins too. To make matters worse, most
APIs out there support either an fd or a path, but very few support
the *at() style dirfd + basename approach so plugins are stuck with
absolute paths for now.
This is of course a plugin API/ABI change too.
Fapolicyd (File Access Policy Daemon) implements application whitelisting
to decide file access rights. Applications that are known via a reputation
source are allowed access while unknown applications are not.
The rpm plugin allows us to use rpm database as a source of trust.
We used dnf plugin since the beggining but it only provides notification
when transaction ends. With "integrity checking" requirement we need
a continual addition of files which are installed during the system
update. With fapolicyd rpm plugin we can allow using of recently
added/updated files in scriptlets during rpm transaction.
The fapolicyd plugin gathers metadata of currently installed files.
It sends the information about files and about ongoing rpm transaction
to the fapolicyd daemon. The information is written to Linux pipe which
is placed in /var/run/fapolicyd/fapolicyd.fifo.
The data format is "%s %lu %64s\n". [path, size, sha256]
The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
configure option.
Related PRs:
https://github.com/linux-application-whitelisting/fapolicyd/pull/105https://github.com/linux-application-whitelisting/fapolicyd/pull/106
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
In libselinux >= 3.1 these cause deprecation warnings on build.
security_context_t always was nothing but typedef to plain old "char *"
so just using that is entirely backwards compatible too.
This plugin installs fsverity signatures for regular files, when a signature
is found in the RPM. It tries to enable them unconditionally, but fails
gracefully if fsverity isn't supported or enabled.
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
Refactor the custom exec context setting code to look like setexecfilecon()
in case the real one is not available to eliminate pesky behavioral
differences between the two cases.
This fixes a concrete bug of libselinux setexecfilecon() returning with
an error when security_getenforce() returns with -1 (such as a bare
chroot with no /sys mounts etc), causing us to spit out useless error
messages in that case ever since fixing the bogus if-logic in
commit ab601b882b.
Fixes: #1077
Commit 708e61307b introduced a memory leak
on the error object: if the message is suppressed then the error object
is never freed. Test for the suppression conditions separately to fix.
We already filter out -EOPNOTSUPP and return OK, but the message was
getting logged before the filtering so we'd spit out spurious error
messages on filesystems that don't support SELinux (RhBug:1777502)
Turns out this isn't a safe thing to do, as an API user could have
their own dbus connections in the same process and shutting those
down is a rather impolite thing to do (and causes crash, burn and
other injuries, eg RhBug:1750575)
This reverts commit d5f201345f.
The message may just confuse users if DBus is not running as default,
e.g. single-user mode. We suppress it when DBus is not available,
which is done by checking two cases:
socket does not exist (DBUS_ERROR_FILE_NOT_FOUND), or
unable to connect to server (DBUS_ERROR_NO_SERVER).
Note that this is an approximate but not an exact way to detect
whether DBus service should be running in the environment or not.
dbus_shutdown() frees internal DBUS memory allocations that will otherwise
show up as memory leaks. This is of little consequence in practise
but shuts up valgrind...
When enabled, log audit events for package install, update and remove.
The log includes the operation, package nevra, signature check result,
whether signatures are being enforced enforced and overall operation
result code. Package install/update/remove are logged as such,
obsoletion is logged as install + remove (whereas the erasure element
on updates is silent). Enable compilation in CI.
Loosely based on initial RHEL 7-8 implementations by Pavlina Moravcova
Varekova and Florian Festi (RhBug:1555326, RhBug:1607612)
When there's an actual error, people will want to know without having
to rerun in verbose mode. Such as in RhBug:1641631 where configured
selinux policy differs from what is installed - the former message
error: Plugin selinux: hook tsm_pre failed
...is not particularly helpful to anybody, whereas this actually provides
some clues now:
error: selabel_open: (/etc/selinux/ponies/contexts/files/file_contexts) No such file or directory
error: Plugin selinux: hook tsm_pre failed
Even though config files may be close to what could be described as
'mutuable files', we now want to give the user control over the
installation of signatures on these files as well. We enable this
through a variable in the macro file. For this, we should be aware
that the signatures of these files may become incorrect or missing
once RPM post installation scripts or other programs have modified
these configuration files.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com