summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/common/getrlimit.c
diff options
context:
space:
mode:
authorPavel Kozlov <pavel.kozlov@synopsys.com>2023-10-17 14:01:22 +0400
committerWaldemar Brodkorb <wbx@openadk.org>2023-10-27 18:10:33 +0200
commit8c2f6218f81ab5303e07bad4e13f181aa9581d92 (patch)
tree14030c5133917d0f27f375c53e05ecd60b761cc1 /libc/sysdeps/linux/common/getrlimit.c
parent223d46f66af17e18be6e1eb2933a2c70eb64ad47 (diff)
setrlimit/getrlimit: fix prlimit64 syscall use for 32-bit CPUs
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@synopsys.com>
Diffstat (limited to 'libc/sysdeps/linux/common/getrlimit.c')
-rw-r--r--libc/sysdeps/linux/common/getrlimit.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/libc/sysdeps/linux/common/getrlimit.c b/libc/sysdeps/linux/common/getrlimit.c
index ad3f4a0e4..46726fcbd 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