From: Ryan Bloom Date: Tue, 6 Jun 2000 21:45:16 +0000 (+0000) Subject: Add the resource limiting code back to Apache 2.0. This only works on X-Git-Tag: APACHE_2_0_ALPHA_5~422 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c8e0cb24f3d2bd699b89ac441f8489ce2c8bfcc;p=thirdparty%2Fapache%2Fhttpd.git Add the resource limiting code back to Apache 2.0. This only works on 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 --- diff --git a/STATUS b/STATUS index b8c2b38072b..a7479cf93fa 100644 --- 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> diff --git a/include/http_core.h b/include/http_core.h index 15f4d32afca..ee9a020872d 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -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 */ diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index dbfa41ad8f8..97bfa4e1804 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -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 #ifdef HAVE_PWD_H #include @@ -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, diff --git a/modules/generators/mod_cgi.c b/modules/generators/mod_cgi.c index 5055a89db3b..f95b86a1771 100644 --- a/modules/generators/mod_cgi.c +++ b/modules/generators/mod_cgi.c @@ -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, diff --git a/modules/http/http_core.c b/modules/http/http_core.c index d4d76ccdc69..ea5617a6daf 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -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 } }; diff --git a/os/unix/unixd.c b/os/unix/unixd.c index 9eb08c2c4ae..054f8491be9 100644 --- a/os/unix/unixd.c +++ b/os/unix/unixd.c @@ -63,6 +63,8 @@ #include "http_log.h" #include "unixd.h" #include +#include +#include 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 + diff --git a/os/unix/unixd.h b/os/unix/unixd.h index ae09fe3ec7a..f97020d6e30 100644 --- a/os/unix/unixd.h +++ b/os/unix/unixd.h @@ -60,6 +60,7 @@ #define UNIXD_H #include "httpd.h" +#include /* 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 */ diff --git a/server/mpm/dexter/mpm.h b/server/mpm/dexter/mpm.h index 5fd932fe2a5..e950de3f29c 100644 --- a/server/mpm/dexter/mpm.h +++ b/server/mpm/dexter/mpm.h @@ -58,6 +58,7 @@ #include "httpd.h" #include "mpm_default.h" +#include "unixd.h" #ifndef APACHE_MPM_DEXTER_H #define APACHE_MPM_DEXTER_H diff --git a/server/mpm/mpmt_pthread/mpm.h b/server/mpm/mpmt_pthread/mpm.h index b0a119095d7..33497a1979a 100644 --- a/server/mpm/mpmt_pthread/mpm.h +++ b/server/mpm/mpmt_pthread/mpm.h @@ -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 diff --git a/server/mpm/prefork/mpm.h b/server/mpm/prefork/mpm.h index df8ea97d62d..2d45e743c86 100644 --- a/server/mpm/prefork/mpm.h +++ b/server/mpm/prefork/mpm.h @@ -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