1 /*
2 reslimit.c - resource limit functions
3
4 Copyright (C) 2002, 2003 Arthur de Jong.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #include "config.h"
23
24 #include <unistd.h>
25 #include <string.h>
26 #include <sys/time.h>
27 #include <sys/resource.h>
28 #include <errno.h>
29
30 #include "reslimit.h"
31 #include "xmalloc.h"
32 #include "log.h"
33
34
35 /* workaround for old BSD systems */
36 #ifndef RLIMIT_NOFILE
37 #define RLIMIT_NOFILE RLIMIT_OFILE
38 #endif
39
40
41 /* definition of all settable resources */
42 static struct resource {
43 int resource; /* the id of the resource for setrlimit() */
44 char *name; /* symbolic name of resource, see below */
45 int type; /* the type of the resource, see reslimit.h defines */
46 } knownresources[]= {
47 { RLIMIT_CORE, "coredumpsize", RESTYPE_SIZE },
48 { RLIMIT_CORE, "core", RESTYPE_SIZE },
49 { RLIMIT_CPU, "cputime", RESTYPE_TIME },
50 { RLIMIT_CPU, "cpu", RESTYPE_TIME },
51 { RLIMIT_DATA, "datasize", RESTYPE_SIZE },
52 { RLIMIT_DATA, "data", RESTYPE_SIZE },
53 { RLIMIT_FSIZE, "filesize", RESTYPE_SIZE },
54 { RLIMIT_FSIZE, "fsize", RESTYPE_SIZE },
55 #ifdef RLIMIT_MEMLOCK
56 { RLIMIT_MEMLOCK, "memorylocked", RESTYPE_SIZE },
57 { RLIMIT_MEMLOCK, "memlock", RESTYPE_SIZE },
58 #endif /* RLIMIT_MEMLOCK */
59 { RLIMIT_NOFILE, "openfiles", RESTYPE_NUM },
60 { RLIMIT_NOFILE, "nofile", RESTYPE_NUM },
61 #ifdef RLIMIT_NPROC
62 { RLIMIT_NPROC, "maxproc", RESTYPE_NUM },
63 { RLIMIT_NPROC, "nproc", RESTYPE_NUM },
64 #endif /* RLIMIT_NPROC */
65 #ifdef RLIMIT_RSS
66 { RLIMIT_RSS, "memoryuse", RESTYPE_SIZE },
67 { RLIMIT_RSS, "rss", RESTYPE_SIZE },
68 #endif /* RLIMIT_RSS */
69 { RLIMIT_STACK, "stacksize", RESTYPE_SIZE },
70 { RLIMIT_STACK, "stack", RESTYPE_SIZE },
71 #ifdef RLIMIT_AS
72 { RLIMIT_AS, "virtmem", RESTYPE_SIZE },
73 { RLIMIT_AS, "as", RESTYPE_SIZE },
74 #endif /* RLIMIT_AS */
75 #ifdef RLIMIT_VMEM
76 { RLIMIT_VMEM, "virtmem", RESTYPE_SIZE },
77 #endif /* RLIMIT_VMEM */
78 #ifdef RLIMIT_PTHREAD
79 { RLIMIT_PTHREAD, "pthreads", RESTYPE_NUM },
80 #endif /* RLIMIT_PTHREAD */
81 { -1, NULL, -1 }
82 };
83
84
85 /* the list of resource limitations configured */
86 static struct reslimit
87 {
88 struct resource *resource;
89 struct rlimit limit;
90 struct reslimit *next;
91 } *savedlimits=NULL;
92
93
94 /* find the resource record for the given name */
getresourcebyname(const char * name)95 static struct resource *getresourcebyname(const char *name)
96 {
97 struct resource *tmp;
98 for (tmp=knownresources;tmp->name!=NULL;tmp++)
99 {
100 if (strcmp(name,tmp->name)==0)
101 {
102 return tmp;
103 }
104 }
105 return NULL;
106 }
107
108
109 /* return the type of the resource defined by name */
getresourcetype(const char * name)110 int getresourcetype(const char *name)
111 {
112 struct resource *res;
113 res=getresourcebyname(name);
114 if (res==NULL)
115 return RESTYPE_UNKNOWN;
116 return res->type;
117 }
118
119
120 /* save the limit to the specified values
121 note: limit will be set only when setreslimits() is called */
savereslimit(const char * name,rlim_t soft,rlim_t hard)122 void savereslimit(const char *name,rlim_t soft,rlim_t hard)
123 {
124 struct resource *res;
125 struct reslimit *lim;
126 res=getresourcebyname(name);
127 if (res==NULL)
128 {
129 log_log(LOG_ERR,"cannot find resource %s",name);
130 exit(1);
131 }
132 lim=(struct reslimit *)xmalloc(sizeof(struct reslimit));
133 lim->resource=res;
134 lim->limit.rlim_cur=soft;
135 lim->limit.rlim_max=hard;
136 lim->next=savedlimits;
137 savedlimits=lim;
138 }
139
140
141 /* set all the resources defined */
setreslimits(void)142 void setreslimits(void)
143 {
144 struct reslimit *tmp;
145 for (tmp=savedlimits;tmp!=NULL;tmp=tmp->next)
146 {
147 log_log(LOG_DEBUG,"debug: limit %s to %d(soft) and %d(hard)",
148 tmp->resource->name,
149 (int)(tmp->limit.rlim_cur),
150 (int)(tmp->limit.rlim_max));
151 if (setrlimit(tmp->resource->resource,&(tmp->limit)))
152 {
153 log_log(LOG_ERR,"cannot limit %s: %s",tmp->resource->name,strerror(errno));
154 exit(1);
155 }
156 }
157 }
158