1 /*
2  * ProFTPD - FTP server daemon
3  * Copyright (c) 2013-2016 The ProFTPD Project team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  *
19  * As a special exemption, The ProFTPD Project team and other respective
20  * copyright holders give permission to link this program with OpenSSL, and
21  * distribute the resulting executable, without including the source code for
22  * OpenSSL in the source distribution.
23  */
24 
25 /* Resource limits implementation */
26 
27 #include "conf.h"
28 
get_rlimit(int resource,rlim_t * current,rlim_t * max)29 static int get_rlimit(int resource, rlim_t *current, rlim_t *max) {
30   struct rlimit rlim;
31   int res;
32 
33   if (current == NULL &&
34       max == NULL) {
35     errno = EINVAL;
36     return -1;
37   }
38 
39   res = getrlimit(resource, &rlim);
40   if (res < 0) {
41     /* Some libcs use EPERM instead of ENOSYS; weird. */
42     if (errno == EPERM) {
43       errno = ENOSYS;
44     }
45 
46     return res;
47   }
48 
49   if (current != NULL) {
50     *current = rlim.rlim_cur;
51   }
52 
53   if (max != NULL) {
54     *max = rlim.rlim_max;
55   }
56 
57   return 0;
58 }
59 
set_rlimit(int resource,rlim_t current,rlim_t max)60 static int set_rlimit(int resource, rlim_t current, rlim_t max) {
61   struct rlimit rlim;
62   int res;
63 
64   rlim.rlim_cur = current;
65   rlim.rlim_max = max;
66 
67   res = setrlimit(resource, &rlim);
68   return res;
69 }
70 
pr_rlimit_get_core(rlim_t * current,rlim_t * max)71 int pr_rlimit_get_core(rlim_t *current, rlim_t *max) {
72 #if defined(RLIMIT_CORE)
73   return get_rlimit(RLIMIT_CORE, current, max);
74 
75 #else
76   errno = ENOSYS;
77   return -1;
78 #endif /* No RLIMIT_CORE */
79 }
80 
pr_rlimit_set_core(rlim_t current,rlim_t max)81 int pr_rlimit_set_core(rlim_t current, rlim_t max) {
82 #if defined(RLIMIT_CORE)
83   return set_rlimit(RLIMIT_CORE, current, max);
84 
85 #else
86   errno = ENOSYS;
87   return -1;
88 #endif /* No RLIMIT_CORE */
89 }
90 
pr_rlimit_get_cpu(rlim_t * current,rlim_t * max)91 int pr_rlimit_get_cpu(rlim_t *current, rlim_t *max) {
92 #if defined(RLIMIT_CPU)
93   return get_rlimit(RLIMIT_CPU, current, max);
94 
95 #else
96   errno = ENOSYS;
97   return -1;
98 #endif /* No RLIMIT_CPU */
99 }
100 
pr_rlimit_set_cpu(rlim_t current,rlim_t max)101 int pr_rlimit_set_cpu(rlim_t current, rlim_t max) {
102 #if defined(RLIMIT_CPU)
103   return set_rlimit(RLIMIT_CPU, current, max);
104 
105 #else
106   errno = ENOSYS;
107   return -1;
108 #endif /* No RLIMIT_CPU */
109 }
110 
pr_rlimit_get_files(rlim_t * current,rlim_t * max)111 int pr_rlimit_get_files(rlim_t *current, rlim_t *max) {
112 #if defined(RLIMIT_NOFILE)
113   return get_rlimit(RLIMIT_NOFILE, current, max);
114 
115 #elif defined(RLIMIT_OFILE)
116   return get_rlimit(RLIMIT_OFILE, current, max);
117 
118 #else
119   errno = ENOSYS;
120   return -1;
121 #endif /* No RLIMIT_NOFILE or RLIMIT_OFILE */
122 }
123 
pr_rlimit_set_files(rlim_t current,rlim_t max)124 int pr_rlimit_set_files(rlim_t current, rlim_t max) {
125 #if defined(RLIMIT_NOFILE)
126   return set_rlimit(RLIMIT_NOFILE, current, max);
127 
128 #elif defined(RLIMIT_OFILE)
129   return set_rlimit(RLIMIT_OFILE, current, max);
130 
131 #else
132   errno = ENOSYS;
133   return -1;
134 #endif /* No RLIMIT_NOFILE or RLIMIT_OFILE */
135 }
136 
pr_rlimit_get_memory(rlim_t * current,rlim_t * max)137 int pr_rlimit_get_memory(rlim_t *current, rlim_t *max) {
138 #if defined(RLIMIT_AS)
139   return get_rlimit(RLIMIT_AS, current, max);
140 
141 #elif defined(RLIMIT_DATA)
142   return get_rlimit(RLIMIT_DATA, current, max);
143 
144 #elif defined(RLIMIT_VMEM)
145   return get_rlimit(RLIMIT_VMEM, current, max);
146 
147 #else
148   errno = ENOSYS;
149   return -1;
150 #endif /* No RLIMIT_AS, RLIMIT_DATA, or RLIMIT_VMEM. */
151 }
152 
pr_rlimit_set_memory(rlim_t current,rlim_t max)153 int pr_rlimit_set_memory(rlim_t current, rlim_t max) {
154 #if defined(RLIMIT_AS)
155   return set_rlimit(RLIMIT_AS, current, max);
156 
157 #elif defined(RLIMIT_DATA)
158   return set_rlimit(RLIMIT_DATA, current, max);
159 
160 #else
161   errno = ENOSYS;
162   return -1;
163 #endif /* No RLIMIT_AS or RLIMIT_DATA */
164 }
165 
pr_rlimit_get_nproc(rlim_t * current,rlim_t * max)166 int pr_rlimit_get_nproc(rlim_t *current, rlim_t *max) {
167 #if defined(RLIMIT_NPROC)
168   return get_rlimit(RLIMIT_NPROC, current, max);
169 
170 #else
171   errno = ENOSYS;
172   return -1;
173 #endif /* No RLIMIT_NPROC */
174 }
175 
pr_rlimit_set_nproc(rlim_t current,rlim_t max)176 int pr_rlimit_set_nproc(rlim_t current, rlim_t max) {
177 #if defined(RLIMIT_NPROC)
178   return set_rlimit(RLIMIT_NPROC, current, max);
179 
180 #else
181   errno = ENOSYS;
182   return -1;
183 #endif /* No RLIMIT_NPROC */
184 }
185 
186