From nobody Thu Nov 28 09:38:07 2024 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD80019F406 for ; Wed, 2 Oct 2024 09:25:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727861150; cv=none; b=AZjPjLbehlQ0oYsoZDcz0VjKEx7ivWrbbIh88FaPGhBKl8sFEZ1qBu6e6/pik407dNUGS+LxTA/0o7ab44k9jpWv3ImCPIr+8KBYO02okYT3KOdaQRqTpATyBx9bien2v2wTCPa6oLp7uWgh3mMRRQtAHmX03yKvQSvU+lQCZT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727861150; c=relaxed/simple; bh=jkOhvIJFzwlypDxF5YYVCihy/SSMSVQh8E+lvmQS/3E=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=HXzVjSVQjme6KhPEt2a35xAjCiD3arucRQgOqqixF/hVU6ebz8N1lY6QFqG3x6T31qfoi4yn29RjUEg4pEBSfVg1gZjlmHqdkoJO+6r62zVzr1De75jQyR3xrYw0jqjKIf6kMRx/fliG0IxMf2equXhchazNQTd+Qyjml6Uai40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Xmglu/Sy; arc=none smtp.client-ip=209.85.218.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Xmglu/Sy" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-a8a7463c3d0so17149266b.2 for ; Wed, 02 Oct 2024 02:25:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727861146; x=1728465946; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=5ollbz8c+bB7Kyjb7uPuwWKRTLiK7jYrmwZYzwGbbGo=; b=Xmglu/Sy2tN6d4/k8KAfewARL0jGdFUXWFbPx6jMQXrGstFhMMe3k0cEGAXY+sX5ZC 1gxzmIt8b1klZezVdMhLmtWLalvMw/0MltvnhrCI6A0AaiTrIqiL6DxDYiel8cDyry84 eU1SeFvfZnXPjh89+EKoL2pfUsTn6iQIrL8hZ2Ct6kdMVd5VWOFiZAJYYWXble8xHfov amTMF5BwY0mvg0K0uKAPWngNHJnjJkm55b2/gb/HTZ0VvYYBtpOr+U8b4Yi1yOwCHTKD mD5GQP0RP6OuBXhzWYSlefcGWkoef0JH1BNVNDUclcqvKrWeFq3QechIuxfVPDey4Jcm OPKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727861146; x=1728465946; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=5ollbz8c+bB7Kyjb7uPuwWKRTLiK7jYrmwZYzwGbbGo=; b=QSbR3PkfMnyjbj8toMhJx6CkJefWnN0r8Pdt0M9k0vOOqOsHS8UrSwob7GWOZrGaZ+ t6stoNJCwU6Pjr+aKe5zPIJ9PCrPCnlEyIRhzpohKmFlyEMiauZyZm3ka/OEKIQr9IRw MwCjm8yI+4h5IVKqdfGdpQSxnf9HFndTAh5Pe5irS6ig1n79EfIyS/x87Ikbokb4CtSO 1IHG1xqP67vWgt2FcFYNa1gSqpGpdOo6cXXoNFoapBV4wzAuSdiP7+8M1Vrp5tGci9/h tYbaYfoY6Z+OCwHdX/B/7Q0JV0l5WKyZXjxtzS9YjBM2aVx6Ij1zHilYLsHBnluf3LZV 7teA== X-Forwarded-Encrypted: i=1; AJvYcCVVU4RWffMWV+NytmS82Y9VJNQtGipAGPAEMn1hT+RW9fo5e8Nrj+nnf3yTIjLGsa8ZdObcJjaPYfVEYkE=@vger.kernel.org X-Gm-Message-State: AOJu0YwW/ncsqA3TSdHgcNMoFVeO80IU42cjeISwd0a/v9wPntCRMXxb rCGJZ1UnRNToswKWuFvRqL9x59fuPltrrBR5hSY/ryesZ9nDL8399iInh1wIiV7EhSuyzA== X-Google-Smtp-Source: AGHT+IHxzYeJufPU4CpPO21AfUtt8gvJswNciwLBD+I3TZS2zkFMNpfb0MVOWY7y9Yyscz/1Az+gA+M/ X-Received: from palermo.c.googlers.com ([fda3:e722:ac3:cc00:7b:198d:ac11:8138]) (user=ardb job=sendgmr) by 2002:a17:906:52c8:b0:a7a:8eef:7640 with SMTP id a640c23a62f3a-a98f834bb5emr114566b.8.1727861145742; Wed, 02 Oct 2024 02:25:45 -0700 (PDT) Date: Wed, 2 Oct 2024 11:25:35 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=4844; i=ardb@kernel.org; h=from:subject; bh=/9G5pIkj16wJJBC7+tVn5gr0UvoCw53qGK7jQPTaWb4=; b=owGbwMvMwCFmkMcZplerG8N4Wi2JIe2vYH92D/PuQN6cg+ufHQztsLxp2WsleKvp1jrHM5YLd 18/JJbfUcrCIMbBICumyCIw+++7nacnStU6z5KFmcPKBDKEgYtTACYS+oDhN8vXq9+2frum1+L5 XUFiDs/Z7zt2R5blez9Nb/ef9uySSg3DX/G3u7kmHz9uY2BV0lIaxn6pbzqn73ObxLaftptuCfp rsAMA X-Mailer: git-send-email 2.46.1.824.gd892dcdcdd-goog Message-ID: <20241002092534.3163838-2-ardb+git@google.com> Subject: [PATCH] x86/stackprotector: Work around strict Clang TLS symbol requirements From: Ard Biesheuvel To: x86@kernel.org Cc: llvm@lists.linux.dev, linux-kernel@vger.kernel.org, Ard Biesheuvel , stable@vger.kernel.org, Fangrui Song , Brian Gerst , Uros Bizjak , Nathan Chancellor , Andy Lutomirski Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ard Biesheuvel GCC and Clang both implement stack protector support based on Thread Local Storage (TLS) variables, and this is used in the kernel to implement per-task stack cookies, by copying a task's stack cookie into a per-CPU variable every time it is scheduled in. Both now also implement -mstack-protector-guard-symbol=3D, which permits the TLS variable to be specified directly. This is useful because it will allow us to move away from using a fixed offset of 40 bytes into the per-CPU area on x86_64, which requires a lot of special handling in the per-CPU code and the runtime relocation code. However, while GCC is rather lax in its implementation of this command line option, Clang actually requires that the provided symbol name refers to a TLS variable (i.e., one declared with __thread), although it also permits the variable to be undeclared entirely, in which case it will use an implicit declaration of the right type. The upshot of this is that Clang will emit the correct references to the stack cookie variable in most cases, e.g., 10d: 64 a1 00 00 00 00 mov %fs:0x0,%eax 10f: R_386_32 __stack_chk_guard However, if a non-TLS definition of the symbol in question is visible in the same compilation unit (which amounts to the whole of vmlinux if LTO is enabled), it will drop the per-CPU prefix and emit a load from a bogus address. Work around this by using a symbol name that never occurs in C code, and emit it as an alias in the linker script. Fixes: 3fb0fdb3bbe7 ("x86/stackprotector/32: Make the canary into a regular= percpu variable") Cc: Cc: Fangrui Song Cc: Brian Gerst Cc: Uros Bizjak Cc: Nathan Chancellor Cc: Andy Lutomirski Link: https://github.com/ClangBuiltLinux/linux/issues/1854 Signed-off-by: Ard Biesheuvel --- arch/x86/Makefile | 5 +++-- arch/x86/entry/entry.S | 16 ++++++++++++++++ arch/x86/kernel/cpu/common.c | 2 ++ arch/x86/kernel/vmlinux.lds.S | 3 +++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index cd75e78a06c1..5b773b34768d 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -142,9 +142,10 @@ ifeq ($(CONFIG_X86_32),y) =20 ifeq ($(CONFIG_STACKPROTECTOR),y) ifeq ($(CONFIG_SMP),y) - KBUILD_CFLAGS +=3D -mstack-protector-guard-reg=3Dfs -mstack-protector-g= uard-symbol=3D__stack_chk_guard + KBUILD_CFLAGS +=3D -mstack-protector-guard-reg=3Dfs \ + -mstack-protector-guard-symbol=3D__ref_stack_= chk_guard else - KBUILD_CFLAGS +=3D -mstack-protector-guard=3Dglobal + KBUILD_CFLAGS +=3D -mstack-protector-guard=3Dglobal endif endif else diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S index d9feadffa972..a503e6d535f8 100644 --- a/arch/x86/entry/entry.S +++ b/arch/x86/entry/entry.S @@ -46,3 +46,19 @@ EXPORT_SYMBOL_GPL(mds_verw_sel); .popsection =20 THUNK warn_thunk_thunk, __warn_thunk + +#ifndef CONFIG_X86_64 +/* + * Clang's implementation of TLS stack cookies requires the variable in + * question to be a TLS variable. If the variable happens to be defined as= an + * ordinary variable with external linkage in the same compilation unit (w= hich + * amounts to the whole of vmlinux with LTO enabled), Clang will drop the + * segment register prefix from the references, resulting in broken code. = Work + * around this by avoiding the symbol used in -mstack-protector-guard-symb= ol=3D + * entirely in the C code, and use an alias emitted by the linker script + * instead. + */ +#ifdef CONFIG_STACKPROTECTOR +EXPORT_SYMBOL(__ref_stack_chk_guard); +#endif +#endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 07a34d723505..ba83f54dfaa8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2085,8 +2085,10 @@ void syscall_init(void) =20 #ifdef CONFIG_STACKPROTECTOR DEFINE_PER_CPU(unsigned long, __stack_chk_guard); +#ifndef CONFIG_SMP EXPORT_PER_CPU_SYMBOL(__stack_chk_guard); #endif +#endif =20 #endif /* CONFIG_X86_64 */ =20 diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 2b7c8c14c6fd..a80ad2bf8da4 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -490,6 +490,9 @@ SECTIONS . =3D ASSERT((_end - LOAD_OFFSET <=3D KERNEL_IMAGE_SIZE), "kernel image bigger than KERNEL_IMAGE_SIZE"); =20 +/* needed for Clang - see arch/x86/entry/entry.S */ +PROVIDE(__ref_stack_chk_guard =3D __stack_chk_guard); + #ifdef CONFIG_X86_64 /* * Per-cpu symbols which need to be offset from __per_cpu_load --=20 2.46.1.824.gd892dcdcdd-goog