]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Add the resource limiting code back to Apache 2.0. This only works on
authorRyan Bloom <rbb@apache.org>
Tue, 6 Jun 2000 21:45:16 +0000 (21:45 +0000)
committerRyan Bloom <rbb@apache.org>
Tue, 6 Jun 2000 21:45:16 +0000 (21:45 +0000)
Unix because I can't find any other platforms with rlimit.  If there are
other platforms that need this code, then some of the code needs to move.
This has just barely been tested, so it could probably use some good
testing.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@85449 13f79535-47bb-0310-9956-ffa450edef68

STATUS
include/http_core.h
modules/filters/mod_include.c
modules/generators/mod_cgi.c
modules/http/http_core.c
os/unix/unixd.c
os/unix/unixd.h
server/mpm/dexter/mpm.h
server/mpm/mpmt_pthread/mpm.h
server/mpm/prefork/mpm.h

diff --git a/STATUS b/STATUS
index b8c2b38072bbdc8d1640f6c241d37784dcc1e1b1..a7479cf93fa5d5943dff4f6e3a6d838ff329c4a0 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 Apache 2.0 STATUS:
-Last modified at [$Date: 2000/06/05 19:43:57 $]
+Last modified at [$Date: 2000/06/06 21:45:07 $]
 
 Release:
 
@@ -23,8 +23,6 @@ RELEASE SHOWSTOPPERS:
             module.  This should be override-able of course.
           Status: Jim Jagielski is looking into this.
 
-    * Put back resource limit code
-
     * suEXEC doesn't work
         Status: Manoj has posted an patch to fix this.
         <19991103003605.A20612@samosa.mindspring.com>
