2021-11-12 10:33:00

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 0/6] x86/cpu: Do some janitorial work

From: Borislav Petkov <[email protected]>

Beef up clearcpuid= so that it supports the strings from /proc/cpuinfo
too and remove a bunch of useless, and, in some cases even downright
dangerous, chicken bits we have added over the years.

Thx.

Borislav Petkov (6):
x86/cpu: Allow feature bit names from /proc/cpuinfo in clearcpuid=
x86/cpu: Remove "nosep"
x86/cpu: Remove CONFIG_X86_SMAP and "nosmap"
x86/cpu: Remove "nosmep"
x86/cpu: Remove "noexec"
x86/cpu: Remove "noclflush"

.../admin-guide/kernel-parameters.txt | 28 ++----
Documentation/x86/cpuinfo.rst | 5 +-
Documentation/x86/x86_64/boot-options.rst | 9 --
arch/x86/Kconfig | 11 ---
arch/x86/include/asm/disabled-features.h | 8 +-
arch/x86/include/asm/proto.h | 1 -
arch/x86/include/asm/smap.h | 24 -----
arch/x86/kernel/cpu/common.c | 88 +++++++++----------
arch/x86/kernel/setup.c | 28 +++++-
arch/x86/mm/Makefile | 3 +-
arch/x86/mm/init_64.c | 1 -
arch/x86/mm/setup_nx.c | 62 -------------
scripts/Makefile.lib | 4 +-
scripts/link-vmlinux.sh | 6 +-
.../arch/x86/include/asm/disabled-features.h | 8 +-
15 files changed, 83 insertions(+), 203 deletions(-)
delete mode 100644 arch/x86/mm/setup_nx.c

--
2.29.2



2021-11-12 10:33:02

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 1/6] x86/cpu: Allow feature bit names from /proc/cpuinfo in clearcpuid=

From: Borislav Petkov <[email protected]>

Having to give the X86_FEATURE array indices in order to disable a
feature bit for testing is not really user-friendly. So accept the
feature bit names too.

Some feature bits don't have names so there the array indices are still
accepted, of course.

Clearing CPUID flags is not something which should be done in production
so taint the kernel too.

An exemplary cmdline would then be something like:

clearcpuid=de,440,smca,succory,bmi1,3dnow ("succory" is wrong on
purpose).

and it says:

[ 0.000000] Clearing CPUID bits: de 13:24 smca bmi1 3dnow

Signed-off-by: Borislav Petkov <[email protected]>
---
.../admin-guide/kernel-parameters.txt | 11 ++--
arch/x86/kernel/cpu/common.c | 51 ++++++++++++++-----
2 files changed, 47 insertions(+), 15 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 0905d2cdb2d5..dadb09d30212 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -622,12 +622,17 @@
Defaults to zero when built as a module and to
10 seconds when built into the kernel.

