Re: [RFC PATCH] x86/entry: Disable ia32 syscalls and introduce a boot time toggle
From: Brian Gerst
Date: Fri May 26 2023 - 11:53:48 EST
On Fri, May 26, 2023 at 9:50 AM Nikolay Borisov <nik.borisov@xxxxxxxx> wrote:
>
> Distributions would like to reduce their attack surface as much as
> possible but at the same time they have to cater to a wide variety of
> legacy software. One such avenue where distros have to strike a balance
> is the support for 32bit syscalls on a 64bit kernel. Ideally the compat
> support should be disabled for the majority of the time, yet in the few
> cases where it might be needed it'd be good if there is some toggle
> which would allow users to turn on back compat support.
>
> This patch aims to cater for this use case by disabling ia32 syscalls
> and introducing a boot time parameter 'ia32_enabled' which if set to
> 'true' brings backs 32bit syscall support.
>
> Signed-off-by: Nikolay Borisov <nik.borisov@xxxxxxxx>
> ---
>
> Rather than being a final implementation I'd like this to serve as a conversation
> starter and agree on a final solution that's acceptable to everyone.
>
> arch/x86/entry/common.c | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
> index 6c2826417b33..6063727a75fe 100644
> --- a/arch/x86/entry/common.c
> +++ b/arch/x86/entry/common.c
> @@ -19,6 +19,7 @@
> #include <linux/nospec.h>
> #include <linux/syscalls.h>
> #include <linux/uaccess.h>
> +#include <linux/init.h>
>
> #ifdef CONFIG_XEN_PV
> #include <xen/xen-ops.h>
> @@ -96,6 +97,20 @@ static __always_inline int syscall_32_enter(struct pt_regs *regs)
> return (int)regs->orig_ax;
> }
>
> +int ia32_enabled = 0;
> +
> +static int __init ia32_enabled_parsecmdline(char *arg)
> +{
> + if (!strcmp(arg, "true"))
> + ia32_enabled = 1;
> + else
> + pr_crit("Unsupported ia32_enabled=%s, ia32 syscalls disabled\n",
> + arg);
> +
> + return 0;
> +}
> +early_param("ia32_enabled", ia32_enabled_parsecmdline);
> +
> /*
> * Invoke a 32-bit syscall. Called with IRQs on in CONTEXT_KERNEL.
> */
> @@ -107,7 +122,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
> */
> unsigned int unr = nr;
>
> - if (likely(unr < IA32_NR_syscalls)) {
> + if (likely(unr < IA32_NR_syscalls) && ia32_enabled) {
> unr = array_index_nospec(unr, IA32_NR_syscalls);
> regs->ax = ia32_sys_call_table[unr](regs);
> } else if (nr != -1) {
> --
> 2.34.1
>
Compat syscalls should be enabled by default (opt-out). You can't
break a user's working setup by just upgrading the kernel. Also, it
needs to work for 32-bit kernels, since this code is used by both
native and compat.