From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: libc-alpha@sourceware.org
Subject: [PATCH v2 3/5] posix: Optimize stack Linux posix_spawn
Date: Wed, 31 Jul 2019 18:31:00 -0000 [thread overview]
Message-ID: <20190731183136.21545-3-adhemerval.zanella@linaro.org> (raw)
In-Reply-To: <20190731183136.21545-1-adhemerval.zanella@linaro.org>
Changes from previous version:
* Move the logic of stack mapping creation to stackmap.h and
added a guard page allocation for the compatibility case.
--
The current internal posix_spawn symbol for Linux (__spawni) requires
to allocate a dynamic stack based on input arguments to handle the
SPAWN_XFLAGS_USE_PATH internal flag, which re-issue the input binary
as a shell script if execve call return ENOEXEC (to execute shell
scripts with an initial shebang).
This is done only for compatibility mode and the generic case does not
require the extra calculation plus the potential large mmap/munmap
call. For default case, a pre-defined buffer is sufficed to use on the
clone call instead.
This patch optimizes Linux spawni by allocating a dynamic stack only
for compatibility symbol (SPAWN_XFLAGS_USE_PATH). For generic case,
an mmap allocated buffer is used along with a guard page, similar to
what NPTL uses for thread stacks hardening.
For default case, it is a fixed code path with fixed stack usage in helper
process, so assuming a large enough stack buffer it would never overflow.
It also does not prevent to adapt to the vfork-like to re-use process
stack, once it is implemented.
Checked x86_64-linux-gnu and i686-linux-gnu.
* sysdeps/unix/sysv/linux/spawni.c (posix_spawn_args): Remove
argc member.
(maybe_script_execute): Remove function.
(execve_compat, __spawni_clone, __spawnix_compat): New function.
(__spawni_child): Remove maybe_script_execute call.
(__spawnix): Remove magic stack slack constant with stack_slack
identifier.
(__spawni): Only allocates a variable stack when
SPAWN_XFLAGS_TRY_SHELL is used.
* posix/stackmap.h: New file.
* sysdeps/ia64/nptl/pthreaddef.h (NEED_SEPARATE_REGISTER_STACK): Move
to ...
* sysdeps/ia64/stackinfo.h: ... here.
---
posix/stackmap.h | 115 +++++++++++++
sysdeps/ia64/nptl/pthreaddef.h | 3 -
sysdeps/ia64/stackinfo.h | 3 +
sysdeps/unix/sysv/linux/spawni.c | 277 +++++++++++++++++++------------
4 files changed, 285 insertions(+), 113 deletions(-)
create mode 100644 posix/stackmap.h
diff --git a/posix/stackmap.h b/posix/stackmap.h
new file mode 100644
index 0000000000..be500e378a
--- /dev/null
+++ b/posix/stackmap.h
@@ -0,0 +1,115 @@
+/* Functions to create stack mappings for helper processes.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _STACKMAP_H
+#define _STACKMAP_H
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <ldsodefs.h>
+#include <stdbool.h>
+
+static inline int
+stack_prot (void)
+{
+ return (PROT_READ | PROT_WRITE
+ | ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
+}
+
+static inline size_t
+stack_guard_size (void)
+{
+ return GLRO (dl_pagesize);
+}
+
+/* Return a aligning mask based on system pagesize. */
+static inline size_t
+stack_pagesize_m1_mask (void)
+{
+ size_t pagesize_m1 = __getpagesize () - 1;
+ return ~pagesize_m1;
+}
+
+/* Return the guard page position on memory segment MEM with total size SIZE
+ and with a guard page of size GUARDIZE. */
+static inline void *
+stack_guard_position (void *mem, size_t size, size_t guardsize)
+{
+#ifdef NEED_SEPARATE_REGISTER_STACK
+ return mem + (((size - guardsize) / 2) & stack_pagesize_m1_mask ());
+#elif _STACK_GROWS_DOWN
+ return mem;
+#elif _STACK_GROWS_UP
+ return (void *) (((uintptr_t)(mem + size)- guardsize)
+ & stack_pagesize_m1_mask ());
+#endif
+}
+
+/* Setup the expected stack memory protection value (based on stack_prot)
+ for the memory segment MEM with size SIZE based on the guard page
+ GUARD with size GUARDSIZE. The memory segment is expected to be allocated
+ with PROT_NOTE. */
+static inline bool
+stack_setup_prot (char *mem, size_t size, char *guard, size_t guardsize)
+{
+ const int prot = stack_prot ();
+
+ char *guardend = guard + guardsize;
+#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK)
+ /* As defined at guard_position, for architectures with downward stack
+ the guard page is always at start of the allocated area. */
+ if (__mprotect (guardend, size - guardsize, prot) != 0)
+ return false;
+#else
+ size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
+ if (__mprotect (mem, mprots1, prot) != 0)
+ return false;
+ size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
+ if (__mprotect (guardend, mprots2, prot) != 0)
+ return false;
+#endif
+ return true;
+}
+
+/* Allocated a memory segment with size SIZE plus GUARSIZE with mmap and
+ setup the expected protection for both a guard page and the stack
+ itself. */
+static inline void *
+stack_allocate (size_t size, size_t guardsize)
+{
+ const int prot = stack_prot ();
+
+ /* If a guard page is required, avoid committing memory by first
+ allocate with PROT_NONE and then reserve with required permission
+ excluding the guard page. */
+ void *mem = __mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
+ if (guardsize)
+ {
+ void *guard = stack_guard_position (mem, size, guardsize);
+ if (!stack_setup_prot (mem, size, guard, guardsize))
+ {
+ __munmap (mem, size);
+ return MAP_FAILED;
+ }
+ }
+
+ return mem;
+}
+
+#endif /* _STACKMAP_H */
diff --git a/sysdeps/ia64/nptl/pthreaddef.h b/sysdeps/ia64/nptl/pthreaddef.h
index bf52d5af62..11579f11b4 100644
--- a/sysdeps/ia64/nptl/pthreaddef.h
+++ b/sysdeps/ia64/nptl/pthreaddef.h
@@ -18,9 +18,6 @@
/* Default stack size. */
#define ARCH_STACK_DEFAULT_SIZE (32 * 1024 * 1024)
-/* IA-64 uses a normal stack and a register stack. */
-#define NEED_SEPARATE_REGISTER_STACK
-
/* Required stack pointer alignment at beginning. */
#define STACK_ALIGN 16
diff --git a/sysdeps/ia64/stackinfo.h b/sysdeps/ia64/stackinfo.h
index 6433a89945..d942426fcf 100644
--- a/sysdeps/ia64/stackinfo.h
+++ b/sysdeps/ia64/stackinfo.h
@@ -30,4 +30,7 @@
/* Default to a non-executable stack. */
#define DEFAULT_STACK_PERMS (PF_R|PF_W)
+/* IA-64 uses a normal stack and a register stack. */
+#define NEED_SEPARATE_REGISTER_STACK
+
#endif /* stackinfo.h */
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
index ca7bf99825..0f7a8ca5df 100644
--- a/sysdeps/unix/sysv/linux/spawni.c
+++ b/sysdeps/unix/sysv/linux/spawni.c
@@ -23,10 +23,11 @@
#include <not-cancel.h>
#include <local-setxid.h>
#include <shlib-compat.h>
-#include <sigsetops.h>
-#include <internal-signals.h>
-#include <ldsodefs.h>
+#include <nptl/pthreadP.h>
#include <ctype.h>
+#include <dl-sysdep.h>
+#include <libc-pointer-arith.h>
+#include <stackmap.h>
#include "spawn_int.h"
/* The Linux implementation of posix_spawn{p} uses the clone syscall directly
@@ -70,7 +71,6 @@
# define STACK(__stack, __stack_size) (__stack + __stack_size)
#endif
-
struct posix_spawn_args
{
sigset_t oldmask;
@@ -79,37 +79,11 @@ struct posix_spawn_args
const posix_spawn_file_actions_t *fa;
const posix_spawnattr_t *restrict attr;
char *const *argv;
- ptrdiff_t argc;
char *const *envp;
int xflags;
int err;
};
-/* Older version requires that shell script without shebang definition
- to be called explicitly using /bin/sh (_PATH_BSHELL). */
-static void
-maybe_script_execute (struct posix_spawn_args *args)
-{
- if (SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15)
- && (args->xflags & SPAWN_XFLAGS_TRY_SHELL) && errno == ENOEXEC)
- {
- char *const *argv = args->argv;
- ptrdiff_t argc = args->argc;
-
- /* Construct an argument list for the shell. */
- char *new_argv[argc + 2];
- new_argv[0] = (char *) _PATH_BSHELL;
- new_argv[1] = (char *) args->file;
- if (argc > 1)
- memcpy (new_argv + 2, argv + 1, argc * sizeof (char *));
- else
- new_argv[2] = NULL;
-
- /* Execute the shell. */
- args->exec (new_argv[0], new_argv, args->envp);
- }
-}
-
/* Close all file descriptor up to FROM by interacting /proc/self/fd. */
static bool
spawn_closefrom (int from)
@@ -152,7 +126,7 @@ spawn_closefrom (int from)
attributes, and file actions. It run on its own stack (provided by the
posix_spawn call). */
static int
-__spawni_child (void *arguments)
+spawni_child (void *arguments)
{
struct posix_spawn_args *args = arguments;
const posix_spawnattr_t *restrict attr = args->attr;
@@ -330,11 +304,6 @@ __spawni_child (void *arguments)
args->exec (args->file, args->argv, args->envp);
- /* This is compatibility function required to enable posix_spawn run
- script without shebang definition for older posix_spawn versions
- (2.15). */
- maybe_script_execute (args);
-
fail:
/* errno should have an appropriate non-zero value; otherwise,
there's a bug in glibc or the kernel. For lack of an error code
@@ -345,71 +314,12 @@ fail:
_exit (SPAWN_ERROR);
}
-/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
- Before running the process perform the actions described in FILE-ACTIONS. */
static int
-__spawnix (pid_t * pid, const char *file,
- const posix_spawn_file_actions_t * file_actions,
- const posix_spawnattr_t * attrp, char *const argv[],
- char *const envp[], int xflags,
- int (*exec) (const char *, char *const *, char *const *))
+spawni_clone (struct posix_spawn_args *args, void *stack, size_t stack_size,
+ pid_t *pid)
{
- pid_t new_pid;
- struct posix_spawn_args args;
int ec;
-
- /* To avoid imposing hard limits on posix_spawn{p} the total number of
- arguments is first calculated to allocate a mmap to hold all possible
- values. */
- ptrdiff_t argc = 0;
- /* Linux allows at most max (0x7FFFFFFF, 1/4 stack size) arguments
- to be used in a execve call. We limit to INT_MAX minus one due the
- compatiblity code that may execute a shell script (maybe_script_execute)
- where it will construct another argument list with an additional
- argument. */
- ptrdiff_t limit = INT_MAX - 1;
- while (argv[argc++] != NULL)
- if (argc == limit)
- {
- errno = E2BIG;
- return errno;
- }
-
- int prot = (PROT_READ | PROT_WRITE
- | ((GL (dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
-
- size_t argv_size = (argc * sizeof (void *));
- /* We need at least a few pages in case the compiler's stack checking is
- enabled. In some configs, it is known to use at least 24KiB. We use
- 32KiB to be "safe" from anything the compiler might do. Besides, the
- extra pages won't actually be allocated unless they get used.
- It also acts the slack for spawn_closefrom (including MIPS64 getdents64
- where it might use about 1k extra stack space. */
- argv_size += (32 * 1024);
- size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
- void *stack = __mmap (NULL, stack_size, prot,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
- if (__glibc_unlikely (stack == MAP_FAILED))
- return errno;
-
- /* Disable asynchronous cancellation. */
- int state;
- __libc_ptf_call (__pthread_setcancelstate,
- (PTHREAD_CANCEL_DISABLE, &state), 0);
-
- /* Child must set args.err to something non-negative - we rely on
- the parent and child sharing VM. */
- args.err = 0;
- args.file = file;
- args.exec = exec;
- args.fa = file_actions;
- args.attr = attrp ? attrp : &(const posix_spawnattr_t) { 0 };
- args.argv = argv;
- args.argc = argc;
- args.envp = envp;
- args.xflags = xflags;
-
- __libc_signal_block_all (&args.oldmask);
+ pid_t new_pid;
/* The clone flags used will create a new child that will run in the same
memory space (CLONE_VM) and the execution of calling thread will be
@@ -419,8 +329,8 @@ __spawnix (pid_t * pid, const char *file,
need for CLONE_SETTLS. Although parent and child share the same TLS
namespace, there will be no concurrent access for TLS variables (errno
for instance). */
- new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
- CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
+ new_pid = CLONE (spawni_child, STACK (stack, stack_size), stack_size,
+ CLONE_VM | CLONE_VFORK | SIGCHLD, args);
/* It needs to collect the case where the auxiliary process was created
but failed to execute the file (due either any preparation step or
@@ -433,7 +343,7 @@ __spawnix (pid_t * pid, const char *file,
only in case of failure, so in case of premature termination
due a signal args.err will remain zeroed and it will be up to
caller to actually collect it. */
- ec = args.err;
+ ec = args->err;
if (ec > 0)
/* There still an unlikely case where the child is cancelled after
setting args.err, due to a positive error value. Also there is
@@ -446,14 +356,139 @@ __spawnix (pid_t * pid, const char *file,
else
ec = -new_pid;
- __munmap (stack, stack_size);
-
if ((ec == 0) && (pid != NULL))
*pid = new_pid;
- __libc_signal_restore_set (&args.oldmask);
+ return ec;
+}
- __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
+#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15)
+/* This is compatibility function required to enable posix_spawn run
+ script without shebang definition for older posix_spawn versions
+ (2.15). */
+static int
+execve_compat (const char *filename, char *const argv[], char *const envp[])
+{
+ __execve (filename, argv, envp);
+
+ if (errno == ENOEXEC)
+ {
+ char *const *cargv = argv;
+ ptrdiff_t argc = 0;
+ while (cargv[argc++] != NULL);
+
+ /* Construct an argument list for the shell. */
+ char *new_argv[argc + 2];
+ new_argv[0] = (char *) _PATH_BSHELL;
+ new_argv[1] = (char *) filename;
+ if (argc > 1)
+ memcpy (new_argv + 2, argv + 1, argc * sizeof (char *));
+ else
+ new_argv[2] = NULL;
+
+ /* Execute the shell. */
+ __execve (new_argv[0], new_argv, envp);
+ }
+
+ return -1;
+}
+
+/* Allocates a stack using mmap to call clone. The stack size is based on
+ number of arguments since it would be used on compat mode which may call
+ execvpe/execve_compat. */
+static int
+spawnix_compat (struct posix_spawn_args *args, pid_t *pid)
+{
+ char *const *argv = args->argv;
+
+ /* To avoid imposing hard limits on posix_spawn{p} the total number of
+ arguments is first calculated to allocate a mmap to hold all possible
+ values. */
+ ptrdiff_t argc = 0;
+ /* Linux allows at most max (0x7FFFFFFF, 1/4 stack size) arguments
+ to be used in a execve call. We limit to INT_MAX minus one due the
+ compatiblity code that may execute a shell script (maybe_script_execute)
+ where it will construct another argument list with an additional
+ argument. */
+ ptrdiff_t limit = INT_MAX - 1;
+ while (argv[argc++] != NULL)
+ if (argc == limit)
+ {
+ errno = E2BIG;
+ return errno;
+ }
+
+ size_t argv_size = (argc * sizeof (void *));
+ /* We need at least a few pages in case the compiler's stack checking is
+ enabled. In some configs, it is known to use at least 24KiB. We use
+ 32KiB to be "safe" from anything the compiler might do. Besides, the
+ extra pages won't actually be allocated unless they get used.
+ It also acts the slack for spawn_closefrom (including MIPS64 getdents64
+ where it might use about 1k extra stack space. */
+ argv_size += (32 * 1024);
+
+ /* Allocate a stack with an extra guard page. */
+ size_t guard_size = stack_guard_size ();
+ size_t stack_size = guard_size + ALIGN_UP (argv_size, __getpagesize ());
+ void *stack = stack_allocate (stack_size, guard_size);
+ if (__glibc_unlikely (stack == MAP_FAILED))
+ return errno;
+
+ int ec = spawni_clone (args, stack, stack_size, pid);
+
+ __munmap (stack, stack_size);
+
+ return ec;
+}
+#endif
+
+/* For SPAWN_XFLAGS_TRY_SHELL we need to execute a script even without
+ a shebang. To accomplish it we pass as callback to spawni_child
+ __execvpe (which call maybe_script_execute for such case) or
+ execve_compat (which mimics the semantic using execve). */
+static int
+spawn_process (struct posix_spawn_args *args, pid_t *pid)
+{
+ int ec;
+
+#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15)
+ if (args->xflags & SPAWN_XFLAGS_TRY_SHELL)
+ {
+ args->exec = args->xflags & SPAWN_XFLAGS_USE_PATH
+ ? __execvpe : execve_compat;
+ ec = spawnix_compat (args, pid);
+ }
+ else
+#endif
+ {
+ args->exec = args->xflags & SPAWN_XFLAGS_USE_PATH
+ ? __execvpex : __execve;
+
+ /* spawni_clone stack usage need to take in consideration spawni_child
+ stack usage and subsequent functions called:
+
+ - sigprocmask: might allocate an extra sigset_t (128 bytes).
+ - __libc_sigaction: allocate a struct kernel_sigaction (144 bytes on
+ 64-bit, 136 on 32-bit).
+ - __sched_setparam, __sched_setscheduler, __setsig, __setpgid,
+ local_seteuid, local_setegid, __close_nocancel, __getrlimit64,
+ __close_nocancel, __open_nocancel, __dup2, __chdir, __fchdir:
+ and direct syscall.
+ - __fcntl: wrapper only uses local variables.
+ - spawn_closefrom: uses up to 1024 bytes as local buffer
+ - __direntries_read
+ - __getdents64: MIPS64 uses up to buffer size used, 1024 in this
+ specific usage.
+ - __direntries_next: local variables.
+ - __close_nocancel: direct syscall.
+ - execvpe allocates at least (NAME_MAX + 1) + PATH_MAX to create the
+ combination of PATH entry and program name (1024 + 255 + 1).
+
+ It allocates 2048 plus some stack for automatic variables and function
+ calls. */
+ char stack[2560];
+ ec = spawni_clone (args, stack, sizeof stack, pid);
+ }
return ec;
}
@@ -462,12 +497,34 @@ __spawnix (pid_t * pid, const char *file,
Before running the process perform the actions described in FILE-ACTIONS. */
int
__spawni (pid_t * pid, const char *file,
- const posix_spawn_file_actions_t * acts,
+ const posix_spawn_file_actions_t * file_actions,
const posix_spawnattr_t * attrp, char *const argv[],
char *const envp[], int xflags)
{
- /* It uses __execvpex to avoid run ENOEXEC in non compatibility mode (it
- will be handled by maybe_script_execute). */
- return __spawnix (pid, file, acts, attrp, argv, envp, xflags,
- xflags & SPAWN_XFLAGS_USE_PATH ? __execvpex :__execve);
+ /* Child must set args.err to something non-negative - we rely on
+ the parent and child sharing VM. */
+ struct posix_spawn_args args = {
+ .err = 0,
+ .file = file,
+ .fa = file_actions,
+ .attr = attrp ? attrp : &(const posix_spawnattr_t) { 0 },
+ .argv = argv,
+ .envp = envp,
+ .xflags = xflags
+ };
+
+ /* Disable asynchronous cancellation. */
+ int state;
+ __libc_ptf_call (__pthread_setcancelstate,
+ (PTHREAD_CANCEL_DISABLE, &state), 0);
+
+ __libc_signal_block_all (&args.oldmask);
+
+ int ec = spawn_process (&args, pid);
+
+ __libc_signal_restore_set (&args.oldmask);
+
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
+
+ return ec;
}
--
2.17.1
next prev parent reply other threads:[~2019-07-31 18:31 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-31 18:31 [PATCH v2 1/5] mips: Do not malloc on getdents64 fallback Adhemerval Zanella
2019-07-31 18:31 ` [PATCH v2 5/5] posix: Use posix_spawn for wordexp Adhemerval Zanella
2019-08-28 14:10 ` Adhemerval Zanella
2019-10-07 17:51 ` Adhemerval Zanella
2019-10-07 19:33 ` Florian Weimer
2019-10-07 21:04 ` Carlos O'Donell
2019-10-08 9:58 ` Florian Weimer
2019-10-08 17:41 ` Adhemerval Zanella
2019-10-09 9:11 ` Florian Weimer
2019-10-09 12:18 ` Adhemerval Zanella
2019-07-31 18:31 ` [PATCH 4/5] linux: Optimize posix_spawn spurious sigaction calls Adhemerval Zanella
2019-08-28 14:09 ` Adhemerval Zanella
2019-08-29 8:38 ` Florian Weimer
2019-08-29 11:26 ` Adhemerval Zanella
2019-08-30 10:07 ` Florian Weimer
2019-08-30 13:05 ` Adhemerval Zanella
2019-09-02 13:14 ` Florian Weimer
2019-09-02 19:47 ` Adhemerval Zanella
2019-10-07 17:51 ` Adhemerval Zanella
2019-10-07 18:25 ` Christian Brauner
2019-10-07 18:32 ` Florian Weimer
2019-10-07 21:08 ` Christian Brauner
2019-10-07 18:35 ` Adhemerval Zanella
2019-10-07 18:40 ` Florian Weimer
2019-10-07 19:20 ` Adhemerval Zanella
2019-10-09 9:37 ` Florian Weimer
2019-10-09 10:25 ` Christian Brauner
2019-10-09 12:17 ` Adhemerval Zanella
2019-10-09 19:16 ` Florian Weimer
2019-10-07 21:00 ` Joseph Myers
2019-10-07 18:41 ` Florian Weimer
2019-07-31 18:31 ` Adhemerval Zanella [this message]
2019-08-28 14:09 ` [PATCH v2 3/5] posix: Optimize stack Linux posix_spawn Adhemerval Zanella
2019-10-07 17:50 ` Adhemerval Zanella
2019-07-31 18:31 ` [PATCH v2 2/5] posix: Add posix_spawn_file_actions_closefrom Adhemerval Zanella
2019-08-28 14:09 ` Adhemerval Zanella
2019-08-28 17:22 ` Joseph Myers
2019-08-28 21:03 ` Adhemerval Zanella
2019-08-28 14:09 ` [PATCH v2 1/5] mips: Do not malloc on getdents64 fallback Adhemerval Zanella
2019-08-28 14:35 ` Andreas Schwab
2019-08-28 17:01 ` Adhemerval Zanella
2019-08-28 14:42 ` Florian Weimer
2019-08-28 21:02 ` Adhemerval Zanella
2019-08-28 21:23 ` Florian Weimer
2019-08-29 11:04 ` Adhemerval Zanella
2019-08-30 9:53 ` Florian Weimer
2019-08-30 12:53 ` Adhemerval Zanella
2019-09-02 12:59 ` Florian Weimer
2019-09-02 17:38 ` Adhemerval Zanella
2019-10-07 17:49 ` Adhemerval Zanella
2019-10-07 18:29 ` Florian Weimer
2019-10-08 17:38 ` Adhemerval Zanella
2019-10-08 18:52 ` Florian Weimer
2019-10-08 19:52 ` Adhemerval Zanella
2019-10-08 19:59 ` Florian Weimer
2019-10-09 13:02 ` Adhemerval Zanella
2020-11-02 19:51 ` Joseph Myers
2020-11-02 22:10 ` Adhemerval Zanella
2020-11-03 10:27 ` Florian Weimer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190731183136.21545-3-adhemerval.zanella@linaro.org \
--to=adhemerval.zanella@linaro.org \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).