- clearcpuid=BITNUM[,BITNUM...] [X86]
+ clearcpuid=X[,X...] [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
- numbers. Note the Linux specific bits are not necessarily
- stable over kernel options, but the vendor specific
+ numbers X. Note the Linux-specific bits are not necessarily
+ stable over kernel options, but the vendor-specific
ones should be.
+ X can also be a string as appearing in the flags: line
+ in /proc/cpuinfo which does not have the above
+ instability issue. However, not all features have names
+ in /proc/cpuinfo.
+ Note that using this option will taint your kernel.
Also note that user programs calling CPUID directly
or using the feature without checking anything
will still see it. This just prevents it from
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0083464de5e3..0d1cf5c65b0c 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1237,8 +1237,8 @@ static void detect_nopl(void)
static void __init cpu_parse_early_param(void)
{
char arg[128];
- char *argptr = arg;
- int arglen, res, bit;
+ char *argptr = arg, *opt;
+ int arglen, taint = 0;

#ifdef CONFIG_X86_32
if (cmdline_find_option_bool(boot_command_line, "no387"))
@@ -1266,21 +1266,48 @@ static void __init cpu_parse_early_param(void)
return;

pr_info("Clearing CPUID bits:");
- do {
- res = get_option(&argptr, &bit);
- if (res == 0 || res == 3)
- break;

- /* If the argument was too long, the last bit may be cut off */
- if (res == 1 && arglen >= sizeof(arg))
- break;
+ while (argptr) {
+ unsigned int bit;

- if (bit >= 0 && bit < NCAPINTS * 32) {
- pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+ opt = strsep(&argptr, ",");
+
+ /*
+ * Handle naked numbers first for feature flags which don't
+ * have names.
+ */
+ if (!kstrtouint(opt, 10, &bit)) {
+ if (bit < NCAPINTS * 32) {
+ pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+ setup_clear_cpu_cap(bit);
+ taint++;
+ }
+ /*
+ * The assumption is that there are no feature names with only
+ * numbers in the name thus go to the next argument.
+ */
+ continue;
+ }
+
+#ifdef CONFIG_X86_FEATURE_NAMES
+ for (bit = 0; bit < 32 * NCAPINTS; bit++) {
+ if (!x86_cap_flag(bit))
+ continue;
+
+ if (strcmp(x86_cap_flag(bit), opt))
+ continue;
+
+ pr_cont(" %s", opt);
setup_clear_cpu_cap(bit);
+ taint++;
+ break;
}
- } while (res == 2);
+#endif
+ }
pr_cont("\n");
+
+ if (taint)
+ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
}

/*
--
2.29.2


2021-11-12 10:33:03

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 2/6] x86/cpu: Remove "nosep"

From: Borislav Petkov <[email protected]>

That chicken bit was added by

4f88651125e2 ("[PATCH] i386: allow disabling X86_FEATURE_SEP at boot")

but measuring int80 vsyscall performance on 32-bit doesn't matter
anymore.

If still needed, one can boot with

clearcpuid=sep

to disable that feature for testing.

Signed-off-by: Borislav Petkov <[email protected]>
---
Documentation/admin-guide/kernel-parameters.txt | 2 --
arch/x86/kernel/cpu/common.c | 7 -------
2 files changed, 9 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index dadb09d30212..13e6f0100970 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3563,8 +3563,6 @@

nosbagart [IA-64]

- nosep [BUGS=X86-32] Disables x86 SYSENTER/SYSEXIT support.
-
nosgx [X86-64,SGX] Disables Intel SGX kernel support.

nosmp [SMP] Tells an SMP kernel to act as a UP kernel,
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0d1cf5c65b0c..b4598659d4a8 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -220,13 +220,6 @@ static int __init cachesize_setup(char *str)
}
__setup("cachesize=", cachesize_setup);

-static int __init x86_sep_setup(char *s)
-{
- setup_clear_cpu_cap(X86_FEATURE_SEP);
- return 1;
-}
-__setup("nosep", x86_sep_setup);
-
/* Standard macro to see if a specific flag is changeable */
static inline int flag_is_changeable_p(u32 flag)
{
--
2.29.2


2021-11-12 10:33:05

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 4/6] x86/cpu: Remove "nosmep"

From: Borislav Petkov <[email protected]>

There should be no need to disable SMEP anymore.

Signed-off-by: Borislav Petkov <[email protected]>
---
Documentation/admin-guide/kernel-parameters.txt | 4 ----
Documentation/x86/cpuinfo.rst | 4 ++--
arch/x86/kernel/cpu/common.c | 7 -------
3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 54ae0378add4..b3fbb0930997 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3365,10 +3365,6 @@
noexec=on: enable non-executable mappings (default)
noexec=off: disable non-executable mappings

- nosmep [X86,PPC]
- Disable SMEP (Supervisor Mode Execution Prevention)
- even if it is supported by processor.
-
noexec32 [X86-64]
This affects only 32-bit executables.
noexec32=on: enable non-executable mappings (default)
diff --git a/Documentation/x86/cpuinfo.rst b/Documentation/x86/cpuinfo.rst
index 12fbe2b1e98a..08246e8ac835 100644
--- a/Documentation/x86/cpuinfo.rst
+++ b/Documentation/x86/cpuinfo.rst
@@ -140,8 +140,8 @@ from #define X86_FEATURE_UMIP (16*32 + 2).

In addition, there exists a variety of custom command-line parameters that
disable specific features. The list of parameters includes, but is not limited
-to, nofsgsbase, and nosmep. 5-level paging can also be disabled using
-"no5lvl". SMEP is disabled with the aforementioned parameter.
+to, nofsgsbase, nosgx, noxsave, etc. 5-level paging can also be disabled using
+"no5lvl".

e: The feature was known to be non-functional.
----------------------------------------------
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 796aa31fd3c8..7e70c54cdff5 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -291,13 +291,6 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
}
#endif

-static __init int setup_disable_smep(char *arg)
-{
- setup_clear_cpu_cap(X86_FEATURE_SMEP);
- return 1;
-}
-__setup("nosmep", setup_disable_smep);
-
static __always_inline void setup_smep(struct cpuinfo_x86 *c)
{
if (cpu_has(c, X86_FEATURE_SMEP))
--
2.29.2


2021-11-12 10:33:09

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 3/6] x86/cpu: Remove CONFIG_X86_SMAP and "nosmap"

From: Borislav Petkov <[email protected]>

Those were added as part of the SMAP enablement but SMAP is currently
an integral part of kernel proper and there's no need to disable it
anymore.

Rip out that functionality.

If still needed - clearcpuid=smap.

Signed-off-by: Borislav Petkov <[email protected]>
---
.../admin-guide/kernel-parameters.txt | 4 ----
Documentation/x86/cpuinfo.rst | 5 ++--
arch/x86/Kconfig | 11 ---------
arch/x86/include/asm/disabled-features.h | 8 +------
arch/x86/include/asm/smap.h | 24 -------------------
arch/x86/kernel/cpu/common.c | 15 +-----------
scripts/Makefile.lib | 4 ++--
scripts/link-vmlinux.sh | 6 ++---
.../arch/x86/include/asm/disabled-features.h | 8 +------
9 files changed, 10 insertions(+), 75 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 13e6f0100970..54ae0378add4 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3365,10 +3365,6 @@
noexec=on: enable non-executable mappings (default)
noexec=off: disable non-executable mappings

- nosmap [X86,PPC]
- Disable SMAP (Supervisor Mode Access Prevention)
- even if it is supported by processor.
-
nosmep [X86,PPC]
Disable SMEP (Supervisor Mode Execution Prevention)
even if it is supported by processor.
diff --git a/Documentation/x86/cpuinfo.rst b/Documentation/x86/cpuinfo.rst
index 5d54c39a063f..12fbe2b1e98a 100644
--- a/Documentation/x86/cpuinfo.rst
+++ b/Documentation/x86/cpuinfo.rst
@@ -140,9 +140,8 @@ from #define X86_FEATURE_UMIP (16*32 + 2).

In addition, there exists a variety of custom command-line parameters that
disable specific features. The list of parameters includes, but is not limited
-to, nofsgsbase, nosmap, and nosmep. 5-level paging can also be disabled using
-"no5lvl". SMAP and SMEP are disabled with the aforementioned parameters,
-respectively.
+to, nofsgsbase, and nosmep. 5-level paging can also be disabled using
+"no5lvl". SMEP is disabled with the aforementioned parameter.

e: The feature was known to be non-functional.
----------------------------------------------
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 95dd1ee01546..8959c7c55991 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1822,17 +1822,6 @@ config ARCH_RANDOM
If supported, this is a high bandwidth, cryptographically
secure hardware random number generator.

-config X86_SMAP
- def_bool y
- prompt "Supervisor Mode Access Prevention" if EXPERT
- help
- Supervisor Mode Access Prevention (SMAP) is a security
- feature in newer Intel processors. There is a small
- performance cost if this enabled and turned on; there is
- also a small increase in the kernel size if this is enabled.
-
- If unsure, say Y.
-
config X86_UMIP
def_bool y
prompt "User Mode Instruction Prevention" if EXPERT
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 8f28fafa98b3..c2808f4d61f0 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -10,12 +10,6 @@
* cpu_feature_enabled().
*/

-#ifdef CONFIG_X86_SMAP
-# define DISABLE_SMAP 0
-#else
-# define DISABLE_SMAP (1<<(X86_FEATURE_SMAP & 31))
-#endif
-
#ifdef CONFIG_X86_UMIP
# define DISABLE_UMIP 0
#else
@@ -77,7 +71,7 @@
#define DISABLED_MASK6 0
#define DISABLED_MASK7 (DISABLE_PTI)
#define DISABLED_MASK8 0
-#define DISABLED_MASK9 (DISABLE_SMAP|DISABLE_SGX)
+#define DISABLED_MASK9 (DISABLE_SGX)
#define DISABLED_MASK10 0
#define DISABLED_MASK11 0
#define DISABLED_MASK12 0
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
index d17b39893b79..bab490379c65 100644
--- a/arch/x86/include/asm/smap.h
+++ b/arch/x86/include/asm/smap.h
@@ -19,25 +19,14 @@

#ifdef __ASSEMBLY__

-#ifdef CONFIG_X86_SMAP
-
#define ASM_CLAC \
ALTERNATIVE "", __ASM_CLAC, X86_FEATURE_SMAP

#define ASM_STAC \
ALTERNATIVE "", __ASM_STAC, X86_FEATURE_SMAP

-#else /* CONFIG_X86_SMAP */
-
-#define ASM_CLAC
-#define ASM_STAC
-
-#endif /* CONFIG_X86_SMAP */
-
#else /* __ASSEMBLY__ */

-#ifdef CONFIG_X86_SMAP
-
static __always_inline void clac(void)
{
/* Note: a barrier is implicit in alternative() */
@@ -76,19 +65,6 @@ static __always_inline void smap_restore(unsigned long flags)
#define ASM_STAC \
ALTERNATIVE("", __ASM_STAC, X86_FEATURE_SMAP)

-#else /* CONFIG_X86_SMAP */
-
-static inline void clac(void) { }
-static inline void stac(void) { }
-
-static inline unsigned long smap_save(void) { return 0; }
-static inline void smap_restore(unsigned long flags) { }
-
-#define ASM_CLAC
-#define ASM_STAC
-
-#endif /* CONFIG_X86_SMAP */
-
#endif /* __ASSEMBLY__ */

#endif /* _ASM_X86_SMAP_H */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index b4598659d4a8..796aa31fd3c8 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -304,13 +304,6 @@ static __always_inline void setup_smep(struct cpuinfo_x86 *c)
cr4_set_bits(X86_CR4_SMEP);
}

-static __init int setup_disable_smap(char *arg)
-{
- setup_clear_cpu_cap(X86_FEATURE_SMAP);
- return 1;
-}
-__setup("nosmap", setup_disable_smap);
-
static __always_inline void setup_smap(struct cpuinfo_x86 *c)
{
unsigned long eflags = native_save_fl();
@@ -318,14 +311,8 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
/* This should have been cleared long ago */
BUG_ON(eflags & X86_EFLAGS_AC);

- if (cpu_has(c, X86_FEATURE_SMAP)) {
-#ifdef CONFIG_X86_SMAP
+ if (cpu_has(c, X86_FEATURE_SMAP))
cr4_set_bits(X86_CR4_SMAP);
-#else
- clear_cpu_cap(c, X86_FEATURE_SMAP);
- cr4_clear_bits(X86_CR4_SMAP);
-#endif
- }
}

static __always_inline void setup_umip(struct cpuinfo_x86 *c)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 56d50eb0cd80..3e4e8d97ff40 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -240,8 +240,8 @@ objtool_args = \
$(if $(CONFIG_FRAME_POINTER),, --no-fp) \
$(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
$(if $(CONFIG_RETPOLINE), --retpoline) \
- $(if $(CONFIG_X86_SMAP), --uaccess) \
- $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
+ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \
+ --uaccess

# Useful for describing the dependency of composite objects
# Usage:
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 3ea7cece7c97..6180860e9e1d 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -136,9 +136,9 @@ objtool_link()
if [ -n "${CONFIG_RETPOLINE}" ]; then
objtoolopt="${objtoolopt} --retpoline"
fi
- if [ -n "${CONFIG_X86_SMAP}" ]; then
- objtoolopt="${objtoolopt} --uaccess"
- fi
+
+ objtoolopt="${objtoolopt} --uaccess"
+
info OBJTOOL ${1}
tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
fi
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
index 8f28fafa98b3..c2808f4d61f0 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -10,12 +10,6 @@
* cpu_feature_enabled().
*/

-#ifdef CONFIG_X86_SMAP
-# define DISABLE_SMAP 0
-#else
-# define DISABLE_SMAP (1<<(X86_FEATURE_SMAP & 31))
-#endif
-
#ifdef CONFIG_X86_UMIP
# define DISABLE_UMIP 0
#else
@@ -77,7 +71,7 @@
#define DISABLED_MASK6 0
#define DISABLED_MASK7 (DISABLE_PTI)
#define DISABLED_MASK8 0
-#define DISABLED_MASK9 (DISABLE_SMAP|DISABLE_SGX)
+#define DISABLED_MASK9 (DISABLE_SGX)
#define DISABLED_MASK10 0
#define DISABLED_MASK11 0
#define DISABLED_MASK12 0
--
2.29.2


2021-11-12 10:33:10

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 5/6] x86/cpu: Remove "noexec"

From: Borislav Petkov <[email protected]>

It doesn't make any sense to disable non-executable mappings -
security-wise or else.

So rip out that switch and move the remaining code into setup.c and
delete setup_nx.c

Signed-off-by: Borislav Petkov <[email protected]>
---
.../admin-guide/kernel-parameters.txt | 5 --
Documentation/x86/x86_64/boot-options.rst | 9 ---
arch/x86/include/asm/proto.h | 1 -
arch/x86/kernel/setup.c | 28 ++++++++-
arch/x86/mm/Makefile | 3 +-
arch/x86/mm/init_64.c | 1 -
arch/x86/mm/setup_nx.c | 62 -------------------
7 files changed, 26 insertions(+), 83 deletions(-)
delete mode 100644 arch/x86/mm/setup_nx.c

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index b3fbb0930997..3a4c3fc88bf1 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3360,11 +3360,6 @@

noexec [IA-64]

- noexec [X86]
- On X86-32 available only on PAE configured kernels.
- noexec=on: enable non-executable mappings (default)
- noexec=off: disable non-executable mappings
-
noexec32 [X86-64]
This affects only 32-bit executables.
noexec32=on: enable non-executable mappings (default)
diff --git a/Documentation/x86/x86_64/boot-options.rst b/Documentation/x86/x86_64/boot-options.rst
index ccb7e86bf8d9..e72c60210285 100644
--- a/Documentation/x86/x86_64/boot-options.rst
+++ b/Documentation/x86/x86_64/boot-options.rst
@@ -164,15 +164,6 @@ Rebooting
newer BIOS, or newer board) using this option will ignore the built-in
quirk table, and use the generic default reboot actions.

