Compare commits

...

4 Commits

Author SHA1 Message Date
Samuel Thibault b7e0ec907b hurd: Fix RLIM_INFINITY on 64b
rlim_t is 64b on 64b systems, so we should extend RLIM_INFINITY to that,
not only RLIM64_INFINITY or requiring 64b offsets.

This is similar to Linux headers.
2025-09-22 02:30:14 +02:00
Samuel Thibault 81a6e97791 hurd: Note BZ #30166 as fixed
802b0eba51 ("hurd: implement RLIMIT_AS against Mach RPCs") brought the
needed RLIMIT_AS support for memory-crunchy tests.
2025-09-22 02:17:50 +02:00
Diego Nieto Cid 802b0eba51 hurd: implement RLIMIT_AS against Mach RPCs
Check for VM limit RPCs

  * config.h.in: add #undef for HAVE_MACH_VM_GET_SIZE_LIMIT and
    HAVE_MACH_VM_SET_SIZE_LIMIT.
  * sysdeps/mach/configure.ac: use mach_RPC_CHECK to check for
    vm_set_size_limit and vm_get_size_limit RPCs in gnumach.defs.
  * sysdeps/mach/configure: regenerate file.

Use vm_get_size_limit to initialize RLIMIT_AS

  * hurd/hurdrlimit.c(init_rlimit): use vm_get_size_limit to initialize
    RLIMIT_AS entry of the _hurd_rlimits array.

Notify the kernel of the new VM size limits

  * sysdeps/mach/hurd/setrlimit.c: use the vm_set_size_limit RPC,
    if available, to notify the kernel of the new limits. Retry RPC
    calls if they were interrupted by a signal.
Message-ID: <03fb90a795b354a366ee73f56f73e6ad22a86cda.1755220108.git.dnietoc@gmail.com>
2025-09-22 00:52:37 +02:00
Samuel Thibault c9cc047e9f hurd: catch SIGSEGV on returning from signal handler
On stack overflow typically, we may not actually have room on the stack to
trampoline back from the signal handler.  We have to detect this before
locking the ss, otherwise the signal thread will be stuck on taking the
ss lock while trying to post SIGSEGV.
2025-09-21 23:45:40 +02:00
9 changed files with 146 additions and 35 deletions

View File

@ -77,7 +77,7 @@ enum __rlimit_resource
/* Value to indicate that there is no limit. */
#ifndef __USE_FILE_OFFSET64
# define RLIM_INFINITY 0x7fffffff
# define RLIM_INFINITY ((__rlim_t) -1)
#else
# define RLIM_INFINITY 0x7fffffffffffffffLL
#endif

View File

@ -164,6 +164,12 @@
/* Mach specific: define if the `thread_get_name' RPC is available. */
#undef HAVE_MACH_THREAD_GET_NAME
/* Mach specific: define if the `vm_get_size_limit' RPC is available. */
#undef HAVE_MACH_VM_GET_SIZE_LIMIT
/* Mach specific: define if the `vm_set_size_limit' RPC is available. */
#undef HAVE_MACH_VM_SET_SIZE_LIMIT
/* Mach/i386 specific: define if the `i386_io_perm_*' RPCs are available. */
#undef HAVE_I386_IO_PERM_MODIFY

View File

