diff --git a/valgrind-3.15.0-pkey.patch b/valgrind-3.15.0-pkey.patch new file mode 100644 index 0000000..3f534c5 --- /dev/null +++ b/valgrind-3.15.0-pkey.patch @@ -0,0 +1,226 @@ +commit b064131bdf099d3647b4501e5d15391e1e9623e6 +Author: Mark Wielaard +Date: Thu May 30 00:29:58 2019 +0200 + + linux x86 and amd64 memory protection key syscalls. + + This implements minimal support for the pkey_alloc, pkey_free and + pkey_mprotect syscalls. pkey_alloc will simply indicate that pkeys + are not supported. pkey_free always fails. pkey_mprotect works just + like mprotect if the special pkey -1 is provided. + + https://bugs.kde.org/show_bug.cgi?id=408091 + +diff --git a/coregrind/m_syswrap/priv_syswrap-generic.h b/coregrind/m_syswrap/priv_syswrap-generic.h +index 88530f0..3e1c8b6 100644 +--- a/coregrind/m_syswrap/priv_syswrap-generic.h ++++ b/coregrind/m_syswrap/priv_syswrap-generic.h +@@ -106,6 +106,10 @@ extern Bool + ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename, + int flags); + ++/* Helper function for generic mprotect and linux pkey_mprotect. */ ++extern void handle_sys_mprotect (ThreadId tid, SyscallStatus *status, ++ Addr *addr, SizeT *len, Int *prot); ++ + DECL_TEMPLATE(generic, sys_ni_syscall); // * P -- unimplemented + DECL_TEMPLATE(generic, sys_exit); + DECL_TEMPLATE(generic, sys_fork); +diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h +index 5cf5407..2471524 100644 +--- a/coregrind/m_syswrap/priv_syswrap-linux.h ++++ b/coregrind/m_syswrap/priv_syswrap-linux.h +@@ -299,6 +299,11 @@ DECL_TEMPLATE(linux, sys_bpf); + // Linux-specific (new in Linux 4.11) + DECL_TEMPLATE(linux, sys_statx); + ++// Linux-specific memory protection key syscalls (since Linux 4.9) ++DECL_TEMPLATE(linux, sys_pkey_alloc); ++DECL_TEMPLATE(linux, sys_pkey_free); ++DECL_TEMPLATE(linux, sys_pkey_mprotect); ++ + /* --------------------------------------------------------------------- + Wrappers for sockets and ipc-ery. These are split into standalone + procedures because x86-linux hides them inside multiplexors +diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c +index d4fe413..2d6b95f 100644 +--- a/coregrind/m_syswrap/syswrap-amd64-linux.c ++++ b/coregrind/m_syswrap/syswrap-amd64-linux.c +@@ -863,6 +863,10 @@ static SyscallTableEntry syscall_table[] = { + LINX_(__NR_membarrier, sys_membarrier), // 324 + + LINX_(__NR_copy_file_range, sys_copy_file_range), // 326 ++ ++ LINXY(__NR_pkey_mprotect, sys_pkey_mprotect), // 329 ++ LINX_(__NR_pkey_alloc, sys_pkey_alloc), // 330 ++ LINX_(__NR_pkey_free, sys_pkey_free), // 331 + }; + + SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno ) +diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c +index 0b64919..01191f6 100644 +--- a/coregrind/m_syswrap/syswrap-generic.c ++++ b/coregrind/m_syswrap/syswrap-generic.c +@@ -3842,12 +3842,28 @@ PRE(sys_mprotect) + PRE_REG_READ3(long, "mprotect", + unsigned long, addr, vki_size_t, len, unsigned long, prot); + +- if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) { ++ Addr addr = ARG1; ++ SizeT len = ARG2; ++ Int prot = ARG3; ++ ++ handle_sys_mprotect (tid, status, &addr, &len, &prot); ++ ++ ARG1 = addr; ++ ARG2 = len; ++ ARG3 = prot; ++} ++/* This will be called from the generic mprotect, or the linux specific ++ pkey_mprotect. Pass pointers to ARG1, ARG2 and ARG3 as addr, len and prot, ++ they might be adjusted and have to assigned back to ARG1, ARG2 and ARG3. */ ++void handle_sys_mprotect(ThreadId tid, SyscallStatus* status, ++ Addr *addr, SizeT *len, Int *prot) ++{ ++ if (!ML_(valid_client_addr)(*addr, *len, tid, "mprotect")) { + SET_STATUS_Failure( VKI_ENOMEM ); + } + #if defined(VKI_PROT_GROWSDOWN) + else +- if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) { ++ if (*prot & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) { + /* Deal with mprotects on growable stack areas. + + The critical files to understand all this are mm/mprotect.c +@@ -3862,8 +3878,8 @@ PRE(sys_mprotect) + + The sanity check provided by the kernel is that the vma must + have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */ +- UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP); +- NSegment const *aseg = VG_(am_find_nsegment)(ARG1); ++ UInt grows = *prot & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP); ++ NSegment const *aseg = VG_(am_find_nsegment)(*addr); + NSegment const *rseg; + + vg_assert(aseg); +@@ -3874,10 +3890,10 @@ PRE(sys_mprotect) + && rseg->kind == SkResvn + && rseg->smode == SmUpper + && rseg->end+1 == aseg->start) { +- Addr end = ARG1 + ARG2; +- ARG1 = aseg->start; +- ARG2 = end - aseg->start; +- ARG3 &= ~VKI_PROT_GROWSDOWN; ++ Addr end = *addr + *len; ++ *addr = aseg->start; ++ *len = end - aseg->start; ++ *prot &= ~VKI_PROT_GROWSDOWN; + } else { + SET_STATUS_Failure( VKI_EINVAL ); + } +@@ -3887,8 +3903,8 @@ PRE(sys_mprotect) + && rseg->kind == SkResvn + && rseg->smode == SmLower + && aseg->end+1 == rseg->start) { +- ARG2 = aseg->end - ARG1 + 1; +- ARG3 &= ~VKI_PROT_GROWSUP; ++ *len = aseg->end - *addr + 1; ++ *prot &= ~VKI_PROT_GROWSUP; + } else { + SET_STATUS_Failure( VKI_EINVAL ); + } +diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c +index 810ca24..5452b8d 100644 +--- a/coregrind/m_syswrap/syswrap-linux.c ++++ b/coregrind/m_syswrap/syswrap-linux.c +@@ -12120,6 +12120,76 @@ PRE(sys_copy_file_range) + } + } + ++PRE(sys_pkey_alloc) ++{ ++ PRINT("pkey_alloc (%lu, %lu)", ARG1, ARG2); ++ ++ PRE_REG_READ2(long, "pkey_alloc", ++ unsigned long, "flags", ++ unsigned long, "access_rights"); ++ ++ /* The kernel says: pkey_alloc() is always safe to call regardless of ++ whether or not the operating system supports protection keys. It can be ++ used in lieu of any other mechanism for detecting pkey support and will ++ simply fail with the error ENOSPC if the operating system has no pkey ++ support. ++ ++ So we simply always return ENOSPC to signal memory protection keys are ++ not supported under valgrind, unless there are unknown flags, then we ++ return EINVAL. */ ++ unsigned long pkey_flags = ARG1; ++ if (pkey_flags != 0) ++ SET_STATUS_Failure( VKI_EINVAL ); ++ else ++ SET_STATUS_Failure( VKI_ENOSPC ); ++} ++ ++PRE(sys_pkey_free) ++{ ++ PRINT("pkey_free (%" FMT_REGWORD "u )", ARG1); ++ ++ PRE_REG_READ1(long, "pkey_free", ++ unsigned long, "pkey"); ++ ++ /* Since pkey_alloc () can never succeed, see above, freeing any pkey is ++ always an error. */ ++ SET_STATUS_Failure( VKI_EINVAL ); ++} ++ ++PRE(sys_pkey_mprotect) ++{ ++ PRINT("sys_pkey_mprotect ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" ++ FMT_REGWORD "u %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4); ++ PRE_REG_READ4(long, "pkey_mprotect", ++ unsigned long, addr, vki_size_t, len, unsigned long, prot, ++ unsigned long, pkey); ++ ++ Addr addr = ARG1; ++ SizeT len = ARG2; ++ Int prot = ARG3; ++ Int pkey = ARG4; ++ ++ /* Since pkey_alloc () can never succeed, see above, any pkey is ++ invalid. Except for -1, then pkey_mprotect acts just like mprotect. */ ++ if (pkey != -1) ++ SET_STATUS_Failure( VKI_EINVAL ); ++ else ++ handle_sys_mprotect (tid, status, &addr, &len, &prot); ++ ++ ARG1 = addr; ++ ARG2 = len; ++ ARG3 = prot; ++} ++ ++POST(sys_pkey_mprotect) ++{ ++ Addr addr = ARG1; ++ SizeT len = ARG2; ++ Int prot = ARG3; ++ ++ ML_(notify_core_and_tool_of_mprotect)(addr, len, prot); ++} ++ + + #undef PRE + #undef POST +diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c +index ad54cf6..3829fa4 100644 +--- a/coregrind/m_syswrap/syswrap-x86-linux.c ++++ b/coregrind/m_syswrap/syswrap-x86-linux.c +@@ -1608,6 +1608,9 @@ static SyscallTableEntry syscall_table[] = { + + LINX_(__NR_copy_file_range, sys_copy_file_range), // 377 + ++ LINXY(__NR_pkey_mprotect, sys_pkey_mprotect), // 380 ++ LINX_(__NR_pkey_alloc, sys_pkey_alloc), // 381 ++ LINX_(__NR_pkey_free, sys_pkey_free), // 382 + LINXY(__NR_statx, sys_statx), // 383 + + /* Explicitly not supported on i386 yet. */ diff --git a/valgrind.spec b/valgrind.spec index 21d9e15..ff0c5f5 100644 --- a/valgrind.spec +++ b/valgrind.spec @@ -3,7 +3,7 @@ Summary: Tool for finding memory management bugs in programs Name: %{?scl_prefix}valgrind Version: 3.15.0 -Release: 8%{?dist} +Release: 9%{?dist} Epoch: 1 License: GPLv2+ URL: http://www.valgrind.org/ @@ -121,6 +121,9 @@ Patch14: valgrind-3.15.0-some-Wl-z-now.patch # KDE#408009 Expose rdrand and f16c even on avx if host cpu supports them Patch15: valgrind-3.15.0-avx-rdrand-f16c.patch +# KDE#408091 Missing pkey syscalls +Patch16: valgrind-3.15.0-pkey.patch + BuildRequires: glibc-devel %if %{build_openmpi} @@ -267,6 +270,7 @@ Valgrind User Manual for details. %endif %patch15 -p1 +%patch16 -p1 %build @@ -487,6 +491,9 @@ fi %endif %changelog +* Wed May 29 2019 Mark Wielaard - 3.15.0-9 +- Add valgrind-3.15.0-pkey.patch + * Tue May 28 2019 Mark Wielaard - 3.15.0-8 - Update valgrind-3.15.0-copy_file_range.patch. - Add valgrind-3.15.0-avx-rdrand-f16c.patch.