-Non Executable Mappings
-=======================
-
- noexec=on|off
- on
- Enable(default)
- off
- Disable
-
NUMA
====

diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
index feed36d44d04..0f899c8d7a4e 100644
--- a/arch/x86/include/asm/proto.h
+++ b/arch/x86/include/asm/proto.h
@@ -35,7 +35,6 @@ void xen_entry_INT80_compat(void);
#endif

void x86_configure_nx(void);
-void x86_report_nx(void);

extern int reboot_force;

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 49b596db5631..2f49fef15745 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -742,6 +742,30 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
return 0;
}

+void x86_configure_nx(void)
+{
+ if (boot_cpu_has(X86_FEATURE_NX))
+ __supported_pte_mask |= _PAGE_NX;
+ else
+ __supported_pte_mask &= ~_PAGE_NX;
+}
+
+static void __init x86_report_nx(void)
+{
+ if (!boot_cpu_has(X86_FEATURE_NX)) {
+ printk(KERN_NOTICE "Notice: NX (Execute Disable) protection "
+ "missing in CPU!\n");
+ } else {
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+ printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+#else
+ /* 32bit non-PAE kernel, NX cannot be used */
+ printk(KERN_NOTICE "Notice: NX (Execute Disable) protection "
+ "cannot be enabled: non-PAE kernel!\n");
+#endif
+ }
+}
+
/*
* Determine if we were loaded by an EFI loader. If so, then we have also been
* passed the efi memmap, systab, etc., so we should use these data structures
@@ -882,9 +906,7 @@ void __init setup_arch(char **cmdline_p)
/*
* x86_configure_nx() is called before parse_early_param() to detect
* whether hardware doesn't support NX (so that the early EHCI debug
- * console setup can safely call set_fixmap()). It may then be called
- * again from within noexec_setup() during parsing early parameters
- * to honor the respective command line option.
+ * console setup can safely call set_fixmap()).
*/
x86_configure_nx();

diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 5864219221ca..5bdf0e881897 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -17,13 +17,12 @@ CFLAGS_REMOVE_mem_encrypt_identity.o = -pg
endif

obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o mmap.o \
- pgtable.o physaddr.o setup_nx.o tlb.o cpu_entry_area.o maccess.o
+ pgtable.o physaddr.o tlb.o cpu_entry_area.o maccess.o

obj-y += pat/

# Make sure __phys_addr has no stackprotector
CFLAGS_physaddr.o := -fno-stack-protector
-CFLAGS_setup_nx.o := -fno-stack-protector
CFLAGS_mem_encrypt_identity.o := -fno-stack-protector

CFLAGS_fault.o := -I $(srctree)/$(src)/../include/asm/trace
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 36098226a957..757d57c40d33 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -110,7 +110,6 @@ int force_personality32;
/*
* noexec32=on|off
* Control non executable heap for 32bit processes.
- * To control the stack too use noexec=off
*
* on PROT_READ does not imply PROT_EXEC for 32-bit processes (default)
* off PROT_READ implies PROT_EXEC
diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c
deleted file mode 100644
index ed5667f5169f..000000000000
--- a/arch/x86/mm/setup_nx.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/pgtable.h>
-
-#include <asm/proto.h>
-#include <asm/cpufeature.h>
-
-static int disable_nx;
-
-/*
- * noexec = on|off
- *
- * Control non-executable mappings for processes.
- *
- * on Enable
- * off Disable
- */
-static int __init noexec_setup(char *str)
-{
- if (!str)
- return -EINVAL;
- if (!strncmp(str, "on", 2)) {
- disable_nx = 0;
- } else if (!strncmp(str, "off", 3)) {
- disable_nx = 1;
- }
- x86_configure_nx();
- return 0;
-}
-early_param("noexec", noexec_setup);
-
-void x86_configure_nx(void)
-{
- if (boot_cpu_has(X86_FEATURE_NX) && !disable_nx)
- __supported_pte_mask |= _PAGE_NX;
- else
- __supported_pte_mask &= ~_PAGE_NX;
-}
-
-void __init x86_report_nx(void)
-{
- if (!boot_cpu_has(X86_FEATURE_NX)) {
- printk(KERN_NOTICE "Notice: NX (Execute Disable) protection "
- "missing in CPU!\n");
- } else {
-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
- if (disable_nx) {
- printk(KERN_INFO "NX (Execute Disable) protection: "
- "disabled by kernel command line option\n");
- } else {
- printk(KERN_INFO "NX (Execute Disable) protection: "
- "active\n");
- }
-#else
- /* 32bit non-PAE kernel, NX cannot be used */
- printk(KERN_NOTICE "Notice: NX (Execute Disable) protection "
- "cannot be enabled: non-PAE kernel!\n");
-#endif
- }
-}
--
2.29.2