@ -37,6 +37,11 @@ init_rlimit (void)
__mutex_init (&_hurd_rlimit_lock);
#ifdef HAVE_MACH_VM_GET_SIZE_LIMIT
__vm_get_size_limit (__mach_task_self (),
&_hurd_rlimits[RLIMIT_AS].rlim_cur, &_hurd_rlimits[RLIMIT_AS].rlim_max);
#endif
for (i = 0; i < RLIM_NLIMITS; ++i)
{
if (_hurd_rlimits[i].rlim_max == 0)

60
sysdeps/mach/configure vendored Normal file → Executable file
View File

@ -581,6 +581,66 @@ if test $libc_cv_mach_rpc_thread_get_name = yes; then
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for vm_set_size_limit in gnumach.defs" >&5
printf %s "checking for vm_set_size_limit in gnumach.defs... " >&6; }
if test ${libc_cv_mach_rpc_vm_set_size_limit+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <mach/gnumach.defs>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP_TRADITIONAL "vm_set_size_limit" >/dev/null 2>&1
then :
libc_cv_mach_rpc_vm_set_size_limit=yes
else case e in #(
e) libc_cv_mach_rpc_vm_set_size_limit=no ;;
esac
fi
rm -rf conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mach_rpc_vm_set_size_limit" >&5
printf "%s\n" "$libc_cv_mach_rpc_vm_set_size_limit" >&6; }
if test $libc_cv_mach_rpc_vm_set_size_limit = yes; then
printf "%s\n" "#define HAVE_MACH_VM_SET_SIZE_LIMIT 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for vm_get_size_limit in gnumach.defs" >&5
printf %s "checking for vm_get_size_limit in gnumach.defs... " >&6; }
if test ${libc_cv_mach_rpc_vm_get_size_limit+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <mach/gnumach.defs>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP_TRADITIONAL "vm_get_size_limit" >/dev/null 2>&1
then :
libc_cv_mach_rpc_vm_get_size_limit=yes
else case e in #(
e) libc_cv_mach_rpc_vm_get_size_limit=no ;;
esac
fi
rm -rf conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mach_rpc_vm_get_size_limit" >&5
printf "%s\n" "$libc_cv_mach_rpc_vm_get_size_limit" >&6; }
if test $libc_cv_mach_rpc_vm_get_size_limit = yes; then
printf "%s\n" "#define HAVE_MACH_VM_GET_SIZE_LIMIT 1" >>confdefs.h
fi
ac_fn_c_check_header_preproc "$LINENO" "mach/machine/ndr_def.h" "ac_cv_header_mach_machine_ndr_def_h"
if test "x$ac_cv_header_mach_machine_ndr_def_h" = xyes

View File

