When selinux_restorecon() is used to relabel symlinks, it performs the
following syscalls (as seen by running strace on restorecond):
lstat("/root/symlink", {st_mode=S_IFLNK|0777, st_size=6, ...}) = 0
statfs("/root/symlink", 0x7ffd6bb4d090) = -1 ENOENT (No such file or directory)
lstat("/root/symlink", {st_mode=S_IFLNK|0777, st_size=6, ...}) = 0
lgetxattr("/root/symlink", "security.selinux", "sysadm_u:object_r:user_home_t", 255) = 30
The second one triggers a SELinux check for lnk_file:read, as statfs()
dereferences symbolic links. This call to statfs() is only used to find
out whether "restoreconlast" xattr can be ignored, which is always the
case for non-directory files (the first syscall, lstat(), is actually
used to perform this check).
Skip the call to statfs() when setrestoreconlast is already false.
This silences an AVC denial that would otherwise be reported to
audit.log (cf. https://github.com/SELinuxProject/refpolicy/pull/22).
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Build with strict overflow checking enabled. If the compiler optimizes
code that could be removed due to undefined signed overflow, then the
compiler will issue a warning.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
Use -D_FO0RTIFY_SOURCE=2 when building libselinux and it's util library.
Note that this can be overridden by setting CFLAGS during the build.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
Certain builds of gcc enable _FORTIFY_SOURCE which results in the error:
<command-line>:0:0: warning: "_FORTIFY_SOURCE" redefined
<command-line>:0:0: note: this is the location of the previous definition
Correct this by undefining it first and redefining it. Also, the previous
command line option was using -Wp which is passing the value *AS IS* to the
pre-processor rather than to the compiler driver. The C pre-processor has
an undocumented interface subject to change per man 1 gcc. Just use the
-D option to specify this value.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
fc_count is defined as uint64_t, which needs to be printed with PRIu64
(it is "llu" on x86 and "lu" on x86-64). Otherwise, building with
'CC="gcc -m32"' fails with:
selinux_restorecon.c: In function ‘restorecon_sb’:
selinux_restorecon.c:633:26: error: format ‘%lu’ expects argument of
type ‘long unsigned int’, but argument 3 has type ‘uint64_t’ {aka
‘long long unsigned int’} [-Werror=format=]
fprintf(stdout, "\r%luk", fc_count / STAR_COUNT);
~~^
%llu
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
load_mmap and regex_load_mmap (in the !USE_PCRE2 case) were
incorrectly treating the absence of any fixed stems or study data
as an error, rejecting valid file_contexts.bin files. Remove
the extraneous validation checks.
Test:
$ cat > file_contexts <<EOF
(/.*)? u:object_r:system_file:s0
/lib u:object_r:system_dir:s0
EOF
$ sefcontext_compile file_contexts
$ selabel_lookup -b file -k /lib -f file_contexts.bin
Before:
ERROR: selabel_open - Could not obtain handle.
After:
Default context: u:object_r:system_dir:s0
Reported-by: Jiyong Park <jiyong@google.com>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
The __atomic_* GCC primitives were introduced in GCC 4.7, but Red Hat
Enterprise Linux 6.x (for example) provides GCC 4.4. Tweak the current code to
use the (most conservative) __sync_synchronize() primitive provided by those
older GCC versions.
Fixes https://github.com/SELinuxProject/selinux/issues/97
(Really, no __atomic or __sync operations are needed here at all, since POSIX
4.12 "Memory Synchronization" says pthread_mutex_lock() and
pthread_mutex_unlock() "synchronize memory with respect to other threads"...)
On systems using Python 3.7, when compiling libselinux Python wrappers
(with "make install-pywrap"), the following warning is reported by gcc:
audit2why.c: In function ‘analyze’:
audit2why.c:364:11: warning: assignment discards ‘const’ qualifier
from pointer target type [-Wdiscarded-qualifiers]
permstr = _PyUnicode_AsString( strObj );
^
Make permstr "const char *" in order to suppress this warning.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
flake8, a Python linter, complains:
libselinux/src/selinux.py💯1: F401 'errno' imported but unused
libselinux/src/selinux.py💯1: F401 'stat' imported but unused
libselinux/src/selinux.py💯14: E401 multiple imports on one line
libselinux/src/selinux.py:130:16: E111 indentation is not a multiple of four
libselinux/src/selinux.py:130:45: E231 missing whitespace after ','
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Musl libc does not include the fts(3) functions so need to link to the
musl-fts library
https://github.com/pullmoll/musl-fts
Signed-off-by: Jason Zaman <jason@perfinion.com>
Fix the following build warnings.
audit2why.c: In function ‘__policy_init’:
audit2why.c:207:22: warning: ‘%s’ directive output may be truncated writing up to 4095 bytes into a region of size 4081 [-Wformat-truncation=]
"unable to open %s: %s\n",
^~
path, strerror(errno));
~~~~
audit2why.c:206:4: note: ‘snprintf’ output 20 or more bytes (assuming 4115) into a destination of size 4096
snprintf(errormsg, sizeof(errormsg),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"unable to open %s: %s\n",
~~~~~~~~~~~~~~~~~~~~~~~~~~~
path, strerror(errno));
~~~~~~~~~~~~~~~~~~~~~~
audit2why.c:253:28: warning: ‘%s’ directive output may be truncated writing up to 4095 bytes into a region of size 4074 [-Wformat-truncation=]
"invalid binary policy %s\n", path);
^~ ~~~~
audit2why.c:252:3: note: ‘snprintf’ output between 24 and 4119 bytes into a destination of size 4096
snprintf(errormsg, sizeof(errormsg),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"invalid binary policy %s\n", path);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Fix the following warning in save_booleans(). We could likely drop
the function altogether, either ignoring or returning EINVAL if
a non-zero permanent argument is passed to security_set_boolean_list(),
since setting persistent booleans is now handled via libsemanage. This
code and the corresponding security_load_booleans() code is legacy from
RHEL4 days and could be removed although we would need to keep the ABI
for compatibility.
booleans.c: In function ‘save_booleans’:
booleans.c:441:13: error: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 8191 [-Werror=format-truncation=]
"%s=%d\n", boolname,
^~
booleans.c:440:7: note: ‘snprintf’ output between 4 and 8205 bytes into a destination of size 8192
snprintf(outbuf, sizeof(outbuf),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"%s=%d\n", boolname,
~~~~~~~~~~~~~~~~~~~~
boollist[i].value);
~~~~~~~~~~~~~~~~~~
booleans.c:454:12: error: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 8191 [-Werror=format-truncation=]
"%s=%d\n", boolname, val);
^~
booleans.c:453:6: note: ‘snprintf’ output between 4 and 8205 bytes into a destination of size 8192
snprintf(outbuf, sizeof(outbuf),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"%s=%d\n", boolname, val);
~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
This reverts commit 814631d3ae.
As reported by Petr Lautrbach, this commit changed the behavior
of selabel_open() when SELABEL_OPT_VALIDATE is 0, and this would
be an API change.
Reported-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
In getconlist.c's main(), "level" is duplicated from an optional
argument without being ever freed. clang's static analyzer warns about
this memory leak.
Free the allocated memory properly in order to remove a warning reported
by clang's static analyzer.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
If store_stem() fails to expand the memory allocated on data->stem_arr,
some things go wrong:
* the memory referenced by "buf" is leaked,
* data->alloc_stems has been increased without data->stem_arr having
been expanded. So the next time store_stem() is called, the function
will behave as if the buffer holds enough space, and will write data
after the end of data->stem_arr.
The first issue is being spotted by clang's static analyzer, which warns
about leaking variable "stem" in find_stem_from_spec() (this function
calls store_stem()).
This both issues by freeing buf when realloc(data->stem_arr) fails, and
by not increasing data->alloc_stems when this happens.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Keep track of line numbers for each file context in
selabel_handle. If an error occurs in selabel_fini(), the
line number of an invalid file context is echoed to the user.
Signed-off-by: Yuli Khodorkovskiy <ykhodo@gmail.com>
In permissive mode, calling restorecon with a bad label in file_contexts
does not verify the label's existence in the loaded policy. This
results in any label successfully applying to a file, as long as the
file exists.
This issue has two assumptions:
1) file_contexts must be manually updated with the invalid label.
Running `semanage fcontext` will error when attempting to add
an invalid label to file_contexts.
2) the system must be in permissive. Although applying an invalid label
in enforcing gives an error and fails, successfully labeling a file with a
bad label could cause issues during policy development in permissive.
Instead, as each context is used, verify it is valid before blindly
applying the label. If an error with validation occurs in restorecon,
application of remaining valid labels will be uninterrupted as before.
Signed-off-by: Yuli Khodorkovskiy <ykhodo@gmail.com>
libselinux and libsemanage Makefiles invoke site.getsitepackages() in
order to get the path to the directory /usr/lib/pythonX.Y/site-packages
that matches the Python interpreter chosen with $(PYTHON). This method
is incompatible with Python virtual environments, as described in
https://github.com/pypa/virtualenv/issues/355#issuecomment-10250452 .
This issue has been opened for more than 5 years.
On the contrary python/semanage/ and python/sepolgen/ Makefiles use
distutils.sysconfig.get_python_lib() in order to get the site-packages
path into a variable named PYTHONLIBDIR. This way of computing
PYTHONLIBDIR is compatible with virtual environments and gives the same
result as PYSITEDIR.
As PYTHONLIBDIR works in more cases than PYSITEDIR, make libselinux and
libsemanage Makefiles use it. And as native code is installed (as part
of the SWIG wrapper), use "plat_specific=1" in order to use /usr/lib64
on systems which distinguish /usr/lib64 from /usr/lib.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
This patch solves the following issues:
- The pkg-config files generates odd paths when using DESTDIR without PREFIX
- DESTDIR is needed during compile time to compute library and header paths which it should not.
- Installing with both DESTDIR and PREFIX set gives us odd paths
- Make usage of DESTDIR and PREFIX more standard
Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
The selabel_media(5) man page incorrectly stated that the
removable_context(5) would be read if an selabel_lookup(3)
failed. Correct the man pages that fixes [1].
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1395621
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
When libselinux is built using USE_PCRE2 libselinux.pc needs to require
libpcre2-8 instead of libpcre.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1487521
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
There are two problems with lookup_common() and therefore
selabel_lookup() and related functions that this patch fixes:
1) A race with the lazy compilation of regexes. Since the struct
regex_data is allocated and assigned immediately to the parent struct
spec, it's possible for a second thread to see that this pointer is
non-NULL before the regex compilation has finished. This typically
results in a -1 return from selabel_lookup() with ENOENT as errno.
This is fixed by adding synchronization in compile_regex().
2) A race with PCRE2 regex_match(). A struct pcre2_match_data is
created once and used for all regex matches for a given regex. This
is problematic if two threads are attempting to evaluate the same
regex simultaneously. This typically results in a successful return
from selabel_lookup() but with an erroneous selabel.
This is fixed by adding a pthread_mutex within regex_match() for
PCRE2. Note, on my system, creating new matchdata takes roughly an
order of magnitude more time than locking a non-contended
pthread_mutex. I don't believe programs will have enough contention
on this lock to justify that cost.
Bug: 63861738
Test: ueventd unit tests
Change-Id: I13bf782d81d0a0b896d444e396f307ad0dbacb6a
The RUBYLIBS definition introduced by commit f5b9bc2a06
("libselinux,libsemanage: link Ruby wrappers with -lruby") did
not work on Debian. Fix it based on a patch by Nicolas Iooss.
Reported-by: Laurent Bigonville <bigon@debian.org>
Suggested-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Two makefiles of ours pass `-D_FORTIFY_SOURCE=2` directly to the
preprocessor. While this does not pose any problems when the value has
not been previously set, it can break the build if it is part of the
standard build flags.
The issue can easily be fixed by instead defining `_FORTIFY_SOURCE`
without specifying a concrete value. In this case, gcc will not error
out and simply keep using the previously defined value. On the other
hand, if no value has been defined, we will now compile with
`_FORTIFY_SOURCE=1`. From feature_test_macros(7):
If _FORTIFY_SOURCE is set to 1, with compiler optimization level 1
(gcc -O1) and above, checks that shouldn't change the behavior of
conforming programs are performed. With _FORTIFY_SOURCE set to 2,
some more checking is added, but some conforming programs might
fail.
While this leaves us with less checks for buffer overflows, it will only
enable checks that should not change behaviour of conforming programs.
With _FORTIFY_SOURCE=2, the compiler may even unintentionally change
behaviour of conforming programs. So in fact, one could even argue that
we should only be setting the value to 1 anyway to avoid surprising side
effects.
So this patch changes our CFLAGS to only pass `-D_FORTIFY_SOURCE`
without any concrete value, fixing the build issue.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
As reported by Nicolas Iooss, there are still some inconsistencies
in the definitions and usage of Makefile variables related to bin
and sbin directories. Since we need to still support non-usrmerge
systems, we cannot completely synchronize them, but we can eliminate
unnecessary differences, remove unused variables, and drop the
USRSBINDIR variables.
Before:
$ find . -name Makefile -exec cat {} + |grep '^[A-Z_]*BINDIR' |sort -u
BINDIR=$(PREFIX)/bin
BINDIR ?= $(PREFIX)/bin
BINDIR ?= $(PREFIX)/sbin
SBINDIR ?= $(DESTDIR)/sbin
SBINDIR ?= $(PREFIX)/sbin
USRSBINDIR ?= $(PREFIX)/sbin
After:
$ find . -name Makefile -exec cat {} + | grep '^[A-Z_]*BINDIR' | sort -u
BINDIR ?= $(PREFIX)/bin
SBINDIR ?= $(DESTDIR)/sbin
SBINDIR ?= $(PREFIX)/sbin
This does not change the actual install location of any file.
It does drop the legacy symlink from /usr/sbin/load_policy to
/sbin/load_policy; packagers can create that separately if
desired.
Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
the utils dir link to libselinux.so which was just built, if LDFLAGS or
LDLIBS were specificed on the make commandline then the search path is
not appended. Add the override directive to fix this.
Gentoo-Bug: https://bugs.gentoo.org/621762
Signed-off-by: Jason Zaman <jason@perfinion.com>
As reported in:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=864479
using a kernel configuration with CONFIG_SECURITY_SELINUX_DISABLE=n
and a /etc/selinux/config with SELINUX=disabled leads to a boot
failure.
Fix this by always unmounting selinuxfs if /etc/selinux/config has
SELINUX=disabled even if unable to successfully disable SELinux.
This will ensure that subsequent is_selinux_enabled() tests will
return 0 (disabled) and userspace will therefore skip any SELinux
processing.
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Reported-by: Laurent Bigonville <bigon@debian.org>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
As originally reported in
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863854
, "systemd-hwdb --usr update" was assigning /lib/udev/hwdb.bin the
wrong security context. This turned out to be a result of systemd-hwdb
calling selabel_lookup_raw() with a path with a leading double slash
(//lib/udev/hwdb.bin). While the selabel file backend already removes
duplicate slashes, this was occurring after any substitution matching
and replacement had occurred in the generic selabel frontend, and thus
the double slash was still preventing the /lib -> /usr/lib substitution
specified by file_contexts.subs_dist from occurring. As a consequence,
the final path (/lib/udev/hwdb.bin) used to look up did not match the
/usr/lib/udev/[^/]* entry in file_contexts.
There were two options for resolving:
1) move the double slash removal to the selabel frontend code before
substitutions, or
2) move the substitution processing to the selabel file backend code
after double slash removal.
Since substitutions are currently only supported for the file backend,
and since the slash character may have no particular meaning in the
keys for other backends, it seems more correct to do the latter.
This has the advantage of taking all of the substitution data
structures and code private to the selabel file backend.
Test case:
Compare the output of:
selabel_lookup -r -b file -k //lib/udev/hwdb.bin
versus:
selabel_lookup -r -b file -k /lib/udev/hwdb.bin
Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863854
Reported-by: Russell Coker <russell@coker.com.au>
Reported-by: Michael Biebl <biebl@debian.org>
Reported-by: Laurent Bigonville <bigon@debian.org>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
when building packages (e.g. for openSUSE Linux)
(random) filesystem order of input files
influences ordering of functions in the output,
thus without the patch, builds (in disposable VMs) would usually differ.
See https://reproducible-builds.org/ for why this matters.
https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/
Fixes the following warnings by annotating with a /* FALLTHRU */ comment.
Unfortunately, the __attribute__ ((fallthrough)); approach does not appear
to work with older compilers.
../cil/src/cil_parser.c: In function ‘cil_parser’:
../cil/src/cil_parser.c:253:14: warning: this statement may fall through [-Wimplicit-fallthrough=]
tok.value = tok.value+1;
~~~~~~~~~~^~~~~~~~~~~~~
../cil/src/cil_parser.c:254:3: note: here
case SYMBOL:
^~~~
../cil/src/cil_parser.c:275:7: warning: this statement may fall through [-Wimplicit-fallthrough=]
if (tok.type != END_OF_FILE) {
^
../cil/src/cil_parser.c:279:3: note: here
case END_OF_FILE:
^~~~
../cil/src/cil_post.c: In function ‘cil_post_fc_fill_data’:
../cil/src/cil_post.c:104:5: warning: this statement may fall through [-Wimplicit-fallthrough=]
c++;
~^~
../cil/src/cil_post.c:105:3: note: here
default:
^~~~~~~
regex.c: In function ‘regex_format_error’:
regex.c:541:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:542:2: note: here
case 3:
^~~~
regex.c:543:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:544:2: note: here
case 2:
^~~~
regex.c:545:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:546:2: note: here
case 1:
^~~~
regex.c: In function ‘regex_format_error’:
regex.c:541:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:542:2: note: here
case 3:
^~~~
regex.c:543:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:544:2: note: here
case 2:
^~~~
regex.c:545:10: warning: this statement may fall through [-Wimplicit-fallthrough=]
*ptr++ = '.';
~~~~~~~^~~~~
regex.c:546:2: note: here
case 1:
^~~~
modules.c: In function ‘semanage_module_get_path’:
modules.c:602:7: warning: this statement may fall through [-Wimplicit-fallthrough=]
if (file == NULL) file = "hll";
^
modules.c:603:3: note: here
case SEMANAGE_MODULE_PATH_CIL:
^~~~
modules.c:604:7: warning: this statement may fall through [-Wimplicit-fallthrough=]
if (file == NULL) file = "cil";
^
modules.c:605:3: note: here
case SEMANAGE_MODULE_PATH_LANG_EXT:
^~~~
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Memory allocation failures in selabel_subs_init() should be fatal,
contrary to failures which come from the non-existence of the
substitution files (subs or subs_dist).
Modify selabel_subs_init()'s prototype in order to return the error
state. This forces the pointer to the created substitution list to be
moved to an output function argument.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
In selabel_subs_init(), when digest_add_specfile() fails, the returned
value is a pointer to data which has been freed (because label "err"
frees variable "sub" which is equals to the returned variable, "list").
Moreover since since commit fd56c5230c ("Separate out the calling of
local subs and dist subs in selabel_sub"), argument "list" of
selabel_subs_init() has always been NULL (rec->subs and rec->dist_subs
are both initialized to NULL in selabel_open() before
selabel_file_init() is called).
Drop selabel_file_init()'s "list" argument and free all the list items
which have been allocated in this function, when the code encounters an
error.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>