2021-11-12 10:33:12

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH 6/6] x86/cpu: Remove "noclflush"

From: Borislav Petkov <[email protected]>

Not really needed anymore and there's clearcpuid=.

Signed-off-by: Borislav Petkov <[email protected]>
---
Documentation/admin-guide/kernel-parameters.txt | 2 --
arch/x86/kernel/cpu/common.c | 8 --------
2 files changed, 10 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 3a4c3fc88bf1..5239d4ae2b91 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3348,8 +3348,6 @@

nocache [ARM]

- noclflush [BUGS=X86] Don't use the CLFLUSH instruction
-
delayacct [KNL] Enable per-task delay accounting

nodsp [SH] Disable hardware DSP at boot time.
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 7e70c54cdff5..9a8ecb388f2f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1721,14 +1721,6 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
update_srbds_msr();
}

-static __init int setup_noclflush(char *arg)
-{
- setup_clear_cpu_cap(X86_FEATURE_CLFLUSH);
- setup_clear_cpu_cap(X86_FEATURE_CLFLUSHOPT);
- return 1;
-}
-__setup("noclflush", setup_noclflush);
-
void print_cpu_info(struct cpuinfo_x86 *c)
{
const char *vendor = NULL;
--
2.29.2


2021-11-15 09:04:52

by Lai Jiangshan

[permalink] [raw]
Subject: Re: [PATCH 6/6] x86/cpu: Remove "noclflush"

On Fri, Nov 12, 2021 at 6:37 PM Borislav Petkov <[email protected]> wrote:
>
> From: Borislav Petkov <[email protected]>
>
> Not really needed anymore and there's clearcpuid=.
>
> Signed-off-by: Borislav Petkov <[email protected]>
> ---
> Documentation/admin-guide/kernel-parameters.txt | 2 --
> arch/x86/kernel/cpu/common.c | 8 --------
> 2 files changed, 10 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 3a4c3fc88bf1..5239d4ae2b91 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -3348,8 +3348,6 @@
>
> nocache [ARM]
>
> - noclflush [BUGS=X86] Don't use the CLFLUSH instruction
> -

The patch is definitely good for me, but I have no idea what
"BUGS=" relates to here.
(In the commit 191679fdfa63 ("x86: add noclflush option"))

In Documentation/admin-guide/kernel-parameters.rst:
BUGS= Relates to possible processor bugs on the said processor.

For patch 3,4,5, they can have my reviewed-by:

Reviewed-by: Lai Jiangshan <[email protected]>

2021-11-15 09:13:41

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH 6/6] x86/cpu: Remove "noclflush"