@ -100,6 +100,10 @@ mach_RPC_CHECK(gnumach.defs, thread_set_name,
HAVE_MACH_THREAD_SET_NAME)
mach_RPC_CHECK(gnumach.defs, thread_get_name,
HAVE_MACH_THREAD_GET_NAME)
mach_RPC_CHECK(gnumach.defs, vm_set_size_limit,
HAVE_MACH_VM_SET_SIZE_LIMIT)
mach_RPC_CHECK(gnumach.defs, vm_get_size_limit,
HAVE_MACH_VM_GET_SIZE_LIMIT)
AC_CHECK_HEADER(mach/machine/ndr_def.h, [dnl
DEFINES="$DEFINES -DNDR_DEF_HEADER='<mach/machine/ndr_def.h>'"], [dnl

View File

@ -306,43 +306,12 @@ test-xfail-tst-origin = yes
CFLAGS-tst-execstack.c += -DDEFAULT_RWX_STACK=1
endif
# For bug 30166
# (missing RLIMIT_AS support)
ifeq ($(subdir),htl)
tests-unsupported += tst-basic7
endif
ifeq ($(subdir),libio)
tests-unsupported += tst-asprintf-null
endif
ifeq ($(subdir),malloc)
tests-unsupported += tst-malloc-thread-fail
tests-unsupported += tst-malloc-thread-fail-malloc-check
tests-unsupported += tst-malloc-thread-fail-mcheck
tests-unsupported += tst-malloc-thread-fail-malloc-hugetlb1
tests-unsupported += tst-malloc-thread-fail-malloc-hugetlb2
tests-unsupported += tst-malloc-thread-fail-malloc-largetcache
tests-unsupported += tst-dynarray-fail
endif
ifeq ($(subdir),misc)
tests-unsupported += bug18240
endif
ifeq ($(subdir),stdio-common)
tests-unsupported += tst-getline-enomem
tests-unsupported += tst-getline-enomem-mem
tests-unsupported += tst-vfprintf-width-prec
tests-unsupported += tst-vfprintf-width-prec-mem
tests-unsupported += tst-vfprintf-width-prec-alloc
endif
ifeq ($(subdir),stdlib)
tests-unsupported += test-bz22786 tst-strtod-overflow
# pthread_cleanup_combined_push/pthread_cleanup_combined_pop requires cleanup
# support (BZ 32058).
test-xfail-tst-qsort7-mem = yes
test-xfail-tst-qsortx7-mem = yes
endif
ifeq ($(subdir),timezone)
tests-unsupported += tst-tzset
endif
# For bug 30167
# (select requests overflow)

View File

@ -89,10 +89,21 @@ __sigreturn (struct sigcontext *scp)
{
struct hurd_sigstate *ss;
struct hurd_userlink *link = (void *) &scp[1];
int *usp;
/* Stack usage while trampolining back:
* register dump, parameters, and rough estimation of usage in __sigreturn2
* before unlocking ss. */
size_t tramp_usage = 18 * sizeof (uintptr_t) + 32;
if (__glibc_unlikely (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)))
return __hurd_fail (EINVAL);
usp = (int *) scp->sc_uesp;
/* If we are to segfault, do it now before locking the ss. */
memset ((void*) usp - tramp_usage, 0, tramp_usage);
ss = _hurd_self_sigstate ();
_hurd_sigstate_lock (ss);
@ -160,7 +171,7 @@ __sigreturn (struct sigcontext *scp)
copy the registers onto the user's stack, switch there, pop and
return. */
int usp_arg, *usp = (int *) scp->sc_uesp;
int usp_arg;
*--usp = scp->sc_eip;
*--usp = scp->sc_efl;

View File

@ -28,6 +28,8 @@ int
__setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits)
{
struct rlimit lim;
error_t err = 0;
mach_port_t host = MACH_PORT_NULL;
if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS)
return __hurd_fail (EINVAL);
@ -41,13 +43,57 @@ __setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits)
if (lim.rlim_cur > lim.rlim_max)
lim.rlim_cur = lim.rlim_max;
retry:
HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_rlimit_lock);
#ifdef HAVE_MACH_VM_SET_SIZE_LIMIT
if (resource == RLIMIT_AS)
{
if (host == MACH_PORT_NULL)
{
/* Check whether the privileged host control port is required */
if (_hurd_rlimits[resource].rlim_max < lim.rlim_max)
{
err = __get_privileged_ports (&host, NULL);
if (err)
goto fail;
}
else
host = __mach_host_self ();
}
err = __vm_set_size_limit (host, __mach_task_self (),
lim.rlim_cur, lim.rlim_max);
if (err == MIG_BAD_ID)
/* MIG_BAD_ID returned as kernel support is missing, clear error */
err = 0;
else if (err)
{
if (err == KERN_NO_ACCESS)
err = EPERM;
goto fail;
}
}
#endif
_hurd_rlimits[resource] = lim;
#ifdef HAVE_MACH_VM_SET_SIZE_LIMIT
fail:
#endif
__mutex_unlock (&_hurd_rlimit_lock);
HURD_CRITICAL_END;
return 0;
if (err == EINTR)
/* Got a signal while inside an RPC of the critical section, retry */
goto retry;
if (host != MACH_PORT_NULL && host != __mach_host_self ())
__mach_port_deallocate (__mach_task_self (), host);
return __hurd_fail (err);
}
libc_hidden_def (__setrlimit)

View File

@ -83,9 +83,20 @@ __sigreturn (struct sigcontext *scp)
uintptr_t *usp;
mach_port_t sc_reply_port;
/* Stack usage while trampolining back:
* register dump, 16B round-up, and rough estimation of usage in __sigreturn2
* before unlocking ss. */
size_t tramp_usage = 17 * sizeof (uintptr_t) + 16 + 64;
if (__glibc_unlikely (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)))
return __hurd_fail (EINVAL);
/* Respect the redzone. */
usp = (uintptr_t *) (scp->sc_ursp - 128);
/* If we are to segfault, do it now before locking the ss. */
memset ((void*) usp - tramp_usage, 0, tramp_usage);
ss = _hurd_self_sigstate ();
_hurd_sigstate_lock (ss);
@ -160,7 +171,6 @@ __sigreturn (struct sigcontext *scp)
located at a larger address than the sigcontext. */
sc_reply_port = scp->sc_reply_port;
usp = (uintptr_t *) (scp->sc_ursp - 128);
*--usp = scp->sc_rip;
*--usp = scp->sc_rfl;