index 15f4d32afca84fbdc9b92a80c81beec507ed579c..ee9a020872da4ba5c32f248773dde8865ccd8247 100644 (file)
@@ -256,6 +256,16 @@ typedef struct {
     unsigned add_default_charset : 2;
     char *add_default_charset_name;
 
+    /* System Resource Control */
+#ifdef RLIMIT_CPU
+    struct rlimit *limit_cpu;
+#endif
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
+    struct rlimit *limit_mem;
+#endif
+#ifdef RLIMIT_NPROC
+    struct rlimit *limit_nproc;
+#endif
     unsigned long limit_req_body;  /* limit on bytes in request msg body */
 
     /* logging options */
index dbfa41ad8f85810ebd490f082f2547b5392ad680..97bfa4e18041adba83dd71d37fe39b393983bfce 100644 (file)
@@ -76,6 +76,8 @@
  * -Doug MacEachern
  */
 
+#define CORE_PRIVATE
+
 #ifdef USE_PERL_SSI
 #include "config.h"
 #undef VOIDUSED
@@ -94,6 +96,7 @@
 #include "http_log.h"
 #include "http_main.h"
 #include "util_script.h"
+#include "http_core.h"
 #include <string.h>
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -828,6 +831,12 @@ static int include_cmd(char *s, request_rec *r)
     char **argv;
     ap_file_t *file = NULL;
     ap_iol *iol;
+#if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
+    defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
+    core_dir_config *conf; 
+    conf = (core_dir_config *) ap_get_module_config(r->per_dir_config,
+                                                    &core_module);
+#endif
 
     arg.r = r;
     arg.s = s;
@@ -863,6 +872,15 @@ static int include_cmd(char *s, request_rec *r)
         (ap_setprocattr_io(procattr, APR_NO_PIPE, 
                            APR_FULL_BLOCK, APR_NO_PIPE) != APR_SUCCESS) ||
         (ap_setprocattr_dir(procattr, ap_make_dirstr_parent(r->pool, r->filename)) != APR_SUCCESS) ||
+#ifdef RLIMIT_CPU
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_CPU, conf->limit_cpu)) != APR_SUCCESS) ||
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_MEM, conf->limit_mem)) != APR_SUCCESS) ||
+#endif
+#ifdef RLIMIT_NPROC
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
+#endif
         (ap_setprocattr_cmdtype(procattr, APR_SHELLCMD) != APR_SUCCESS)) {
         /* Something bad happened, tell the world. */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
index 5055a89db3bb2152654fb5ca3d41090eaa35f551..f95b86a1771ef11e2c2d2fa99283a06fb38f814f 100644 (file)
@@ -69,6 +69,8 @@
  * they fail.
  */
 
+#define CORE_PRIVATE
+
 #include "ap_config.h"
 #include "httpd.h"
 #include "http_config.h"
@@ -305,6 +307,12 @@ static ap_status_t run_cgi_child(BUFF **script_out, BUFF **script_in, BUFF **scr
     ap_status_t rc = APR_SUCCESS;
     ap_file_t *file = NULL;
     ap_iol *iol;
+#if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
+    defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
+    core_dir_config *conf;
+    conf = (core_dir_config *) ap_get_module_config(r->per_dir_config,                                                              &core_module);
+#endif
+
 
 #ifdef DEBUG_CGI
 #ifdef OS2
@@ -341,6 +349,15 @@ static ap_status_t run_cgi_child(BUFF **script_out, BUFF **script_in, BUFF **scr
                                  APR_CHILD_BLOCK)) != APR_SUCCESS) ||
         ((rc = ap_setprocattr_dir(procattr, 
                                   ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
+#ifdef RLIMIT_CPU
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_CPU, conf->limit_cpu)) != APR_SUCCESS) ||
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_MEM, conf->limit_mem)) != APR_SUCCESS) ||
+#endif
+#ifdef RLIMIT_NPROC
+        ((rc = ap_setprocattr_limit(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
+#endif
         ((rc = ap_setprocattr_cmdtype(procattr, APR_PROGRAM)) != APR_SUCCESS)) {
         /* Something bad happened, tell the world. */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
index d4d76ccdc691e05d2ddafef77f391330e945719b..ea5617a6daf51925f536c57a3445d7901c4803a0 100644 (file)
@@ -72,6 +72,7 @@
 #include "apr_fnmatch.h"
 #include "http_connection.h"
 #include "util_ebcdic.h"
+#include "mpm.h"
 
 /* Allow Apache to use ap_mmap */
 #ifdef USE_MMAP_FILES
@@ -140,6 +141,16 @@ static void *create_core_dir_config(ap_pool_t *a, char *dir)
     conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
     conf->satisfy = SATISFY_NOSPEC;
 
+#ifdef RLIMIT_CPU
+    conf->limit_cpu = NULL;
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+    conf->limit_mem = NULL;
+#endif
+#ifdef RLIMIT_NPROC
+    conf->limit_nproc = NULL;
+#endif
+
     conf->limit_req_body = 0;
     conf->sec = ap_make_array(a, 2, sizeof(void *));
 #ifdef WIN32
@@ -243,6 +254,22 @@ static void *merge_core_dir_configs(ap_pool_t *a, void *basev, void *newv)
        conf->use_canonical_name = new->use_canonical_name;
     }
 
+#ifdef RLIMIT_CPU
+    if (new->limit_cpu) {
+        conf->limit_cpu = new->limit_cpu;
+    }
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+    if (new->limit_mem) {
+        conf->limit_mem = new->limit_mem;
+    }
+#endif
+#ifdef RLIMIT_NPROC
+    if (new->limit_nproc) {
+        conf->limit_nproc = new->limit_nproc;
+    }
+#endif
+
     if (new->limit_req_body) {
         conf->limit_req_body = new->limit_req_body;
     }
@@ -2225,6 +2252,49 @@ static const char *set_interpreter_source(cmd_parms *cmd, core_dir_config *d,
 }
 #endif
 
+#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
+static const char *no_set_limit(cmd_parms *cmd, core_dir_config *conf,
+                                char *arg, char *arg2)
+{
+    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, cmd->server,
+                "%s not supported on this platform", cmd->cmd->name);
+    return NULL;
+}
+#endif
+
+#ifdef RLIMIT_CPU
+static const char *set_limit_cpu(cmd_parms *cmd, core_dir_config *conf,
+                                 char *arg, char *arg2)
+{
+    unixd_set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
+    return NULL;
+}
+#endif
+
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
+static const char *set_limit_mem(cmd_parms *cmd, core_dir_config *conf,
+                                 char *arg, char * arg2)
+{
+#if defined(RLIMIT_AS)
+    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
+#elif defined(RLIMIT_DATA)
+    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
+#elif defined(RLIMIT_VMEM)
+    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
+#endif
+    return NULL;
+}
+#endif
+
+#ifdef RLIMIT_NPROC
+static const char *set_limit_nproc(cmd_parms *cmd, core_dir_config *conf,
+                                   char *arg, char * arg2)
+{
+    unixd_set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
+    return NULL;
+}
+#endif
+
 /* Note --- ErrorDocument will now work from .htaccess files.  
  * The AllowOverride of Fileinfo allows webmasters to turn it off
  */
@@ -2363,6 +2433,28 @@ static const command_rec core_cmds[] = {
   (void*)XtOffsetOf(core_dir_config, limit_req_body),
   OR_ALL, TAKE1,
   "Limit (in bytes) on maximum size of request message body" },
+/* System Resource Controls */
+{ "RLimitCPU",
+#ifdef RLIMIT_CPU
+  set_limit_cpu, (void*)XtOffsetOf(core_dir_config, limit_cpu),
+#else
+  no_set_limit, NULL,
+#endif
+  OR_ALL, TAKE12, "Soft/hard limits for max CPU usage in seconds" },
+{ "RLimitMEM",
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
+  set_limit_mem, (void*)XtOffsetOf(core_dir_config, limit_mem),
+#else
+  no_set_limit, NULL,
+#endif
+  OR_ALL, TAKE12, "Soft/hard limits for max memory usage per process" },
+{ "RLimitNPROC",
+#ifdef RLIMIT_NPROC
+  set_limit_nproc, (void*)XtOffsetOf(core_dir_config, limit_nproc),
+#else
+  no_set_limit, NULL,
+#endif
+   OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
 { NULL }
 };
 
index 9eb08c2c4ae63105061257f48bf5c58e24312010..054f8491be92a26331f996429095404eec5782a4 100644 (file)
@@ -63,6 +63,8 @@
 #include "http_log.h"
 #include "unixd.h"
 #include <pwd.h>
+#include <sys/resource.h>
+#include <sys/resource.h>
 
 unixd_config_rec unixd_config;
 
@@ -394,4 +396,60 @@ void unixd_siglist_init(void)
             ap_sys_siglist[sig] = "";
 }
 #endif /* NEED_AP_SYS_SIGLIST */