On Mon, Nov 15, 2021 at 05:03:29PM +0800, Lai Jiangshan wrote:
> The patch is definitely good for me, but I have no idea what
> "BUGS=" relates to here.
> (In the commit 191679fdfa63 ("x86: add noclflush option"))
>
> In Documentation/admin-guide/kernel-parameters.rst:
> BUGS= Relates to possible processor bugs on the said processor.

Probably some CLFLUSH-related erratum from more than 10 years ago.
Probably not relevant anymore - otherwise we would have heard about it.

> For patch 3,4,5, they can have my reviewed-by:
>
> Reviewed-by: Lai Jiangshan <[email protected]>

Thx.

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2022-01-25 16:45:34

by Borislav Petkov

[permalink] [raw]
Subject: [PATCH v1.1] x86/cpu: Allow feature bit names from /proc/cpuinfo in clearcpuid=

On Fri, Nov 12, 2021 at 11:32:41AM +0100, Borislav Petkov wrote:
> clearcpuid=de,440,smca,succory,bmi1,3dnow ("succory" is wrong on
> purpose).

Here's v1.1 which handles the case where we have ""-defined feature
flags - for example:

#define X86_FEATURE_AMD_SSBD (13*32+24) /* "" Speculative Store Bypass Disable */

and for which there's no string name generated.

