a13xp0p0v / kernel-hardening-checker

A tool for checking the security hardening options of the Linux kernel
GNU General Public License v3.0
1.69k stars 156 forks source link

skip CONFIG_DEBUG_NOTIFIERS requirement when CONFIG_CFI_CLANG is set with CONFIG_CFI_PERMISSIVE disabled #99

Closed thestinger closed 10 months ago

thestinger commented 10 months ago

CONFIG_DEBUG_NOTIFIERS only checks that the notifier function pointer is in kernel text. CFI already does that for everything that's not excluded from it. CONFIG_DEBUG_NOTIFIERS is obsolete when using CFI, and there should be no clear reason to enable it.

thestinger commented 10 months ago

This is partly motivated by CONFIG_DEBUG_NOTIFIERS being buggy on some architectures. It works properly on x86 but we had issues with it on arm64 previously. It's the only user of func_ptr_is_kernel_text so there's little motivation for that function to work universally for such a niche feature that's no longer even useful if you use CFI. The whole feature is this:

#ifdef CONFIG_DEBUG_NOTIFIERS
        if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
            WARN(1, "Invalid notifier called!");
            nb = next_nb;
            continue;
        }
#endif
a13xp0p0v commented 10 months ago

@thestinger, thanks for the idea!

Added the commit https://github.com/a13xp0p0v/kernel-hardening-checker/commit/cd5bb8a0364e6a28b2d03a8ac0d7520194a9f07a.

a13xp0p0v commented 10 months ago

One moment, you are right, CFI_PERMISSIVE should be disabled as well.

a13xp0p0v commented 10 months ago

Added the commit https://github.com/a13xp0p0v/kernel-hardening-checker/commit/65ff79dbe2c36347283d71d3fa1959030bf6838f.

Now the verbose result for checking this config ...

# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_CFI_CLANG=y
CONFIG_CFI_PERMISSIVE=y

... looks like that:

-------------------------------------------------------------------------------------------------------------------------
    <<< OR >>>                                                                             | FAIL: "is not set"
CONFIG_DEBUG_NOTIFIERS                  |kconfig|     y      |   kspp   | self_protection  | FAIL: "is not set"
    <<< AND >>>                                                                            | FAIL: CONFIG_CFI_PERMISSIVE is not "is not set"
CONFIG_CFI_CLANG                        |kconfig|     y      |   kspp   | self_protection  | OK
CONFIG_CFI_PERMISSIVE                   |kconfig| is not set |   kspp   | self_protection  | FAIL: "y"
-------------------------------------------------------------------------------------------------------------------------

And the verbose result of checking this config...

# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_CFI_CLANG=y
# CONFIG_CFI_PERMISSIVE is not set

... looks like that:

-------------------------------------------------------------------------------------------------------------------------
    <<< OR >>>                                                                             | OK: CONFIG_CFI_CLANG is "y"
CONFIG_DEBUG_NOTIFIERS                  |kconfig|     y      |   kspp   | self_protection  | FAIL: "is not set"
    <<< AND >>>                                                                            | OK
CONFIG_CFI_CLANG                        |kconfig|     y      |   kspp   | self_protection  | OK
CONFIG_CFI_PERMISSIVE                   |kconfig| is not set |   kspp   | self_protection  | OK
-------------------------------------------------------------------------------------------------------------------------