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);