From nobody Mon Feb 9 10:58:26 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1701165873; cv=none; d=zohomail.com; s=zohoarc; b=njRhO5rEF5Ibaoh5+sqaKUuRpMmQg/bfwJyfB8axNOyGklsv2b4NUz7o/0cRBtux4pLgK40X10KdEWuludf63TubnBueKYVbFvjSY4SEvgT71ag3qp5BoWQffNRoYHZjMTNh5Z4ZQfNdexsSROD5yQfdx6ke3lEZ8TCTp3yhf8E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1701165873; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=M3yKV/RFZSYIusyATo8RxWzm7Bfr63u910kNQKsr5wU=; b=YU5K1x9Z6ti2FJ2nrvmN6z9f/H3Ph2u1Uq2pAG1QqzCpjm2V1msq6Hr7TKaWfVzla/AQMBVlOo9934eFvsrYUox5RybBl6POMDuACGhPnqdDFjcAaw0ItCgz2YQTpDqYoMjneOrBVeZb5x4YfO1Tc4DJbeFmC1KIA9jrgjg2g3Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1701165873531806.9296165761667; Tue, 28 Nov 2023 02:04:33 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.642877.1002675 (Exim 4.92) (envelope-from ) id 1r7uws-0003AT-1W; Tue, 28 Nov 2023 10:04:10 +0000 Received: by outflank-mailman (output) from mailman id 642877.1002675; Tue, 28 Nov 2023 10:04:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r7uwr-0003A7-Tb; Tue, 28 Nov 2023 10:04:09 +0000 Received: by outflank-mailman (input) for mailman id 642877; Tue, 28 Nov 2023 10:04:08 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r7uwq-0002NP-9A for xen-devel@lists.xenproject.org; Tue, 28 Nov 2023 10:04:08 +0000 Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [2a00:1450:4864:20::231]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 77f89934-8dd5-11ee-98e3-6d05b1d4d9a1; Tue, 28 Nov 2023 11:04:07 +0100 (CET) Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2c9b5b72983so4151171fa.2 for ; Tue, 28 Nov 2023 02:04:07 -0800 (PST) Received: from localhost ([213.195.113.99]) by smtp.gmail.com with ESMTPSA id o7-20020a05600c510700b0040b36ad5413sm16784552wms.46.2023.11.28.02.04.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 02:04:06 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 77f89934-8dd5-11ee-98e3-6d05b1d4d9a1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1701165846; x=1701770646; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=M3yKV/RFZSYIusyATo8RxWzm7Bfr63u910kNQKsr5wU=; b=OppS1gb/idvKi6zG2UoTdtxquNDadKMPiBJHV5UO2LzZBfjyv+pIIqClBWykfpPmst Gx5HbEUzPOmLGNVmPkxYIAXgeWZaFLfIhBzELVrmzbojiU1kqxAWY4iQc14AJuUdW0rW O2ZDHwbgLKtYjC3NcuADjQjTbqR19soL1dquM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701165846; x=1701770646; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=M3yKV/RFZSYIusyATo8RxWzm7Bfr63u910kNQKsr5wU=; b=Vceb7xnvAYUSp9zXRYziV6aYF7PschBWcRaPkzDFIcmw/wtPc+trX8NA/pcyr8Ti2x IHXC3/lilTGcU0Wp+U58JuJD/I/wGL9cvZiSyoXYuUZS6R7Rc4iPzyw+xJ6l5NRK8P+w WgLqHcok4KtRdm1+0MRsVtIh/BYaWIlD/al7sfQRicR5STf4/IU1ofQsNgyOQiV0IZ9Q bIe0xlKijtUuVie76PuIros/sY67E0CpWTVUeFkrWEKQYUvkITt3q7lL/rej4nNWibAB VgtNW5OahX1vjcyB33wCnY55smvs1h4Suin30UPMXQjOXwiiE7FMSI3OFkH+vbbOPXSM Ro9Q== X-Gm-Message-State: AOJu0YyH2UzLOUaLiWWCzv9K6FKx48ykYzgdM39YKnqUoIFCE4QIORuS r1hHXgs01RrVhbu6NoufiNPlrdz2L+CVAvPJ0IE= X-Google-Smtp-Source: AGHT+IGUr4ORQZi+oIxzqruDPiO803YUuddIpmkAqngLT3LpdjlpHf0BiBh0Sx7bAd60OcacEiNMAw== X-Received: by 2002:ac2:504f:0:b0:50b:bf06:ea0b with SMTP id a15-20020ac2504f000000b0050bbf06ea0bmr405848lfm.53.1701165846522; Tue, 28 Nov 2023 02:04:06 -0800 (PST) From: Roger Pau Monne To: xen-devel@lists.xenproject.org Cc: Roger Pau Monne , Wei Liu , Anthony PERARD , Juergen Gross , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini Subject: [PATCH v2 3/5] xen/x86: introduce self modifying code test Date: Tue, 28 Nov 2023 11:03:50 +0100 Message-ID: <20231128100352.35430-4-roger.pau@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231128100352.35430-1-roger.pau@citrix.com> References: <20231128100352.35430-1-roger.pau@citrix.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1701165875606000001 Introduce a helper to perform checks related to self modifying code, and st= art by creating a simple test to check that alternatives have been applied. Such test is hooked into the boot process and called just after alternatives have been applied. In case of failure a message is printed, and the hyperv= isor is tainted as not having passed the tests, this does require introducing a = new taint bit (printed as 'A'). A new sysctl is also introduced to run the tests on demand. While there ar= e no current users introduced here, further changes will introduce those, and it= 's helpful to have the interface defined in the sysctl header from the start. Signed-off-by: Roger Pau Monn=C3=A9 --- Changes since v1: - Rework test and interface. --- tools/include/xenctrl.h | 2 + tools/libs/ctrl/xc_misc.c | 14 ++++++ xen/arch/x86/Makefile | 1 + xen/arch/x86/include/asm/test-smc.h | 18 ++++++++ xen/arch/x86/setup.c | 3 ++ xen/arch/x86/sysctl.c | 7 +++ xen/arch/x86/test-smc.c | 68 +++++++++++++++++++++++++++++ xen/common/kernel.c | 5 ++- xen/include/public/sysctl.h | 9 ++++ xen/include/xen/lib.h | 1 + 10 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 xen/arch/x86/include/asm/test-smc.h create mode 100644 xen/arch/x86/test-smc.c diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h index 2ef8b4e05422..0f87ffa4affd 100644 --- a/tools/include/xenctrl.h +++ b/tools/include/xenctrl.h @@ -2658,6 +2658,8 @@ int xc_dt_overlay(xc_interface *xch, void *overlay_fd= t, uint32_t overlay_fdt_size, uint8_t overlay_op); #endif =20 +int xc_test_smc(xc_interface *xch, uint32_t tests, uint32_t *result); + /* Compat shims */ #include "xenctrl_compat.h" =20 diff --git a/tools/libs/ctrl/xc_misc.c b/tools/libs/ctrl/xc_misc.c index 5ecdfa2c7934..7f7ece589cc2 100644 --- a/tools/libs/ctrl/xc_misc.c +++ b/tools/libs/ctrl/xc_misc.c @@ -1021,6 +1021,20 @@ int xc_livepatch_replace(xc_interface *xch, char *na= me, uint32_t timeout, uint32 return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeo= ut, flags); } =20 +int xc_test_smc(xc_interface *xch, uint32_t tests, uint32_t *result) +{ + struct xen_sysctl sysctl =3D { + .cmd =3D XEN_SYSCTL_test_smc, + .u.smc.tests =3D tests, + }; + int rc =3D do_sysctl(xch, &sysctl); + + if ( !rc ) + *result =3D sysctl.u.smc.results; + + return rc; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index f629157086d0..bdd2183a2fd7 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -65,6 +65,7 @@ obj-y +=3D smpboot.o obj-y +=3D spec_ctrl.o obj-y +=3D srat.o obj-y +=3D string.o +obj-y +=3D test-smc.o obj-y +=3D time.o obj-y +=3D traps.o obj-y +=3D tsx.o diff --git a/xen/arch/x86/include/asm/test-smc.h b/xen/arch/x86/include/asm= /test-smc.h new file mode 100644 index 000000000000..18b23dbdbf2d --- /dev/null +++ b/xen/arch/x86/include/asm/test-smc.h @@ -0,0 +1,18 @@ +#ifndef _ASM_X86_TEST_SMC_H_ +#define _ASM_X86_TEST_SMC_H_ + +#include + +int test_smc(uint32_t selection, uint32_t *results); + +#endif /* _ASM_X86_TEST_SMC_H_ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index f6b8a3efd752..1f90d30204fe 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -58,6 +58,7 @@ #include #include #include +#include =20 /* opt_nosmp: If true, secondary processors are ignored. */ static bool __initdata opt_nosmp; @@ -1952,6 +1953,8 @@ void __init noreturn __start_xen(unsigned long mbi_p) =20 alternative_branches(); =20 + test_smc(XEN_SYSCTL_TEST_SMC_ALL, NULL); + /* * NB: when running as a PV shim VCPUOP_up/down is wired to the shim * physical cpu_add/remove functions, so launch the guest with only diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 1d40d82c5ad2..77d091f4bd59 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -423,6 +424,12 @@ long arch_do_sysctl( break; } =20 + case XEN_SYSCTL_test_smc: + ret =3D test_smc(sysctl->u.smc.tests, &sysctl->u.smc.results); + if ( !ret && __copy_field_to_guest(u_sysctl, sysctl, u.smc.results= ) ) + ret =3D -EFAULT; + break; + default: ret =3D -ENOSYS; break; diff --git a/xen/arch/x86/test-smc.c b/xen/arch/x86/test-smc.c new file mode 100644 index 000000000000..8916c185d60a --- /dev/null +++ b/xen/arch/x86/test-smc.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include + +#include +#include +#include + +static bool cf_check test_insn_replacement(void) +{ +#define EXPECTED_VALUE 2 + unsigned int r =3D ~EXPECTED_VALUE; + + alternative_io("", "mov $" STR(EXPECTED_VALUE) ", %0", + X86_FEATURE_ALWAYS, "=3Dr"(r)); + + return r =3D=3D EXPECTED_VALUE; +#undef EXPECTED_VALUE +} + +int test_smc(uint32_t selection, uint32_t *results) +{ + struct { + unsigned int mask; + bool (*test)(void); + const char *name; + } static const tests[] =3D { + { XEN_SYSCTL_TEST_SMC_INSN_REPL, &test_insn_replacement, + "alternative instruction replacement" }, + }; + unsigned int i; + + if ( selection & ~XEN_SYSCTL_TEST_SMC_ALL ) + return -EINVAL; + + if ( results ) + *results =3D 0; + + printk(XENLOG_INFO "Checking Self Modify Code\n"); + + for ( i =3D 0; i < ARRAY_SIZE(tests); i++ ) + { + if ( !(selection & tests[i].mask) ) + continue; + + if ( tests[i].test() ) + { + if ( results ) + *results |=3D tests[i].mask; + continue; + } + + add_taint(TAINT_ERROR_SMC); + printk(XENLOG_ERR "%s test failed\n", tests[i].name); + } + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 08dbaa2a054c..fed7ed0d587f 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -386,13 +386,14 @@ char *print_tainted(char *str) { if ( tainted ) { - snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c%c%c", + snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c%c%c%c", tainted & TAINT_MACHINE_INSECURE ? 'I' : ' ', tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ', tainted & TAINT_ERROR_INJECT ? 'E' : ' ', tainted & TAINT_HVM_FEP ? 'H' : ' ', - tainted & TAINT_CPU_OUT_OF_SPEC ? 'S' : ' '); + tainted & TAINT_CPU_OUT_OF_SPEC ? 'S' : ' ', + tainted & TAINT_ERROR_SMC ? 'A' : ' '); } else { diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 9b19679caeb1..94287009387c 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -1201,6 +1201,13 @@ struct xen_sysctl_dt_overlay { }; #endif =20 +struct xen_sysctl_test_smc { + uint32_t tests; /* IN: bitmap with selected tests to execute. */ +#define XEN_SYSCTL_TEST_SMC_INSN_REPL (1U << 0) +#define XEN_SYSCTL_TEST_SMC_ALL (XEN_SYSCTL_TEST_SMC_INSN_REPL) + uint32_t results; /* OUT: test result: 1 -> success, 0 -> failure. */ +}; + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -1232,6 +1239,7 @@ struct xen_sysctl { /* #define XEN_SYSCTL_set_parameter 28 */ #define XEN_SYSCTL_get_cpu_policy 29 #define XEN_SYSCTL_dt_overlay 30 +#define XEN_SYSCTL_test_smc 31 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -1261,6 +1269,7 @@ struct xen_sysctl { struct xen_sysctl_livepatch_op livepatch; #if defined(__i386__) || defined(__x86_64__) struct xen_sysctl_cpu_policy cpu_policy; + struct xen_sysctl_test_smc smc; #endif =20 #if defined(__arm__) || defined (__aarch64__) diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 1793be5b6b89..1bec6a01b18a 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -167,6 +167,7 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c); #define TAINT_HVM_FEP (1u << 3) #define TAINT_MACHINE_INSECURE (1u << 4) #define TAINT_CPU_OUT_OF_SPEC (1u << 5) +#define TAINT_ERROR_SMC (1U << 6) extern unsigned int tainted; #define TAINT_STRING_MAX_LEN 20 extern char *print_tainted(char *str); --=20 2.43.0