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


Reply via email to