From: Diego Nieto Cid <dnie...@gmail.com> 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. --- config.h.in | 6 ++++ hurd/hurdrlimit.c | 5 +++ sysdeps/mach/configure | 60 +++++++++++++++++++++++++++++++++++ sysdeps/mach/configure.ac | 4 +++ sysdeps/mach/hurd/setrlimit.c | 57 ++++++++++++++++++++++++++++++++- 5 files changed, 131 insertions(+), 1 deletion(-) mode change 100644 => 100755 sysdeps/mach/configure diff --git a/config.h.in b/config.h.in index 29126ea933..3dbb3fd6af 100644 --- a/config.h.in +++ b/config.h.in @@ -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 diff --git a/hurd/hurdrlimit.c b/hurd/hurdrlimit.c index 6cb5045bfe..6b0d8a26a3 100644 --- a/hurd/hurdrlimit.c +++ b/hurd/hurdrlimit.c @@ -39,6 +39,11 @@ init_rlimit (void) for (i = 0; i < RLIM_NLIMITS; ++i) { +#ifdef HAVE_MACH_VM_GET_SIZE_LIMIT + if (i == RLIMIT_AS) + __vm_get_size_limit (__mach_task_self (), + &_hurd_rlimits[i].rlim_cur, &_hurd_rlimits[i].rlim_max); +#endif if (_hurd_rlimits[i].rlim_max == 0) _hurd_rlimits[i].rlim_max = RLIM_INFINITY; if (_hurd_rlimits[i].rlim_cur == 0) diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure old mode 100644 new mode 100755 index 311b2dd30b..0161937ab4 --- a/sysdeps/mach/configure +++ b/sysdeps/mach/configure @@ -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 diff --git a/sysdeps/mach/configure.ac b/sysdeps/mach/configure.ac index 3a6f2443e2..237b8be937 100644 --- a/sysdeps/mach/configure.ac +++ b/sysdeps/mach/configure.ac @@ -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 diff --git a/sysdeps/mach/hurd/setrlimit.c b/sysdeps/mach/hurd/setrlimit.c index cbc172ee75..ce01efbac8 100644 --- a/sysdeps/mach/hurd/setrlimit.c +++ b/sysdeps/mach/hurd/setrlimit.c @@ -28,6 +28,8 @@ int __setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits) { struct rlimit lim; + error_t err; + mach_port_t host = MACH_PORT_NULL; if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS) return __hurd_fail (EINVAL); @@ -41,13 +43,66 @@ __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) + { + /* XXX initialize err to 0 for skipping error handling in + * non-privileged host port branch. + */ + err = 0; + + /* Check whether the privileged host control port is required */ + if (_hurd_rlimits[resource].rlim_max < lim.rlim_max) + err = __get_privileged_ports (&host, NULL); + else + host = __mach_host_self (); + + /* If we were interrupted, leave the error unchanged so cleanup code can retry */ + if (err == EINTR) + goto fail; + + /* Handle any error getting the privileged ports by mapping them to EPERM */ + if (err) + { + err = EPERM; + goto fail; + } + } + + err = __vm_set_size_limit (host, __mach_task_self (), + lim.rlim_cur, lim.rlim_max); + + if (err != MIG_BAD_ID) + { + if (err) + goto fail; + } + else /* XXX MIG_BAD_ID returned as kernel support is missing, clear error */ + err = 0; + } +#endif + _hurd_rlimits[resource] = lim; + +fail: __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 err != 0 ? __hurd_fail (err) : 0; } libc_hidden_def (__setrlimit) -- 2.47.1