From 5540dd8e5f159adc00841b7669e2b6ca4b78e88e08c8e37a05e22baef45e78fc Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Wed, 28 Feb 2024 09:37:09 +0000 Subject: [PATCH] Accepting request 1152871 from home:Andreas_Schwab:Factory - s390-clone-error-clobber-r7.patch: S390: Do not clobber r7 in clone (BZ #31402) OBS-URL: https://build.opensuse.org/request/show/1152871 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=696 --- glibc.changes | 6 ++ glibc.spec | 2 + s390-clone-error-clobber-r7.patch | 148 ++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 s390-clone-error-clobber-r7.patch diff --git a/glibc.changes b/glibc.changes index c2a0873..528b9f6 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Feb 26 12:48:48 UTC 2024 - Andreas Schwab + +- s390-clone-error-clobber-r7.patch: S390: Do not clobber r7 in clone (BZ + #31402) + ------------------------------------------------------------------- Wed Feb 7 09:08:50 UTC 2024 - Andreas Schwab diff --git a/glibc.spec b/glibc.spec index 5d9b502..de4a33c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -304,6 +304,8 @@ Patch306: glibc-fix-double-loopback.diff ### # PATCH-FIX-UPSTREAM arm: Remove wrong ldr from _dl_start_user (BZ #31339) Patch1000: arm-dl-start-user.patch +# PATCH-FIX-UPSTREAM S390: Do not clobber r7 in clone (BZ #31402) +Patch1001: s390-clone-error-clobber-r7.patch %endif ### diff --git a/s390-clone-error-clobber-r7.patch b/s390-clone-error-clobber-r7.patch new file mode 100644 index 0000000..c82cf53 --- /dev/null +++ b/s390-clone-error-clobber-r7.patch @@ -0,0 +1,148 @@ +From 02782fd12849b6673cb5c2728cb750e8ec295aa3 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Thu, 22 Feb 2024 15:03:27 +0100 +Subject: [PATCH] S390: Do not clobber r7 in clone [BZ #31402] + +Starting with commit e57d8fc97b90127de4ed3e3a9cdf663667580935 +"S390: Always use svc 0" +clone clobbers the call-saved register r7 in error case: +function or stack is NULL. + +This patch restores the saved registers also in the error case. +Furthermore the existing test misc/tst-clone is extended to check +all error cases and that clone does not clobber registers in this +error case. +--- + sysdeps/unix/sysv/linux/s390/s390-32/clone.S | 1 + + sysdeps/unix/sysv/linux/s390/s390-64/clone.S | 1 + + sysdeps/unix/sysv/linux/tst-clone.c | 73 ++++++++++++++++---- + 3 files changed, 63 insertions(+), 12 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S +index 4c882ef2ee..a7a863242c 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S +@@ -53,6 +53,7 @@ ENTRY(__clone) + br %r14 + error: + lhi %r2,-EINVAL ++ lm %r6,%r7,24(%r15) /* Load registers. */ + j SYSCALL_ERROR_LABEL + PSEUDO_END (__clone) + +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S +index 4eb104be71..c552a6b8de 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S +@@ -54,6 +54,7 @@ ENTRY(__clone) + br %r14 + error: + lghi %r2,-EINVAL ++ lmg %r6,%r7,48(%r15) /* Restore registers. */ + jg SYSCALL_ERROR_LABEL + PSEUDO_END (__clone) + +diff --git a/sysdeps/unix/sysv/linux/tst-clone.c b/sysdeps/unix/sysv/linux/tst-clone.c +index 470676ab2b..2bc7124983 100644 +--- a/sysdeps/unix/sysv/linux/tst-clone.c ++++ b/sysdeps/unix/sysv/linux/tst-clone.c +@@ -16,12 +16,16 @@ + License along with the GNU C Library; if not, see + . */ + +-/* BZ #2386 */ ++/* BZ #2386, BZ #31402 */ + #include + #include + #include + #include + #include ++#include /* For _STACK_GROWS_{UP,DOWN}. */ ++#include ++ ++volatile unsigned v = 0xdeadbeef; + + int child_fn(void *arg) + { +@@ -30,22 +34,67 @@ int child_fn(void *arg) + } + + static int +-do_test (void) ++__attribute__((noinline)) ++do_clone (int (*fn)(void *), void *stack) + { + int result; ++ unsigned int a = v; ++ unsigned int b = v; ++ unsigned int c = v; ++ unsigned int d = v; ++ unsigned int e = v; ++ unsigned int f = v; ++ unsigned int g = v; ++ unsigned int h = v; ++ unsigned int i = v; ++ unsigned int j = v; ++ unsigned int k = v; ++ unsigned int l = v; ++ unsigned int m = v; ++ unsigned int n = v; ++ unsigned int o = v; ++ ++ result = clone (fn, stack, 0, NULL); ++ ++ /* Check that clone does not clobber call-saved registers. */ ++ TEST_VERIFY (a == v && b == v && c == v && d == v && e == v && f == v ++ && g == v && h == v && i == v && j == v && k == v && l == v ++ && m == v && n == v && o == v); ++ ++ return result; ++} ++ ++static void ++__attribute__((noinline)) ++do_test_single (int (*fn)(void *), void *stack) ++{ ++ printf ("%s (fn=%p, stack=%p)\n", __FUNCTION__, fn, stack); ++ errno = 0; ++ ++ int result = do_clone (fn, stack); ++ ++ TEST_COMPARE (errno, EINVAL); ++ TEST_COMPARE (result, -1); ++} + +- result = clone (child_fn, NULL, 0, NULL); ++static int ++do_test (void) ++{ ++ char st[128 * 1024] __attribute__ ((aligned)); ++ void *stack = NULL; ++#if _STACK_GROWS_DOWN ++ stack = st + sizeof (st); ++#elif _STACK_GROWS_UP ++ stack = st; ++#else ++# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" ++#endif + +- if (errno != EINVAL || result != -1) +- { +- printf ("FAIL: clone()=%d (wanted -1) errno=%d (wanted %d)\n", +- result, errno, EINVAL); +- return 1; +- } ++ do_test_single (child_fn, NULL); ++ do_test_single (NULL, stack); ++ do_test_single (NULL, NULL); + +- puts ("All OK"); + return 0; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include +-- +2.44.0 +