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