From: Kyle Huey <me(a)kylehuey.com>
When management of the PKRU register was moved away from XSTATE, emulation
of PKRU's existence in XSTATE was added for reading PKRU through ptrace,
but not for writing PKRU through ptrace. This can be seen by running gdb
and executing `p $pkru`, `set $pkru = 42`, and `p $pkru`. On affected
kernels (5.14+) the write to the PKRU register (which gdb performs through
ptrace) is ignored.
There are three APIs that write PKRU: sigreturn, PTRACE_SETREGSET with
NT_X86_XSTATE, and KVM_SET_XSAVE. sigreturn still uses XRSTOR to write to
PKRU. KVM_SET_XSAVE has its own special handling to make PKRU writes take
effect (in fpu_copy_uabi_to_guest_fpstate). Push that down into
copy_uabi_to_xstate and have PTRACE_SETREGSET with NT_X86_XSTATE pass in
a pointer to the appropriate PKRU slot. copy_sigframe_from_user_to_xstate
depends on copy_uabi_to_xstate populating the PKRU field in the task's
XSTATE so that __fpu_restore_sig can do a XRSTOR from it, so continue doing
that.
This also adds code to initialize the PKRU value to the hardware init value
(namely 0) if the PKRU bit is not set in the XSTATE header provided to
ptrace, to match XRSTOR.
Fixes: e84ba47e313d ("x86/fpu: Hook up PKRU into ptrace()")
Signed-off-by: Kyle Huey <me(a)kylehuey.com>
Cc: Dave Hansen <dave.hansen(a)linux.intel.com>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Borislav Petkov <bp(a)suse.de>
Cc: stable(a)vger.kernel.org # 5.14+
---
arch/x86/kernel/fpu/core.c | 20 +++++++++-----------
arch/x86/kernel/fpu/regset.c | 2 +-
arch/x86/kernel/fpu/signal.c | 2 +-
arch/x86/kernel/fpu/xstate.c | 25 ++++++++++++++++++++-----
arch/x86/kernel/fpu/xstate.h | 4 ++--
5 files changed, 33 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 3b28c5b25e12..c273669e8a00 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -391,8 +391,6 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
{
struct fpstate *kstate = gfpu->fpstate;
const union fpregs_state *ustate = buf;
- struct pkru_state *xpkru;
- int ret;
if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) {
if (ustate->xsave.header.xfeatures & ~XFEATURE_MASK_FPSSE)
@@ -406,16 +404,16 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
if (ustate->xsave.header.xfeatures & ~xcr0)
return -EINVAL;
- ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
- if (ret)
- return ret;
+ /*
+ * Nullify @vpkru to preserve its current value if PKRU's bit isn't set
+ * in the header. KVM's odd ABI is to leave PKRU untouched in this
+ * case (all other components are eventually re-initialized).
+ * (Not clear that this is actually necessary for compat).
+ */
+ if (!(ustate->xsave.header.xfeatures & XFEATURE_MASK_PKRU))
+ vpkru = NULL;
- /* Retrieve PKRU if not in init state */
- if (kstate->regs.xsave.header.xfeatures & XFEATURE_MASK_PKRU) {
- xpkru = get_xsave_addr(&kstate->regs.xsave, XFEATURE_PKRU);
- *vpkru = xpkru->pkru;
- }
- return 0;
+ return copy_uabi_from_kernel_to_xstate(kstate, ustate, vpkru);
}
EXPORT_SYMBOL_GPL(fpu_copy_uabi_to_guest_fpstate);
#endif /* CONFIG_KVM */
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index 75ffaef8c299..6d056b68f4ed 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -167,7 +167,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
}
fpu_force_restore(fpu);
- ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf);
+ ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf, &target->thread.pkru);
out:
vfree(tmpbuf);
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 91d4b6de58ab..558076dbde5b 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -396,7 +396,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
fpregs = &fpu->fpstate->regs;
if (use_xsave() && !fx_only) {
- if (copy_sigframe_from_user_to_xstate(fpu->fpstate, buf_fx))
+ if (copy_sigframe_from_user_to_xstate(tsk, buf_fx))
return false;
} else {
if (__copy_from_user(&fpregs->fxsave, buf_fx,
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index c8340156bfd2..8f14981a3936 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1197,7 +1197,7 @@ static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
- const void __user *ubuf)
+ const void __user *ubuf, u32 *pkru)
{
struct xregs_state *xsave = &fpstate->regs.xsave;
unsigned int offset, size;
@@ -1246,6 +1246,21 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
}
}
+ /*
+ * Update the user protection key storage. Allow KVM to
+ * pass in a NULL pkru pointer if the mask bit is unset
+ * for its legacy ABI behavior.
+ */
+ if (pkru)
+ *pkru = 0;
+
+ if (hdr.xfeatures & XFEATURE_MASK_PKRU) {
+ struct pkru_state *xpkru;
+
+ xpkru = __raw_xsave_addr(xsave, XFEATURE_PKRU);
+ *pkru = xpkru->pkru;
+ }
+
/*
* The state that came in from userspace was user-state only.
* Mask all the user states out of 'xfeatures':
@@ -1264,9 +1279,9 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
* Convert from a ptrace standard-format kernel buffer to kernel XSAVE[S]
* format and copy to the target thread. Used by ptrace and KVM.
*/
-int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
+int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru)
{
- return copy_uabi_to_xstate(fpstate, kbuf, NULL);
+ return copy_uabi_to_xstate(fpstate, kbuf, NULL, pkru);
}
/*
@@ -1274,10 +1289,10 @@ int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
* XSAVE[S] format and copy to the target thread. This is called from the
* sigreturn() and rt_sigreturn() system calls.
*/
-int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate,
+int copy_sigframe_from_user_to_xstate(struct task_struct *tsk,
const void __user *ubuf)
{
- return copy_uabi_to_xstate(fpstate, NULL, ubuf);
+ return copy_uabi_to_xstate(tsk->thread.fpu.fpstate, NULL, ubuf, &tsk->thread.pkru);
}
static bool validate_independent_components(u64 mask)
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index 5ad47031383b..a4ecb04d8d64 100644
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -46,8 +46,8 @@ extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
u32 pkru_val, enum xstate_copy_mode copy_mode);
extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode mode);
-extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf);
-extern int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate, const void __user *ubuf);
+extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru);
+extern int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void __user *ubuf);
extern void fpu__init_cpu_xstate(void);
--
2.37.2
Changelog since v5:
- Avoids a second copy from the uabi buffer as suggested.
- Preserves old KVM_SET_XSAVE behavior where leaving the PKRU bit in the
XSTATE header results in PKRU remaining unchanged instead of
reinitializing it.
- Fixed up patch metadata as requested.
Changelog since v4:
- Selftest additionally checks PKRU readbacks through ptrace.
- Selftest flips all PKRU bits (except the default key).
Changelog since v3:
- The v3 patch is now part 1 of 2.
- Adds a selftest in part 2 of 2.
Changelog since v2:
- Removed now unused variables in fpu_copy_uabi_to_guest_fpstate
Changelog since v1:
- Handles the error case of copy_to_buffer().
hi,
The test error is caused by g_vsyscall set failed.
Error output:
selftests: proc: proc-pid-vm
proc-pid-vm: proc-pid-vm.c:389: main: Assertion `rv == len' failed.
Aborted
g_vsyscall is set to 0.
In proc-pid-vm.c:
/*
* 0: vsyscall VMA doesn't exist vsyscall=none
* 1: vsyscall VMA is r-xp vsyscall=emulate
* 2: vsyscall VMA is --xp vsyscall=xonly
*/
static int g_vsyscall;
static const char *str_vsyscall;
static const char str_vsyscall_0[] = "";
static const char str_vsyscall_1[] =
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
static const char str_vsyscall_2[] =
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n";
The /proc/%u/maps output is:
buf=100000000-100001000 r-xp 00000000 00:2d 2 /tmp/#2 (deleted)
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
So the g_vsyscall should be 2 according to commentary(2: vsyscall VMA is --xp).
Is it a bug?
best regards,
Libhugetlbfs is not being maintained actively, and some distro is
dropping support for it. There are some tests that are good for testing
hugetlb functionality in kernel, which can be migrated to either kernel
kselftests or LTP.
I am submitting this patch to get comments from community on the
following
1. The test framework in ltp is most suitable for the tests that are
in libhugetlbfs/tests/ which follow similar test framework. And there
is already a section for hugetlb specific tests in LTP. So it makes
more sense and less effort to migrate the test to LTP. Though I
recommend migrating these tests to LTP, I would like to discuss tests
should be migrated to LTP or kselftests.
2. Libhugetlbfs tests has license GNU Lesser GPL 2.1 or later, while
kernel and LTP has license GPL2 or later, so can the test be
migrated to kernel/kselftests or LTP.
The below patch is libhugetlbfs/tests/direct.c which has been migrated
to ltp/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
Signed-off-by: Tarun Sahu <tsahu(a)linux.ibm.com>
---
runtest/hugetlb | 2 +
testcases/kernel/mem/.gitignore | 1 +
.../kernel/mem/hugetlb/hugemmap/hugemmap07.c | 106 ++++++++++++++++++
3 files changed, 109 insertions(+)
create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
diff --git a/runtest/hugetlb b/runtest/hugetlb
index f719217ab..ee02835d3 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -3,6 +3,8 @@ hugemmap02 hugemmap02
hugemmap04 hugemmap04
hugemmap05 hugemmap05
hugemmap06 hugemmap06
+hugemmap07 hugemmap07
+
hugemmap05_1 hugemmap05 -m
hugemmap05_2 hugemmap05 -s
hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index ff2910533..df5256ec8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -4,6 +4,7 @@
/hugetlb/hugemmap/hugemmap04
/hugetlb/hugemmap/hugemmap05
/hugetlb/hugemmap/hugemmap06
+/hugetlb/hugemmap/hugemmap07
/hugetlb/hugeshmat/hugeshmat01
/hugetlb/hugeshmat/hugeshmat02
/hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
new file mode 100644
index 000000000..798735ed0
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
@@ -0,0 +1,106 @@
+/*
+ * License/Copyright Details
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "tst_test.h"
+
+#define P0 "ffffffff"
+#define IOSZ 4096
+char buf[IOSZ] __attribute__((aligned(IOSZ)));
+static int fildes = -1, nfildes = -1;
+static char TEMPFILE[MAXPATHLEN];
+static char NTEMPFILE[MAXPATHLEN];
+
+void test_directio(void)
+{
+ long hpage_size;
+ void *p;
+ int ret;
+
+ hpage_size = SAFE_READ_MEMINFO("Hugepagesize:");
+
+ fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0600);
+ nfildes = SAFE_OPEN(NTEMPFILE, O_CREAT|O_EXCL|O_RDWR|O_DIRECT, 0600);
+
+ p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fildes, 0);
+ if (p == MAP_FAILED)
+ tst_brk(TFAIL | TERRNO, "mmap() Failed on %s", TEMPFILE);
+
+ memcpy(p, P0, 8);
+
+ /* Direct write from huge page */
+ ret = write(nfildes, p, IOSZ);
+ if (ret == -1)
+ tst_brk(TFAIL | TERRNO, "Direct-IO write from huge page");
+ if (ret != IOSZ)
+ tst_brk(TFAIL, "Short direct-IO write from huge page");
+ if (lseek(nfildes, 0, SEEK_SET) == -1)
+ tst_brk(TFAIL | TERRNO, "lseek");
+
+ /* Check for accuracy */
+ ret = read(nfildes, buf, IOSZ);
+ if (ret == -1)
+ tst_brk(TFAIL | TERRNO, "Direct-IO read to normal memory");
+ if (ret != IOSZ)
+ tst_brk(TFAIL, "Short direct-IO read to normal memory");
+ if (memcmp(P0, buf, 8))
+ tst_brk(TFAIL, "Memory mismatch after Direct-IO write");
+ if (lseek(nfildes, 0, SEEK_SET) == -1)
+ tst_brk(TFAIL | TERRNO, "lseek");
+
+ /* Direct read to huge page */
+ memset(p, 0, IOSZ);
+ ret = read(nfildes, p, IOSZ);
+ if (ret == -1)
+ tst_brk(TFAIL | TERRNO, "Direct-IO read to huge page");
+ if (ret != IOSZ)
+ tst_brk(TFAIL, "Short direct-IO read to huge page");
+
+ /* Check for accuracy */
+ if (memcmp(p, P0, 8))
+ tst_brk(TFAIL, "Memory mismatch after Direct-IO read");
+ tst_res(TPASS, "Successfully tested Hugepage Direct I/O");
+}
+
+void setup(void)
+{
+ if (tst_hugepages == 0)
+ tst_brk(TCONF, "Not enough hugepages for testing.");
+
+ if (!Hopt)
+ Hopt = tst_get_tmpdir();
+ SAFE_MOUNT("none", Hopt, "hugetlbfs", 0, NULL);
+
+ snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid());
+ snprintf(NTEMPFILE, sizeof(NTEMPFILE), "%s/nmmapfile%d", "/home/", getpid());
+}
+
+void cleanup(void)
+{
+ close(fildes);
+ close(nfildes);
+ remove(TEMPFILE);
+ remove(NTEMPFILE);
+ umount2(Hopt, MNT_DETACH);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .needs_tmpdir = 1,
+ .options = (struct tst_option[]) {
+ {"H:", &Hopt, "Location of hugetlbfs, i.e. -H /var/hugetlbfs"},
+ {"s:", &nr_opt, "Set the number of the been allocated hugepages"},
+ {}
+ },
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = test_directio,
+ .hugepages = {2, TST_REQUEST},
+};
--
2.31.1
This patchset contains minor fixes and cleanups for DAMON including
- selftest for a bug we found before (Patch 1),
- fix of region holes in vaddr corner case and a kunit test for it
(Patches 2 and 3), and
- documents/Kconfig updates for title wordsmithing (Patch 4) and more
aggressive DAMON debugfs interface deprecation announcement
(Patches 5-7).
SeongJae Park (7):
selftest/damon: add a test for duplicate context dirs creation
mm/damon/core: avoid holes in newly set monitoring target ranges
mm/damon/core-test: test damon_set_regions
Docs/admin-guide/mm/damon: rename the title of the document
mm/damon/Kconfig: Notify debugfs deprecation plan
Docs/DAMON/start: mention the dependency as sysfs instead of debugfs
Docs/admin-guide/mm/damon/usage: note DAMON debugfs interface
deprecation plan
Documentation/admin-guide/mm/damon/index.rst | 6 ++---
Documentation/admin-guide/mm/damon/start.rst | 13 +++------
Documentation/admin-guide/mm/damon/usage.rst | 5 ++++
mm/damon/Kconfig | 3 +++
mm/damon/core-test.h | 23 ++++++++++++++++
mm/damon/core.c | 24 +++++++++++++++++
tools/testing/selftests/damon/Makefile | 1 +
.../debugfs_duplicate_context_creation.sh | 27 +++++++++++++++++++
8 files changed, 89 insertions(+), 13 deletions(-)
create mode 100644 tools/testing/selftests/damon/debugfs_duplicate_context_creation.sh
--
2.25.1
Hi All,
Intel's Trust Domain Extensions (TDX) protect guest VMs from malicious
hosts and some physical attacks. VM guest with TDX support is called
as a TDX Guest.
In TDX guest, attestation process is used to verify the TDX guest
trustworthiness to other entities before provisioning secrets to the
guest. For example, a key server may request for attestation before
releasing the encryption keys to mount the encrypted rootfs or
secondary drive.
This patch set adds attestation support for the TDX guest. Details
about the TDX attestation process and the steps involved are explained
in the commit log of Patch 1/3 or in Documentation/x86/tdx.rst (added
by patch 3/3).
Following are the details of the patch set:
Patch 1/3 -> Adds TDREPORT support.
Patch 2/3 -> Adds selftest support for TDREPORT feature.
Patch 3/3 -> Add attestation related documentation.
Commit log history is maintained in the individual patches.
Kuppuswamy Sathyanarayanan (3):
x86/tdx: Add TDX Guest attestation interface driver
selftests: tdx: Test TDX attestation GetReport support
Documentation/x86: Document TDX attestation process
Documentation/x86/tdx.rst | 75 +++++++++
arch/x86/coco/tdx/tdx.c | 112 +++++++++++++
arch/x86/include/uapi/asm/tdx.h | 54 ++++++
tools/arch/x86/include/uapi/asm/tdx.h | 54 ++++++
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/tdx/Makefile | 11 ++
tools/testing/selftests/tdx/config | 1 +
tools/testing/selftests/tdx/tdx_attest_test.c | 155 ++++++++++++++++++
8 files changed, 463 insertions(+)
create mode 100644 arch/x86/include/uapi/asm/tdx.h
create mode 100644 tools/arch/x86/include/uapi/asm/tdx.h
create mode 100644 tools/testing/selftests/tdx/Makefile
create mode 100644 tools/testing/selftests/tdx/config
create mode 100644 tools/testing/selftests/tdx/tdx_attest_test.c
--
2.34.1
Hi Linus,
Please pull the following KUnit fixes update for Linux 6.0-rc5.
This KUnit fixes update for Linux 6.0-rc5 consists of 2 fixes to test
build and a fix to incorrect taint reason reporting.
Please note that this update touches drivers/thunderbolt and drivers/virt
Kconfig files.
diff is attached.
thanks,
-- Shuah
----------------------------------------------------------------
The following changes since commit 41a55567b9e31cb852670684404654ec4fd0d8d6:
module: kunit: Load .kunit_test_suites section when CONFIG_KUNIT=m (2022-08-15 13:51:07 -0600)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest tags/linux-kselftest-kunit-fixes-6.0-rc5
for you to fetch changes up to 2a2dfc869d3345ccdd91322b023f4b0da84acbe7:
tools: Add new "test" taint to kernel-chktaint (2022-09-07 14:51:12 -0600)
----------------------------------------------------------------
linux-kselftest-kunit-fixes-6.0-rc5
This KUnit fixes update for Linux 6.0-rc5 consists of 2 fixes to test
build and a fix to incorrect taint reason reporting.
----------------------------------------------------------------
Joe Fradley (1):
tools: Add new "test" taint to kernel-chktaint
Nico Pache (1):
kunit: fix Kconfig for build-in tests USB4 and Nitro Enclaves
Sander Vanheule (1):
kunit: fix assert_type for comparison macros
drivers/thunderbolt/Kconfig | 3 +--
drivers/virt/nitro_enclaves/Kconfig | 2 +-
include/kunit/test.h | 6 +++---
tools/debugging/kernel-chktaint | 9 +++++++++
4 files changed, 14 insertions(+), 6 deletions(-)
----------------------------------------------------------------