xref: /freebsd/sys/kern/kern_rctl.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
1 /*-
2  * Copyright (c) 2010 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Edward Tomasz Napierala under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <sys/refcount.h>
40 #include <sys/jail.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/loginclass.h>
44 #include <sys/priv.h>
45 #include <sys/proc.h>
46 #include <sys/racct.h>
47 #include <sys/rctl.h>
48 #include <sys/resourcevar.h>
49 #include <sys/sx.h>
50 #include <sys/sysent.h>
51 #include <sys/sysproto.h>
52 #include <sys/systm.h>
53 #include <sys/types.h>
54 #include <sys/eventhandler.h>
55 #include <sys/lock.h>
56 #include <sys/mutex.h>
57 #include <sys/rwlock.h>
58 #include <sys/sbuf.h>
59 #include <sys/taskqueue.h>
60 #include <sys/tree.h>
61 #include <vm/uma.h>
62 
63 #ifdef RCTL
64 #ifndef RACCT
65 #error "The RCTL option requires the RACCT option"
66 #endif
67 
68 FEATURE(rctl, "Resource Limits");
69 
70 #define	HRF_DEFAULT		0
71 #define	HRF_DONT_INHERIT	1
72 #define	HRF_DONT_ACCUMULATE	2
73 
74 /* Default buffer size for rctl_get_rules(2). */
75 #define	RCTL_DEFAULT_BUFSIZE	4096
76 #define	RCTL_MAX_INBUFLEN	4096
77 #define	RCTL_LOG_BUFSIZE	128
78 
79 #define	RCTL_PCPU_SHIFT		(10 * 1000000)
80 
81 /*
82  * 'rctl_rule_link' connects a rule with every racct it's related to.
83  * For example, rule 'user:X:openfiles:deny=N/process' is linked
84  * with uidinfo for user X, and to each process of that user.
85  */
86 struct rctl_rule_link {
87 	LIST_ENTRY(rctl_rule_link)	rrl_next;
88 	struct rctl_rule		*rrl_rule;
89 	int				rrl_exceeded;
90 };
91 
92 struct dict {
93 	const char	*d_name;
94 	int		d_value;
95 };
96 
97 static struct dict subjectnames[] = {
98 	{ "process", RCTL_SUBJECT_TYPE_PROCESS },
99 	{ "user", RCTL_SUBJECT_TYPE_USER },
100 	{ "loginclass", RCTL_SUBJECT_TYPE_LOGINCLASS },
101 	{ "jail", RCTL_SUBJECT_TYPE_JAIL },
102 	{ NULL, -1 }};
103 
104 static struct dict resourcenames[] = {
105 	{ "cputime", RACCT_CPU },
106 	{ "datasize", RACCT_DATA },
107 	{ "stacksize", RACCT_STACK },
108 	{ "coredumpsize", RACCT_CORE },
109 	{ "memoryuse", RACCT_RSS },
110 	{ "memorylocked", RACCT_MEMLOCK },
111 	{ "maxproc", RACCT_NPROC },
112 	{ "openfiles", RACCT_NOFILE },
113 	{ "vmemoryuse", RACCT_VMEM },
114 	{ "pseudoterminals", RACCT_NPTS },
115 	{ "swapuse", RACCT_SWAP },
116 	{ "nthr", RACCT_NTHR },
117 	{ "msgqqueued", RACCT_MSGQQUEUED },
118 	{ "msgqsize", RACCT_MSGQSIZE },
119 	{ "nmsgq", RACCT_NMSGQ },
120 	{ "nsem", RACCT_NSEM },
121 	{ "nsemop", RACCT_NSEMOP },
122 	{ "nshm", RACCT_NSHM },
123 	{ "shmsize", RACCT_SHMSIZE },
124 	{ "wallclock", RACCT_WALLCLOCK },
125 	{ "pcpu", RACCT_PCTCPU },
126 	{ NULL, -1 }};
127 
128 static struct dict actionnames[] = {
129 	{ "sighup", RCTL_ACTION_SIGHUP },
130 	{ "sigint", RCTL_ACTION_SIGINT },
131 	{ "sigquit", RCTL_ACTION_SIGQUIT },
132 	{ "sigill", RCTL_ACTION_SIGILL },
133 	{ "sigtrap", RCTL_ACTION_SIGTRAP },
134 	{ "sigabrt", RCTL_ACTION_SIGABRT },
135 	{ "sigemt", RCTL_ACTION_SIGEMT },
136 	{ "sigfpe", RCTL_ACTION_SIGFPE },
137 	{ "sigkill", RCTL_ACTION_SIGKILL },
138 	{ "sigbus", RCTL_ACTION_SIGBUS },
139 	{ "sigsegv", RCTL_ACTION_SIGSEGV },
140 	{ "sigsys", RCTL_ACTION_SIGSYS },
141 	{ "sigpipe", RCTL_ACTION_SIGPIPE },
142 	{ "sigalrm", RCTL_ACTION_SIGALRM },
143 	{ "sigterm", RCTL_ACTION_SIGTERM },
144 	{ "sigurg", RCTL_ACTION_SIGURG },
145 	{ "sigstop", RCTL_ACTION_SIGSTOP },
146 	{ "sigtstp", RCTL_ACTION_SIGTSTP },
147 	{ "sigchld", RCTL_ACTION_SIGCHLD },
148 	{ "sigttin", RCTL_ACTION_SIGTTIN },
149 	{ "sigttou", RCTL_ACTION_SIGTTOU },
150 	{ "sigio", RCTL_ACTION_SIGIO },
151 	{ "sigxcpu", RCTL_ACTION_SIGXCPU },
152 	{ "sigxfsz", RCTL_ACTION_SIGXFSZ },
153 	{ "sigvtalrm", RCTL_ACTION_SIGVTALRM },
154 	{ "sigprof", RCTL_ACTION_SIGPROF },
155 	{ "sigwinch", RCTL_ACTION_SIGWINCH },
156 	{ "siginfo", RCTL_ACTION_SIGINFO },
157 	{ "sigusr1", RCTL_ACTION_SIGUSR1 },
158 	{ "sigusr2", RCTL_ACTION_SIGUSR2 },
159 	{ "sigthr", RCTL_ACTION_SIGTHR },
160 	{ "deny", RCTL_ACTION_DENY },
161 	{ "log", RCTL_ACTION_LOG },
162 	{ "devctl", RCTL_ACTION_DEVCTL },
163 	{ NULL, -1 }};
164 
165 static void rctl_init(void);
166 SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL);
167 
168 static uma_zone_t rctl_rule_link_zone;
169 static uma_zone_t rctl_rule_zone;
170 static struct rwlock rctl_lock;
171 RW_SYSINIT(rctl_lock, &rctl_lock, "RCTL lock");
172 
173 static int rctl_rule_fully_specified(const struct rctl_rule *rule);
174 static void rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule);
175 
176 static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits");
177 
178 static const char *
179 rctl_subject_type_name(int subject)
180 {
181 	int i;
182 
183 	for (i = 0; subjectnames[i].d_name != NULL; i++) {
184 		if (subjectnames[i].d_value == subject)
185 			return (subjectnames[i].d_name);
186 	}
187 
188 	panic("rctl_subject_type_name: unknown subject type %d", subject);
189 }
190 
191 static const char *
192 rctl_action_name(int action)
193 {
194 	int i;
195 
196 	for (i = 0; actionnames[i].d_name != NULL; i++) {
197 		if (actionnames[i].d_value == action)
198 			return (actionnames[i].d_name);
199 	}
200 
201 	panic("rctl_action_name: unknown action %d", action);
202 }
203 
204 const char *
205 rctl_resource_name(int resource)
206 {
207 	int i;
208 
209 	for (i = 0; resourcenames[i].d_name != NULL; i++) {
210 		if (resourcenames[i].d_value == resource)
211 			return (resourcenames[i].d_name);
212 	}
213 
214 	panic("rctl_resource_name: unknown resource %d", resource);
215 }
216 
217 /*
218  * Return the amount of resource that can be allocated by 'p' before
219  * hitting 'rule'.
220  */
221 static int64_t
222 rctl_available_resource(const struct proc *p, const struct rctl_rule *rule)
223 {
224 	int resource;
225 	int64_t available = INT64_MAX;
226 	struct ucred *cred = p->p_ucred;
227 
228 	ASSERT_RACCT_ENABLED();
229 	rw_assert(&rctl_lock, RA_LOCKED);
230 
231 	resource = rule->rr_resource;
232 	switch (rule->rr_per) {
233 	case RCTL_SUBJECT_TYPE_PROCESS:
234 		available = rule->rr_amount -
235 		    p->p_racct->r_resources[resource];
236 		break;
237 	case RCTL_SUBJECT_TYPE_USER:
238 		available = rule->rr_amount -
239 		    cred->cr_ruidinfo->ui_racct->r_resources[resource];
240 		break;
241 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
242 		available = rule->rr_amount -
243 		    cred->cr_loginclass->lc_racct->r_resources[resource];
244 		break;
245 	case RCTL_SUBJECT_TYPE_JAIL:
246 		available = rule->rr_amount -
247 		    cred->cr_prison->pr_prison_racct->prr_racct->
248 		        r_resources[resource];
249 		break;
250 	default:
251 		panic("rctl_compute_available: unknown per %d",
252 		    rule->rr_per);
253 	}
254 
255 	return (available);
256 }
257 
258 /*
259  * Return non-zero if allocating 'amount' by proc 'p' would exceed
260  * resource limit specified by 'rule'.
261  */
262 static int
263 rctl_would_exceed(const struct proc *p, const struct rctl_rule *rule,
264     int64_t amount)
265 {
266 	int64_t available;
267 
268 	ASSERT_RACCT_ENABLED();
269 
270 	rw_assert(&rctl_lock, RA_LOCKED);
271 
272 	available = rctl_available_resource(p, rule);
273 	if (available >= amount)
274 		return (0);
275 
276 	return (1);
277 }
278 
279 /*
280  * Special version of rctl_available() function for the %cpu resource.
281  * We slightly cheat here and return less than we normally would.
282  */
283 int64_t
284 rctl_pcpu_available(const struct proc *p) {
285 	struct rctl_rule *rule;
286 	struct rctl_rule_link *link;
287 	int64_t available, minavailable, limit;
288 
289 	ASSERT_RACCT_ENABLED();
290 
291 	minavailable = INT64_MAX;
292 	limit = 0;
293 
294 	rw_rlock(&rctl_lock);
295 
296 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
297 		rule = link->rrl_rule;
298 		if (rule->rr_resource != RACCT_PCTCPU)
299 			continue;
300 		if (rule->rr_action != RCTL_ACTION_DENY)
301 			continue;
302 		available = rctl_available_resource(p, rule);
303 		if (available < minavailable) {
304 			minavailable = available;
305 			limit = rule->rr_amount;
306 		}
307 	}
308 
309 	rw_runlock(&rctl_lock);
310 
311 	/*
312 	 * Return slightly less than actual value of the available
313 	 * %cpu resource.  This makes %cpu throttling more agressive
314 	 * and lets us act sooner than the limits are already exceeded.
315 	 */
316 	if (limit != 0) {
317 		if (limit > 2 * RCTL_PCPU_SHIFT)
318 			minavailable -= RCTL_PCPU_SHIFT;
319 		else
320 			minavailable -= (limit / 2);
321 	}
322 
323 	return (minavailable);
324 }
325 
326 /*
327  * Check whether the proc 'p' can allocate 'amount' of 'resource' in addition
328  * to what it keeps allocated now.  Returns non-zero if the allocation should
329  * be denied, 0 otherwise.
330  */
331 int
332 rctl_enforce(struct proc *p, int resource, uint64_t amount)
333 {
334 	struct rctl_rule *rule;
335 	struct rctl_rule_link *link;
336 	struct sbuf sb;
337 	int should_deny = 0;
338 	char *buf;
339 	static int curtime = 0;
340 	static struct timeval lasttime;
341 
342 	ASSERT_RACCT_ENABLED();
343 
344 	rw_rlock(&rctl_lock);
345 
346 	/*
347 	 * There may be more than one matching rule; go through all of them.
348 	 * Denial should be done last, after logging and sending signals.
349 	 */
350 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
351 		rule = link->rrl_rule;
352 		if (rule->rr_resource != resource)
353 			continue;
354 		if (!rctl_would_exceed(p, rule, amount)) {
355 			link->rrl_exceeded = 0;
356 			continue;
357 		}
358 
359 		switch (rule->rr_action) {
360 		case RCTL_ACTION_DENY:
361 			should_deny = 1;
362 			continue;
363 		case RCTL_ACTION_LOG:
364 			/*
365 			 * If rrl_exceeded != 0, it means we've already
366 			 * logged a warning for this process.
367 			 */
368 			if (link->rrl_exceeded != 0)
369 				continue;
370 
371 			/*
372 			 * If the process state is not fully initialized yet,
373 			 * we can't access most of the required fields, e.g.
374 			 * p->p_comm.  This happens when called from fork1().
375 			 * Ignore this rule for now; it will be processed just
376 			 * after fork, when called from racct_proc_fork_done().
377 			 */
378 			if (p->p_state != PRS_NORMAL)
379 				continue;
380 
381 			if (!ppsratecheck(&lasttime, &curtime, 10))
382 				continue;
383 
384 			buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
385 			if (buf == NULL) {
386 				printf("rctl_enforce: out of memory\n");
387 				continue;
388 			}
389 			sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN);
390 			rctl_rule_to_sbuf(&sb, rule);
391 			sbuf_finish(&sb);
392 			printf("rctl: rule \"%s\" matched by pid %d "
393 			    "(%s), uid %d, jail %s\n", sbuf_data(&sb),
394 			    p->p_pid, p->p_comm, p->p_ucred->cr_uid,
395 			    p->p_ucred->cr_prison->pr_prison_racct->prr_name);
396 			sbuf_delete(&sb);
397 			free(buf, M_RCTL);
398 			link->rrl_exceeded = 1;
399 			continue;
400 		case RCTL_ACTION_DEVCTL:
401 			if (link->rrl_exceeded != 0)
402 				continue;
403 
404 			if (p->p_state != PRS_NORMAL)
405 				continue;
406 
407 			buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
408 			if (buf == NULL) {
409 				printf("rctl_enforce: out of memory\n");
410 				continue;
411 			}
412 			sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN);
413 			sbuf_printf(&sb, "rule=");
414 			rctl_rule_to_sbuf(&sb, rule);
415 			sbuf_printf(&sb, " pid=%d ruid=%d jail=%s",
416 			    p->p_pid, p->p_ucred->cr_ruid,
417 			    p->p_ucred->cr_prison->pr_prison_racct->prr_name);
418 			sbuf_finish(&sb);
419 			devctl_notify_f("RCTL", "rule", "matched",
420 			    sbuf_data(&sb), M_NOWAIT);
421 			sbuf_delete(&sb);
422 			free(buf, M_RCTL);
423 			link->rrl_exceeded = 1;
424 			continue;
425 		default:
426 			if (link->rrl_exceeded != 0)
427 				continue;
428 
429 			if (p->p_state != PRS_NORMAL)
430 				continue;
431 
432 			KASSERT(rule->rr_action > 0 &&
433 			    rule->rr_action <= RCTL_ACTION_SIGNAL_MAX,
434 			    ("rctl_enforce: unknown action %d",
435 			     rule->rr_action));
436 
437 			/*
438 			 * We're using the fact that RCTL_ACTION_SIG* values
439 			 * are equal to their counterparts from sys/signal.h.
440 			 */
441 			kern_psignal(p, rule->rr_action);
442 			link->rrl_exceeded = 1;
443 			continue;
444 		}
445 	}
446 
447 	rw_runlock(&rctl_lock);
448 
449 	if (should_deny) {
450 		/*
451 		 * Return fake error code; the caller should change it
452 		 * into one proper for the situation - EFSIZ, ENOMEM etc.
453 		 */
454 		return (EDOOFUS);
455 	}
456 
457 	return (0);
458 }
459 
460 uint64_t
461 rctl_get_limit(struct proc *p, int resource)
462 {
463 	struct rctl_rule *rule;
464 	struct rctl_rule_link *link;
465 	uint64_t amount = UINT64_MAX;
466 
467 	ASSERT_RACCT_ENABLED();
468 
469 	rw_rlock(&rctl_lock);
470 
471 	/*
472 	 * There may be more than one matching rule; go through all of them.
473 	 * Denial should be done last, after logging and sending signals.
474 	 */
475 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
476 		rule = link->rrl_rule;
477 		if (rule->rr_resource != resource)
478 			continue;
479 		if (rule->rr_action != RCTL_ACTION_DENY)
480 			continue;
481 		if (rule->rr_amount < amount)
482 			amount = rule->rr_amount;
483 	}
484 
485 	rw_runlock(&rctl_lock);
486 
487 	return (amount);
488 }
489 
490 uint64_t
491 rctl_get_available(struct proc *p, int resource)
492 {
493 	struct rctl_rule *rule;
494 	struct rctl_rule_link *link;
495 	int64_t available, minavailable, allocated;
496 
497 	minavailable = INT64_MAX;
498 
499 	ASSERT_RACCT_ENABLED();
500 
501 	rw_rlock(&rctl_lock);
502 
503 	/*
504 	 * There may be more than one matching rule; go through all of them.
505 	 * Denial should be done last, after logging and sending signals.
506 	 */
507 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
508 		rule = link->rrl_rule;
509 		if (rule->rr_resource != resource)
510 			continue;
511 		if (rule->rr_action != RCTL_ACTION_DENY)
512 			continue;
513 		available = rctl_available_resource(p, rule);
514 		if (available < minavailable)
515 			minavailable = available;
516 	}
517 
518 	rw_runlock(&rctl_lock);
519 
520 	/*
521 	 * XXX: Think about this _hard_.
522 	 */
523 	allocated = p->p_racct->r_resources[resource];
524 	if (minavailable < INT64_MAX - allocated)
525 		minavailable += allocated;
526 	if (minavailable < 0)
527 		minavailable = 0;
528 	return (minavailable);
529 }
530 
531 static int
532 rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter)
533 {
534 
535 	ASSERT_RACCT_ENABLED();
536 
537 	if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED) {
538 		if (rule->rr_subject_type != filter->rr_subject_type)
539 			return (0);
540 
541 		switch (filter->rr_subject_type) {
542 		case RCTL_SUBJECT_TYPE_PROCESS:
543 			if (filter->rr_subject.rs_proc != NULL &&
544 			    rule->rr_subject.rs_proc !=
545 			    filter->rr_subject.rs_proc)
546 				return (0);
547 			break;
548 		case RCTL_SUBJECT_TYPE_USER:
549 			if (filter->rr_subject.rs_uip != NULL &&
550 			    rule->rr_subject.rs_uip !=
551 			    filter->rr_subject.rs_uip)
552 				return (0);
553 			break;
554 		case RCTL_SUBJECT_TYPE_LOGINCLASS:
555 			if (filter->rr_subject.rs_loginclass != NULL &&
556 			    rule->rr_subject.rs_loginclass !=
557 			    filter->rr_subject.rs_loginclass)
558 				return (0);
559 			break;
560 		case RCTL_SUBJECT_TYPE_JAIL:
561 			if (filter->rr_subject.rs_prison_racct != NULL &&
562 			    rule->rr_subject.rs_prison_racct !=
563 			    filter->rr_subject.rs_prison_racct)
564 				return (0);
565 			break;
566 		default:
567 			panic("rctl_rule_matches: unknown subject type %d",
568 			    filter->rr_subject_type);
569 		}
570 	}
571 
572 	if (filter->rr_resource != RACCT_UNDEFINED) {
573 		if (rule->rr_resource != filter->rr_resource)
574 			return (0);
575 	}
576 
577 	if (filter->rr_action != RCTL_ACTION_UNDEFINED) {
578 		if (rule->rr_action != filter->rr_action)
579 			return (0);
580 	}
581 
582 	if (filter->rr_amount != RCTL_AMOUNT_UNDEFINED) {
583 		if (rule->rr_amount != filter->rr_amount)
584 			return (0);
585 	}
586 
587 	if (filter->rr_per != RCTL_SUBJECT_TYPE_UNDEFINED) {
588 		if (rule->rr_per != filter->rr_per)
589 			return (0);
590 	}
591 
592 	return (1);
593 }
594 
595 static int
596 str2value(const char *str, int *value, struct dict *table)
597 {
598 	int i;
599 
600 	if (value == NULL)
601 		return (EINVAL);
602 
603 	for (i = 0; table[i].d_name != NULL; i++) {
604 		if (strcasecmp(table[i].d_name, str) == 0) {
605 			*value =  table[i].d_value;
606 			return (0);
607 		}
608 	}
609 
610 	return (EINVAL);
611 }
612 
613 static int
614 str2id(const char *str, id_t *value)
615 {
616 	char *end;
617 
618 	if (str == NULL)
619 		return (EINVAL);
620 
621 	*value = strtoul(str, &end, 10);
622 	if ((size_t)(end - str) != strlen(str))
623 		return (EINVAL);
624 
625 	return (0);
626 }
627 
628 static int
629 str2int64(const char *str, int64_t *value)
630 {
631 	char *end;
632 
633 	if (str == NULL)
634 		return (EINVAL);
635 
636 	*value = strtoul(str, &end, 10);
637 	if ((size_t)(end - str) != strlen(str))
638 		return (EINVAL);
639 
640 	return (0);
641 }
642 
643 /*
644  * Connect the rule to the racct, increasing refcount for the rule.
645  */
646 static void
647 rctl_racct_add_rule(struct racct *racct, struct rctl_rule *rule)
648 {
649 	struct rctl_rule_link *link;
650 
651 	ASSERT_RACCT_ENABLED();
652 	KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
653 
654 	rctl_rule_acquire(rule);
655 	link = uma_zalloc(rctl_rule_link_zone, M_WAITOK);
656 	link->rrl_rule = rule;
657 	link->rrl_exceeded = 0;
658 
659 	rw_wlock(&rctl_lock);
660 	LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next);
661 	rw_wunlock(&rctl_lock);
662 }
663 
664 static int
665 rctl_racct_add_rule_locked(struct racct *racct, struct rctl_rule *rule)
666 {
667 	struct rctl_rule_link *link;
668 
669 	ASSERT_RACCT_ENABLED();
670 	KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
671 	rw_assert(&rctl_lock, RA_WLOCKED);
672 
673 	link = uma_zalloc(rctl_rule_link_zone, M_NOWAIT);
674 	if (link == NULL)
675 		return (ENOMEM);
676 	rctl_rule_acquire(rule);
677 	link->rrl_rule = rule;
678 	link->rrl_exceeded = 0;
679 
680 	LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next);
681 	return (0);
682 }
683 
684 /*
685  * Remove limits for a rules matching the filter and release
686  * the refcounts for the rules, possibly freeing them.  Returns
687  * the number of limit structures removed.
688  */
689 static int
690 rctl_racct_remove_rules(struct racct *racct,
691     const struct rctl_rule *filter)
692 {
693 	int removed = 0;
694 	struct rctl_rule_link *link, *linktmp;
695 
696 	ASSERT_RACCT_ENABLED();
697 	rw_assert(&rctl_lock, RA_WLOCKED);
698 
699 	LIST_FOREACH_SAFE(link, &racct->r_rule_links, rrl_next, linktmp) {
700 		if (!rctl_rule_matches(link->rrl_rule, filter))
701 			continue;
702 
703 		LIST_REMOVE(link, rrl_next);
704 		rctl_rule_release(link->rrl_rule);
705 		uma_zfree(rctl_rule_link_zone, link);
706 		removed++;
707 	}
708 	return (removed);
709 }
710 
711 static void
712 rctl_rule_acquire_subject(struct rctl_rule *rule)
713 {
714 
715 	ASSERT_RACCT_ENABLED();
716 
717 	switch (rule->rr_subject_type) {
718 	case RCTL_SUBJECT_TYPE_UNDEFINED:
719 	case RCTL_SUBJECT_TYPE_PROCESS:
720 		break;
721 	case RCTL_SUBJECT_TYPE_JAIL:
722 		if (rule->rr_subject.rs_prison_racct != NULL)
723 			prison_racct_hold(rule->rr_subject.rs_prison_racct);
724 		break;
725 	case RCTL_SUBJECT_TYPE_USER:
726 		if (rule->rr_subject.rs_uip != NULL)
727 			uihold(rule->rr_subject.rs_uip);
728 		break;
729 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
730 		if (rule->rr_subject.rs_loginclass != NULL)
731 			loginclass_hold(rule->rr_subject.rs_loginclass);
732 		break;
733 	default:
734 		panic("rctl_rule_acquire_subject: unknown subject type %d",
735 		    rule->rr_subject_type);
736 	}
737 }
738 
739 static void
740 rctl_rule_release_subject(struct rctl_rule *rule)
741 {
742 
743 	ASSERT_RACCT_ENABLED();
744 
745 	switch (rule->rr_subject_type) {
746 	case RCTL_SUBJECT_TYPE_UNDEFINED:
747 	case RCTL_SUBJECT_TYPE_PROCESS:
748 		break;
749 	case RCTL_SUBJECT_TYPE_JAIL:
750 		if (rule->rr_subject.rs_prison_racct != NULL)
751 			prison_racct_free(rule->rr_subject.rs_prison_racct);
752 		break;
753 	case RCTL_SUBJECT_TYPE_USER:
754 		if (rule->rr_subject.rs_uip != NULL)
755 			uifree(rule->rr_subject.rs_uip);
756 		break;
757 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
758 		if (rule->rr_subject.rs_loginclass != NULL)
759 			loginclass_free(rule->rr_subject.rs_loginclass);
760 		break;
761 	default:
762 		panic("rctl_rule_release_subject: unknown subject type %d",
763 		    rule->rr_subject_type);
764 	}
765 }
766 
767 struct rctl_rule *
768 rctl_rule_alloc(int flags)
769 {
770 	struct rctl_rule *rule;
771 
772 	ASSERT_RACCT_ENABLED();
773 
774 	rule = uma_zalloc(rctl_rule_zone, flags);
775 	if (rule == NULL)
776 		return (NULL);
777 	rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED;
778 	rule->rr_subject.rs_proc = NULL;
779 	rule->rr_subject.rs_uip = NULL;
780 	rule->rr_subject.rs_loginclass = NULL;
781 	rule->rr_subject.rs_prison_racct = NULL;
782 	rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED;
783 	rule->rr_resource = RACCT_UNDEFINED;
784 	rule->rr_action = RCTL_ACTION_UNDEFINED;
785 	rule->rr_amount = RCTL_AMOUNT_UNDEFINED;
786 	refcount_init(&rule->rr_refcount, 1);
787 
788 	return (rule);
789 }
790 
791 struct rctl_rule *
792 rctl_rule_duplicate(const struct rctl_rule *rule, int flags)
793 {
794 	struct rctl_rule *copy;
795 
796 	ASSERT_RACCT_ENABLED();
797 
798 	copy = uma_zalloc(rctl_rule_zone, flags);
799 	if (copy == NULL)
800 		return (NULL);
801 	copy->rr_subject_type = rule->rr_subject_type;
802 	copy->rr_subject.rs_proc = rule->rr_subject.rs_proc;
803 	copy->rr_subject.rs_uip = rule->rr_subject.rs_uip;
804 	copy->rr_subject.rs_loginclass = rule->rr_subject.rs_loginclass;
805 	copy->rr_subject.rs_prison_racct = rule->rr_subject.rs_prison_racct;
806 	copy->rr_per = rule->rr_per;
807 	copy->rr_resource = rule->rr_resource;
808 	copy->rr_action = rule->rr_action;
809 	copy->rr_amount = rule->rr_amount;
810 	refcount_init(&copy->rr_refcount, 1);
811 	rctl_rule_acquire_subject(copy);
812 
813 	return (copy);
814 }
815 
816 void
817 rctl_rule_acquire(struct rctl_rule *rule)
818 {
819 
820 	ASSERT_RACCT_ENABLED();
821 	KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0"));
822 
823 	refcount_acquire(&rule->rr_refcount);
824 }
825 
826 static void
827 rctl_rule_free(void *context, int pending)
828 {
829 	struct rctl_rule *rule;
830 
831 	rule = (struct rctl_rule *)context;
832 
833 	ASSERT_RACCT_ENABLED();
834 	KASSERT(rule->rr_refcount == 0, ("rule->rr_refcount != 0"));
835 
836 	/*
837 	 * We don't need locking here; rule is guaranteed to be inaccessible.
838 	 */
839 
840 	rctl_rule_release_subject(rule);
841 	uma_zfree(rctl_rule_zone, rule);
842 }
843 
844 void
845 rctl_rule_release(struct rctl_rule *rule)
846 {
847 
848 	ASSERT_RACCT_ENABLED();
849 	KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0"));
850 
851 	if (refcount_release(&rule->rr_refcount)) {
852 		/*
853 		 * rctl_rule_release() is often called when iterating
854 		 * over all the uidinfo structures in the system,
855 		 * holding uihashtbl_lock.  Since rctl_rule_free()
856 		 * might end up calling uifree(), this would lead
857 		 * to lock recursion.  Use taskqueue to avoid this.
858 		 */
859 		TASK_INIT(&rule->rr_task, 0, rctl_rule_free, rule);
860 		taskqueue_enqueue(taskqueue_thread, &rule->rr_task);
861 	}
862 }
863 
864 static int
865 rctl_rule_fully_specified(const struct rctl_rule *rule)
866 {
867 
868 	ASSERT_RACCT_ENABLED();
869 
870 	switch (rule->rr_subject_type) {
871 	case RCTL_SUBJECT_TYPE_UNDEFINED:
872 		return (0);
873 	case RCTL_SUBJECT_TYPE_PROCESS:
874 		if (rule->rr_subject.rs_proc == NULL)
875 			return (0);
876 		break;
877 	case RCTL_SUBJECT_TYPE_USER:
878 		if (rule->rr_subject.rs_uip == NULL)
879 			return (0);
880 		break;
881 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
882 		if (rule->rr_subject.rs_loginclass == NULL)
883 			return (0);
884 		break;
885 	case RCTL_SUBJECT_TYPE_JAIL:
886 		if (rule->rr_subject.rs_prison_racct == NULL)
887 			return (0);
888 		break;
889 	default:
890 		panic("rctl_rule_fully_specified: unknown subject type %d",
891 		    rule->rr_subject_type);
892 	}
893 	if (rule->rr_resource == RACCT_UNDEFINED)
894 		return (0);
895 	if (rule->rr_action == RCTL_ACTION_UNDEFINED)
896 		return (0);
897 	if (rule->rr_amount == RCTL_AMOUNT_UNDEFINED)
898 		return (0);
899 	if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED)
900 		return (0);
901 
902 	return (1);
903 }
904 
905 static int
906 rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep)
907 {
908 	int error = 0;
909 	char *subjectstr, *subject_idstr, *resourcestr, *actionstr,
910 	     *amountstr, *perstr;
911 	struct rctl_rule *rule;
912 	id_t id;
913 
914 	ASSERT_RACCT_ENABLED();
915 
916 	rule = rctl_rule_alloc(M_WAITOK);
917 
918 	subjectstr = strsep(&rulestr, ":");
919 	subject_idstr = strsep(&rulestr, ":");
920 	resourcestr = strsep(&rulestr, ":");
921 	actionstr = strsep(&rulestr, "=/");
922 	amountstr = strsep(&rulestr, "/");
923 	perstr = rulestr;
924 
925 	if (subjectstr == NULL || subjectstr[0] == '\0')
926 		rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED;
927 	else {
928 		error = str2value(subjectstr, &rule->rr_subject_type, subjectnames);
929 		if (error != 0)
930 			goto out;
931 	}
932 
933 	if (subject_idstr == NULL || subject_idstr[0] == '\0') {
934 		rule->rr_subject.rs_proc = NULL;
935 		rule->rr_subject.rs_uip = NULL;
936 		rule->rr_subject.rs_loginclass = NULL;
937 		rule->rr_subject.rs_prison_racct = NULL;
938 	} else {
939 		switch (rule->rr_subject_type) {
940 		case RCTL_SUBJECT_TYPE_UNDEFINED:
941 			error = EINVAL;
942 			goto out;
943 		case RCTL_SUBJECT_TYPE_PROCESS:
944 			error = str2id(subject_idstr, &id);
945 			if (error != 0)
946 				goto out;
947 			sx_assert(&allproc_lock, SA_LOCKED);
948 			rule->rr_subject.rs_proc = pfind(id);
949 			if (rule->rr_subject.rs_proc == NULL) {
950 				error = ESRCH;
951 				goto out;
952 			}
953 			PROC_UNLOCK(rule->rr_subject.rs_proc);
954 			break;
955 		case RCTL_SUBJECT_TYPE_USER:
956 			error = str2id(subject_idstr, &id);
957 			if (error != 0)
958 				goto out;
959 			rule->rr_subject.rs_uip = uifind(id);
960 			break;
961 		case RCTL_SUBJECT_TYPE_LOGINCLASS:
962 			rule->rr_subject.rs_loginclass =
963 			    loginclass_find(subject_idstr);
964 			if (rule->rr_subject.rs_loginclass == NULL) {
965 				error = ENAMETOOLONG;
966 				goto out;
967 			}
968 			break;
969 		case RCTL_SUBJECT_TYPE_JAIL:
970 			rule->rr_subject.rs_prison_racct =
971 			    prison_racct_find(subject_idstr);
972 			if (rule->rr_subject.rs_prison_racct == NULL) {
973 				error = ENAMETOOLONG;
974 				goto out;
975 			}
976 			break;
977                default:
978                        panic("rctl_string_to_rule: unknown subject type %d",
979                            rule->rr_subject_type);
980                }
981 	}
982 
983 	if (resourcestr == NULL || resourcestr[0] == '\0')
984 		rule->rr_resource = RACCT_UNDEFINED;
985 	else {
986 		error = str2value(resourcestr, &rule->rr_resource,
987 		    resourcenames);
988 		if (error != 0)
989 			goto out;
990 	}
991 
992 	if (actionstr == NULL || actionstr[0] == '\0')
993 		rule->rr_action = RCTL_ACTION_UNDEFINED;
994 	else {
995 		error = str2value(actionstr, &rule->rr_action, actionnames);
996 		if (error != 0)
997 			goto out;
998 	}
999 
1000 	if (amountstr == NULL || amountstr[0] == '\0')
1001 		rule->rr_amount = RCTL_AMOUNT_UNDEFINED;
1002 	else {
1003 		error = str2int64(amountstr, &rule->rr_amount);
1004 		if (error != 0)
1005 			goto out;
1006 		if (RACCT_IS_IN_MILLIONS(rule->rr_resource))
1007 			rule->rr_amount *= 1000000;
1008 	}
1009 
1010 	if (perstr == NULL || perstr[0] == '\0')
1011 		rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED;
1012 	else {
1013 		error = str2value(perstr, &rule->rr_per, subjectnames);
1014 		if (error != 0)
1015 			goto out;
1016 	}
1017 
1018 out:
1019 	if (error == 0)
1020 		*rulep = rule;
1021 	else
1022 		rctl_rule_release(rule);
1023 
1024 	return (error);
1025 }
1026 
1027 /*
1028  * Link a rule with all the subjects it applies to.
1029  */
1030 int
1031 rctl_rule_add(struct rctl_rule *rule)
1032 {
1033 	struct proc *p;
1034 	struct ucred *cred;
1035 	struct uidinfo *uip;
1036 	struct prison *pr;
1037 	struct prison_racct *prr;
1038 	struct loginclass *lc;
1039 	struct rctl_rule *rule2;
1040 	int match;
1041 
1042 	ASSERT_RACCT_ENABLED();
1043 	KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
1044 
1045 	/*
1046 	 * Some rules just don't make sense.  Note that the one below
1047 	 * cannot be rewritten using RACCT_IS_DENIABLE(); the RACCT_PCTCPU,
1048 	 * for example, is not deniable in the racct sense, but the
1049 	 * limit is enforced in a different way, so "deny" rules for %CPU
1050 	 * do make sense.
1051 	 */
1052 	if (rule->rr_action == RCTL_ACTION_DENY &&
1053 	    (rule->rr_resource == RACCT_CPU ||
1054 	    rule->rr_resource == RACCT_WALLCLOCK))
1055 		return (EOPNOTSUPP);
1056 
1057 	if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS &&
1058 	    RACCT_IS_SLOPPY(rule->rr_resource))
1059 		return (EOPNOTSUPP);
1060 
1061 	/*
1062 	 * Make sure there are no duplicated rules.  Also, for the "deny"
1063 	 * rules, remove ones differing only by "amount".
1064 	 */
1065 	if (rule->rr_action == RCTL_ACTION_DENY) {
1066 		rule2 = rctl_rule_duplicate(rule, M_WAITOK);
1067 		rule2->rr_amount = RCTL_AMOUNT_UNDEFINED;
1068 		rctl_rule_remove(rule2);
1069 		rctl_rule_release(rule2);
1070 	} else
1071 		rctl_rule_remove(rule);
1072 
1073 	switch (rule->rr_subject_type) {
1074 	case RCTL_SUBJECT_TYPE_PROCESS:
1075 		p = rule->rr_subject.rs_proc;
1076 		KASSERT(p != NULL, ("rctl_rule_add: NULL proc"));
1077 
1078 		rctl_racct_add_rule(p->p_racct, rule);
1079 		/*
1080 		 * In case of per-process rule, we don't have anything more
1081 		 * to do.
1082 		 */
1083 		return (0);
1084 
1085 	case RCTL_SUBJECT_TYPE_USER:
1086 		uip = rule->rr_subject.rs_uip;
1087 		KASSERT(uip != NULL, ("rctl_rule_add: NULL uip"));
1088 		rctl_racct_add_rule(uip->ui_racct, rule);
1089 		break;
1090 
1091 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
1092 		lc = rule->rr_subject.rs_loginclass;
1093 		KASSERT(lc != NULL, ("rctl_rule_add: NULL loginclass"));
1094 		rctl_racct_add_rule(lc->lc_racct, rule);
1095 		break;
1096 
1097 	case RCTL_SUBJECT_TYPE_JAIL:
1098 		prr = rule->rr_subject.rs_prison_racct;
1099 		KASSERT(prr != NULL, ("rctl_rule_add: NULL pr"));
1100 		rctl_racct_add_rule(prr->prr_racct, rule);
1101 		break;
1102 
1103 	default:
1104 		panic("rctl_rule_add: unknown subject type %d",
1105 		    rule->rr_subject_type);
1106 	}
1107 
1108 	/*
1109 	 * Now go through all the processes and add the new rule to the ones
1110 	 * it applies to.
1111 	 */
1112 	sx_assert(&allproc_lock, SA_LOCKED);
1113 	FOREACH_PROC_IN_SYSTEM(p) {
1114 		cred = p->p_ucred;
1115 		switch (rule->rr_subject_type) {
1116 		case RCTL_SUBJECT_TYPE_USER:
1117 			if (cred->cr_uidinfo == rule->rr_subject.rs_uip ||
1118 			    cred->cr_ruidinfo == rule->rr_subject.rs_uip)
1119 				break;
1120 			continue;
1121 		case RCTL_SUBJECT_TYPE_LOGINCLASS:
1122 			if (cred->cr_loginclass == rule->rr_subject.rs_loginclass)
1123 				break;
1124 			continue;
1125 		case RCTL_SUBJECT_TYPE_JAIL:
1126 			match = 0;
1127 			for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) {
1128 				if (pr->pr_prison_racct == rule->rr_subject.rs_prison_racct) {
1129 					match = 1;
1130 					break;
1131 				}
1132 			}
1133 			if (match)
1134 				break;
1135 			continue;
1136 		default:
1137 			panic("rctl_rule_add: unknown subject type %d",
1138 			    rule->rr_subject_type);
1139 		}
1140 
1141 		rctl_racct_add_rule(p->p_racct, rule);
1142 	}
1143 
1144 	return (0);
1145 }
1146 
1147 static void
1148 rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3)
1149 {
1150 	struct rctl_rule *filter = (struct rctl_rule *)arg2;
1151 	int found = 0;
1152 
1153 	ASSERT_RACCT_ENABLED();
1154 
1155 	rw_wlock(&rctl_lock);
1156 	found += rctl_racct_remove_rules(racct, filter);
1157 	rw_wunlock(&rctl_lock);
1158 
1159 	*((int *)arg3) += found;
1160 }
1161 
1162 /*
1163  * Remove all rules that match the filter.
1164  */
1165 int
1166 rctl_rule_remove(struct rctl_rule *filter)
1167 {
1168 	int found = 0;
1169 	struct proc *p;
1170 
1171 	ASSERT_RACCT_ENABLED();
1172 
1173 	if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_PROCESS &&
1174 	    filter->rr_subject.rs_proc != NULL) {
1175 		p = filter->rr_subject.rs_proc;
1176 		rw_wlock(&rctl_lock);
1177 		found = rctl_racct_remove_rules(p->p_racct, filter);
1178 		rw_wunlock(&rctl_lock);
1179 		if (found)
1180 			return (0);
1181 		return (ESRCH);
1182 	}
1183 
1184 	loginclass_racct_foreach(rctl_rule_remove_callback, filter,
1185 	    (void *)&found);
1186 	ui_racct_foreach(rctl_rule_remove_callback, filter,
1187 	    (void *)&found);
1188 	prison_racct_foreach(rctl_rule_remove_callback, filter,
1189 	    (void *)&found);
1190 
1191 	sx_assert(&allproc_lock, SA_LOCKED);
1192 	rw_wlock(&rctl_lock);
1193 	FOREACH_PROC_IN_SYSTEM(p) {
1194 		found += rctl_racct_remove_rules(p->p_racct, filter);
1195 	}
1196 	rw_wunlock(&rctl_lock);
1197 
1198 	if (found)
1199 		return (0);
1200 	return (ESRCH);
1201 }
1202 
1203 /*
1204  * Appends a rule to the sbuf.
1205  */
1206 static void
1207 rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule)
1208 {
1209 	int64_t amount;
1210 
1211 	ASSERT_RACCT_ENABLED();
1212 
1213 	sbuf_printf(sb, "%s:", rctl_subject_type_name(rule->rr_subject_type));
1214 
1215 	switch (rule->rr_subject_type) {
1216 	case RCTL_SUBJECT_TYPE_PROCESS:
1217 		if (rule->rr_subject.rs_proc == NULL)
1218 			sbuf_printf(sb, ":");
1219 		else
1220 			sbuf_printf(sb, "%d:",
1221 			    rule->rr_subject.rs_proc->p_pid);
1222 		break;
1223 	case RCTL_SUBJECT_TYPE_USER:
1224 		if (rule->rr_subject.rs_uip == NULL)
1225 			sbuf_printf(sb, ":");
1226 		else
1227 			sbuf_printf(sb, "%d:",
1228 			    rule->rr_subject.rs_uip->ui_uid);
1229 		break;
1230 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
1231 		if (rule->rr_subject.rs_loginclass == NULL)
1232 			sbuf_printf(sb, ":");
1233 		else
1234 			sbuf_printf(sb, "%s:",
1235 			    rule->rr_subject.rs_loginclass->lc_name);
1236 		break;
1237 	case RCTL_SUBJECT_TYPE_JAIL:
1238 		if (rule->rr_subject.rs_prison_racct == NULL)
1239 			sbuf_printf(sb, ":");
1240 		else
1241 			sbuf_printf(sb, "%s:",
1242 			    rule->rr_subject.rs_prison_racct->prr_name);
1243 		break;
1244 	default:
1245 		panic("rctl_rule_to_sbuf: unknown subject type %d",
1246 		    rule->rr_subject_type);
1247 	}
1248 
1249 	amount = rule->rr_amount;
1250 	if (amount != RCTL_AMOUNT_UNDEFINED &&
1251 	    RACCT_IS_IN_MILLIONS(rule->rr_resource))
1252 		amount /= 1000000;
1253 
1254 	sbuf_printf(sb, "%s:%s=%jd",
1255 	    rctl_resource_name(rule->rr_resource),
1256 	    rctl_action_name(rule->rr_action),
1257 	    amount);
1258 
1259 	if (rule->rr_per != rule->rr_subject_type)
1260 		sbuf_printf(sb, "/%s", rctl_subject_type_name(rule->rr_per));
1261 }
1262 
1263 /*
1264  * Routine used by RCTL syscalls to read in input string.
1265  */
1266 static int
1267 rctl_read_inbuf(char **inputstr, const char *inbufp, size_t inbuflen)
1268 {
1269 	int error;
1270 	char *str;
1271 
1272 	ASSERT_RACCT_ENABLED();
1273 
1274 	if (inbuflen <= 0)
1275 		return (EINVAL);
1276 	if (inbuflen > RCTL_MAX_INBUFLEN)
1277 		return (E2BIG);
1278 
1279 	str = malloc(inbuflen + 1, M_RCTL, M_WAITOK);
1280 	error = copyinstr(inbufp, str, inbuflen, NULL);
1281 	if (error != 0) {
1282 		free(str, M_RCTL);
1283 		return (error);
1284 	}
1285 
1286 	*inputstr = str;
1287 
1288 	return (0);
1289 }
1290 
1291 /*
1292  * Routine used by RCTL syscalls to write out output string.
1293  */
1294 static int
1295 rctl_write_outbuf(struct sbuf *outputsbuf, char *outbufp, size_t outbuflen)
1296 {
1297 	int error;
1298 
1299 	ASSERT_RACCT_ENABLED();
1300 
1301 	if (outputsbuf == NULL)
1302 		return (0);
1303 
1304 	sbuf_finish(outputsbuf);
1305 	if (outbuflen < sbuf_len(outputsbuf) + 1) {
1306 		sbuf_delete(outputsbuf);
1307 		return (ERANGE);
1308 	}
1309 	error = copyout(sbuf_data(outputsbuf), outbufp,
1310 	    sbuf_len(outputsbuf) + 1);
1311 	sbuf_delete(outputsbuf);
1312 	return (error);
1313 }
1314 
1315 static struct sbuf *
1316 rctl_racct_to_sbuf(struct racct *racct, int sloppy)
1317 {
1318 	int i;
1319 	int64_t amount;
1320 	struct sbuf *sb;
1321 
1322 	ASSERT_RACCT_ENABLED();
1323 
1324 	sb = sbuf_new_auto();
1325 	for (i = 0; i <= RACCT_MAX; i++) {
1326 		if (sloppy == 0 && RACCT_IS_SLOPPY(i))
1327 			continue;
1328 		amount = racct->r_resources[i];
1329 		if (RACCT_IS_IN_MILLIONS(i))
1330 			amount /= 1000000;
1331 		sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount);
1332 	}
1333 	sbuf_setpos(sb, sbuf_len(sb) - 1);
1334 	return (sb);
1335 }
1336 
1337 int
1338 sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap)
1339 {
1340 	int error;
1341 	char *inputstr;
1342 	struct rctl_rule *filter;
1343 	struct sbuf *outputsbuf = NULL;
1344 	struct proc *p;
1345 	struct uidinfo *uip;
1346 	struct loginclass *lc;
1347 	struct prison_racct *prr;
1348 
1349 	if (!racct_enable)
1350 		return (ENOSYS);
1351 
1352 	error = priv_check(td, PRIV_RCTL_GET_RACCT);
1353 	if (error != 0)
1354 		return (error);
1355 
1356 	error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
1357 	if (error != 0)
1358 		return (error);
1359 
1360 	sx_slock(&allproc_lock);
1361 	error = rctl_string_to_rule(inputstr, &filter);
1362 	free(inputstr, M_RCTL);
1363 	if (error != 0) {
1364 		sx_sunlock(&allproc_lock);
1365 		return (error);
1366 	}
1367 
1368 	switch (filter->rr_subject_type) {
1369 	case RCTL_SUBJECT_TYPE_PROCESS:
1370 		p = filter->rr_subject.rs_proc;
1371 		if (p == NULL) {
1372 			error = EINVAL;
1373 			goto out;
1374 		}
1375 		outputsbuf = rctl_racct_to_sbuf(p->p_racct, 0);
1376 		break;
1377 	case RCTL_SUBJECT_TYPE_USER:
1378 		uip = filter->rr_subject.rs_uip;
1379 		if (uip == NULL) {
1380 			error = EINVAL;
1381 			goto out;
1382 		}
1383 		outputsbuf = rctl_racct_to_sbuf(uip->ui_racct, 1);
1384 		break;
1385 	case RCTL_SUBJECT_TYPE_LOGINCLASS:
1386 		lc = filter->rr_subject.rs_loginclass;
1387 		if (lc == NULL) {
1388 			error = EINVAL;
1389 			goto out;
1390 		}
1391 		outputsbuf = rctl_racct_to_sbuf(lc->lc_racct, 1);
1392 		break;
1393 	case RCTL_SUBJECT_TYPE_JAIL:
1394 		prr = filter->rr_subject.rs_prison_racct;
1395 		if (prr == NULL) {
1396 			error = EINVAL;
1397 			goto out;
1398 		}
1399 		outputsbuf = rctl_racct_to_sbuf(prr->prr_racct, 1);
1400 		break;
1401 	default:
1402 		error = EINVAL;
1403 	}
1404 out:
1405 	rctl_rule_release(filter);
1406 	sx_sunlock(&allproc_lock);
1407 	if (error != 0)
1408 		return (error);
1409 
1410 	error = rctl_write_outbuf(outputsbuf, uap->outbufp, uap->outbuflen);
1411 
1412 	return (error);
1413 }
1414 
1415 static void
1416 rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3)
1417 {
1418 	struct rctl_rule *filter = (struct rctl_rule *)arg2;
1419 	struct rctl_rule_link *link;
1420 	struct sbuf *sb = (struct sbuf *)arg3;
1421 
1422 	ASSERT_RACCT_ENABLED();
1423 
1424 	rw_rlock(&rctl_lock);
1425 	LIST_FOREACH(link, &racct->r_rule_links, rrl_next) {
1426 		if (!rctl_rule_matches(link->rrl_rule, filter))
1427 			continue;
1428 		rctl_rule_to_sbuf(sb, link->rrl_rule);
1429 		sbuf_printf(sb, ",");
1430 	}
1431 	rw_runlock(&rctl_lock);
1432 }
1433 
1434 int
1435 sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap)
1436 {
1437 	int error;
1438 	size_t bufsize = RCTL_DEFAULT_BUFSIZE;
1439 	char *inputstr, *buf;
1440 	struct sbuf *sb;
1441 	struct rctl_rule *filter;
1442 	struct rctl_rule_link *link;
1443 	struct proc *p;
1444 
1445 	if (!racct_enable)
1446 		return (ENOSYS);
1447 
1448 	error = priv_check(td, PRIV_RCTL_GET_RULES);
1449 	if (error != 0)
1450 		return (error);
1451 
1452 	error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
1453 	if (error != 0)
1454 		return (error);
1455 
1456 	sx_slock(&allproc_lock);
1457 	error = rctl_string_to_rule(inputstr, &filter);
1458 	free(inputstr, M_RCTL);
1459 	if (error != 0) {
1460 		sx_sunlock(&allproc_lock);
1461 		return (error);
1462 	}
1463 
1464 again:
1465 	buf = malloc(bufsize, M_RCTL, M_WAITOK);
1466 	sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
1467 	KASSERT(sb != NULL, ("sbuf_new failed"));
1468 
1469 	sx_assert(&allproc_lock, SA_LOCKED);
1470 	FOREACH_PROC_IN_SYSTEM(p) {
1471 		rw_rlock(&rctl_lock);
1472 		LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
1473 			/*
1474 			 * Non-process rules will be added to the buffer later.
1475 			 * Adding them here would result in duplicated output.
1476 			 */
1477 			if (link->rrl_rule->rr_subject_type !=
1478 			    RCTL_SUBJECT_TYPE_PROCESS)
1479 				continue;
1480 			if (!rctl_rule_matches(link->rrl_rule, filter))
1481 				continue;
1482 			rctl_rule_to_sbuf(sb, link->rrl_rule);
1483 			sbuf_printf(sb, ",");
1484 		}
1485 		rw_runlock(&rctl_lock);
1486 	}
1487 
1488 	loginclass_racct_foreach(rctl_get_rules_callback, filter, sb);
1489 	ui_racct_foreach(rctl_get_rules_callback, filter, sb);
1490 	prison_racct_foreach(rctl_get_rules_callback, filter, sb);
1491 	if (sbuf_error(sb) == ENOMEM) {
1492 		sbuf_delete(sb);
1493 		free(buf, M_RCTL);
1494 		bufsize *= 4;
1495 		goto again;
1496 	}
1497 
1498 	/*
1499 	 * Remove trailing ",".
1500 	 */
1501 	if (sbuf_len(sb) > 0)
1502 		sbuf_setpos(sb, sbuf_len(sb) - 1);
1503 
1504 	error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen);
1505 
1506 	rctl_rule_release(filter);
1507 	sx_sunlock(&allproc_lock);
1508 	free(buf, M_RCTL);
1509 	return (error);
1510 }
1511 
1512 int
1513 sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap)
1514 {
1515 	int error;
1516 	size_t bufsize = RCTL_DEFAULT_BUFSIZE;
1517 	char *inputstr, *buf;
1518 	struct sbuf *sb;
1519 	struct rctl_rule *filter;
1520 	struct rctl_rule_link *link;
1521 
1522 	if (!racct_enable)
1523 		return (ENOSYS);
1524 
1525 	error = priv_check(td, PRIV_RCTL_GET_LIMITS);
1526 	if (error != 0)
1527 		return (error);
1528 
1529 	error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
1530 	if (error != 0)
1531 		return (error);
1532 
1533 	sx_slock(&allproc_lock);
1534 	error = rctl_string_to_rule(inputstr, &filter);
1535 	free(inputstr, M_RCTL);
1536 	if (error != 0) {
1537 		sx_sunlock(&allproc_lock);
1538 		return (error);
1539 	}
1540 
1541 	if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_UNDEFINED) {
1542 		rctl_rule_release(filter);
1543 		sx_sunlock(&allproc_lock);
1544 		return (EINVAL);
1545 	}
1546 	if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_PROCESS) {
1547 		rctl_rule_release(filter);
1548 		sx_sunlock(&allproc_lock);
1549 		return (EOPNOTSUPP);
1550 	}
1551 	if (filter->rr_subject.rs_proc == NULL) {
1552 		rctl_rule_release(filter);
1553 		sx_sunlock(&allproc_lock);
1554 		return (EINVAL);
1555 	}
1556 
1557 again:
1558 	buf = malloc(bufsize, M_RCTL, M_WAITOK);
1559 	sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
1560 	KASSERT(sb != NULL, ("sbuf_new failed"));
1561 
1562 	rw_rlock(&rctl_lock);
1563 	LIST_FOREACH(link, &filter->rr_subject.rs_proc->p_racct->r_rule_links,
1564 	    rrl_next) {
1565 		rctl_rule_to_sbuf(sb, link->rrl_rule);
1566 		sbuf_printf(sb, ",");
1567 	}
1568 	rw_runlock(&rctl_lock);
1569 	if (sbuf_error(sb) == ENOMEM) {
1570 		sbuf_delete(sb);
1571 		free(buf, M_RCTL);
1572 		bufsize *= 4;
1573 		goto again;
1574 	}
1575 
1576 	/*
1577 	 * Remove trailing ",".
1578 	 */
1579 	if (sbuf_len(sb) > 0)
1580 		sbuf_setpos(sb, sbuf_len(sb) - 1);
1581 
1582 	error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen);
1583 	rctl_rule_release(filter);
1584 	sx_sunlock(&allproc_lock);
1585 	free(buf, M_RCTL);
1586 	return (error);
1587 }
1588 
1589 int
1590 sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap)
1591 {
1592 	int error;
1593 	struct rctl_rule *rule;
1594 	char *inputstr;
1595 
1596 	if (!racct_enable)
1597 		return (ENOSYS);
1598 
1599 	error = priv_check(td, PRIV_RCTL_ADD_RULE);
1600 	if (error != 0)
1601 		return (error);
1602 
1603 	error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
1604 	if (error != 0)
1605 		return (error);
1606 
1607 	sx_slock(&allproc_lock);
1608 	error = rctl_string_to_rule(inputstr, &rule);
1609 	free(inputstr, M_RCTL);
1610 	if (error != 0) {
1611 		sx_sunlock(&allproc_lock);
1612 		return (error);
1613 	}
1614 	/*
1615 	 * The 'per' part of a rule is optional.
1616 	 */
1617 	if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED &&
1618 	    rule->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED)
1619 		rule->rr_per = rule->rr_subject_type;
1620 
1621 	if (!rctl_rule_fully_specified(rule)) {
1622 		error = EINVAL;
1623 		goto out;
1624 	}
1625 
1626 	error = rctl_rule_add(rule);
1627 
1628 out:
1629 	rctl_rule_release(rule);
1630 	sx_sunlock(&allproc_lock);
1631 	return (error);
1632 }
1633 
1634 int
1635 sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap)
1636 {
1637 	int error;
1638 	struct rctl_rule *filter;
1639 	char *inputstr;
1640 
1641 	if (!racct_enable)
1642 		return (ENOSYS);
1643 
1644 	error = priv_check(td, PRIV_RCTL_REMOVE_RULE);
1645 	if (error != 0)
1646 		return (error);
1647 
1648 	error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
1649 	if (error != 0)
1650 		return (error);
1651 
1652 	sx_slock(&allproc_lock);
1653 	error = rctl_string_to_rule(inputstr, &filter);
1654 	free(inputstr, M_RCTL);
1655 	if (error != 0) {
1656 		sx_sunlock(&allproc_lock);
1657 		return (error);
1658 	}
1659 
1660 	error = rctl_rule_remove(filter);
1661 	rctl_rule_release(filter);
1662 	sx_sunlock(&allproc_lock);
1663 
1664 	return (error);
1665 }
1666 
1667 /*
1668  * Update RCTL rule list after credential change.
1669  */
1670 void
1671 rctl_proc_ucred_changed(struct proc *p, struct ucred *newcred)
1672 {
1673 	int rulecnt, i;
1674 	struct rctl_rule_link *link, *newlink;
1675 	struct uidinfo *newuip;
1676 	struct loginclass *newlc;
1677 	struct prison_racct *newprr;
1678 	LIST_HEAD(, rctl_rule_link) newrules;
1679 
1680 	ASSERT_RACCT_ENABLED();
1681 
1682 	newuip = newcred->cr_ruidinfo;
1683 	newlc = newcred->cr_loginclass;
1684 	newprr = newcred->cr_prison->pr_prison_racct;
1685 
1686 	LIST_INIT(&newrules);
1687 
1688 again:
1689 	/*
1690 	 * First, count the rules that apply to the process with new
1691 	 * credentials.
1692 	 */
1693 	rulecnt = 0;
1694 	rw_rlock(&rctl_lock);
1695 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
1696 		if (link->rrl_rule->rr_subject_type ==
1697 		    RCTL_SUBJECT_TYPE_PROCESS)
1698 			rulecnt++;
1699 	}
1700 	LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next)
1701 		rulecnt++;
1702 	LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next)
1703 		rulecnt++;
1704 	LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next)
1705 		rulecnt++;
1706 	rw_runlock(&rctl_lock);
1707 
1708 	/*
1709 	 * Create temporary list.  We've dropped the rctl_lock in order
1710 	 * to use M_WAITOK.
1711 	 */
1712 	for (i = 0; i < rulecnt; i++) {
1713 		newlink = uma_zalloc(rctl_rule_link_zone, M_WAITOK);
1714 		newlink->rrl_rule = NULL;
1715 		LIST_INSERT_HEAD(&newrules, newlink, rrl_next);
1716 	}
1717 
1718 	newlink = LIST_FIRST(&newrules);
1719 
1720 	/*
1721 	 * Assign rules to the newly allocated list entries.
1722 	 */
1723 	rw_wlock(&rctl_lock);
1724 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
1725 		if (link->rrl_rule->rr_subject_type ==
1726 		    RCTL_SUBJECT_TYPE_PROCESS) {
1727 			if (newlink == NULL)
1728 				goto goaround;
1729 			rctl_rule_acquire(link->rrl_rule);
1730 			newlink->rrl_rule = link->rrl_rule;
1731 			newlink = LIST_NEXT(newlink, rrl_next);
1732 			rulecnt--;
1733 		}
1734 	}
1735 
1736 	LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) {
1737 		if (newlink == NULL)
1738 			goto goaround;
1739 		rctl_rule_acquire(link->rrl_rule);
1740 		newlink->rrl_rule = link->rrl_rule;
1741 		newlink = LIST_NEXT(newlink, rrl_next);
1742 		rulecnt--;
1743 	}
1744 
1745 	LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) {
1746 		if (newlink == NULL)
1747 			goto goaround;
1748 		rctl_rule_acquire(link->rrl_rule);
1749 		newlink->rrl_rule = link->rrl_rule;
1750 		newlink = LIST_NEXT(newlink, rrl_next);
1751 		rulecnt--;
1752 	}
1753 
1754 	LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) {
1755 		if (newlink == NULL)
1756 			goto goaround;
1757 		rctl_rule_acquire(link->rrl_rule);
1758 		newlink->rrl_rule = link->rrl_rule;
1759 		newlink = LIST_NEXT(newlink, rrl_next);
1760 		rulecnt--;
1761 	}
1762 
1763 	if (rulecnt == 0) {
1764 		/*
1765 		 * Free the old rule list.
1766 		 */
1767 		while (!LIST_EMPTY(&p->p_racct->r_rule_links)) {
1768 			link = LIST_FIRST(&p->p_racct->r_rule_links);
1769 			LIST_REMOVE(link, rrl_next);
1770 			rctl_rule_release(link->rrl_rule);
1771 			uma_zfree(rctl_rule_link_zone, link);
1772 		}
1773 
1774 		/*
1775 		 * Replace lists and we're done.
1776 		 *
1777 		 * XXX: Is there any way to switch list heads instead
1778 		 *      of iterating here?
1779 		 */
1780 		while (!LIST_EMPTY(&newrules)) {
1781 			newlink = LIST_FIRST(&newrules);
1782 			LIST_REMOVE(newlink, rrl_next);
1783 			LIST_INSERT_HEAD(&p->p_racct->r_rule_links,
1784 			    newlink, rrl_next);
1785 		}
1786 
1787 		rw_wunlock(&rctl_lock);
1788 
1789 		return;
1790 	}
1791 
1792 goaround:
1793 	rw_wunlock(&rctl_lock);
1794 
1795 	/*
1796 	 * Rule list changed while we were not holding the rctl_lock.
1797 	 * Free the new list and try again.
1798 	 */
1799 	while (!LIST_EMPTY(&newrules)) {
1800 		newlink = LIST_FIRST(&newrules);
1801 		LIST_REMOVE(newlink, rrl_next);
1802 		if (newlink->rrl_rule != NULL)
1803 			rctl_rule_release(newlink->rrl_rule);
1804 		uma_zfree(rctl_rule_link_zone, newlink);
1805 	}
1806 
1807 	goto again;
1808 }
1809 
1810 /*
1811  * Assign RCTL rules to the newly created process.
1812  */
1813 int
1814 rctl_proc_fork(struct proc *parent, struct proc *child)
1815 {
1816 	int error;
1817 	struct rctl_rule_link *link;
1818 	struct rctl_rule *rule;
1819 
1820 	LIST_INIT(&child->p_racct->r_rule_links);
1821 
1822 	ASSERT_RACCT_ENABLED();
1823 	KASSERT(parent->p_racct != NULL, ("process without racct; p = %p", parent));
1824 
1825 	rw_wlock(&rctl_lock);
1826 
1827 	/*
1828 	 * Go through limits applicable to the parent and assign them
1829 	 * to the child.  Rules with 'process' subject have to be duplicated
1830 	 * in order to make their rr_subject point to the new process.
1831 	 */
1832 	LIST_FOREACH(link, &parent->p_racct->r_rule_links, rrl_next) {
1833 		if (link->rrl_rule->rr_subject_type ==
1834 		    RCTL_SUBJECT_TYPE_PROCESS) {
1835 			rule = rctl_rule_duplicate(link->rrl_rule, M_NOWAIT);
1836 			if (rule == NULL)
1837 				goto fail;
1838 			KASSERT(rule->rr_subject.rs_proc == parent,
1839 			    ("rule->rr_subject.rs_proc != parent"));
1840 			rule->rr_subject.rs_proc = child;
1841 			error = rctl_racct_add_rule_locked(child->p_racct,
1842 			    rule);
1843 			rctl_rule_release(rule);
1844 			if (error != 0)
1845 				goto fail;
1846 		} else {
1847 			error = rctl_racct_add_rule_locked(child->p_racct,
1848 			    link->rrl_rule);
1849 			if (error != 0)
1850 				goto fail;
1851 		}
1852 	}
1853 
1854 	rw_wunlock(&rctl_lock);
1855 	return (0);
1856 
1857 fail:
1858 	while (!LIST_EMPTY(&child->p_racct->r_rule_links)) {
1859 		link = LIST_FIRST(&child->p_racct->r_rule_links);
1860 		LIST_REMOVE(link, rrl_next);
1861 		rctl_rule_release(link->rrl_rule);
1862 		uma_zfree(rctl_rule_link_zone, link);
1863 	}
1864 	rw_wunlock(&rctl_lock);
1865 	return (EAGAIN);
1866 }
1867 
1868 /*
1869  * Release rules attached to the racct.
1870  */
1871 void
1872 rctl_racct_release(struct racct *racct)
1873 {
1874 	struct rctl_rule_link *link;
1875 
1876 	ASSERT_RACCT_ENABLED();
1877 
1878 	rw_wlock(&rctl_lock);
1879 	while (!LIST_EMPTY(&racct->r_rule_links)) {
1880 		link = LIST_FIRST(&racct->r_rule_links);
1881 		LIST_REMOVE(link, rrl_next);
1882 		rctl_rule_release(link->rrl_rule);
1883 		uma_zfree(rctl_rule_link_zone, link);
1884 	}
1885 	rw_wunlock(&rctl_lock);
1886 }
1887 
1888 static void
1889 rctl_init(void)
1890 {
1891 
1892 	if (!racct_enable)
1893 		return;
1894 
1895 	rctl_rule_link_zone = uma_zcreate("rctl_rule_link",
1896 	    sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL,
1897 	    UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
1898 	rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule),
1899 	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
1900 }
1901 
1902 #else /* !RCTL */
1903 
1904 int
1905 sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap)
1906 {
1907 
1908 	return (ENOSYS);
1909 }
1910 
1911 int
1912 sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap)
1913 {
1914 
1915 	return (ENOSYS);
1916 }
1917 
1918 int
1919 sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap)
1920 {
1921 
1922 	return (ENOSYS);
1923 }
1924 
1925 int
1926 sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap)
1927 {
1928 
1929 	return (ENOSYS);
1930 }
1931 
1932 int
1933 sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap)
1934 {
1935 
1936 	return (ENOSYS);
1937 }
1938 
1939 #endif /* !RCTL */
1940