Merge tag 'hardening-v6.2-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Dec 2022 20:00:24 +0000 (12:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Dec 2022 20:00:24 +0000 (12:00 -0800)
Pull kernel hardening fixes from Kees Cook:

 - Fix CFI failure with KASAN (Sami Tolvanen)

 - Fix LKDTM + CFI under GCC 7 and 8 (Kristina Martsenko)

 - Limit CONFIG_ZERO_CALL_USED_REGS to Clang > 15.0.6 (Nathan
   Chancellor)

 - Ignore "contents" argument in LoadPin's LSM hook handling

 - Fix paste-o in /sys/kernel/warn_count API docs

 - Use READ_ONCE() consistently for oops/warn limit reading

* tag 'hardening-v6.2-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  cfi: Fix CFI failure with KASAN
  exit: Use READ_ONCE() for all oops/warn limit reads
  security: Restrict CONFIG_ZERO_CALL_USED_REGS to gcc or clang > 15.0.6
  lkdtm: cfi: Make PAC test work with GCC 7 and 8
  docs: Fix path paste-o for /sys/kernel/warn_count
  LoadPin: Ignore the "contents" argument of the LSM hooks

Documentation/ABI/testing/sysfs-kernel-warn_count
drivers/misc/lkdtm/cfi.c
kernel/Makefile
kernel/exit.c
kernel/panic.c
security/Kconfig.hardening
security/loadpin/loadpin.c

index 08f083d2fd51bf59bd8a6b8dd4abe77af3be6a35..90a029813717dc5d327df120815b57a7eba6e113 100644 (file)
@@ -1,4 +1,4 @@
-What:          /sys/kernel/oops_count
+What:          /sys/kernel/warn_count
 Date:          November 2022
 KernelVersion: 6.2.0
 Contact:       Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
index 5245cf6013c95560af1434bc04dd312cffa71075..fc28714ae3a610e44c361e8c608a70148fe02f91 100644 (file)
@@ -54,7 +54,11 @@ static void lkdtm_CFI_FORWARD_PROTO(void)
 # ifdef CONFIG_ARM64_BTI_KERNEL
 #  define __no_pac             "branch-protection=bti"
 # else
-#  define __no_pac             "branch-protection=none"
+#  ifdef CONFIG_CC_HAS_BRANCH_PROT_PAC_RET
+#   define __no_pac            "branch-protection=none"
+#  else
+#   define __no_pac            "sign-return-address=none"
+#  endif
 # endif
 # define __no_ret_protection   __noscs __attribute__((__target__(__no_pac)))
 #else
index e7fc37a6806979f07b63cf624829aa517d937c36..10ef068f598d5db37a00f951f057c90b61e04326 100644 (file)
@@ -41,9 +41,6 @@ UBSAN_SANITIZE_kcov.o := n
 KMSAN_SANITIZE_kcov.o := n
 CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack) -fno-stack-protector
 
-# Don't instrument error handlers
-CFLAGS_REMOVE_cfi.o := $(CC_FLAGS_CFI)
-
 obj-y += sched/
 obj-y += locking/
 obj-y += power/
index deffb8e4b1b242d2cd7b7322f8a7e854f78676ee..15dc2ec80c46729299f4b2c13ee4df8453d6a745 100644 (file)
@@ -931,6 +931,7 @@ void __noreturn make_task_dead(int signr)
         * Then do everything else.
         */
        struct task_struct *tsk = current;
+       unsigned int limit;
 
        if (unlikely(in_interrupt()))
                panic("Aiee, killing interrupt handler!");
@@ -954,8 +955,9 @@ void __noreturn make_task_dead(int signr)
         * To make sure this can't happen, place an upper bound on how often the
         * kernel may oops without panic().
         */
-       if (atomic_inc_return(&oops_count) >= READ_ONCE(oops_limit) && oops_limit)
-               panic("Oopsed too often (kernel.oops_limit is %d)", oops_limit);
+       limit = READ_ONCE(oops_limit);
+       if (atomic_inc_return(&oops_count) >= limit && limit)
+               panic("Oopsed too often (kernel.oops_limit is %d)", limit);
 
        /*
         * We're taking recursive faults here in make_task_dead. Safest is to just
index 326d91505f04d6a6c32845f178238ff144610547..463c9295bc28a69b0fa3d32ee24c724010c1afb9 100644 (file)
@@ -232,12 +232,15 @@ static void panic_print_sys_info(bool console_flush)
 
 void check_panic_on_warn(const char *origin)
 {
+       unsigned int limit;
+
        if (panic_on_warn)
                panic("%s: panic_on_warn set ...\n", origin);
 
-       if (atomic_inc_return(&warn_count) >= READ_ONCE(warn_limit) && warn_limit)
+       limit = READ_ONCE(warn_limit);
+       if (atomic_inc_return(&warn_count) >= limit && limit)
                panic("%s: system warned too often (kernel.warn_limit is %d)",
-                     origin, warn_limit);
+                     origin, limit);
 }
 
 /**
index d766b7d0ffd138592862e9706413ac584ee990da..53baa95cb644fd047ff790526f501ffc89d1753e 100644 (file)
@@ -257,6 +257,9 @@ config INIT_ON_FREE_DEFAULT_ON
 
 config CC_HAS_ZERO_CALL_USED_REGS
        def_bool $(cc-option,-fzero-call-used-regs=used-gpr)
+       # https://github.com/ClangBuiltLinux/linux/issues/1766
+       # https://github.com/llvm/llvm-project/issues/59242
+       depends on !CC_IS_CLANG || CLANG_VERSION > 150006
 
 config ZERO_CALL_USED_REGS
        bool "Enable register zeroing on function exit"
index de41621f4998e37fcdce46c1fba88e458e8fd9c8..110a5ab2b46bceff5d68eb78600beeae1b486fa5 100644 (file)
@@ -122,21 +122,11 @@ static void loadpin_sb_free_security(struct super_block *mnt_sb)
        }
 }
 
-static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
-                            bool contents)
+static int loadpin_check(struct file *file, enum kernel_read_file_id id)
 {
        struct super_block *load_root;
        const char *origin = kernel_read_file_id_str(id);
 
-       /*
-        * If we will not know that we'll be seeing the full contents
-        * then we cannot trust a load will be complete and unchanged
-        * off disk. Treat all contents=false hooks as if there were
-        * no associated file struct.
-        */
-       if (!contents)
-               file = NULL;
-
        /* If the file id is excluded, ignore the pinning. */
        if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
            ignore_read_file_id[id]) {
@@ -192,9 +182,25 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
        return 0;
 }
 
+static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
+                            bool contents)
+{
+       /*
+        * LoadPin only cares about the _origin_ of a file, not its
+        * contents, so we can ignore the "are full contents available"
+        * argument here.
+        */
+       return loadpin_check(file, id);
+}
+
 static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
 {
-       return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents);
+       /*
+        * LoadPin only cares about the _origin_ of a file, not its
+        * contents, so a NULL file is passed, and we can ignore the
+        * state of "contents".
+        */
+       return loadpin_check(NULL, (enum kernel_read_file_id) id);
 }
 
 static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {