Print this page
3830 SIGQUEUE_MAX's limit of 32 is too low
Reviewed by: Cedric Blancher <cedric.blancher@gmail.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Irek Szczesniak <iszczesniak@gmail.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/rctl_proc.c
+++ new/usr/src/uts/common/os/rctl_proc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 #include <sys/types.h>
29 27 #include <sys/cmn_err.h>
30 28 #include <sys/sysmacros.h>
31 29 #include <sys/proc.h>
32 30 #include <sys/rctl.h>
33 31 #include <sys/rctl_impl.h>
34 32 #include <sys/port_kernel.h>
33 +#include <sys/signal.h>
34 +#include <sys/var.h>
35 35
36 36 #include <sys/vmparam.h>
37 37 #include <sys/machparam.h>
38 38
39 39 /*
40 40 * Process-based resource controls
41 41 * The structure of the kernel leaves us no particular place where the process
42 42 * abstraction can be declared--it is intertwined with the growth of the Unix
43 43 * kernel. Accordingly, we place all of the resource control logic associated
44 44 * with processes, both existing and future, in this file.
45 45 */
46 46
47 47 rctl_hndl_t rctlproc_legacy[RLIM_NLIMITS];
48 48 uint_t rctlproc_flags[RLIM_NLIMITS] = {
49 49 RCTL_LOCAL_SIGNAL, /* RLIMIT_CPU */
50 50 RCTL_LOCAL_DENY | RCTL_LOCAL_SIGNAL, /* RLIMIT_FSIZE */
51 51 RCTL_LOCAL_DENY, /* RLIMIT_DATA */
52 52 RCTL_LOCAL_DENY, /* RLIMIT_STACK */
53 53 RCTL_LOCAL_DENY, /* RLIMIT_CORE */
54 54 RCTL_LOCAL_DENY, /* RLIMIT_NOFILE */
55 55 RCTL_LOCAL_DENY /* RLIMIT_VMEM */
56 56 };
57 57 int rctlproc_signals[RLIM_NLIMITS] = {
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
58 58 SIGXCPU, /* RLIMIT_CPU */
59 59 SIGXFSZ, /* RLIMIT_FSIZE */
60 60 0, 0, 0, 0, 0 /* remainder do not signal */
61 61 };
62 62
63 63 rctl_hndl_t rc_process_msgmnb;
64 64 rctl_hndl_t rc_process_msgtql;
65 65 rctl_hndl_t rc_process_semmsl;
66 66 rctl_hndl_t rc_process_semopm;
67 67 rctl_hndl_t rc_process_portev;
68 +rctl_hndl_t rc_process_sigqueue;
68 69
69 70 /*
70 71 * process.max-cpu-time / RLIMIT_CPU
71 72 */
72 73 /*ARGSUSED*/
73 74 static int
74 75 proc_cpu_time_test(struct rctl *rctl, struct proc *p, rctl_entity_p_t *e,
75 76 rctl_val_t *rval, rctl_qty_t inc, uint_t flags)
76 77 {
77 78 return (inc >= rval->rcv_value);
78 79 }
79 80
80 81 static rctl_ops_t proc_cpu_time_ops = {
81 82 rcop_no_action,
82 83 rcop_no_usage,
83 84 rcop_no_set,
84 85 proc_cpu_time_test
85 86 };
86 87
87 88 /*
88 89 * process.max-file-size / RLIMIT_FSIZE
89 90 */
90 91 static int
91 92 proc_filesize_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
92 93 rctl_qty_t nv)
93 94 {
94 95 if (p->p_model == DATAMODEL_NATIVE)
95 96 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
96 97 else
97 98 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
98 99
99 100 ASSERT(e->rcep_t == RCENTITY_PROCESS);
100 101 e->rcep_p.proc->p_fsz_ctl = nv;
101 102
102 103 return (0);
103 104 }
104 105
105 106 static rctl_ops_t proc_filesize_ops = {
106 107 rcop_no_action,
107 108 rcop_no_usage,
108 109 proc_filesize_set,
109 110 rcop_no_test
110 111 };
111 112
112 113 /*
113 114 * process.max-data / RLIMIT_DATA
114 115 */
115 116
116 117 /*
117 118 * process.max-stack-size / RLIMIT_STACK
118 119 */
119 120 static int
120 121 proc_stack_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
121 122 rctl_qty_t nv)
122 123 {
123 124 klwp_t *lwp = ttolwp(curthread);
124 125
125 126 if (p->p_model == DATAMODEL_NATIVE)
126 127 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
127 128 else
128 129 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
129 130
130 131 /*
131 132 * In the process of changing the rlimit, this function actually
132 133 * gets called a number of times. We only want to save the current
133 134 * rlimit the first time we come through here. In post_syscall(),
134 135 * we copyin() the lwp's ustack, and compare it to the rlimit we
135 136 * save here; if the two match, we adjust the ustack to reflect
136 137 * the new stack bounds.
137 138 *
138 139 * We check to make sure that we're changing the rlimit of our
139 140 * own process rather than on behalf of some other process. The
140 141 * notion of changing this resource limit on behalf of another
141 142 * process is problematic at best, and changing the amount of stack
142 143 * space a process is allowed to consume is a rather antiquated
143 144 * notion that has limited applicability in our multithreaded
144 145 * process model.
145 146 */
146 147 ASSERT(e->rcep_t == RCENTITY_PROCESS);
147 148 if (lwp != NULL && lwp->lwp_procp == e->rcep_p.proc &&
148 149 lwp->lwp_ustack && lwp->lwp_old_stk_ctl == 0) {
149 150 lwp->lwp_old_stk_ctl = (size_t)e->rcep_p.proc->p_stk_ctl;
150 151 curthread->t_post_sys = 1;
151 152 }
152 153
153 154 e->rcep_p.proc->p_stk_ctl = nv;
154 155
155 156 return (0);
156 157 }
157 158
158 159 static rctl_ops_t proc_stack_ops = {
159 160 rcop_no_action,
160 161 rcop_no_usage,
161 162 proc_stack_set,
162 163 rcop_no_test
163 164 };
164 165
165 166 /*
166 167 * process.max-file-descriptors / RLIMIT_NOFILE
167 168 */
168 169 static int
169 170 proc_nofile_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t nv)
170 171 {
171 172 ASSERT(e->rcep_t == RCENTITY_PROCESS);
172 173 if (p->p_model == DATAMODEL_NATIVE)
173 174 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
174 175 else
175 176 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
176 177
177 178 e->rcep_p.proc->p_fno_ctl = nv;
178 179
179 180 return (0);
180 181 }
181 182
182 183 static rctl_ops_t proc_nofile_ops = {
183 184 rcop_no_action,
184 185 rcop_no_usage,
185 186 proc_nofile_set,
186 187 rcop_absolute_test
187 188 };
188 189
189 190 /*
190 191 * process.max-address-space / RLIMIT_VMEM
191 192 */
192 193 static int
193 194 proc_vmem_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t nv)
194 195 {
195 196 ASSERT(e->rcep_t == RCENTITY_PROCESS);
196 197 if (p->p_model == DATAMODEL_ILP32)
197 198 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
198 199 else
199 200 nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
200 201
201 202 e->rcep_p.proc->p_vmem_ctl = nv;
202 203
203 204 return (0);
204 205 }
205 206
206 207 static rctl_ops_t proc_vmem_ops = {
207 208 rcop_no_action,
208 209 rcop_no_usage,
209 210 proc_vmem_set,
210 211 rcop_no_test
211 212 };
212 213
213 214 /*
214 215 * void rctlproc_default_init()
215 216 *
216 217 * Overview
217 218 * Establish default basic and privileged control values on the init process.
218 219 * These correspond to the soft and hard limits, respectively.
219 220 */
220 221 void
221 222 rctlproc_default_init(struct proc *initp, rctl_alloc_gp_t *gp)
222 223 {
223 224 struct rlimit64 rlp64;
224 225
225 226 /*
226 227 * RLIMIT_CPU: deny never, sigtoproc(pp, NULL, SIGXCPU).
227 228 */
228 229 rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
229 230 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_CPU], initp, &rlp64, gp,
230 231 RCTL_LOCAL_SIGNAL, SIGXCPU, kcred);
231 232
232 233 /*
233 234 * RLIMIT_FSIZE: deny always, sigtoproc(pp, NULL, SIGXFSZ).
234 235 */
235 236 rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
236 237 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_FSIZE], initp, &rlp64, gp,
237 238 RCTL_LOCAL_SIGNAL | RCTL_LOCAL_DENY, SIGXFSZ, kcred);
238 239
239 240 /*
240 241 * RLIMIT_DATA: deny always, no default action.
241 242 */
242 243 rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
243 244 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_DATA], initp, &rlp64, gp,
244 245 RCTL_LOCAL_DENY, 0, kcred);
245 246
246 247 /*
247 248 * RLIMIT_STACK: deny always, no default action.
248 249 */
249 250 #ifdef __sparc
250 251 rlp64.rlim_cur = DFLSSIZ;
251 252 rlp64.rlim_max = LONG_MAX;
252 253 #else
253 254 rlp64.rlim_cur = DFLSSIZ;
254 255 rlp64.rlim_max = MAXSSIZ;
255 256 #endif
256 257 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_STACK], initp, &rlp64, gp,
257 258 RCTL_LOCAL_DENY, 0, kcred);
258 259
259 260 /*
260 261 * RLIMIT_CORE: deny always, no default action.
261 262 */
262 263 rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
263 264 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_CORE], initp, &rlp64, gp,
264 265 RCTL_LOCAL_DENY, 0, kcred);
265 266
266 267 /*
267 268 * RLIMIT_NOFILE: deny always, no action.
268 269 */
269 270 rlp64.rlim_cur = rlim_fd_cur;
270 271 rlp64.rlim_max = rlim_fd_max;
271 272 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE], initp, &rlp64,
272 273 gp, RCTL_LOCAL_DENY, 0, kcred);
273 274
274 275 /*
275 276 * RLIMIT_VMEM
276 277 */
277 278 rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
278 279 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_VMEM], initp, &rlp64, gp,
279 280 RCTL_LOCAL_DENY, 0, kcred);
280 281 }
↓ open down ↓ |
203 lines elided |
↑ open up ↑ |
281 282
282 283 /*
283 284 * void rctlproc_init()
284 285 *
285 286 * Overview
286 287 * Register the various resource controls associated with process entities.
287 288 * The historical rlim_infinity_map and rlim_infinity32_map are now encoded
288 289 * here as the native and ILP32 infinite values for each resource control.
289 290 */
290 291 void
291 -rctlproc_init()
292 +rctlproc_init(void)
292 293 {
293 294 rctl_set_t *set;
294 295 rctl_alloc_gp_t *gp;
295 296 rctl_entity_p_t e;
296 297
297 298 rctlproc_legacy[RLIMIT_CPU] = rctl_register("process.max-cpu-time",
298 299 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_NEVER |
299 300 RCTL_GLOBAL_CPU_TIME | RCTL_GLOBAL_INFINITE | RCTL_GLOBAL_SECONDS,
300 301 UINT64_MAX, UINT64_MAX, &proc_cpu_time_ops);
301 302 rctlproc_legacy[RLIMIT_FSIZE] = rctl_register("process.max-file-size",
302 303 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
303 304 RCTL_GLOBAL_FILE_SIZE | RCTL_GLOBAL_BYTES,
304 305 MAXOFFSET_T, MAXOFFSET_T, &proc_filesize_ops);
305 306 rctlproc_legacy[RLIMIT_DATA] = rctl_register("process.max-data-size",
306 307 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
307 308 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
308 309 ULONG_MAX, UINT32_MAX, &rctl_default_ops);
309 310 #ifdef _LP64
310 311 #ifdef __sparc
311 312 rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
312 313 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
313 314 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
314 315 LONG_MAX, INT32_MAX, &proc_stack_ops);
315 316 #else /* __sparc */
316 317 rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
317 318 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
318 319 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
319 320 MAXSSIZ, USRSTACK32 - PAGESIZE, &proc_stack_ops);
320 321 #endif /* __sparc */
321 322 #else /* _LP64 */
322 323 rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
323 324 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
324 325 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
325 326 USRSTACK - PAGESIZE, USRSTACK - PAGESIZE, &proc_stack_ops);
326 327 #endif
327 328 rctlproc_legacy[RLIMIT_CORE] = rctl_register("process.max-core-size",
328 329 RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
329 330 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
330 331 MIN(MAXOFFSET_T, ULONG_MAX), UINT32_MAX, &rctl_default_ops);
331 332 rctlproc_legacy[RLIMIT_NOFILE] = rctl_register(
332 333 "process.max-file-descriptor", RCENTITY_PROCESS,
333 334 RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
334 335 RCTL_GLOBAL_COUNT, INT32_MAX, INT32_MAX, &proc_nofile_ops);
335 336 rctlproc_legacy[RLIMIT_VMEM] =
336 337 rctl_register("process.max-address-space", RCENTITY_PROCESS,
337 338 RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
338 339 RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
339 340 ULONG_MAX, UINT32_MAX, &proc_vmem_ops);
340 341
341 342 rc_process_semmsl = rctl_register("process.max-sem-nsems",
342 343 RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
343 344 SHRT_MAX, SHRT_MAX, &rctl_absolute_ops);
344 345 rctl_add_legacy_limit("process.max-sem-nsems", "semsys",
345 346 "seminfo_semmsl", 512, SHRT_MAX);
346 347
347 348 rc_process_semopm = rctl_register("process.max-sem-ops",
348 349 RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
349 350 INT_MAX, INT_MAX, &rctl_absolute_ops);
350 351 rctl_add_legacy_limit("process.max-sem-ops", "semsys",
351 352 "seminfo_semopm", 512, INT_MAX);
352 353
353 354 rc_process_msgmnb = rctl_register("process.max-msg-qbytes",
354 355 RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_BYTES,
355 356 ULONG_MAX, ULONG_MAX, &rctl_absolute_ops);
356 357 rctl_add_legacy_limit("process.max-msg-qbytes", "msgsys",
357 358 "msginfo_msgmnb", 65536, ULONG_MAX);
358 359
359 360 rc_process_msgtql = rctl_register("process.max-msg-messages",
360 361 RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
361 362 UINT_MAX, UINT_MAX, &rctl_absolute_ops);
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
362 363 rctl_add_legacy_limit("process.max-msg-messages", "msgsys",
363 364 "msginfo_msgtql", 8192, UINT_MAX);
364 365
365 366 rc_process_portev = rctl_register("process.max-port-events",
366 367 RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
367 368 PORT_MAX_EVENTS, PORT_MAX_EVENTS, &rctl_absolute_ops);
368 369 rctl_add_default_limit("process.max-port-events", PORT_DEFAULT_EVENTS,
369 370 RCPRIV_PRIVILEGED, RCTL_LOCAL_DENY);
370 371
371 372 /*
373 + * We set the upper limit to the maximum number of processes per user
374 + * to make it theoretical possible to deliver all SIGCHILD signals on
375 + * child termination, but at least to 8k.
376 + */
377 + rc_process_sigqueue = rctl_register("process.max-sigqueue-size",
378 + RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
379 + RCTL_GLOBAL_COUNT, MAX(v.v_maxup, 8192), MAX(v.v_maxup, 8192),
380 + &rctl_absolute_ops);
381 + rctl_add_default_limit("process.max-sigqueue-size",
382 + _SIGQUEUE_SIZE_BASIC, RCPRIV_BASIC, RCTL_LOCAL_DENY);
383 + rctl_add_default_limit("process.max-sigqueue-size",
384 + _SIGQUEUE_SIZE_PRIVILEGED, RCPRIV_PRIVILEGED, RCTL_LOCAL_DENY);
385 +
386 + /*
372 387 * Place minimal set of controls on "sched" process for inheritance by
373 388 * processes created via newproc().
374 389 */
375 390 set = rctl_set_create();
376 391 gp = rctl_set_init_prealloc(RCENTITY_PROCESS);
377 392 mutex_enter(&curproc->p_lock);
378 393 e.rcep_p.proc = curproc;
379 394 e.rcep_t = RCENTITY_PROCESS;
380 395 curproc->p_rctls = rctl_set_init(RCENTITY_PROCESS, curproc, &e,
381 396 set, gp);
382 397 mutex_exit(&curproc->p_lock);
383 398 rctl_prealloc_destroy(gp);
384 399 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX