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>
This commit is contained in:
Diego Nieto Cid 2025-08-15 02:57:30 +01:00 committed by Samuel Thibault
parent c9cc047e9f
commit 802b0eba51
5 changed files with 122 additions and 1 deletions

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

@ -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)