For the use case of rebuilding the policy after package updates, we need
the check_ext_changes operation to always do at least the do_write_kernel
step, because the various semanage dbs may have also changed content
relative to the current binary policy. As this step is itself relatively
fast, we can do it unconditionally.
Fixes: 286a679fad ("libsemanage: optionally rebuild policy when modules are changed externally")
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
The code generated by swig triggers the following warning:
semanageswig_wrap.c:2759:24: warning: no previous prototype for ‘PyInit__semanage’ [-Wmissing-prototypes]
2759 | # define SWIG_init PyInit__semanage
| ^~~~~~~~~~~~~~~~
semanageswig_wrap.c:17772:1: note: in expansion of macro ‘SWIG_init’
17772 | SWIG_init(void) {
| ^~~~~~~~~
Ignore -Wmissing-prototypes for swig generated source files.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The functions helper_port_validate_local_proto(), get_type(), and
get_fcontext_new() are not used, so remove them.
Signed-off-by: James Carter <jwcart2@gmail.com>
Found by typos[1].
[1]: https://github.com/crate-ci/typos
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The cleanup goto block in `semanage_direct_set_enabled()` closes the
file stream pointer fp if not NULL. Set the stream to NULL after a
manual fclose(3), even on failure.
direct_api.c: In function ‘semanage_direct_set_enabled’:
direct_api.c:2130:25: error: pointer ‘fp’ may be used after ‘fclose’ [-Werror=use-after-free]
2130 | if (fp != NULL) fclose(fp);
| ^~~~~~~~~~
direct_api.c:2092:29: note: call to ‘fclose’ here
2092 | if (fclose(fp) != 0) {
| ^~~~~~~~~~
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>From fclose(3):
Upon successful completion, 0 is returned. Otherwise, EOF is returned
and errno is set to indicate the error. In either case, any further
access (including another call to fclose()) to the stream results in
undefined behavior.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Acked-by: James Carter <jwcart2@gmail.com>
In some circumstances, like semanage-store being on overlayfs, rename()
could fail with EXDEV - Invalid cross-device link. This is due to the
fact that overlays doesn't support rename() if source and target are not
on the same layer, e.g. in containers built from several layers. Even
though it's not atomic operation, it's better to try to copy files from
src to dst on our own in this case. Next rebuild will probably not fail
as the new directories will be on the same layer.
Fixes: https://github.com/SELinuxProject/selinux/issues/343
Reproducer:
$ cd selinux1
$ cat Dockerfile
FROM fedora:35
RUN dnf install -y selinux-policy selinux-policy-targeted
$ podman build -t localhost/selinux . --no-cache
$ cd ../selinux2
$ cat Dockerfile
FROM localhost/selinux
RUN semodule -B
$ podman build -t localhost/selinux2 . --no-cache
STEP 2/2: RUN semodule -B
libsemanage.semanage_commit_sandbox: Error while renaming /var/lib/selinux/targeted/active to /var/lib/selinux/targeted/previous. (Invalid cross-device link).
semodule: Failed!
Error: error building at STEP "RUN semodule -B": error while running runtime: exit status 1
With the fix:
$ podman build -t localhost/selinux2 . --no-cache
STEP 2/2: RUN semodule -B
libsemanage.semanage_rename: Warning: rename(/var/lib/selinux/targeted/active, /var/lib/selinux/targeted/previous) failed: Invalid cross-device link, fall back to non-atomic semanage_copy_dir_flags()
COMMIT localhost/selinux2
--> d2cfcebc1a1
Successfully tagged localhost/selinux2:latest
d2cfcebc1a1b34f1c2cd661ac18292b0612c3e5fa71d6fa1441be244da91b1af
Reported-by: Joseph Marrero Corchado <jmarrero@redhat.com>
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
"semanage login -a" accepts whitespaces in user/group name
(e.g. users/groups from Active Directory), which may lead to issues down
the line since libsemanage doesn't expect whitespaces in
/var/lib/selinux/targeted/active/seusers and other config files.
Fixes:
Artificial but simple reproducer
# groupadd server_admins
# sed -i "s/^server_admins/server admins/" /etc/group
# semanage login -a -s staff_u %server\ admins
# semanage login -l (or "semodule -B")
libsemanage.parse_assert_ch: expected character ':', but found 'a' (/var/lib/selinux/targeted/active/seusers: 6):
%server admins:staff_u:s0-s0:c0.c1023 (No such file or directory).
libsemanage.seuser_parse: could not parse seuser record (No such file or directory).
libsemanage.dbase_file_cache: could not cache file database (No such file or directory).
libsemanage.enter_ro: could not enter read-only section (No such file or directory).
FileNotFoundError: [Errno 2] No such file or directory
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
In Fedora/RHEL's selinux-policy package we ship a pre-built SELinux
policy store in the RPMs. When updating the main policy RPM, care must
be taken to rebuild the policy using `semodule -B` if there are any
other SELinux modules installed (whether shipped via another RPM or
manually installed locally).
However, this way of shipping/managing the policy creates complications
on systems, where system files are managed by rpm-ostree (such as Fedora
CoreOS or Red Hat CoreOS), where the "package update" process is more
sophisticated.
(Disclaimer: The following is written according to my current limited
understanding of rpm-ostree and may not be entirely accurate, but the
gist of it should match the reality.)
Basically, one can think of rpm-ostree as a kind of Git for system
files. The package content is provided on a "branch", where each
"commit" represents a set of package updates layered on top of the
previous commit (i.e. it is a rolling release with some defined
package content snapshots). The user can then maintain their own branch
with additional package updates/installations/... and "rebase" it on top
of the main branch as needed. On top of that, the user can also have
additional configuration files (or modifications to existing files) in
/etc, which represent an additional layer on top of the package content.
When updating the system (i.e. rebasing on a new "commit" of the "main
branch"), the files on the running system are not touched and the new
system state is prepared under a new root directory, which is chrooted
into on the next reboot.
When an rpm-ostree system is updated, there are three moments when the
SELinux module store needs to be rebuilt to ensure that all modules are
included in the binary policy:
1. When the local RPM installations are applied on top of the base
system snapshot.
2. When local user configuartion is applied on top of that.
3. On system shutdown, to ensure that any changes in local configuration
performed since (2.) are reflected in the final new system image.
Forcing a full rebuild at each step is not optimal and in many cases is
not necessary, as the user may not have any custom modules installed.
Thus, this patch extends libsemanage to compute a checksum of the
content of all enabled modules, which is stored in the store, and adds a
flag to the libsemanage handle that instructs it to check the module
content checksum against the one from the last successful transaction
and force a full policy rebuild if they don't match.
This will allow rpm-ostree systems to potentially reduce delays when
reconciling the module store when applying updates.
I wasn't able to measure any noticeable overhead of the hash
computation, which is now added for every transaction (both before and
after this change a full policy rebuild took about 7 seconds on my test
x86 VM). With the new option check_ext_changes enabled, rebuilding a
policy store with unchanged modules took only about 0.96 seconds.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
In order to reduce exisiting and future code duplication and to avoid
some unnecessary allocations and copying, factor the compressed file
utility functions out into a separate C/header file and refactor their
interface.
Note that this change effectively removes the __fsetlocking(3) call from
semanage_load_files() - I haven't been able to figure out what purpose
it serves, but it seems pointless...
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
The main goal of this move is to have the SHA-256 implementation under
libsemanage, since upcoming patches will make use of SHA-256 for a
different (but similar) purpose in libsemanage. Having the hashing code
in libsemanage will reduce code duplication and allow for easier hash
algorithm upgrade in the future.
Note that libselinux currently also contains a hash function
implementation (for yet another different purpose). This patch doesn't
make any effort to address that duplicity yet.
This patch also changes the format of the hash string printed by
semodule to include the name of the hash. The intent is to avoid
ambiguity and potential collisions when the algorithm is potentially
changed in the future.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
See: RFC 2606
foo.com seems to be privately owned.
Signed-off-by: Markus Linnala <Markus.Linnala@knowit.fi>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
Do not sort empty records to avoid calling qsort(3) with a NULL pointer.
qsort(3) might be annotated with the function attribute nonnull and
UBSan then complains:
database_join.c:80:2: runtime error: null pointer passed as argument 1, which is declared to never be null
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>From fclose(3):
Upon successful completion, 0 is returned. Otherwise, EOF is returned
and errno is set to indicate the error. In either case, any further
access (including another call to fclose()) to the stream results in
undefined behavior.
Fixes:
Error: USE_AFTER_FREE (CWE-672): [#def1]
libsemanage-3.2/src/direct_api.c:1023: freed_arg: "fclose" frees "fp".
libsemanage-3.2/src/direct_api.c:1034: use_closed_file: Calling "fclose" uses file handle "fp" after closing it.
# 1032|
# 1033| cleanup:
# 1034|-> if (fp != NULL) fclose(fp);
# 1035|
# 1036| return ret;
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
genhomedircon.c:742:67: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;;
^
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
The passing parameter "arg" of parse_module_store will be freed after
calling. A copy of parameter should be used instead of itself.
Signed-off-by: HuaxinLu <luhuaxin1@foxmail.com>
Acked-by: James Carter <jwcart2@gmail.com>
Commit 331a109f91 ("libsemanage: fsync final files before rename")
added fsync() for policy files and improved situation when something
unexpected happens right after rename(). However the module store could
be affected as well. After the following steps module files could be 0
size:
1. Run `semanage fcontext -a -t var_t "/tmp/abc"`
2. Force shutdown the server during the command is run, or right after
it's finished
3. Boot the system and look for empty files:
# find /var/lib/selinux/targeted/ -type f -size 0 | wc -l
1266
It looks like this situation can be avoided if the filesystem with the
sandbox is sync()ed before we start to rename() directories in the
store.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
This reverts commit ce46daab7c.
The behavior described in the reverted commit is correct. `useradd -Z`
creates new mapping between new created user and *unconfined_u*,
`genhomedircon` then uses this new mapping, not /etc/passwd entries, for
generating new homedir contexts.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
semanage_direct_remove allocates struct semanage_module_key_t on
stack, then calls semanage_module_key_set_name which allocates
modkey->name on heap, but modkey->name wasn't free()-d anywhere,
creating a small leak.
Signed-off-by: Jakub Hrozek <jhrozek@redhat.com>
Previous commits removed some symbols and broke ABI, therefore we need to change
SONAME.
See the following quotes from distribution guidelines:
https://www.debian.org/doc/debian-policy/ch-sharedlibs.html#run-time-shared-libraries
Every time the shared library ABI changes in a way that may break
binaries linked against older versions of the shared library, the SONAME
of the library and the corresponding name for the binary package
containing the runtime shared library should change.
https://docs.fedoraproject.org/en-US/packaging-guidelines/#_downstream_so_name_versioning
When new versions of the library are released, you should use an ABI
comparison tool to check for ABI differences in the built shared
libraries. If it detects any incompatibilities, bump the n number by
one.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
semanage_module_enable() and semanage_module_disable() were deprecated
by commit 9fbc6d1441 ("libsemanage: add back original module
enable/disable functions for ABI compatability") in 2014 in order to
preserve ABI compatibility. As we the libsemanage ABI is changed by the
previous commit, it makes sense to drop them completely.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Versioned duplicate symbols cause problems for LTO. These symbols were
introduced during the CIL integration several releases ago and were only
consumed by other SELinux userspace components.
Related: https://github.com/SELinuxProject/selinux/issues/245
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Prior to rename(2)'ing the final selinux policy files into place,
fsync(2) them to ensure the contents will be fully written prior to
rename. While we are here, also fix checking of write(2) to detect
short writes and treat them as an error. This code could be more
generally improved but keeping to the minimal changes required to fix
this bug.
Fixes: https://github.com/SELinuxProject/selinux/issues/237
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Replace
python3 -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])'
<string>:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
.cpython-38-x86_64-linux-gnu.so
with
python3 -c 'import importlib.machinery;print(importlib.machinery.EXTENSION_SUFFIXES[0])'
.cpython-38-x86_64-linux-gnu.so
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
This routine was never defined, just declared as a prototype.
Thus it never really existed, but remained in the map file.
Remove it.
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: William Roberts <william.c.roberts@intel.com>