[PATCH] x86-64: Align child stack to 16 bytes
H.J. Lu
hjl.tools@gmail.com
Sun May 23 17:29:42 GMT 2021
In the x86-64 clone wrapper, align child stack to 16 bytes per the
x86-64 psABI.
---
sysdeps/unix/sysv/linux/Makefile | 2 +-
sysdeps/unix/sysv/linux/tst-misalign-clone.c | 97 ++++++++++++++++++++
sysdeps/unix/sysv/linux/x86_64/clone.S | 3 +
3 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 sysdeps/unix/sysv/linux/tst-misalign-clone.c
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 9bcd38a732..283b2d0bd8 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -327,5 +327,5 @@ CFLAGS-gai.c += -DNEED_NETLINK
endif
ifeq ($(subdir),nptl)
-tests += tst-align-clone tst-getpid1
+tests += tst-align-clone tst-misalign-clone tst-getpid1
endif
diff --git a/sysdeps/unix/sysv/linux/tst-misalign-clone.c b/sysdeps/unix/sysv/linux/tst-misalign-clone.c
new file mode 100644
index 0000000000..3eb91b9b1f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-misalign-clone.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sched.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <tst-stack-align.h>
+#include <stackinfo.h>
+#include <support/xunistd.h>
+
+static int
+f (void *arg)
+{
+ bool ok = true;
+
+ puts ("in f");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ return ok ? 0 : 1;
+}
+
+static int
+do_test (void)
+{
+ bool ok = true;
+
+ puts ("in main");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+#ifdef __ia64__
+# define STACK_SIZE (256 * 1024)
+#else
+# define STACK_SIZE (128 * 1024)
+#endif
+
+ /* NB: Try to force misaligned child stack. */
+ char st[STACK_SIZE + 4] __attribute__ ((aligned (1)));
+
+#ifdef __ia64__
+ extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+ size_t __child_stack_size, int __flags,
+ void *__arg, ...);
+ pid_t p = __clone2 (f, st, sizeof (st), 0, 0);
+#else
+# if _STACK_GROWS_DOWN
+ pid_t p = clone (f, st + sizeof (st), 0, 0);
+# elif _STACK_GROWS_UP
+ pid_t p = clone (f, st, 0, 0);
+# else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+# endif
+#endif
+ if (p == -1)
+ {
+ printf("clone failed: %m\n");
+ return 1;
+ }
+
+ int e;
+ xwaitpid (p, &e, __WCLONE);
+ if (!WIFEXITED (e))
+ {
+ if (WIFSIGNALED (e))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (e) != 0)
+ ok = false;
+
+ return ok ? 0 : 1;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S
index 31ac12da0c..5f52ce7813 100644
--- a/sysdeps/unix/sysv/linux/x86_64/clone.S
+++ b/sysdeps/unix/sysv/linux/x86_64/clone.S
@@ -57,6 +57,9 @@ ENTRY (__clone)
testq %rsi,%rsi /* no NULL stack pointers */
jz SYSCALL_ERROR_LABEL
+ /* Align stack to 16 bytes per the x86-64 psABI. */
+ andq $-16, %rsi
+
/* Insert the argument onto the new stack. */
subq $16,%rsi
movq %rcx,8(%rsi)
--
2.31.1
More information about the Libc-alpha
mailing list