---
From: Borislav Petkov <[email protected]>
Date: Wed, 10 Nov 2021 19:30:07 +0100
Subject: [PATCH v1.1] x86/cpu: Allow feature bit names from /proc/cpuinfo in clearcpuid=

Having to give the X86_FEATURE array indices in order to disable a
feature bit for testing is not really user-friendly. So accept the
feature bit names too.

Some feature bits don't have names so there the array indices are still
accepted, of course.

Clearing CPUID flags is not something which should be done in production
so taint the kernel too.

An exemplary cmdline would then be something like:

clearcpuid=de,440,smca,succory,bmi1,3dnow

("succory" is wrong on purpose). And it says:

[ 0.000000] Clearing CPUID bits: de 13:24 smca bmi1 3dnow

Signed-off-by: Borislav Petkov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
---
.../admin-guide/kernel-parameters.txt | 11 +++-
arch/x86/include/asm/cpufeature.h | 7 ++-
arch/x86/kernel/cpu/common.c | 57 +++++++++++++++----
3 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index f5a27f067db9..b67d0cf27997 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -631,12 +631,17 @@
Defaults to zero when built as a module and to
10 seconds when built into the kernel.

- clearcpuid=BITNUM[,BITNUM...] [X86]
+ clearcpuid=X[,X...] [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
- numbers. Note the Linux specific bits are not necessarily
- stable over kernel options, but the vendor specific
+ numbers X. Note the Linux-specific bits are not necessarily
+ stable over kernel options, but the vendor-specific
ones should be.
+ X can also be a string as appearing in the flags: line
+ in /proc/cpuinfo which does not have the above
+ instability issue. However, not all features have names
+ in /proc/cpuinfo.
+ Note that using this option will taint your kernel.
Also note that user programs calling CPUID directly
or using the feature without checking anything
will still see it. This just prevents it from
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1261842d006c..66d3e3b1d24d 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -34,14 +34,17 @@ enum cpuid_leafs
CPUID_8000_001F_EAX,
};

