randy 96/07/26 19:49:40
Modified: src http_core.c http_core.h util_script.c Log: Add resource limiting directives, RLimitCPU, RLimitMEM and RLimitNPROC. Reviewed by: Alexei Kosut, Ben Laurie and Robert Thau Revision Changes Path 1.20 +151 -0 apache/src/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache/src/http_core.c,v retrieving revision 1.19 retrieving revision 1.20 diff -C3 -r1.19 -r1.20 *** http_core.c 1996/07/25 19:32:28 1.19 --- http_core.c 1996/07/27 02:49:34 1.20 *************** *** 94,99 **** --- 94,120 ---- conf->hostname_lookups = 2;/* binary, but will use 2 as an "unset = on" */ conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */ + #ifdef RLIMIT_CPU + conf->limit_cpu = (struct rlimit *) pcalloc (a, sizeof (struct rlimit)); + if ((getrlimit(RLIMIT_CPU, conf->limit_cpu)) != 0) + conf->limit_cpu = NULL; + #endif + #ifdef RLIMIT_DATA + conf->limit_mem = (struct rlimit *) pcalloc (a, sizeof (struct rlimit)); + if ((getrlimit(RLIMIT_DATA, conf->limit_mem)) != 0) + conf->limit_mem = NULL; + #endif + #ifdef RLIMIT_VMEM + conf->limit_mem = (struct rlimit *) pcalloc (a, sizeof (struct rlimit)); + if ((getrlimit(RLIMIT_VMEM, conf->limit_mem)) != 0) + conf->limit_mem = NULL; + #endif + #ifdef RLIMIT_NPROC + conf->limit_nproc = (struct rlimit *) pcalloc (a, sizeof (struct rlimit)); + if ((getrlimit(RLIMIT_NPROC, conf->limit_nproc)) != 0) + conf->limit_nproc = NULL; + #endif + conf->sec = make_array (a, 2, sizeof(void *)); return (void *)conf; *************** *** 128,133 **** --- 149,164 ---- if ((new->do_rfc1413 & 2) == 0) conf->do_rfc1413 = new->do_rfc1413; if ((new->content_md5 & 2) == 0) conf->content_md5 = new->content_md5; + #ifdef RLIMIT_CPU + if (new->limit_cpu) conf->limit_cpu = new->limit_cpu; + #endif + #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) + 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 + conf->sec = append_arrays (a, base->sec, new->sec); return (void*)conf; *************** *** 808,813 **** --- 839,958 ---- return NULL; } + char *set_limit_cpu (cmd_parms *cmd, core_dir_config *conf, char *arg) + { + #ifdef RLIMIT_CPU + char *str; + quad_t cur = 0; + quad_t max = 0; + + if ((str = getword_conf(cmd->pool, &arg))) + if (!strcasecmp(str, "max")) + cur = conf->limit_cpu->rlim_max; + else + cur = atol(str); + else { + log_error("Invalid parameters for RLimitCPU", cmd->server); + return NULL; + } + + if ((str = getword_conf(cmd->pool, &arg))) + max = atol(str); + + /* if we aren't running as root, cannot increase max */ + if (geteuid()) { + conf->limit_cpu->rlim_cur = cur; + if (max) + log_error("Must be uid 0 to raise maximum RLIMIT_CPU", cmd->server); + } + else { + if (cur) + conf->limit_cpu->rlim_cur = cur; + if (max) + conf->limit_cpu->rlim_max = max; + } + #else + log_error("RLimitCPU not supported on this platform", cmd->server); + #endif + return NULL; + } + + char *set_limit_mem (cmd_parms *cmd, core_dir_config *conf, char *arg) + { + #if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) + char *str; + quad_t cur = 0; + quad_t max = 0; + + if ((str = getword_conf(cmd->pool, &arg))) + if (!strcasecmp(str, "max")) + cur = conf->limit_mem->rlim_max; + else + cur = atol(str); + else { + log_error("Invalid parameters for RLimitMEM", cmd->server); + return NULL; + } + + if ((str = getword_conf(cmd->pool, &arg))) + max = atol(str); + + /* if we aren't running as root, cannot increase max */ + if (geteuid()) { + conf->limit_mem->rlim_cur = cur; + if (max) + log_error("Must be uid 0 to change maximum RLIMIT_MEM", cmd->server); + } + else { + if (cur) + conf->limit_mem->rlim_cur = cur; + if (max) + conf->limit_mem->rlim_max = max; + } + #else + log_error("RLimitMEM not supported on this platform", cmd->server); + #endif + return NULL; + } + + char *set_limit_nproc (cmd_parms *cmd, core_dir_config *conf, char *arg) + { + #ifdef RLIMIT_NPROC + char *str; + quad_t cur = 0; + quad_t max = 0; + + if ((str = getword_conf(cmd->pool, &arg))) + if (!strcasecmp(str, "max")) + cur = conf->limit_nproc->rlim_max; + else + cur = atol(str); + else { + log_error("Invalid parameters for RLimitNPROC", cmd->server); + return NULL; + } + + if ((str = getword_conf(cmd->pool, &arg))) + max = atol(str); + + /* if we aren't running as root, cannot increase max */ + if (geteuid()) { + conf->limit_nproc->rlim_cur = cur; + if (max) + log_error("Must be uid 0 to raise maximum RLIMIT_NPROC", cmd->server); + } + else { + if (cur) + conf->limit_nproc->rlim_cur = cur; + if (max) + conf->limit_nproc->rlim_max = max; + } + #else + log_error("RLimitNPROC not supported on this platform", cmd->server); + #endif + return NULL; + } + char *set_bind_address (cmd_parms *cmd, void *dummy, char *arg) { bind_address.s_addr = get_virthost_addr (arg, NULL); return NULL; *************** *** 919,924 **** --- 1064,1075 ---- { "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1, NULL }, { "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1, NULL }, { "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1, NULL }, + { "RLimitCPU", set_limit_cpu, (void*)XtOffsetOf(core_dir_config, limit_cpu), + OR_ALL, RAW_ARGS, "soft/hard limits for max CPU usage in seconds" }, + { "RLimitMEM", set_limit_mem, (void*)XtOffsetOf(core_dir_config, limit_mem), + OR_ALL, RAW_ARGS, "soft/hard limits for max memory usage per process" }, + { "RLimitNPROC", set_limit_nproc, (void*)XtOffsetOf(core_dir_config, limit_nproc), + OR_ALL, RAW_ARGS, "soft/hard limits for max number of processes per uid" }, { "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1, "'*', a numeric IP address, or the name of a host with a unique IP address"}, { "Listen", set_listener, NULL, RSRC_CONF, TAKE1, 1.8 +11 -0 apache/src/http_core.h Index: http_core.h =================================================================== RCS file: /export/home/cvs/apache/src/http_core.h,v retrieving revision 1.7 retrieving revision 1.8 diff -C3 -r1.7 -r1.8 *** http_core.h 1996/07/25 19:32:28 1.7 --- http_core.h 1996/07/27 02:49:35 1.8 *************** *** 152,157 **** --- 152,168 ---- int hostname_lookups; int do_rfc1413; /* See if client is advertising a username? */ + /* System Resource Control */ + #ifdef RLIMIT_CPU + struct rlimit *limit_cpu; + #endif + #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) + struct rlimit *limit_mem; + #endif + #ifdef RLIMIT_NPROC + struct rlimit *limit_nproc; + #endif + /* Access control */ array_header *sec; regex_t *r; 1.14 +23 -25 apache/src/util_script.c Index: util_script.c =================================================================== RCS file: /export/home/cvs/apache/src/util_script.c,v retrieving revision 1.13 retrieving revision 1.14 diff -C3 -r1.13 -r1.14 *** util_script.c 1996/07/21 20:03:45 1.13 --- util_script.c 1996/07/27 02:49:35 1.14 *************** *** 53,59 **** --- 53,62 ---- + #define CORE_PRIVATE #include "httpd.h" + #include "http_config.h" + #include "http_conf_globals.h" #include "http_main.h" #include "http_log.h" #include "http_protocol.h" *************** *** 61,66 **** --- 64,70 ---- #include "http_request.h" /* for sub_req_lookup_uri() */ #include "util_script.h" + /* * Various utility functions which are common to a whole lot of * script-type extensions mechanisms, and might as well be gathered *************** *** 365,404 **** void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) { ! ! #ifdef RLIMIT_CPU ! struct rlimit cpulim = { 9, 10 }; ! #endif - #ifdef RLIMIT_DATA - struct rlimit datalim = { 2000000, 2500000 }; - #endif - - #ifdef RLIMIT_NPROC - struct rlimit proclim = { 20, 40 }; - #endif ! #ifdef RLIMIT_VMEM ! struct rlimit vmlim = { 2000000, 2500000 }; ! #endif ! #ifdef RLIMIT_CPU ! setrlimit (RLIMIT_CPU, &cpulim); ! #endif ! #ifdef RLIMIT_DATA ! setrlimit (RLIMIT_DATA, &datalim); #endif - #ifdef RLIMIT_NPROC ! setrlimit (RLIMIT_NPROC, &proclim); #endif - #ifdef RLIMIT_VMEM ! setrlimit (RLIMIT_VMEM, &vmlim); #endif - #ifdef __EMX__ if ((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0)) { int emxloop; --- 369,402 ---- void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) { ! char *execuser; ! core_dir_config *conf = (core_dir_config *)pcalloc(r->pool, sizeof(core_dir_config)); ! conf = (core_dir_config *)get_module_config(r->per_dir_config, &core_module); ! #ifdef RLIMIT_CPU ! if (conf->limit_cpu != NULL) ! if ((setrlimit (RLIMIT_CPU, conf->limit_cpu)) != 0) ! log_unixerr("setrlimit", NULL, "failed to set CPU usage limit", r->server); #endif #ifdef RLIMIT_NPROC ! if (conf->limit_nproc != NULL) ! if ((setrlimit (RLIMIT_NPROC, conf->limit_nproc)) != 0) ! log_unixerr("setrlimit", NULL, "failed to set process limit", r->server); ! #endif ! #ifdef RLIMIT_DATA ! if (conf->limit_mem != NULL) ! if ((setrlimit (RLIMIT_DATA, conf->limit_mem)) != 0) ! log_unixerr("setrlimit", NULL, "failed to set memory usage limit", r->server); #endif #ifdef RLIMIT_VMEM ! if (conf->limit_mem != NULL) ! if ((setrlimit (RLIMIT_VMEM, conf->limit_mem)) != 0) ! log_unixerr("setrlimit", NULL, "failed to set memory usage limit", r->server); #endif #ifdef __EMX__ if ((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0)) { int emxloop; *************** *** 438,444 **** execv(r->filename, create_argv(r->pool, argv0, r->args)); } #else ! if (shellcmd) execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env); --- 436,442 ---- execv(r->filename, create_argv(r->pool, argv0, r->args)); } #else ! if (shellcmd) execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);