Latest SELinux changes:
59bed0a813
introduced two SELinux problems on kernels < 4.17. First, LKRG won't compile
on such kernels due to function name mismatch. However, even if this would be
fixed there is another issue in the same function. Instead of overwriting the
value of SELinux state itself, the code was overwriting pointer. The second bug
could never be triggered because of the first bug failing LKRG compilation for
such kernels.
This commit fixes both problems and addresses #60
Use mkosi to test full system boot with LKRG module loaded early in
initrd. mkosi creates system disk image (quite slow, 5 minutes for
ubuntu focal in my tests, and size is 1.3G), builds lkrg there (using
systemd-nspawn), and finally boots it in qemu. Then we grep boot.log
for possible problems.
Ubuntu is chosen, because it's native to GA. Only successful (for the
test) releases are 'focal' and 'groovy'. It seems mkosi does not support
'hirsute' (yet, failure installing packages into image). Also, 'bionic'
does not build lkrg properly, but mkosi works good. Older Ubuntu seems
to not have systemd, which is a hard mkosi requirement.
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
mkosi is systemd's boot test tool. This support is mainly for GA CI
to implement full boot tests (on Ubuntu). But, this would be useful
on it's own for experiments with lkrg on all mkosi supported distros.
I support only bios (grub) BootProtocol without unified kernel.
- .gitignore updated to exclude mkosi artifacts (otherwise they could
recursively go into created image causing disk full error).
- mkosi.default is mkosi config pre-configured for ubuntu focal, you can
overwrite this with command line options.
- mkosi.build is script to build lkrg and install it into DESTDIR.
- mkosi.postinst hook updates initrd to include and insmod lkrg and
grub to remove 'quiet' cmdline option.
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Made a few minor changes, particularly to punctuation, but also to word
choice and word flow. For example, "might or might not" is more
uncomfortable to say and read than "may or may not" as the ending "t"
requires a stop. I believe these changes **may** (heh) increase readability
marginally. I also did not go through and check the commands and their
descriptions.
New Linux kernels may be built with the CONFIG_GCC_PLUGIN_RANDSTRUCT
option. This randomly changes the order of fields in certain structures,
including selinux_state. Currently, LKRG isn't capable to recreate the
structure layout. Thus, we have to disable LKRG's SELinux monitoring on
kernels built with this option.
CONFIG_GCC_PLUGIN_RANDSTRUCT was introduced to make it harder for attackers
to overwrite particular fields of structures. LKRG's goal was the same.
So even disabling LKRG's monitoring, we still have some mitigations for
SELinux state overwrites.
We might make LKRG capable to recreate randomized structures in the future.
Starting with Linux 5.6 a new kernel configuration option was
introduced: CONFIG_SECURITY_SELINUX_DISABLE.
Reflect in LKRG selinux_struct that the SELinux "disabled"
field is optional for these newer kernels.
As pointed out by Solar Designer, git is somewhat non-germaine to
the script as it's really part of an external workflow replicated
across out-of-tree repos used by Semper Victus for the trees which
we maintain in-house. The meat of the function in ths script puts
data into the right places within a kernel tree, with the commit
semantics being an ancillary function.
Make all of the git operations optional by enclosing them in tests
for the existence of the LKRG_USE_GIT variable.
Since Linux kernel 5.7 SYSCALL_WRAPPER's magic was backported to x86 (32
bits) as well. This commit bring the support for it.
However, regardless of the SYSCALL_WRAPPER's magic LKRG was broken on IA-32
and this commit "resurrects" such support. It also addresses #49 and #46
We do not want to support RT kernels (at least not for now). RT kernels are
commonly used in medical and similar devices, where reliability is crucial.
It is safer to to not support RT kernels in LKRG for now.
For more information please read entire discussion at #40.
Regardless of the fix for #47 (156d2bab39),
LOCKDEP might still report warning messages. This commit silnce them on
non-debug build. If P_LKRG_DEBUG_BUILD is enabled, such information will
be still available.
If kernel is compiled with CONFIG_OPTPROBES we must synchronize with kprobe
optimizer during the process of creating database. LKRG places many
kretprobes which modifies .text section. In the standard scenario after
placing the kprobes, LKRG can safely calculate the hash of all .text
sections. However, if CONFIG_OPTPROBES is enabled, placed kprobes could be
optimized. Optimization modifies .text seciton by converting kprobes into
FTRACE which using different hooking mechanism. If LKRG is in the process
of building the hash database and optimizer is running parallel, at least
we could have FP and at most deadlock.
This fix addresses described issue and reported bug #47
Since kernel 5.8+ 'native_write_cr4' must be manually resolved. However, this is X86 specific code which should nbot be executed on other platforms. This commit fixes that and addresses #48
Some custom compilation of the kernel might aggresively inline critical
functions (from LKRG perspective). That's problematic for the project.
However, some of the problems *might* be solved by uncommenting this new
definition (P_KERNEL_AGGRESSIVE_INLINING). Unfortunately, not all of the
problems can be solved by it (at least no for now). You need to experiment.
This can be useful to address issues like #40
security_bprm_committed_creds does not return any value (void). LKRG's old
logic for handling exec* family verified return code. This is an incorrect
behavior for the current design. Fix it.
Since kernel 5.8 function search_binary_handler is not exported anymore.
On the aggressively optimized kernels it is possible that
`search_binary_handler` can be inlined. However, GCC can splits the
function to put the big part in its own function, which receives as a name
the original function name plus .part + .<some number>, and inlines the
rest in other functions.
This is a very problematic behavior from the LKRG point of view and was
reported as #41 and #45. This commit fixes the problem by replacing the
'search_binary_handler' (or 'do_execveat_common') hook with
security_bprm_committing_creds and security_bprm_committed_creds.
Additionally, this change is desired from the security point of view.
On the aggressively optimized kernels it is possible that kprobe optimizer
won't be fast enough to do the job before LKRG creates own database. This
is problematic because LKRG might snapshot hash of the kernel's .text
section with non-optimized own hooks. As soon as the kprobe optimizer
finishes the job, previously snapshoted hash won't be correct and LKRG will
detect this inconsistency.
To be able to correctly solve this unusual corner case problem, LKRG can
wait for kprobe optimizer before creating database.
We switched to using late_initcall_sync() in order to have LKRG initialize
sufficiently late when it's linked into the kernel. That change was a
no-op when building/loading LKRG as a module on recent kernels, because
their module.h defines late_initcall_sync() as an alias for module_init().
However, it broke LKRG on some older kernels, where late_initcall_sync()
wasn't defined for modules at all.
This commit fixes that by explicitly using module_init() when building LKRG
as a module. This change is a no-op on recent kernels.
Fixes#37, updates ddc14c6544
There are unofficial versions of RANDKSTACK patches floating about
the web, including in VMWare's PhotonOS.
The randomized stack addresses conflict with LKRG's ADDR_LIMIT
checks a la:
```
[ 195.272462] [p_lkrg] <Exploit Detection> Detected ADDR_LIMIT
segment corruption! process[552 | sysctl] has different segment
address! [7ffffffff000 vs ffffffffffffffff]
```
Address this by ensuring that P_VERIFY_ADDR_LIMIT does not get
defined when CONFIG_PAX_RANDKSTACK is enabled.
This is a strange edge-case, and normally wouldn't be submitted as
a pull request to upstream projects, except that users seeking to
harden their kernels with public code are likely to run across
LKRG and some links to the PhotonOS patches or similar extracts
from Grsecurity's old patchsets. The commit is a no-op in 99% of
cases, but may result in one less bug report over the next decade.
Based on #40 it looks like some people compile the kernel with
CONFIG_FTRACE and CONFIG_FUNCTION_TRACER but don't enable
CONFIG_DYNAMIC_FTRACE. Let's try to check that in this commit.
Since kernel 5.11, on x86(-64) architecture TIF_SECCOMP flag is not used
anymore to track SECCOMP state per thread. This commit updates the code
accordingly