+
+#if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)
+API_EXPORT(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit, 
+                           const char *arg, const char * arg2, int type)
+{
+    char *str;
+    struct rlimit *limit;
+    /* If your platform doesn't define rlim_t then typedef it in ap_config.h */
+    rlim_t cur = 0;
+    rlim_t max = 0;
+
+    *plimit = (struct rlimit *)ap_pcalloc(cmd->pool, sizeof(**plimit));
+    limit = *plimit;
+    if ((getrlimit(type, limit)) != 0)  {
+        *plimit = NULL;
+        ap_log_error(APLOG_MARK, APLOG_ERR, cmd->server,
+                     "%s: getrlimit failed", cmd->cmd->name);
+        return;
+    }
+
+    if ((str = ap_getword_conf(cmd->pool, &arg))) {
+        if (!strcasecmp(str, "max")) {
+            cur = limit->rlim_max;
+        }
+        else {
+            cur = atol(str);
+        }
+    }
+    else {
+        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
+                     "Invalid parameters for %s", cmd->cmd->name);
+        return;
+    }
+
+    if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) {
+        max = atol(str);
+    }
+
+    /* if we aren't running as root, cannot increase max */
+    if (geteuid()) {
+        limit->rlim_cur = cur;
+        if (max) {
+            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
+                         "Must be uid 0 to raise maximum %s", cmd->cmd->name);
+        }
+    }
+    else {
+        if (cur) {
+            limit->rlim_cur = cur;
+        }
+        if (max) {
+            limit->rlim_max = max;
+        }
+    }
+}
+#endif
+
index ae09fe3ec7ae055abdb8d8d1516832211d629822..f97020d6e30091a9714e8c48e71928156ed95305 100644 (file)
@@ -60,6 +60,7 @@
 #define UNIXD_H
 
 #include "httpd.h"
+#include <sys/resource.h>
 
 /* common stuff that unix MPMs will want */
 
@@ -85,6 +86,11 @@ int unixd_setup_child(void);
 void unixd_pre_config(void);
 const char *unixd_set_user(cmd_parms *cmd, void *dummy, char *arg);
 const char *unixd_set_group(cmd_parms *cmd, void *dummy, char *arg);
+#if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || \
+    defined(RLIMIT_NPROC) || defined(RLIMIT_AS)
+API_EXPORT(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit,
+                           const char *arg, const char * arg2, int type);
+#endif
 
 /* Information on signals for the various platforms */
 
index 5fd932fe2a5dcba1e7e8744a794bd9adeec0fbbb..e950de3f29cc8843d2bfb11f8978557bb30236c9 100644 (file)
@@ -58,6 +58,7 @@
 
 #include "httpd.h"
 #include "mpm_default.h"
+#include "unixd.h"
 
 #ifndef APACHE_MPM_DEXTER_H
 #define APACHE_MPM_DEXTER_H
index b0a119095d74cb959421ae8e905df7a7d7a704c9..33497a1979a945d9e2a007a75a43516351c8a951 100644 (file)
@@ -56,6 +56,7 @@
  * University of Illinois, Urbana-Champaign.
  */
 #include "scoreboard.h"
+#include "unixd.h"
 
 #ifndef APACHE_MPM_MPMT_PTHREAD_H
 #define APACHE_MPM_MPMT_PTHREAD_H
index df8ea97d62d452078d8545ec139c096268c6d3da..2d45e743c86028212daeb0ff144ccc9378117bc8 100644 (file)
@@ -59,6 +59,7 @@
 #include "httpd.h"
 #include "mpm_default.h"
 #include "scoreboard.h"
+#include "unixd.h"
 
 #ifndef APACHE_MPM_PREFORK_H
 #define APACHE_MPM_PREFORK_H