Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp2027481pxb; Mon, 23 Aug 2021 10:15:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw1Jp+1KoCQ9yNSFo8bupC4GMSR00yFbWxWC1dvXN1AfbccmWMLPU3uAD7FwUgVcq+CUzqP X-Received: by 2002:a5d:8450:: with SMTP id w16mr26140234ior.141.1629738933774; Mon, 23 Aug 2021 10:15:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629738933; cv=none; d=google.com; s=arc-20160816; b=IbWNR0gBhDXaG5P0NhYmMbMHhGyt8ZbPoES5IJbfw1gC+S049/0m7nQK96VdW99a0l T2LJiFHJKkKQV/vBqAEjgZuOMsGhxUj0AcPfzFZwUm+cVBsbofLrJ7yTSdg0Dw1OXT1v l8Dy2yj1osB/IPL04py1qdxX9XmX9L13XPIGxZwyxEdRk/V1/cX99U03rsW252igDqj3 Klohh9wwAsO9jlEeaNrf+B+BZUXIEGDzvWBUh7cHpnaGz/Aimxx9V2Dxgi1U6EQ5fuip uFaKPp/pH1vGZQ1wfqEdihbfcEbTzgQFwqPVddnLfwpaDrsEaCmaPALm/msD00NN50iq 4Jcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=ncGPY7f56TkAnstpGt9m2A+2Y29Iso8+HIed7nMDf8U=; b=lROA0WtZ3NUYbxnzyBza9CE8M5nxRqPtKQXUf3SVrIwpdsttXeTG5dvgEAEFkoZbs8 o5tjcknhJTJNvnvanVzF35vAyu7i8K07nDUnax8JccehxQg6LC2qdNIUkUYhkDqA2b5N WnNcqrGAKIs6Gosx/GqaSUI+ulUAXGX4aVJ7rCTIHqGeEN+2KsYQwVw5OESU4MWBdNIH GA2T3UJgBMEAeKkoyBZaRvY4JvG1BE/70fzuxYwPwWFV2sy9NPdSAM5jFV/HWU7sR3TV DGVKyIzD0Bk885PUp/KgzADRHMyiapc5+g07HvNq0ihbUo+v8XezVVmHuDAaFtnA4Rst fa3A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=TjOoo4Js; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b16si17698471ilf.63.2021.08.23.10.15.19; Mon, 23 Aug 2021 10:15:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=TjOoo4Js; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231716AbhHWRO3 (ORCPT + 99 others); Mon, 23 Aug 2021 13:14:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231425AbhHWROV (ORCPT ); Mon, 23 Aug 2021 13:14:21 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A7419C061757 for ; Mon, 23 Aug 2021 10:13:38 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id u1-20020a25ab01000000b0059949024617so4125510ybi.17 for ; Mon, 23 Aug 2021 10:13:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ncGPY7f56TkAnstpGt9m2A+2Y29Iso8+HIed7nMDf8U=; b=TjOoo4Jsc/7MftdfMRwfywAUGE2Q9udUh4HXKkfNH5WRYs++OpaiRB7Vync6Wjmayx oIEpbU58APRhyODrJyfWfjnEeuIn0DbhMx7SCzF2OKwV6MIu40piSyi7Dd3NUco+fldx V9e1ivFzQVOdoq+CNc9X1DYxRxAC5m2L5slwPFnDGmFi8UijbjvXD27mr5Zdd5oxsc9p WYgDLSE2mIbCqCiHw0De0n+PFTSvcvElO+/APN3hUVRGL11UA9Zna/jlDxRhapsZ3cyN 2itoZkn+qvhwYK7xDO7EPZkTmfPF5w58wIvAXIufeAkHmd3a05BG7WOT97FBO8Do1U3l C9HQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ncGPY7f56TkAnstpGt9m2A+2Y29Iso8+HIed7nMDf8U=; b=T66PUFM3q+9wfuKHHC+zBpktv9TNZHq88C1y77TueqcU4KqhOaSWwG+QyufuHv3Who NJMe3SUzcWFIK0Y0DyNRb6hbnD02M41zR6P+sxANBzICqPDNl1bg5YPs2F1OpqL0To5v 9KdN5o6GoghgAg+aICRtuZjx3XZ7IIGUkf99OL+n+P+LcsF16P/4s9DiTV+dUxaWrwti 9EvxUz85uP+ao8e/bk3PmCfIsVlpTerJTSUJRfbUrXP2jUtHqM/8n1NIxKK8LicYDxU3 7wI9LjWI26K79zSWYM3ZI2D8zMcEu0qnXCjqdBQ3NGZcE7iAbXYd3UePr/NRBcWCR5ZB Yfjg== X-Gm-Message-State: AOAM533INaOz/82o2tWDEUImlOgxWg8d32ZzrPmeO3UK5rN+vj1kSV7C t4elsZsrQCkGNW8zwcajrg87Nx7RccGMWBinQEk= X-Received: from samitolvanen1.mtv.corp.google.com ([2620:15c:201:2:cc48:aa6a:f4ec:7d19]) (user=samitolvanen job=sendgmr) by 2002:a25:a20a:: with SMTP id b10mr45385428ybi.478.1629738817828; Mon, 23 Aug 2021 10:13:37 -0700 (PDT) Date: Mon, 23 Aug 2021 10:13:11 -0700 In-Reply-To: <20210823171318.2801096-1-samitolvanen@google.com> Message-Id: <20210823171318.2801096-8-samitolvanen@google.com> Mime-Version: 1.0 References: <20210823171318.2801096-1-samitolvanen@google.com> X-Mailer: git-send-email 2.33.0.rc2.250.ged5fa647cd-goog Subject: [PATCH v2 07/14] x86: Use an opaque type for functions not callable from C From: Sami Tolvanen To: x86@kernel.org Cc: Kees Cook , Josh Poimboeuf , Peter Zijlstra , Nathan Chancellor , Nick Desaulniers , Sedat Dilek , linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Sami Tolvanen Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The kernel has several assembly functions that are not directly callable from C. Use an opaque type for these function prototypes to make misuse harder, and to avoid the need to annotate references to these functions for Clang's Control-Flow Integrity (CFI). Suggested-by: Andy Lutomirski Suggested-by: Alexander Lobakin Signed-off-by: Sami Tolvanen --- arch/x86/include/asm/ftrace.h | 2 +- arch/x86/include/asm/idtentry.h | 10 +++++----- arch/x86/include/asm/page_64.h | 7 ++++--- arch/x86/include/asm/paravirt_types.h | 3 ++- arch/x86/include/asm/processor.h | 2 +- arch/x86/include/asm/proto.h | 25 +++++++++++++------------ arch/x86/include/asm/uaccess_64.h | 9 +++------ arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/ftrace.c | 2 +- arch/x86/kernel/paravirt.c | 4 ++-- arch/x86/kvm/emulate.c | 4 ++-- arch/x86/kvm/kvm_emulate.h | 9 ++------- arch/x86/xen/enlighten_pv.c | 6 +++--- arch/x86/xen/xen-ops.h | 10 +++++----- 14 files changed, 45 insertions(+), 50 deletions(-) diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 9f3130f40807..54d23f421c16 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -17,7 +17,7 @@ #ifndef __ASSEMBLY__ extern atomic_t modifying_ftrace_code; -extern void __fentry__(void); +DECLARE_ASM_FUNC_SYMBOL(__fentry__); static inline unsigned long ftrace_call_adjust(unsigned long addr) { diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index 1345088e9902..2f6d0528bdd2 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -27,8 +27,8 @@ * as well which is used to emit the entry stubs in entry_32/64.S. */ #define DECLARE_IDTENTRY(vector, func) \ - asmlinkage void asm_##func(void); \ - asmlinkage void xen_asm_##func(void); \ + DECLARE_ASM_FUNC_SYMBOL(asm_##func); \ + DECLARE_ASM_FUNC_SYMBOL(xen_asm_##func); \ __visible void func(struct pt_regs *regs) /** @@ -78,8 +78,8 @@ static __always_inline void __##func(struct pt_regs *regs) * C-handler. */ #define DECLARE_IDTENTRY_ERRORCODE(vector, func) \ - asmlinkage void asm_##func(void); \ - asmlinkage void xen_asm_##func(void); \ + DECLARE_ASM_FUNC_SYMBOL(asm_##func); \ + DECLARE_ASM_FUNC_SYMBOL(xen_asm_##func); \ __visible void func(struct pt_regs *regs, unsigned long error_code) /** @@ -386,7 +386,7 @@ static __always_inline void __##func(struct pt_regs *regs) * - The C handler called from the C shim */ #define DECLARE_IDTENTRY_DF(vector, func) \ - asmlinkage void asm_##func(void); \ + DECLARE_ASM_FUNC_SYMBOL(asm_##func); \ __visible void func(struct pt_regs *regs, \ unsigned long error_code, \ unsigned long address) diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 4bde0dc66100..d6760b6773de 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h @@ -5,6 +5,7 @@ #include #ifndef __ASSEMBLY__ +#include #include /* duplicated to the one in bootmem.h */ @@ -40,9 +41,9 @@ extern unsigned long __phys_addr_symbol(unsigned long); #define pfn_valid(pfn) ((pfn) < max_pfn) #endif -void clear_page_orig(void *page); -void clear_page_rep(void *page); -void clear_page_erms(void *page); +DECLARE_ASM_FUNC_SYMBOL(clear_page_orig); +DECLARE_ASM_FUNC_SYMBOL(clear_page_rep); +DECLARE_ASM_FUNC_SYMBOL(clear_page_erms); static inline void clear_page(void *page) { diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index d9d6b0203ec4..7f71d52c55f5 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -38,6 +38,7 @@ #include #include #include +#include struct page; struct thread_struct; @@ -271,7 +272,7 @@ struct paravirt_patch_template { extern struct pv_info pv_info; extern struct paravirt_patch_template pv_ops; -extern void (*paravirt_iret)(void); +extern asm_func_t paravirt_iret; #define PARAVIRT_PATCH(x) \ (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f3020c54e2cb..005f519c2648 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -447,7 +447,7 @@ static inline unsigned long cpu_kernelmode_gs_base(int cpu) DECLARE_PER_CPU(void *, hardirq_stack_ptr); DECLARE_PER_CPU(bool, hardirq_stack_inuse); -extern asmlinkage void ignore_sysret(void); +DECLARE_ASM_FUNC_SYMBOL(ignore_sysret); /* Save actual FS/GS selectors and bases to current->thread */ void current_save_fsgs(void); diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 8c5d1910a848..a6aa64eb3657 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h @@ -2,6 +2,7 @@ #ifndef _ASM_X86_PROTO_H #define _ASM_X86_PROTO_H +#include #include struct task_struct; @@ -11,26 +12,26 @@ struct task_struct; void syscall_init(void); #ifdef CONFIG_X86_64 -void entry_SYSCALL_64(void); -void entry_SYSCALL_64_safe_stack(void); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSCALL_64); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSCALL_64_safe_stack); long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2); #endif #ifdef CONFIG_X86_32 -void entry_INT80_32(void); -void entry_SYSENTER_32(void); -void __begin_SYSENTER_singlestep_region(void); -void __end_SYSENTER_singlestep_region(void); +DECLARE_ASM_FUNC_SYMBOL(entry_INT80_32); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSENTER_32); +DECLARE_ASM_FUNC_SYMBOL(__begin_SYSENTER_singlestep_region); +DECLARE_ASM_FUNC_SYMBOL(__end_SYSENTER_singlestep_region); #endif #ifdef CONFIG_IA32_EMULATION -void entry_SYSENTER_compat(void); -void __end_entry_SYSENTER_compat(void); -void entry_SYSCALL_compat(void); -void entry_SYSCALL_compat_safe_stack(void); -void entry_INT80_compat(void); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSENTER_compat); +DECLARE_ASM_FUNC_SYMBOL(__end_entry_SYSENTER_compat); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSCALL_compat); +DECLARE_ASM_FUNC_SYMBOL(entry_SYSCALL_compat_safe_stack); +DECLARE_ASM_FUNC_SYMBOL(entry_INT80_compat); #ifdef CONFIG_XEN_PV -void xen_entry_INT80_compat(void); +DECLARE_ASM_FUNC_SYMBOL(xen_entry_INT80_compat); #endif #endif diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index e7265a552f4f..502f72724b8d 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -17,12 +17,9 @@ */ /* Handles exceptions in both to and from, but doesn't do access_ok */ -__must_check unsigned long -copy_user_enhanced_fast_string(void *to, const void *from, unsigned len); -__must_check unsigned long -copy_user_generic_string(void *to, const void *from, unsigned len); -__must_check unsigned long -copy_user_generic_unrolled(void *to, const void *from, unsigned len); +DECLARE_ASM_FUNC_SYMBOL(copy_user_enhanced_fast_string); +DECLARE_ASM_FUNC_SYMBOL(copy_user_generic_string); +DECLARE_ASM_FUNC_SYMBOL(copy_user_generic_unrolled); static __always_inline __must_check unsigned long copy_user_generic(void *to, const void *from, unsigned len) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index e9da3dc71254..0c60a7fa6fa5 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -530,7 +530,7 @@ extern struct paravirt_patch_site __start_parainstructions[], * convention such that we can 'call' it from assembly. */ -extern void int3_magic(unsigned int *ptr); /* defined in asm */ +DECLARE_ASM_FUNC_SYMBOL(int3_magic); asm ( " .pushsection .init.text, \"ax\", @progbits\n" diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 1b3ce3b4a2a2..9e0c07a82b44 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -589,7 +589,7 @@ void arch_ftrace_trampoline_free(struct ftrace_ops *ops) #ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_DYNAMIC_FTRACE -extern void ftrace_graph_call(void); +DECLARE_ASM_FUNC_SYMBOL(ftrace_graph_call); static const char *ftrace_jmp_replace(unsigned long ip, unsigned long addr) { diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 04cafc057bed..7015ec9ca134 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -138,7 +138,7 @@ void paravirt_set_sched_clock(u64 (*func)(void)) } /* These are in entry.S */ -extern void native_iret(void); +DECLARE_ASM_FUNC_SYMBOL(native_iret); static struct resource reserve_ioports = { .start = 0, @@ -376,7 +376,7 @@ NOKPROBE_SYMBOL(native_get_debugreg); NOKPROBE_SYMBOL(native_set_debugreg); NOKPROBE_SYMBOL(native_load_idt); -void (*paravirt_iret)(void) = native_iret; +asm_func_t paravirt_iret = native_iret; #endif EXPORT_SYMBOL(pv_ops); diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 2837110e66ed..1f81f939d982 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -201,7 +201,7 @@ struct opcode { const struct escape *esc; const struct instr_dual *idual; const struct mode_dual *mdual; - void (*fastop)(struct fastop *fake); + fastop_t fastop; } u; int (*check_perm)(struct x86_emulate_ctxt *ctxt); }; @@ -322,7 +322,7 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); __FOP_RET(#name) #define FOP_START(op) \ - extern void em_##op(struct fastop *fake); \ + DECLARE_ASM_FUNC_SYMBOL(em_##op); \ asm(".pushsection .text, \"ax\" \n\t" \ ".global em_" #op " \n\t" \ ".align " __stringify(FASTOP_SIZE) " \n\t" \ diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 68b420289d7e..c9449ebee067 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -290,13 +290,8 @@ enum x86emul_mode { #define X86EMUL_SMM_MASK (1 << 6) #define X86EMUL_SMM_INSIDE_NMI_MASK (1 << 7) -/* - * fastop functions are declared as taking a never-defined fastop parameter, - * so they can't be called from C directly. - */ -struct fastop; - -typedef void (*fastop_t)(struct fastop *); +/* fastop functions cannot be called from C directly. */ +typedef asm_func_t fastop_t; struct x86_emulate_ctxt { void *vcpu; diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 03149422dce2..bbd6cc58f6a8 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -613,8 +613,8 @@ DEFINE_IDTENTRY_RAW(xenpv_exc_machine_check) #endif struct trap_array_entry { - void (*orig)(void); - void (*xen)(void); + asm_func_t orig; + asm_func_t xen; bool ist_okay; }; @@ -673,7 +673,7 @@ static bool __ref get_trap_addr(void **addr, unsigned int ist) struct trap_array_entry *entry = trap_array + nr; if (*addr == entry->orig) { - *addr = entry->xen; + *addr = (void *)entry->xen; ist_okay = entry->ist_okay; found = true; break; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 8d7ec49a35fb..b5ceb3007cfe 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -8,12 +8,12 @@ #include /* These are code, but not functions. Defined in entry.S */ -extern const char xen_failsafe_callback[]; +DECLARE_ASM_FUNC_SYMBOL(xen_failsafe_callback); -void xen_sysenter_target(void); +DECLARE_ASM_FUNC_SYMBOL(xen_sysenter_target); #ifdef CONFIG_X86_64 -void xen_syscall_target(void); -void xen_syscall32_target(void); +DECLARE_ASM_FUNC_SYMBOL(xen_syscall_target); +DECLARE_ASM_FUNC_SYMBOL(xen_syscall32_target); #endif extern void *xen_initial_gdt; @@ -136,7 +136,7 @@ __visible unsigned long xen_read_cr2(void); __visible unsigned long xen_read_cr2_direct(void); /* These are not functions, and cannot be called normally */ -__visible void xen_iret(void); +DECLARE_ASM_FUNC_SYMBOL(xen_iret); extern int xen_panic_handler_init(void); -- 2.33.0.rc2.250.ged5fa647cd-goog