From: Pavel Kozlov <pavel.kozlov(a)synopsys.com>
Fix the [-Warray-parameter=] warning for __sigsetjmp generated by GCC 11 and
later GCC versions:
|
| warning: argument 1 of type 'struct __jmp_buf_tag *' declared as a pointer [-Warray-parameter=]
| extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
| ...
| note: previously declared as an array 'struct __jmp_buf_tag[1]'
| extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask)
|
Use the same fix as in glibc. The fix is to move the struct __jmp_buf_tag
definition to a separate bits/ header so it can be included in
pthread.h, to allow to use an array (as in setjmp.h) rather than a pointer
in the declaration.
Signed-off-by: Pavel Kozlov <pavel.kozlov(a)synopsys.com>
---
include/setjmp.h | 16 +--------
libc/sysdeps/linux/common/bits/jmp_buf_tag.h | 37 ++++++++++++++++++++
libpthread/nptl/sysdeps/pthread/pthread.h | 4 +--
3 files changed, 40 insertions(+), 17 deletions(-)
create mode 100644 libc/sysdeps/linux/common/bits/jmp_buf_tag.h
diff --git a/include/setjmp.h b/include/setjmp.h
index 27cac9500a15..e6f437b93ad9 100644
--- a/include/setjmp.h
+++ b/include/setjmp.h
@@ -27,21 +27,7 @@
__BEGIN_DECLS
#include <bits/setjmp.h> /* Get `__jmp_buf'. */
-#include <bits/sigset.h> /* Get `__sigset_t'. */
-
-
-/* Calling environment, plus possibly a saved signal mask. */
-struct __jmp_buf_tag
- {
- /* NOTE: The machine-dependent definitions of `__sigsetjmp'
- assume that a `jmp_buf' begins with a `__jmp_buf' and that
- `__mask_was_saved' follows it. Do not move these members
- or add others before it. */
- __jmp_buf __jmpbuf; /* Calling environment. */
- int __mask_was_saved; /* Saved the signal mask? */
- __sigset_t __saved_mask; /* Saved signal mask. */
- };
-
+#include <bits/jmp_buf_tag.h>
__BEGIN_NAMESPACE_STD
diff --git a/libc/sysdeps/linux/common/bits/jmp_buf_tag.h b/libc/sysdeps/linux/common/bits/jmp_buf_tag.h
new file mode 100644
index 000000000000..4e1a4310a7e2
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/jmp_buf_tag.h
@@ -0,0 +1,37 @@
+/* Define struct __jmp_buf_tag.
+ Copyright (C) 1991-2023 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/>. */
+
+#ifndef __jmp_buf_tag_defined
+#define __jmp_buf_tag_defined 1
+
+#include <bits/setjmp.h>
+#include <bits/sigset.h>
+
+/* Calling environment, plus possibly a saved signal mask. */
+struct __jmp_buf_tag
+ {
+ /* NOTE: The machine-dependent definitions of `__sigsetjmp'
+ assume that a `jmp_buf' begins with a `__jmp_buf' and that
+ `__mask_was_saved' follows it. Do not move these members
+ or add others before it. */
+ __jmp_buf __jmpbuf; /* Calling environment. */
+ int __mask_was_saved; /* Saved the signal mask? */
+ __sigset_t __saved_mask; /* Saved signal mask. */
+ };
+
+#endif
\ No newline at end of file
diff --git a/libpthread/nptl/sysdeps/pthread/pthread.h b/libpthread/nptl/sysdeps/pthread/pthread.h
index 1fba7fca63c9..531e173220d2 100644
--- a/libpthread/nptl/sysdeps/pthread/pthread.h
+++ b/libpthread/nptl/sysdeps/pthread/pthread.h
@@ -28,6 +28,7 @@
#include <signal.h>
#include <bits/pthreadtypes.h>
#include <bits/setjmp.h>
+#include <bits/jmp_buf_tag.h>
#include <bits/wordsize.h>
#if defined _LIBC && ( defined IS_IN_libc || !defined NOT_IN_libc )
#include <bits/uClibc_pthread.h>
@@ -726,8 +727,7 @@ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
#endif
/* Function used in the macros. */
-struct __jmp_buf_tag;
-extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
+extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROWNL;
/* Mutex handling. */
--
2.25.1
From: Pavel Kozlov <pavel.kozlov(a)synopsys.com>
Commit 95e38b37 ("add support for systems without legacy setrlimit/getrlimit
syscalls") has added use of the prlimit64 syscall in getrlimit and setrlimit
functions. This change causes memory corruption on getrlimit call for 32-bit
CPUs like ARC, as ARC doesn't have ugetrlimit syscall and uses prlimit64.
Also, setrlimit has been broken by prlimit64 call on 32-bit CPUs like, i386,
ARM, ARC.
For the prlimit64 syscall the kernel expects an rlimit struct with 64-bit fields,
but on 32-bit CPUs without _FILE_OFFSET_BITS=64 the struct rlimit has 32-bit
fields.
Add safe implementations of getrlimit, setrlimit, prlimit for 32-bit CPUs with a
local struct rlimit64 variable for use in the prlimit64 syscall.
For 64-bit CPUs and configurations with _FILE_OFFSET_BITS=64 use
getrlimit, setrlimit, prlimit as aliases to getrlimit64, setrlimit64 and
prlimit64. Add a new function prlimit64.
Tested on aarch64, arm, i386, arc.
Fixes: 95e38b37 ("add support for systems without legacy setrlimit/getrlimit syscalls")
Signed-off-by: Pavel Kozlov <pavel.kozlov(a)synopsys.com>
---
include/sys/resource.h | 4 ++
libc/sysdeps/linux/common/getrlimit.c | 55 ++++++++++++++++++-------
libc/sysdeps/linux/common/getrlimit64.c | 26 ++++++++++--
libc/sysdeps/linux/common/prlimit.c | 53 +++++++++++++++++++++---
libc/sysdeps/linux/common/prlimit64.c | 36 ++++++++++++++++
libc/sysdeps/linux/common/setrlimit.c | 41 +++++++++++-------
libc/sysdeps/linux/common/setrlimit64.c | 24 +++++++++--
7 files changed, 197 insertions(+), 42 deletions(-)
create mode 100644 libc/sysdeps/linux/common/prlimit64.c
diff --git a/include/sys/resource.h b/include/sys/resource.h
index 00c63ff0f1e5..e9fac2c656bf 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -106,6 +106,10 @@ libc_hidden_proto(setpriority)
extern int prlimit (__pid_t __pid, enum __rlimit_resource __resource,
const struct rlimit *__new_limit,
struct rlimit *__old_limit) __THROW;
+
+extern int prlimit64 (__pid_t __pid, enum __rlimit_resource __resource,
+ const struct rlimit64 *__new_limit,
+ struct rlimit64 *__old_limit) __THROW;
#endif
__END_DECLS
diff --git a/libc/sysdeps/linux/common/getrlimit.c b/libc/sysdeps/linux/common/getrlimit.c
index ad3f4a0e494d..46726fcbd94f 100644
--- a/libc/sysdeps/linux/common/getrlimit.c
+++ b/libc/sysdeps/linux/common/getrlimit.c
@@ -24,21 +24,53 @@ int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits)
{
return __syscall_ugetrlimit(resource, rlimits);
}
+libc_hidden_def(getrlimit)
-#else
-
-# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__)
+#elif defined(__NR_prlimit64)
+/* Use prlimit64 if present, the prlimit64 syscall is free from a back
+ compatibility stuff for an old getrlimit */
-# if defined(__NR_prlimit64)
+# if __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64)
+/* If struct rlimit has 64-bit fields (if __WORDSIZE == 64 or __USE_FILE_OFFSET64
+ is defined), then use getrlimit as an alias to getrlimit64, see getrlimit64.c */
int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits)
{
- return INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits);
+ struct rlimit64 rlimits64;
+ int res = INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, &rlimits64);
+
+ if (res == 0) {
+ /* If the syscall succeeds but the values do not fit into a
+ rlimit structure set EOVERFLOW errno and retrun -1. */
+ rlimits->rlim_cur = rlimits64.rlim_cur;
+ if (rlimits64.rlim_cur != rlimits->rlim_cur) {
+ if (rlimits64.rlim_cur != RLIM64_INFINITY) {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ rlimits->rlim_cur = RLIM_INFINITY;
+ }
+
+ rlimits->rlim_max = rlimits64.rlim_max;
+ if (rlimits64.rlim_max != rlimits->rlim_max) {
+ if (rlimits64.rlim_max != RLIM64_INFINITY) {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ rlimits->rlim_max = RLIM_INFINITY;
+ }
+ }
+ return res;
}
-# else
+libc_hidden_def(getrlimit)
+# endif
+
+#else
+
+# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__)
+
/* We don't need to wrap getrlimit() */
_syscall2(int, getrlimit, __rlimit_resource_t, resource,
struct rlimit *, rlim)
-# endif
# else
@@ -51,11 +83,7 @@ int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits)
{
int result;
-# if defined(__NR_prlimit64)
- result = INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits);
-# else
result = __syscall_getrlimit(resource, rlimits);
-# endif
if (result == -1)
return result;
@@ -69,9 +97,6 @@ int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits)
return result;
}
# endif
-#endif
-libc_hidden_def(getrlimit)
-#if __WORDSIZE == 64
-strong_alias_untyped(getrlimit, getrlimit64)
+libc_hidden_def(getrlimit)
#endif
diff --git a/libc/sysdeps/linux/common/getrlimit64.c b/libc/sysdeps/linux/common/getrlimit64.c
index be98098a1ee0..47f1410fb3d9 100644
--- a/libc/sysdeps/linux/common/getrlimit64.c
+++ b/libc/sysdeps/linux/common/getrlimit64.c
@@ -17,14 +17,31 @@
#include <_lfs_64.h>
#include <bits/wordsize.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <stddef.h> // needed for NULL to be defined
-/* the regular getrlimit will work just fine for 64bit users */
-#if __WORDSIZE == 32
-# include <sys/resource.h>
+#if defined(__NR_prlimit64)
+
+/* the regular prlimit64 will work just fine for 64-bit users */
+int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits)
+{
+ return INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits);
+}
+
+# if !defined(__NR_ugetrlimit) && (__WORDSIZE == 64 || defined (__USE_FILE_OFFSET64))
+/* If getrlimit is not implemented through the __NR_ugetrlimit and size of
+ rlimit_t == rlimit64_t then use getrlimit as an alias to getrlimit64 */
+strong_alias_untyped(getrlimit64, getrlimit)
+libc_hidden_def(getrlimit)
+# endif
+
+#else
/* Put the soft and hard limits for RESOURCE in *RLIMITS.
- Returns 0 if successful, -1 if not (and sets errno). */
+ Returns 0 if successful, -1 if not (and sets errno).
+ The regular getrlimit will work just fine for 64-bit users */
int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits)
{
struct rlimit rlimits32;
@@ -44,3 +61,4 @@ int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits)
return 0;
}
#endif
+
diff --git a/libc/sysdeps/linux/common/prlimit.c b/libc/sysdeps/linux/common/prlimit.c
index f44dc166492e..f59ade3a379c 100644
--- a/libc/sysdeps/linux/common/prlimit.c
+++ b/libc/sysdeps/linux/common/prlimit.c
@@ -17,14 +17,57 @@
#include <sys/resource.h>
#include <sysdep.h>
-#include <bits/kernel-features.h>
+#include <stddef.h> // needed for NULL to be defined
-#if defined __ASSUME_PRLIMIT64
+#if defined(__NR_prlimit64) && __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64)
int
prlimit (__pid_t pid, enum __rlimit_resource resource,
- const struct rlimit *new_rlimit, struct rlimit *old_rlimit)
+ const struct rlimit *new_rlimit, struct rlimit *old_rlimit)
{
- return INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit,
- old_rlimit);
+ struct rlimit64 new_rlimit64;
+ struct rlimit64 old_rlimit64;
+ int res;
+
+ if (new_rlimit != NULL) {
+ if (new_rlimit->rlim_cur == RLIM_INFINITY)
+ new_rlimit64.rlim_cur = RLIM64_INFINITY;
+ else
+ new_rlimit64.rlim_cur = new_rlimit->rlim_cur;
+ if (new_rlimit->rlim_max == RLIM_INFINITY)
+ new_rlimit64.rlim_max = RLIM64_INFINITY;
+ else
+ new_rlimit64.rlim_max = new_rlimit->rlim_max;
+ }
+
+ res = INLINE_SYSCALL (prlimit64, 4, pid, resource, &new_rlimit64,
+ &old_rlimit64);
+
+ if (res == 0 && old_rlimit != NULL) {
+ /* If the syscall succeeds but the values do not fit into a
+ rlimit structure set EOVERFLOW errno and retrun -1.
+ With current Linux implementation of the prlimit64 syscall,
+ overflow can't happen. An extra condition has been added to get
+ the same behavior as in glibc for future potential overflows. */
+ old_rlimit->rlim_cur = old_rlimit64.rlim_cur;
+ if (old_rlimit64.rlim_cur != old_rlimit->rlim_cur) {
+ if (new_rlimit == NULL &&
+ old_rlimit64.rlim_cur != RLIM64_INFINITY) {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ old_rlimit->rlim_cur = RLIM_INFINITY;
+ }
+ old_rlimit->rlim_max = old_rlimit64.rlim_max;
+ if (old_rlimit64.rlim_max != old_rlimit->rlim_max) {
+ if (new_rlimit == NULL &&
+ old_rlimit64.rlim_max != RLIM64_INFINITY) {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ old_rlimit->rlim_cur = RLIM_INFINITY;
+ }
+ }
+
+ return res;
}
#endif
diff --git a/libc/sysdeps/linux/common/prlimit64.c b/libc/sysdeps/linux/common/prlimit64.c
new file mode 100644
index 000000000000..6f57b939eeca
--- /dev/null
+++ b/libc/sysdeps/linux/common/prlimit64.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2023 uClibc-ng
+ * An prlimit64() - get/set resource limits Linux specific syscall.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/resource.h>
+#include <sysdep.h>
+
+#if defined(__NR_prlimit64)
+
+int
+prlimit64 (__pid_t pid, enum __rlimit_resource resource,
+ const struct rlimit64 *new_rlimit, struct rlimit64 *old_rlimit)
+{
+ return INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit,
+ old_rlimit);
+}
+
+# if __WORDSIZE == 64 || defined (__USE_FILE_OFFSET64)
+strong_alias_untyped(prlimit64, prlimit)
+# endif
+
+#endif
\ No newline at end of file
diff --git a/libc/sysdeps/linux/common/setrlimit.c b/libc/sysdeps/linux/common/setrlimit.c
index 8381afc617fd..9c6707235f3e 100644
--- a/libc/sysdeps/linux/common/setrlimit.c
+++ b/libc/sysdeps/linux/common/setrlimit.c
@@ -23,21 +23,41 @@ int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits)
{
return __syscall_usetrlimit(resource, rlimits);
}
+libc_hidden_def(setrlimit)
-#else
+#elif defined(__NR_prlimit64)
-# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__)
+/* Use prlimit64 if present, the prlimit64 syscall is free from a back
+ compatibility stuff for setrlimit */
-# if defined(__NR_prlimit64)
+ # if __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64)
+/* If struct rlimit has 64-bit fields (if __WORDSIZE == 64 or __USE_FILE_OFFSET64
+ is defined), then use setrlimit as an alias to setrlimit64, see setrlimit64.c */
int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits)
{
- return INLINE_SYSCALL (prlimit64, 4, 0, resource, rlimits, NULL);
+ struct rlimit64 rlimits64;
+
+ if (rlimits->rlim_cur == RLIM_INFINITY)
+ rlimits64.rlim_cur = RLIM64_INFINITY;
+ else
+ rlimits64.rlim_cur = rlimits->rlim_cur;
+ if (rlimits->rlim_max == RLIM_INFINITY)
+ rlimits64.rlim_max = RLIM64_INFINITY;
+ else
+ rlimits64.rlim_max = rlimits->rlim_max;
+
+ return INLINE_SYSCALL (prlimit64, 4, 0, resource, &rlimits64, NULL);
}
-# else
+libc_hidden_def(setrlimit)
+# endif
+
+#else
+
+# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__)
+
/* We don't need to wrap setrlimit() */
_syscall2(int, setrlimit, __rlimit_resource_t, resource,
const struct rlimit *, rlim)
-# endif
# else
@@ -66,16 +86,9 @@ int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits)
RLIM_INFINITY >> 1);
rlimits_small.rlim_max = MIN((unsigned long int) rlimits->rlim_max,
RLIM_INFINITY >> 1);
-# if defined(__NR_prlimit64)
- return INLINE_SYSCALL (prlimit64, 4, 0, resource, &rlimits_small, NULL);
-# else
return __syscall_setrlimit(resource, &rlimits_small);
-# endif
}
# endif
-#endif
-libc_hidden_def(setrlimit)
-#if __WORDSIZE == 64
-strong_alias_untyped(setrlimit, setrlimit64)
+libc_hidden_def(setrlimit)
#endif
diff --git a/libc/sysdeps/linux/common/setrlimit64.c b/libc/sysdeps/linux/common/setrlimit64.c
index fee14f4ad4b2..3446c58fee12 100644
--- a/libc/sysdeps/linux/common/setrlimit64.c
+++ b/libc/sysdeps/linux/common/setrlimit64.c
@@ -17,15 +17,31 @@
#include <_lfs_64.h>
#include <bits/wordsize.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <stddef.h> // needed for NULL to be defined
-/* the regular setrlimit will work just fine for 64bit users */
-#if __WORDSIZE == 32
-# include <sys/resource.h>
+#if defined(__NR_prlimit64)
+
+int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits)
+{
+ return INLINE_SYSCALL (prlimit64, 4, 0, resource, rlimits, NULL);
+}
+
+# if !defined(__NR_usetrlimit) && (__WORDSIZE == 64 || defined (__USE_FILE_OFFSET64))
+/* If setrlimit is not implemented through the __NR_usetrlimit and size of
+ rlimit_t == rlimit64_t then use setrlimit as an alias to setrlimit64 */
+strong_alias_untyped(setrlimit64, setrlimit)
+libc_hidden_def(setrlimit)
+# endif
+
+#else
/* Set the soft and hard limits for RESOURCE to *RLIMITS.
Only the super-user can increase hard limits.
- Return 0 if successful, -1 if not (and sets errno). */
+ Return 0 if successful, -1 if not (and sets errno).
+ The regular setrlimit will work just fine for 64bit users */
int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits)
{
struct rlimit rlimits32;
--
2.25.1
Threads currently have 2-4 MiB stacks by default (depending on the
platform). This is fine on MMU platforms, where this stack space is not
actually allocated until it is used, but tends to waste a large amount
of memory on no-MMU platforms.
This patch adds a PTHREADS_STACK_DEFAULT_SIZE Kconfig option that allows
the user to override the default stack size at build time. This allows
the user to select a reasonable default stack size for the software that
runs on their system, and avoids the need to patch every package to add
calls to pthread_attr_setstacksize().
An alternative to this patch would be to change the hardcoded default
stack size on no-MMU platforms, but it is difficult to choose an
appropriate value because the minimum required stack depends on the
software in use. This would also be a breaking change.
It may also be desirable to completely move the default stack size
configuration to Kconfig, with conditional defaults for each platform.
This would avoid special casing zero as the default value.
Signed-off-by: Ben Wolsieffer <ben.wolsieffer(a)hefring.com>
---
extra/Configs/Config.in | 8 ++++++++
libpthread/nptl/init.c | 20 +++++++++++++-------
2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 6bbb6f572..ecb55ef3f 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -628,6 +628,14 @@ config PTHREADS_DEBUG_SUPPORT
If you are doing development and want to debug applications using
uClibc's pthread library, answer Y. Otherwise, answer N.
+config PTHREADS_STACK_DEFAULT_SIZE
+ int "Default thread stack size"
+ default 0
+ help
+ Set the default thread stack size. If set to zero, an architecture
+ specific default is used. This option is useful on MMU-less systems
+ where the stack size is fixed and the default stack size may be
+ excessively large and waste memory.
config UCLIBC_HAS_SYSLOG
bool "Syslog support"
diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c
index 5d25ded7d..f5c144e7b 100644
--- a/libpthread/nptl/init.c
+++ b/libpthread/nptl/init.c
@@ -35,6 +35,12 @@
#include <bits/kernel-features.h>
#include <stdio.h>
+#if __PTHREADS_STACK_DEFAULT_SIZE__
+#define PTHREAD_STACK_DEFAULT_SIZE __PTHREADS_STACK_DEFAULT_SIZE__
+#else
+#define PTHREAD_STACK_DEFAULT_SIZE ARCH_STACK_DEFAULT_SIZE
+#endif
+
/* Size and alignment of static TLS block. */
size_t __static_tls_size;
size_t __static_tls_align_m1;
@@ -278,17 +284,17 @@ __pthread_initialize_minimal_internal (void)
struct rlimit limit;
if (getrlimit (RLIMIT_STACK, &limit) != 0
|| limit.rlim_cur == RLIM_INFINITY)
- /* The system limit is not usable. Use an architecture-specific
- default. */
- limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE;
- else if (limit.rlim_cur < PTHREAD_STACK_MIN)
+ /* The system limit is not usable. Use a user-specified or
+ architecture-specific default. */
+ limit.rlim_cur = PTHREAD_STACK_DEFAULT_SIZE;
+ if (limit.rlim_cur < PTHREAD_STACK_MIN)
/* The system limit is unusably small.
Use the minimal size acceptable. */
limit.rlim_cur = PTHREAD_STACK_MIN;
- /* Do not exceed architecture specific default */
- if (limit.rlim_cur > ARCH_STACK_DEFAULT_SIZE)
- limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE;
+ /* Do not exceed the user-specified or architecture-specific default */
+ if (limit.rlim_cur > PTHREAD_STACK_DEFAULT_SIZE)
+ limit.rlim_cur = PTHREAD_STACK_DEFAULT_SIZE;
/* Make sure it meets the minimum size that allocate_stack
(allocatestack.c) will demand, which depends on the page size. */
--
2.42.0
Dear uclibc-ng developers,
We have run a static analysis tool (Klocwork) in uclibc and one of its
checkers (ABV.GENERAL) indicates a potential buffer overflow in
uclibc-ng/src/master/libc/stdio/_vfprintf.c:1045
The problem occurs as an out-of-bounds access to array 'argtype', which
is a member of 'ppfs_t'. This array has length 'MAX_ARGS'. According to
the static analysis tool, the array can be accessed using index 'n' of
value '-1' and '9..254' in the conditional shown below:
// File: uclibc-ng/src/master/libc/stdio/_vfprintf.c:1045
if (_is_equal_or_bigger_arg(ppfs->argtype[n], argtype[i])) {
ppfs->argtype[n] = argtype[i];
}
Triggering an out-of-bounds access for 'n=-1' is relatively simply when
using printf or similar functions (e.g. vfprintf). Such out-of-bounds
access occurs when positional arguments are specified, as in the
following statement:
printf("%1$s", "Hello world!");
Although Klocwork claims that the array might be accessed using indexes
'9..254', we were not able to trigger an out-of-bounds access for
indexes in this range.
Kind regards,
Diego Dias
--
Diego M. Dias, Systems Verification Engineer at Kernkonzept, diego.dias(a)kernkonzept.com
Phone: +49 351 41883231
Kernkonzept GmbH at Dresden, Germany, HRB 31129, CEO Dr.-Ing. Michael Hohmuth
From: Ben Wolsieffer <Ben.Wolsieffer(a)hefring.com>
fork() can be implemented using either the fork or clone syscalls on MMU
systems. Therefore the stub is only generated if neither __NR_fork nor
__NR_clone are defined. The stub code manually undefines __NR_fork on
no-MMU systems in an attempt to enable the stub, but this doesn't work
because __NR_clone is still defined. It is not appropriate to undefine
__NR_clone because clone is available on no-MMU, it is just not capable
of implementing fork.
This patch directly enables the fork stub if __ARCH_USE_MMU__ is not
defined. This eliminates the need to undefine __NR_fork, so this code is
removed
Signed-off-by: Ben Wolsieffer <ben.wolsieffer(a)hefring.com>
---
libc/sysdeps/linux/common/stubs.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c
index c17e509b9..634dcde0d 100644
--- a/libc/sysdeps/linux/common/stubs.c
+++ b/libc/sysdeps/linux/common/stubs.c
@@ -34,10 +34,6 @@ __attribute_used__ static int ret_enosys_stub(void)
link_warning(stub, #stub ": this function is not implemented") \
strong_alias(ret_enosys_stub, stub)
-#ifndef __ARCH_USE_MMU__
-# undef __NR_fork
-#endif
-
#ifdef __arm__
# define __NR_fadvise64_64 __NR_arm_fadvise64_64
# define __NR_fadvise64 __NR_arm_fadvise64_64
@@ -120,7 +116,7 @@ make_stub(fgetxattr)
make_stub(flistxattr)
#endif
-#if !defined __NR_fork && !defined __NR_clone
+#if !defined __ARCH_USE_MMU__ || (!defined __NR_fork && !defined __NR_clone)
make_stub(fork)
#endif
--
2.42.0
From: Ben Wolsieffer <Ben.Wolsieffer(a)hefring.com>
The stub code undefs __NR_fork on no-MMU systems, but it also needs to
undef __NR_clone since fork can now be implemented using clone, and
clone is not available either on no-MMU systems.
---
libc/sysdeps/linux/common/stubs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c
index c17e509b9..11849e3ba 100644
--- a/libc/sysdeps/linux/common/stubs.c
+++ b/libc/sysdeps/linux/common/stubs.c
@@ -36,6 +36,7 @@ __attribute_used__ static int ret_enosys_stub(void)
#ifndef __ARCH_USE_MMU__
# undef __NR_fork
+# undef __NR_clone
#endif
#ifdef __arm__
--
2.42.0
The commit cf649082c7d4 ("remove forced gcc optimization") removed -O3
optimization specified in the code for the function _fork_parent, but at
the same time it removed the 'static inline' part of the function
definition. That change seems unintended and _fork_parent is not a part
of the libc interface. Make it static inline again.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
---
libc/unistd/daemon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/unistd/daemon.c b/libc/unistd/daemon.c
index 53fd902bfd72..599c3c8e6cd4 100644
--- a/libc/unistd/daemon.c
+++ b/libc/unistd/daemon.c
@@ -63,7 +63,7 @@
/* use clone() to get fork() like behavior here -- we just want to disassociate
* from the controlling terminal
*/
-pid_t _fork_parent(void)
+static inline pid_t _fork_parent(void)
{
INTERNAL_SYSCALL_DECL(err);
register long ret = INTERNAL_SYSCALL(clone, err, 2, CLONE_VM, 0);
--
2.30.2