+#define X86_CAP_FMT_NUM "%d:%d"
+#define x86_cap_flag_num(flag) ((flag) >> 5), ((flag) & 31)
+
#ifdef CONFIG_X86_FEATURE_NAMES
extern const char * const x86_cap_flags[NCAPINTS*32];
extern const char * const x86_power_flags[32];
#define X86_CAP_FMT "%s"
#define x86_cap_flag(flag) x86_cap_flags[flag]
#else
-#define X86_CAP_FMT "%d:%d"
-#define x86_cap_flag(flag) ((flag) >> 5), ((flag) & 31)
+#define X86_CAP_FMT X86_CAP_FMT_NUM
+#define x86_cap_flag x86_cap_flag_num
#endif

/*
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 7b8382c11788..aaac18d800a4 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1237,8 +1237,8 @@ static void detect_nopl(void)
static void __init cpu_parse_early_param(void)
{
char arg[128];
- char *argptr = arg;
- int arglen, res, bit;
+ char *argptr = arg, *opt;
+ int arglen, taint = 0;

#ifdef CONFIG_X86_32
if (cmdline_find_option_bool(boot_command_line, "no387"))
@@ -1266,21 +1266,54 @@ static void __init cpu_parse_early_param(void)
return;

pr_info("Clearing CPUID bits:");
- do {
- res = get_option(&argptr, &bit);
- if (res == 0 || res == 3)
- break;

- /* If the argument was too long, the last bit may be cut off */
- if (res == 1 && arglen >= sizeof(arg))
- break;
+ while (argptr) {
+ unsigned int bit;
+
+ opt = strsep(&argptr, ",");

- if (bit >= 0 && bit < NCAPINTS * 32) {
- pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+ /*
+ * Handle naked numbers first for feature flags which don't
+ * have names.
+ */
+ if (!kstrtouint(opt, 10, &bit)) {
+ if (bit < NCAPINTS * 32) {
+
+ /* empty-string, i.e., ""-defined feature flags */
+ if (!x86_cap_flags[bit])
+ pr_cont(" " X86_CAP_FMT_NUM, x86_cap_flag_num(bit));
+ else
+ pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+
+ setup_clear_cpu_cap(bit);
+ taint++;
+ }
+ /*
+ * The assumption is that there are no feature names with only
+ * numbers in the name thus go to the next argument.
+ */
+ continue;
+ }
+
+#ifdef CONFIG_X86_FEATURE_NAMES
+ for (bit = 0; bit < 32 * NCAPINTS; bit++) {
+ if (!x86_cap_flag(bit))
+ continue;
+
+ if (strcmp(x86_cap_flag(bit), opt))
+ continue;
+
+ pr_cont(" %s", opt);
setup_clear_cpu_cap(bit);
+ taint++;
+ break;
}
- } while (res == 2);
+#endif
+ }
pr_cont("\n");
+
+ if (taint)
+ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
}

/*
--
2.29.2

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette