Print error description on failure after functions known to set errno.
Also mention the library function name in getenforce, policyvers and
setenforce instead of the program name twice.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
selinux_log() is used in many error branches, where the caller might
expect errno to bet set, e.g. label_file.c::lookup_all():
if (match_count) {
*match_count = 0;
result = calloc(data->nspec, sizeof(struct spec*));
} else {
result = calloc(1, sizeof(struct spec*));
}
if (!result) {
selinux_log(SELINUX_ERROR, "Failed to allocate %zu bytes of data\n",
data->nspec * sizeof(struct spec*));
goto finish;
}
Preserve errno in the macro wrapper itself, also preventing accidental
errno modifications in client specified SELINUX_CB_LOG callbacks.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
In case the allocation for the filename fails, free the memory of the context.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
Pin the file to operate on in restorecon_sb() to prevent symlink attacks
in between the label database lookup, the current context query and the
final context write. Also don't use the file information from
fts_read(3), which might also be out of sync.
Due to querying file information twice, one in fts_read(3) needed for
the cross device check and one on the pinned file descriptor for the
database lookup, there is a slight slowdown:
[current]
Time (mean ± σ): 14.456 s ± 0.306 s [User: 45.863 s, System: 4.463 s]
Range (min … max): 14.275 s … 15.294 s 10 runs
[changed]
Time (mean ± σ): 15.843 s ± 0.045 s [User: 46.274 s, System: 9.495 s]
Range (min … max): 15.787 s … 15.916 s 10 runs
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
selabel_lookup_raw(3) can fail for other reasons than no corresponding
context found, e.g. ENOMEM or EINVAL for invalid key or type.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
* mark read-only parameters const
* check for overflow when adding exclude directory
* use 64 bit integer for file counting
* avoid implicit conversions
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
Operating on a file descriptor avoids TOCTOU issues and one opened via
O_PATH avoids the requirement of having read access to the file. Since
Linux does not natively support file descriptors opened via O_PATH in
fgetxattr(2) and at least glibc and musl does not emulate O_PATH support
in their implementations, fgetfilecon(3) and fsetfilecon(3) also do not
currently support file descriptors opened with O_PATH.
Inspired by CVE-2013-4392: https://github.com/systemd/systemd/pull/8583
Implementation adapted from: 2825f10b7f%5E%21/
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
Currently, if the SELINUX_RESTORECON_ABORT_ON_ERROR flag is clear, then
selinux_restorecon[_parallel]() does not abort the file tree walk upon an
error, but the function itself fails the same, with the same (-1) return
value. This in turn is reported by the setfiles(8) utility to its parent
process with the same exit code (255).
In libguestfs we want to proceed after setfiles(8) fails *at most* with
such errors that occur during the file tree walk. We need setfiles(8) to
exit with a distinct exit status in that situation.
For this, introduce the SELINUX_RESTORECON_COUNT_ERRORS flag, and the
corresponding selinux_restorecon_get_skipped_errors() function, for
selinux_restorecon[_parallel]() to count, but otherwise ignore, errors
during the file tree walk. When no other kind of error occurs, the
relabeling functions will return zero, and the caller can fetch the number
of errors ignored during the file tree walk with
selinux_restorecon_get_skipped_errors().
Importantly, when at least one such error is skipped, we don't write
partial match digests for subdirectories, as any masked error means that
any subdirectory may not have been completely relabeled.
Cc: "Richard W.M. Jones" <rjones@redhat.com>
Cc: Petr Lautrbach <plautrba@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1794518
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
The internal Sha1Update() functions only handles buffers up to a size of
UINT32_MAX, due to its usage of the type uint32_t. This causes issues
when processing more than UINT32_MAX bytes, e.g. with a specfile larger
than 4G. 0aa974a4 ("libselinux: limit has buffer size") tried to
address this issue, but failed since the overflow check
if (digest->hashbuf_size + buf_len < digest->hashbuf_size) {
will be done in the widest common type, which is size_t, the type of
`buf_len`.
Revert the type of `hashbuf_size` to size_t and instead process the data
in blocks of supported size.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Reverts: 0aa974a4 ("libselinux: limit has buffer size")
If selabel_open(3) fails, e.g. when a specfile has the wrong file
permissions, free the memory allocated for digests.
Fixes: e40bbea9 ("libselinux: Add selabel_digest function")
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
selabel_open(3) takes an `unsigned int` as backend parameter.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The `struct selabel_digest` member `hashbuf_size` is used to compute
hashes via `Sha1Update()`, which takes uint32_t as length parameter
type. Use that same type for `hashbuf_size` to avoid potential value
truncations, as the overflow check in `digest_add_specfile()` on
`hashbuf_size` is based on it.
label_support.c: In function ‘digest_gen_hash’:
label_support.c:125:53: warning: conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘uint32_t’ {aka ‘unsigned int’} may change value [-Wconversion]
125 | Sha1Update(&context, digest->hashbuf, digest->hashbuf_size);
| ~~~~~~^~~~~~~~~~~~~~
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Return more detailed error messages when the supplied contexts are
invalid.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Spaces before values in /etc/selinux/config should be ignored just as
spaces after them are.
E.g. "SELINUXTYPE= targeted" should be a valid value.
Fixes:
# sed -i 's/^SELINUXTYPE=/SELINUXTYPE= /g' /etc/selinux/config
# dnf install <any_package>
...
RPM: error: selabel_open: (/etc/selinux/ targeted/contexts/files/file_contexts) No such file or directory
RPM: error: Plugin selinux: hook tsm_pre failed
...
Error: Could not run transaction.
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
Quoting pcre.org:
There are two major versions of the PCRE library. The current
version, PCRE2, released in 2015, is now at version 10.39.
The older, but still widely deployed PCRE library, originally
released in 1997, is at version 8.45. This version of PCRE is now at
end of life, and is no longer being actively maintained. Version
8.45 is expected to be the final release of the older PCRE library,
and new projects should use PCRE2 instead.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
selinux_restorecon_parallel was originally proposed before 3.3, but it
was merged after release so it will be introduced in version 3.4.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
Refactor selinux_restorecon(3) to allow for distributing the relabeling
to multiple threads and add a new function
selinux_restorecon_parallel(3), which allows specifying the number of
threads to use. The existing selinux_restorecon(3) function maintains
the same interface and maintains the same behavior (i.e. relabeling is
done on a single thread).
The parallel implementation takes a simple approach of performing all
the directory tree traversal in a critical section and only letting the
relabeling of individual objects run in parallel. Thankfully, this
approach turns out to be efficient enough in practice, as shown by
restorecon benchmarks (detailed in a subsequent patch that switches
setfiles & restorecon to use selinux_restorecon_parallel(3)).
Note that to be able to use the parallelism, the calling application/
library must be explicitly linked to the libpthread library (statically
or dynamically). This is necessary to mantain the requirement that
libselinux shouldn't explicitly link with libpthread. (I don't know what
exactly was the reason behind this requirement as the commit logs are
fuzzy, but special care has been taken in the past to maintain it, so I
didn't want to break it...)
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Use the __selinux_once() macro to ensure that threads don't race to
initialize the list of customizable types.
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Tested-by: Christian Göttsche <cgzones@googlemail.com>
Ensure that selinux_log() is thread-safe by guarding the call to the
underlying callback with a mutex.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Not very useful on its own, but will allow to implement a parallel
version of selinux_restorecon() in subsequent patches.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
The 'matches' member of 'struct spec' may be written to by different
threads, so it needs to be accessed using the proper atomic constructs.
Since the actual count of matches doesn't matter and is not used,
convert this field to a bool and just atomically set/read it using GCC
__atomic builtins (which are already being used in another place).
If the compiler lacks support for __atomic builtins (which seem to have
been introduced in GCC 4.1), just fail the compilation. I don't think
it's worth tryin to invent a workaround to support a 15 years old
compiler.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Glibc 2.34 added an access function attribute to pthread_setspecific(3).
This leads to the following GCC warnings:
In file included from matchpathcon.c:5:
matchpathcon.c: In function ‘matchpathcon_init_prefix’:
selinux_internal.h:38:25: error: ‘pthread_setspecific’ expecting 1 byte in a region of size 0 [-Werror=stringop-overread]
38 | pthread_setspecific(KEY, VALUE); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
matchpathcon.c:359:9: note: in expansion of macro ‘__selinux_setspecific’
359 | __selinux_setspecific(destructor_key, (void *)1);
| ^~~~~~~~~~~~~~~~~~~~~
In file included from selinux_internal.h:2,
from matchpathcon.c:5:
/usr/include/pthread.h:1167:12: note: in a call to function ‘pthread_setspecific’ declared with attribute ‘access (none, 2)’
1167 | extern int pthread_setspecific (pthread_key_t __key,
| ^~~~~~~~~~~~~~~~~~~
The actual value and the validity of the passed pointer is irrelevant,
since it does not gets accessed internally by glibc and
pthread_getspecific(3) is not used.
Use a pointer to a global object to please GCC.
Closes: https://github.com/SELinuxProject/selinux/issues/311
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
An expression of the form "1 << x" is undefined if x == 31 because
the "1" is an int and cannot be left shifted by 31.
Instead, use "UINT32_C(1) << x" which will be an unsigned int of
at least 32 bits.
Signed-off-by: James Carter <jwcart2@gmail.com>
The extra dependency of sefcontext_compile on its object file causes the
compile and link step to be separated.
During the link step the CFLAGS are not passed, which might contain
optimization or sanitizer flags.
Reorder the LDLIBS requirements to avoid the symbol 'pcre_fullinfo'
being unresolvable at link time.
Current behavior:
gcc-11 **custom CFLAGS** -I../include -D_GNU_SOURCE -c -o sefcontext_compile.o sefcontext_compile.c
gcc-11 -L../src sefcontext_compile.o ../src/regex.o -lselinux -lpcre ../src/libselinux.a -lsepol -o sefcontext_compile
Changed:
gcc-11 **custom CFLAGS** -I../include -D_GNU_SOURCE -L../src sefcontext_compile.c -lselinux ../src/libselinux.a -lpcre -lsepol -o sefcontext_compile
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The standard function `strerror(3)` is not thread safe. This does not
only affect the concurrent usage of libselinux itself but also with
other `strerror(3)` linked libraries.
Use the thread safe GNU extension format specifier `%m`[1].
libselinux already uses the GNU extension format specifier `%ms`.
[1]: https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
sha1.c:90:21: error: empty expression statement has no effect;
remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
^
In file included from selinux_restorecon.c:39:
./label_file.h:458:15: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
lineno);
^
Introduce "do { } while (0)" blocks to silence such warnings.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Fix the following build failure with gcc 4.8 which is raised since
version 3.2 and
156dd0de5c
getseuser.c:53:2: error: 'for' loop initial declarations are only allowed in C99 mode
for (int i = 0; i < n; i++)
^
Fixes:
- http://autobuild.buildroot.org/results/37eb0952a763256fbf6ef3c668f6c95fbdf2dd35
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Using mount flag `nosuid` also affects SELinux domain transitions but
this has not been documented well.
Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
Improve formatting of section DESCRIPTION by adding list points.
Mention errno is set on failure.
Mention the returned context might be NULL if SELinux is not enabled.
Align setcon/_raw parameter by adding const.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
In case of a recurring call to `selinux_status_open(3)`, which
previously has been opened in fallback mode, return `1` according to its
documentation.
Fixes: c5a699046f ("libselinux: make selinux_status_open(3) reentrant")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
Currently `avc_init_internal()`, called by `avc_open(3)` and
`avc_init(3)`, does open the SELinux status page with fallback mode
enabled.
Quote from man:selinux_status_open(3):
In this case, this function tries to open a netlink socket using
.BR avc_netlink_open (3) and overwrite corresponding callbacks
(setenforce and policyload). Thus, we need to pay attention to the
interaction with these interfaces, when fallback mode is enabled.
Calling `selinux_status_open` internally in fallback mode is bad, cause
it overrides callbacks from client applications or the internal
fallback-callbacks get overridden by client applications.
Note that `avc_open(3)` gets called under the hood by
`selinux_check_access(3)` without checking for failure.
Also the status page is available since Linux 2.6.37, so failures of
`selinux_status_open(3)` in non-fallback mode should only be caused by
policies not allowing the client process to open/read/map
the /sys/fs/selinux/status file.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Do not mmap the status page again if `selinux_status_open(3)` has already
been called with success.
`selinux_status_open(3)` might be called unintentionally multiple times,
e.g. once to manually be able to call `selinux_status_getenforce(3)` and
once indirectly through `selinux_check_access(3)`
(since libselinux 3.2).
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Mention in the manpage of avc_destroy(3) that it does close the SELinux
status page, which might have been opened manually by the client
application.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Found by clang-tidy.
libselinux/src/label_file.c:374:4: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
else
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Found by clang-tidy.
libselinux/src/avc_sidtab.h:32:6: warning: function 'sidtab_sid_stats' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]
void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) ;
^
libselinux/src/avc_sidtab.c:103:6: note: the definition seen here
void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
^
libselinux/src/avc_sidtab.h:32:6: note: differing parameters are named here: ('s'), in definition: ('h')
void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) ;
^ ~
h
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Open the file stream with the `e` flag, so that the underlying file
descriptor gets closed on an exec in a potential sibling thread.
Also drop the flag `b`, since it is ignored on POSIX systems.
Found by clang-tidy.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>