1ec125fbbSEdward Tomasz Napierala /*- 2ec125fbbSEdward Tomasz Napierala * Copyright (c) 2010 The FreeBSD Foundation 3ec125fbbSEdward Tomasz Napierala * All rights reserved. 4ec125fbbSEdward Tomasz Napierala * 5ec125fbbSEdward Tomasz Napierala * This software was developed by Edward Tomasz Napierala under sponsorship 6ec125fbbSEdward Tomasz Napierala * from the FreeBSD Foundation. 7ec125fbbSEdward Tomasz Napierala * 8ec125fbbSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 9ec125fbbSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 10ec125fbbSEdward Tomasz Napierala * are met: 11ec125fbbSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 12ec125fbbSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 13ec125fbbSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 14ec125fbbSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 15ec125fbbSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 16ec125fbbSEdward Tomasz Napierala * 17ec125fbbSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18ec125fbbSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19ec125fbbSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20ec125fbbSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21ec125fbbSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22ec125fbbSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23ec125fbbSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24ec125fbbSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25ec125fbbSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26ec125fbbSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27ec125fbbSEdward Tomasz Napierala * SUCH DAMAGE. 28ec125fbbSEdward Tomasz Napierala * 29ec125fbbSEdward Tomasz Napierala * $FreeBSD$ 30ec125fbbSEdward Tomasz Napierala */ 31ec125fbbSEdward Tomasz Napierala 32ec125fbbSEdward Tomasz Napierala #include <sys/cdefs.h> 33ec125fbbSEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 34ec125fbbSEdward Tomasz Napierala 35ec125fbbSEdward Tomasz Napierala #include <sys/param.h> 36ec125fbbSEdward Tomasz Napierala #include <sys/bus.h> 37ec125fbbSEdward Tomasz Napierala #include <sys/malloc.h> 38ec125fbbSEdward Tomasz Napierala #include <sys/queue.h> 39ec125fbbSEdward Tomasz Napierala #include <sys/refcount.h> 40ec125fbbSEdward Tomasz Napierala #include <sys/jail.h> 41ec125fbbSEdward Tomasz Napierala #include <sys/kernel.h> 42ec125fbbSEdward Tomasz Napierala #include <sys/limits.h> 43ec125fbbSEdward Tomasz Napierala #include <sys/loginclass.h> 44ec125fbbSEdward Tomasz Napierala #include <sys/priv.h> 45ec125fbbSEdward Tomasz Napierala #include <sys/proc.h> 46ec125fbbSEdward Tomasz Napierala #include <sys/racct.h> 47ec125fbbSEdward Tomasz Napierala #include <sys/rctl.h> 48ec125fbbSEdward Tomasz Napierala #include <sys/resourcevar.h> 49ec125fbbSEdward Tomasz Napierala #include <sys/sx.h> 50ec125fbbSEdward Tomasz Napierala #include <sys/sysent.h> 51ec125fbbSEdward Tomasz Napierala #include <sys/sysproto.h> 52ec125fbbSEdward Tomasz Napierala #include <sys/systm.h> 53ec125fbbSEdward Tomasz Napierala #include <sys/types.h> 54ec125fbbSEdward Tomasz Napierala #include <sys/eventhandler.h> 55ec125fbbSEdward Tomasz Napierala #include <sys/lock.h> 56ec125fbbSEdward Tomasz Napierala #include <sys/mutex.h> 57ec125fbbSEdward Tomasz Napierala #include <sys/rwlock.h> 58ec125fbbSEdward Tomasz Napierala #include <sys/sbuf.h> 59ec125fbbSEdward Tomasz Napierala #include <sys/taskqueue.h> 60ec125fbbSEdward Tomasz Napierala #include <sys/tree.h> 61ec125fbbSEdward Tomasz Napierala #include <vm/uma.h> 62ec125fbbSEdward Tomasz Napierala 63ec125fbbSEdward Tomasz Napierala #ifdef RCTL 64ec125fbbSEdward Tomasz Napierala #ifndef RACCT 65ec125fbbSEdward Tomasz Napierala #error "The RCTL option requires the RACCT option" 66ec125fbbSEdward Tomasz Napierala #endif 67ec125fbbSEdward Tomasz Napierala 68ec125fbbSEdward Tomasz Napierala FEATURE(rctl, "Resource Limits"); 69ec125fbbSEdward Tomasz Napierala 70ec125fbbSEdward Tomasz Napierala #define HRF_DEFAULT 0 71ec125fbbSEdward Tomasz Napierala #define HRF_DONT_INHERIT 1 72ec125fbbSEdward Tomasz Napierala #define HRF_DONT_ACCUMULATE 2 73ec125fbbSEdward Tomasz Napierala 74ea228b48SEdward Tomasz Napierala #define RCTL_MAX_INBUFSIZE 4 * 1024 75ea228b48SEdward Tomasz Napierala #define RCTL_MAX_OUTBUFSIZE 16 * 1024 * 1024 76ec125fbbSEdward Tomasz Napierala #define RCTL_LOG_BUFSIZE 128 77ec125fbbSEdward Tomasz Napierala 7836af9869SEdward Tomasz Napierala #define RCTL_PCPU_SHIFT (10 * 1000000) 7936af9869SEdward Tomasz Napierala 80*ae34b6ffSEdward Tomasz Napierala static unsigned int rctl_maxbufsize = RCTL_MAX_OUTBUFSIZE; 81f70c075eSEdward Tomasz Napierala static int rctl_log_rate_limit = 10; 82f70c075eSEdward Tomasz Napierala static int rctl_devctl_rate_limit = 10; 83*ae34b6ffSEdward Tomasz Napierala static unsigned int rctl_throttle_min = 0; 84*ae34b6ffSEdward Tomasz Napierala static unsigned int rctl_throttle_max = 0; 85*ae34b6ffSEdward Tomasz Napierala static unsigned int rctl_throttle_pct = 0; 86*ae34b6ffSEdward Tomasz Napierala static unsigned int rctl_throttle_pct2 = 0; 872b4035eeSEdward Tomasz Napierala 882b4035eeSEdward Tomasz Napierala SYSCTL_NODE(_kern_racct, OID_AUTO, rctl, CTLFLAG_RW, 0, "Resource Limits"); 892b4035eeSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, maxbufsize, CTLFLAG_RWTUN, 902b4035eeSEdward Tomasz Napierala &rctl_maxbufsize, 0, "Maximum output buffer size"); 91f70c075eSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, log_rate_limit, CTLFLAG_RW, 92f70c075eSEdward Tomasz Napierala &rctl_log_rate_limit, 0, "Maximum number of log messages per second"); 93f70c075eSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, devctl_rate_limit, CTLFLAG_RW, 94f70c075eSEdward Tomasz Napierala &rctl_devctl_rate_limit, 0, "Maximum number of devctl messages per second"); 95*ae34b6ffSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_min, CTLFLAG_RDTUN, 96*ae34b6ffSEdward Tomasz Napierala &rctl_throttle_min, 0, "Shortest throttling duration, in hz"); 97*ae34b6ffSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_max, CTLFLAG_RDTUN, 98*ae34b6ffSEdward Tomasz Napierala &rctl_throttle_max, 0, "Longest throttling duration, in hz"); 99*ae34b6ffSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_pct, CTLFLAG_RDTUN, 100*ae34b6ffSEdward Tomasz Napierala &rctl_throttle_pct, 0, 101*ae34b6ffSEdward Tomasz Napierala "Throttling penalty for process consumption, in percent"); 102*ae34b6ffSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_pct2, CTLFLAG_RDTUN, 103*ae34b6ffSEdward Tomasz Napierala &rctl_throttle_pct2, 0, 104*ae34b6ffSEdward Tomasz Napierala "Throttling penalty for container consumption, in percent"); 1052b4035eeSEdward Tomasz Napierala 106ec125fbbSEdward Tomasz Napierala /* 107ec125fbbSEdward Tomasz Napierala * 'rctl_rule_link' connects a rule with every racct it's related to. 108ec125fbbSEdward Tomasz Napierala * For example, rule 'user:X:openfiles:deny=N/process' is linked 109ec125fbbSEdward Tomasz Napierala * with uidinfo for user X, and to each process of that user. 110ec125fbbSEdward Tomasz Napierala */ 111ec125fbbSEdward Tomasz Napierala struct rctl_rule_link { 112ec125fbbSEdward Tomasz Napierala LIST_ENTRY(rctl_rule_link) rrl_next; 113ec125fbbSEdward Tomasz Napierala struct rctl_rule *rrl_rule; 114ec125fbbSEdward Tomasz Napierala int rrl_exceeded; 115ec125fbbSEdward Tomasz Napierala }; 116ec125fbbSEdward Tomasz Napierala 117ec125fbbSEdward Tomasz Napierala struct dict { 118ec125fbbSEdward Tomasz Napierala const char *d_name; 119ec125fbbSEdward Tomasz Napierala int d_value; 120ec125fbbSEdward Tomasz Napierala }; 121ec125fbbSEdward Tomasz Napierala 122ec125fbbSEdward Tomasz Napierala static struct dict subjectnames[] = { 123ec125fbbSEdward Tomasz Napierala { "process", RCTL_SUBJECT_TYPE_PROCESS }, 124ec125fbbSEdward Tomasz Napierala { "user", RCTL_SUBJECT_TYPE_USER }, 125ec125fbbSEdward Tomasz Napierala { "loginclass", RCTL_SUBJECT_TYPE_LOGINCLASS }, 126ec125fbbSEdward Tomasz Napierala { "jail", RCTL_SUBJECT_TYPE_JAIL }, 127ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 128ec125fbbSEdward Tomasz Napierala 129ec125fbbSEdward Tomasz Napierala static struct dict resourcenames[] = { 13085a2f1b4SEdward Tomasz Napierala { "cputime", RACCT_CPU }, 13185a2f1b4SEdward Tomasz Napierala { "datasize", RACCT_DATA }, 13285a2f1b4SEdward Tomasz Napierala { "stacksize", RACCT_STACK }, 13385a2f1b4SEdward Tomasz Napierala { "coredumpsize", RACCT_CORE }, 13485a2f1b4SEdward Tomasz Napierala { "memoryuse", RACCT_RSS }, 13585a2f1b4SEdward Tomasz Napierala { "memorylocked", RACCT_MEMLOCK }, 13685a2f1b4SEdward Tomasz Napierala { "maxproc", RACCT_NPROC }, 13785a2f1b4SEdward Tomasz Napierala { "openfiles", RACCT_NOFILE }, 13885a2f1b4SEdward Tomasz Napierala { "vmemoryuse", RACCT_VMEM }, 13985a2f1b4SEdward Tomasz Napierala { "pseudoterminals", RACCT_NPTS }, 14085a2f1b4SEdward Tomasz Napierala { "swapuse", RACCT_SWAP }, 141ec125fbbSEdward Tomasz Napierala { "nthr", RACCT_NTHR }, 142ec125fbbSEdward Tomasz Napierala { "msgqqueued", RACCT_MSGQQUEUED }, 143ec125fbbSEdward Tomasz Napierala { "msgqsize", RACCT_MSGQSIZE }, 144ec125fbbSEdward Tomasz Napierala { "nmsgq", RACCT_NMSGQ }, 145ec125fbbSEdward Tomasz Napierala { "nsem", RACCT_NSEM }, 146ec125fbbSEdward Tomasz Napierala { "nsemop", RACCT_NSEMOP }, 147ec125fbbSEdward Tomasz Napierala { "nshm", RACCT_NSHM }, 148ec125fbbSEdward Tomasz Napierala { "shmsize", RACCT_SHMSIZE }, 149ec125fbbSEdward Tomasz Napierala { "wallclock", RACCT_WALLCLOCK }, 15036af9869SEdward Tomasz Napierala { "pcpu", RACCT_PCTCPU }, 151*ae34b6ffSEdward Tomasz Napierala { "readbps", RACCT_READBPS }, 152*ae34b6ffSEdward Tomasz Napierala { "writebps", RACCT_WRITEBPS }, 153*ae34b6ffSEdward Tomasz Napierala { "readiops", RACCT_READIOPS }, 154*ae34b6ffSEdward Tomasz Napierala { "writeiops", RACCT_WRITEIOPS }, 155ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 156ec125fbbSEdward Tomasz Napierala 157ec125fbbSEdward Tomasz Napierala static struct dict actionnames[] = { 158ec125fbbSEdward Tomasz Napierala { "sighup", RCTL_ACTION_SIGHUP }, 159ec125fbbSEdward Tomasz Napierala { "sigint", RCTL_ACTION_SIGINT }, 160ec125fbbSEdward Tomasz Napierala { "sigquit", RCTL_ACTION_SIGQUIT }, 161ec125fbbSEdward Tomasz Napierala { "sigill", RCTL_ACTION_SIGILL }, 162ec125fbbSEdward Tomasz Napierala { "sigtrap", RCTL_ACTION_SIGTRAP }, 163ec125fbbSEdward Tomasz Napierala { "sigabrt", RCTL_ACTION_SIGABRT }, 164ec125fbbSEdward Tomasz Napierala { "sigemt", RCTL_ACTION_SIGEMT }, 165ec125fbbSEdward Tomasz Napierala { "sigfpe", RCTL_ACTION_SIGFPE }, 166ec125fbbSEdward Tomasz Napierala { "sigkill", RCTL_ACTION_SIGKILL }, 167ec125fbbSEdward Tomasz Napierala { "sigbus", RCTL_ACTION_SIGBUS }, 168ec125fbbSEdward Tomasz Napierala { "sigsegv", RCTL_ACTION_SIGSEGV }, 169ec125fbbSEdward Tomasz Napierala { "sigsys", RCTL_ACTION_SIGSYS }, 170ec125fbbSEdward Tomasz Napierala { "sigpipe", RCTL_ACTION_SIGPIPE }, 171ec125fbbSEdward Tomasz Napierala { "sigalrm", RCTL_ACTION_SIGALRM }, 172ec125fbbSEdward Tomasz Napierala { "sigterm", RCTL_ACTION_SIGTERM }, 173ec125fbbSEdward Tomasz Napierala { "sigurg", RCTL_ACTION_SIGURG }, 174ec125fbbSEdward Tomasz Napierala { "sigstop", RCTL_ACTION_SIGSTOP }, 175ec125fbbSEdward Tomasz Napierala { "sigtstp", RCTL_ACTION_SIGTSTP }, 176ec125fbbSEdward Tomasz Napierala { "sigchld", RCTL_ACTION_SIGCHLD }, 177ec125fbbSEdward Tomasz Napierala { "sigttin", RCTL_ACTION_SIGTTIN }, 178ec125fbbSEdward Tomasz Napierala { "sigttou", RCTL_ACTION_SIGTTOU }, 179ec125fbbSEdward Tomasz Napierala { "sigio", RCTL_ACTION_SIGIO }, 180ec125fbbSEdward Tomasz Napierala { "sigxcpu", RCTL_ACTION_SIGXCPU }, 181ec125fbbSEdward Tomasz Napierala { "sigxfsz", RCTL_ACTION_SIGXFSZ }, 182ec125fbbSEdward Tomasz Napierala { "sigvtalrm", RCTL_ACTION_SIGVTALRM }, 183ec125fbbSEdward Tomasz Napierala { "sigprof", RCTL_ACTION_SIGPROF }, 184ec125fbbSEdward Tomasz Napierala { "sigwinch", RCTL_ACTION_SIGWINCH }, 185ec125fbbSEdward Tomasz Napierala { "siginfo", RCTL_ACTION_SIGINFO }, 186ec125fbbSEdward Tomasz Napierala { "sigusr1", RCTL_ACTION_SIGUSR1 }, 187ec125fbbSEdward Tomasz Napierala { "sigusr2", RCTL_ACTION_SIGUSR2 }, 188ec125fbbSEdward Tomasz Napierala { "sigthr", RCTL_ACTION_SIGTHR }, 189ec125fbbSEdward Tomasz Napierala { "deny", RCTL_ACTION_DENY }, 190ec125fbbSEdward Tomasz Napierala { "log", RCTL_ACTION_LOG }, 191ec125fbbSEdward Tomasz Napierala { "devctl", RCTL_ACTION_DEVCTL }, 192*ae34b6ffSEdward Tomasz Napierala { "throttle", RCTL_ACTION_THROTTLE }, 193ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 194ec125fbbSEdward Tomasz Napierala 195ec125fbbSEdward Tomasz Napierala static void rctl_init(void); 196ec125fbbSEdward Tomasz Napierala SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL); 197ec125fbbSEdward Tomasz Napierala 198ec125fbbSEdward Tomasz Napierala static uma_zone_t rctl_rule_link_zone; 199ec125fbbSEdward Tomasz Napierala static uma_zone_t rctl_rule_zone; 200ec125fbbSEdward Tomasz Napierala static struct rwlock rctl_lock; 201ec125fbbSEdward Tomasz Napierala RW_SYSINIT(rctl_lock, &rctl_lock, "RCTL lock"); 202ec125fbbSEdward Tomasz Napierala 2034c230cdaSEdward Tomasz Napierala #define RCTL_RLOCK() rw_rlock(&rctl_lock) 2044c230cdaSEdward Tomasz Napierala #define RCTL_RUNLOCK() rw_runlock(&rctl_lock) 2054c230cdaSEdward Tomasz Napierala #define RCTL_WLOCK() rw_wlock(&rctl_lock) 2064c230cdaSEdward Tomasz Napierala #define RCTL_WUNLOCK() rw_wunlock(&rctl_lock) 2074c230cdaSEdward Tomasz Napierala #define RCTL_LOCK_ASSERT() rw_assert(&rctl_lock, RA_LOCKED) 2084c230cdaSEdward Tomasz Napierala #define RCTL_WLOCK_ASSERT() rw_assert(&rctl_lock, RA_WLOCKED) 2094c230cdaSEdward Tomasz Napierala 210ec125fbbSEdward Tomasz Napierala static int rctl_rule_fully_specified(const struct rctl_rule *rule); 211ec125fbbSEdward Tomasz Napierala static void rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule); 212ec125fbbSEdward Tomasz Napierala 213d745c852SEd Schouten static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits"); 214ec125fbbSEdward Tomasz Napierala 215ec125fbbSEdward Tomasz Napierala static const char * 216ec125fbbSEdward Tomasz Napierala rctl_subject_type_name(int subject) 217ec125fbbSEdward Tomasz Napierala { 218ec125fbbSEdward Tomasz Napierala int i; 219ec125fbbSEdward Tomasz Napierala 220ec125fbbSEdward Tomasz Napierala for (i = 0; subjectnames[i].d_name != NULL; i++) { 221ec125fbbSEdward Tomasz Napierala if (subjectnames[i].d_value == subject) 222ec125fbbSEdward Tomasz Napierala return (subjectnames[i].d_name); 223ec125fbbSEdward Tomasz Napierala } 224ec125fbbSEdward Tomasz Napierala 225ec125fbbSEdward Tomasz Napierala panic("rctl_subject_type_name: unknown subject type %d", subject); 226ec125fbbSEdward Tomasz Napierala } 227ec125fbbSEdward Tomasz Napierala 228ec125fbbSEdward Tomasz Napierala static const char * 229ec125fbbSEdward Tomasz Napierala rctl_action_name(int action) 230ec125fbbSEdward Tomasz Napierala { 231ec125fbbSEdward Tomasz Napierala int i; 232ec125fbbSEdward Tomasz Napierala 233ec125fbbSEdward Tomasz Napierala for (i = 0; actionnames[i].d_name != NULL; i++) { 234ec125fbbSEdward Tomasz Napierala if (actionnames[i].d_value == action) 235ec125fbbSEdward Tomasz Napierala return (actionnames[i].d_name); 236ec125fbbSEdward Tomasz Napierala } 237ec125fbbSEdward Tomasz Napierala 238ec125fbbSEdward Tomasz Napierala panic("rctl_action_name: unknown action %d", action); 239ec125fbbSEdward Tomasz Napierala } 240ec125fbbSEdward Tomasz Napierala 241ec125fbbSEdward Tomasz Napierala const char * 242ec125fbbSEdward Tomasz Napierala rctl_resource_name(int resource) 243ec125fbbSEdward Tomasz Napierala { 244ec125fbbSEdward Tomasz Napierala int i; 245ec125fbbSEdward Tomasz Napierala 246ec125fbbSEdward Tomasz Napierala for (i = 0; resourcenames[i].d_name != NULL; i++) { 247ec125fbbSEdward Tomasz Napierala if (resourcenames[i].d_value == resource) 248ec125fbbSEdward Tomasz Napierala return (resourcenames[i].d_name); 249ec125fbbSEdward Tomasz Napierala } 250ec125fbbSEdward Tomasz Napierala 251ec125fbbSEdward Tomasz Napierala panic("rctl_resource_name: unknown resource %d", resource); 252ec125fbbSEdward Tomasz Napierala } 253ec125fbbSEdward Tomasz Napierala 254ac3c9819SEdward Tomasz Napierala static struct racct * 255ac3c9819SEdward Tomasz Napierala rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule) 256ac3c9819SEdward Tomasz Napierala { 257ac3c9819SEdward Tomasz Napierala struct ucred *cred = p->p_ucred; 258ac3c9819SEdward Tomasz Napierala 259ac3c9819SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 2604c230cdaSEdward Tomasz Napierala RCTL_LOCK_ASSERT(); 261ac3c9819SEdward Tomasz Napierala 262ac3c9819SEdward Tomasz Napierala switch (rule->rr_per) { 263ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 264ac3c9819SEdward Tomasz Napierala return (p->p_racct); 265ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 266ac3c9819SEdward Tomasz Napierala return (cred->cr_ruidinfo->ui_racct); 267ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 268ac3c9819SEdward Tomasz Napierala return (cred->cr_loginclass->lc_racct); 269ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 270ac3c9819SEdward Tomasz Napierala return (cred->cr_prison->pr_prison_racct->prr_racct); 271ac3c9819SEdward Tomasz Napierala default: 272ac3c9819SEdward Tomasz Napierala panic("%s: unknown per %d", __func__, rule->rr_per); 273ac3c9819SEdward Tomasz Napierala } 274ac3c9819SEdward Tomasz Napierala } 275ac3c9819SEdward Tomasz Napierala 276ec125fbbSEdward Tomasz Napierala /* 277ec125fbbSEdward Tomasz Napierala * Return the amount of resource that can be allocated by 'p' before 278ec125fbbSEdward Tomasz Napierala * hitting 'rule'. 279ec125fbbSEdward Tomasz Napierala */ 280ec125fbbSEdward Tomasz Napierala static int64_t 281ec125fbbSEdward Tomasz Napierala rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) 282ec125fbbSEdward Tomasz Napierala { 283ac3c9819SEdward Tomasz Napierala int64_t available; 284ac3c9819SEdward Tomasz Napierala const struct racct *racct; 285ec125fbbSEdward Tomasz Napierala 2864b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 2874c230cdaSEdward Tomasz Napierala RCTL_LOCK_ASSERT(); 288ec125fbbSEdward Tomasz Napierala 289ac3c9819SEdward Tomasz Napierala racct = rctl_proc_rule_to_racct(p, rule); 290ac3c9819SEdward Tomasz Napierala available = rule->rr_amount - racct->r_resources[rule->rr_resource]; 291ec125fbbSEdward Tomasz Napierala 292ec125fbbSEdward Tomasz Napierala return (available); 293ec125fbbSEdward Tomasz Napierala } 294ec125fbbSEdward Tomasz Napierala 295ec125fbbSEdward Tomasz Napierala /* 296*ae34b6ffSEdward Tomasz Napierala * Called every second for proc, uidinfo, loginclass, and jail containers. 297*ae34b6ffSEdward Tomasz Napierala * If the limit isn't exceeded, it decreases the usage amount to zero. 298*ae34b6ffSEdward Tomasz Napierala * Otherwise, it decreases it by the value of the limit. This way 299*ae34b6ffSEdward Tomasz Napierala * resource consumption exceeding the limit "carries over" to the next 300*ae34b6ffSEdward Tomasz Napierala * period. 301ec125fbbSEdward Tomasz Napierala */ 302*ae34b6ffSEdward Tomasz Napierala void 303*ae34b6ffSEdward Tomasz Napierala rctl_throttle_decay(struct racct *racct, int resource) 304ec125fbbSEdward Tomasz Napierala { 305*ae34b6ffSEdward Tomasz Napierala struct rctl_rule *rule; 306*ae34b6ffSEdward Tomasz Napierala struct rctl_rule_link *link; 307*ae34b6ffSEdward Tomasz Napierala int64_t minavailable; 308ec125fbbSEdward Tomasz Napierala 3094b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 310ec125fbbSEdward Tomasz Napierala 311*ae34b6ffSEdward Tomasz Napierala minavailable = INT64_MAX; 312ec125fbbSEdward Tomasz Napierala 313*ae34b6ffSEdward Tomasz Napierala RCTL_RLOCK(); 314*ae34b6ffSEdward Tomasz Napierala 315*ae34b6ffSEdward Tomasz Napierala LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { 316*ae34b6ffSEdward Tomasz Napierala rule = link->rrl_rule; 317*ae34b6ffSEdward Tomasz Napierala 318*ae34b6ffSEdward Tomasz Napierala if (rule->rr_resource != resource) 319*ae34b6ffSEdward Tomasz Napierala continue; 320*ae34b6ffSEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_THROTTLE) 321*ae34b6ffSEdward Tomasz Napierala continue; 322*ae34b6ffSEdward Tomasz Napierala 323*ae34b6ffSEdward Tomasz Napierala if (rule->rr_amount < minavailable) 324*ae34b6ffSEdward Tomasz Napierala minavailable = rule->rr_amount; 325*ae34b6ffSEdward Tomasz Napierala } 326*ae34b6ffSEdward Tomasz Napierala 327*ae34b6ffSEdward Tomasz Napierala RCTL_RUNLOCK(); 328*ae34b6ffSEdward Tomasz Napierala 329*ae34b6ffSEdward Tomasz Napierala if (racct->r_resources[resource] < minavailable) { 330*ae34b6ffSEdward Tomasz Napierala racct->r_resources[resource] = 0; 331*ae34b6ffSEdward Tomasz Napierala } else { 332*ae34b6ffSEdward Tomasz Napierala /* 333*ae34b6ffSEdward Tomasz Napierala * Cap utilization counter at ten times the limit. Otherwise, 334*ae34b6ffSEdward Tomasz Napierala * if we changed the rule lowering the allowed amount, it could 335*ae34b6ffSEdward Tomasz Napierala * take unreasonably long time for the accumulated resource 336*ae34b6ffSEdward Tomasz Napierala * usage to drop. 337*ae34b6ffSEdward Tomasz Napierala */ 338*ae34b6ffSEdward Tomasz Napierala if (racct->r_resources[resource] > minavailable * 10) 339*ae34b6ffSEdward Tomasz Napierala racct->r_resources[resource] = minavailable * 10; 340*ae34b6ffSEdward Tomasz Napierala 341*ae34b6ffSEdward Tomasz Napierala racct->r_resources[resource] -= minavailable; 342*ae34b6ffSEdward Tomasz Napierala } 343ec125fbbSEdward Tomasz Napierala } 344ec125fbbSEdward Tomasz Napierala 345ec125fbbSEdward Tomasz Napierala /* 346af1a7b25SEdward Tomasz Napierala * Special version of rctl_get_available() for the %CPU resource. 34736af9869SEdward Tomasz Napierala * We slightly cheat here and return less than we normally would. 34836af9869SEdward Tomasz Napierala */ 34936af9869SEdward Tomasz Napierala int64_t 35036af9869SEdward Tomasz Napierala rctl_pcpu_available(const struct proc *p) { 35136af9869SEdward Tomasz Napierala struct rctl_rule *rule; 35236af9869SEdward Tomasz Napierala struct rctl_rule_link *link; 35336af9869SEdward Tomasz Napierala int64_t available, minavailable, limit; 35436af9869SEdward Tomasz Napierala 3554b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 3564b5c9cf6SEdward Tomasz Napierala 35736af9869SEdward Tomasz Napierala minavailable = INT64_MAX; 35836af9869SEdward Tomasz Napierala limit = 0; 35936af9869SEdward Tomasz Napierala 3604c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 36136af9869SEdward Tomasz Napierala 36236af9869SEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 36336af9869SEdward Tomasz Napierala rule = link->rrl_rule; 36436af9869SEdward Tomasz Napierala if (rule->rr_resource != RACCT_PCTCPU) 36536af9869SEdward Tomasz Napierala continue; 36636af9869SEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 36736af9869SEdward Tomasz Napierala continue; 36836af9869SEdward Tomasz Napierala available = rctl_available_resource(p, rule); 36936af9869SEdward Tomasz Napierala if (available < minavailable) { 37036af9869SEdward Tomasz Napierala minavailable = available; 37136af9869SEdward Tomasz Napierala limit = rule->rr_amount; 37236af9869SEdward Tomasz Napierala } 37336af9869SEdward Tomasz Napierala } 37436af9869SEdward Tomasz Napierala 3754c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 37636af9869SEdward Tomasz Napierala 37736af9869SEdward Tomasz Napierala /* 37836af9869SEdward Tomasz Napierala * Return slightly less than actual value of the available 37936af9869SEdward Tomasz Napierala * %cpu resource. This makes %cpu throttling more agressive 38036af9869SEdward Tomasz Napierala * and lets us act sooner than the limits are already exceeded. 38136af9869SEdward Tomasz Napierala */ 38236af9869SEdward Tomasz Napierala if (limit != 0) { 38336af9869SEdward Tomasz Napierala if (limit > 2 * RCTL_PCPU_SHIFT) 38436af9869SEdward Tomasz Napierala minavailable -= RCTL_PCPU_SHIFT; 38536af9869SEdward Tomasz Napierala else 38636af9869SEdward Tomasz Napierala minavailable -= (limit / 2); 38736af9869SEdward Tomasz Napierala } 38836af9869SEdward Tomasz Napierala 38936af9869SEdward Tomasz Napierala return (minavailable); 39036af9869SEdward Tomasz Napierala } 39136af9869SEdward Tomasz Napierala 392*ae34b6ffSEdward Tomasz Napierala static uint64_t 393*ae34b6ffSEdward Tomasz Napierala xadd(uint64_t a, uint64_t b) 394*ae34b6ffSEdward Tomasz Napierala { 395*ae34b6ffSEdward Tomasz Napierala uint64_t c; 396*ae34b6ffSEdward Tomasz Napierala 397*ae34b6ffSEdward Tomasz Napierala c = a + b; 398*ae34b6ffSEdward Tomasz Napierala 399*ae34b6ffSEdward Tomasz Napierala /* 400*ae34b6ffSEdward Tomasz Napierala * Detect overflow. 401*ae34b6ffSEdward Tomasz Napierala */ 402*ae34b6ffSEdward Tomasz Napierala if (c < a || c < b) 403*ae34b6ffSEdward Tomasz Napierala return (UINT64_MAX); 404*ae34b6ffSEdward Tomasz Napierala 405*ae34b6ffSEdward Tomasz Napierala return (c); 406*ae34b6ffSEdward Tomasz Napierala } 407*ae34b6ffSEdward Tomasz Napierala 408*ae34b6ffSEdward Tomasz Napierala static uint64_t 409*ae34b6ffSEdward Tomasz Napierala xmul(uint64_t a, uint64_t b) 410*ae34b6ffSEdward Tomasz Napierala { 411*ae34b6ffSEdward Tomasz Napierala uint64_t c; 412*ae34b6ffSEdward Tomasz Napierala 413*ae34b6ffSEdward Tomasz Napierala if (a == 0 || b == 0) 414*ae34b6ffSEdward Tomasz Napierala return (0); 415*ae34b6ffSEdward Tomasz Napierala 416*ae34b6ffSEdward Tomasz Napierala c = a * b; 417*ae34b6ffSEdward Tomasz Napierala 418*ae34b6ffSEdward Tomasz Napierala if (c < a || c < b) 419*ae34b6ffSEdward Tomasz Napierala return (UINT64_MAX); 420*ae34b6ffSEdward Tomasz Napierala 421*ae34b6ffSEdward Tomasz Napierala return (c); 422*ae34b6ffSEdward Tomasz Napierala } 423*ae34b6ffSEdward Tomasz Napierala 42436af9869SEdward Tomasz Napierala /* 425ec125fbbSEdward Tomasz Napierala * Check whether the proc 'p' can allocate 'amount' of 'resource' in addition 426ec125fbbSEdward Tomasz Napierala * to what it keeps allocated now. Returns non-zero if the allocation should 427ec125fbbSEdward Tomasz Napierala * be denied, 0 otherwise. 428ec125fbbSEdward Tomasz Napierala */ 429ec125fbbSEdward Tomasz Napierala int 430ec125fbbSEdward Tomasz Napierala rctl_enforce(struct proc *p, int resource, uint64_t amount) 431ec125fbbSEdward Tomasz Napierala { 432f70c075eSEdward Tomasz Napierala static struct timeval log_lasttime, devctl_lasttime; 433f70c075eSEdward Tomasz Napierala static int log_curtime = 0, devctl_curtime = 0; 434ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 435ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 436ec125fbbSEdward Tomasz Napierala struct sbuf sb; 437*ae34b6ffSEdward Tomasz Napierala int64_t available; 438*ae34b6ffSEdward Tomasz Napierala uint64_t sleep_ms, sleep_ratio; 439ec125fbbSEdward Tomasz Napierala int should_deny = 0; 440ec125fbbSEdward Tomasz Napierala char *buf; 441ec125fbbSEdward Tomasz Napierala 442*ae34b6ffSEdward Tomasz Napierala 4434b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 4444b5c9cf6SEdward Tomasz Napierala 4454c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 446ec125fbbSEdward Tomasz Napierala 447ec125fbbSEdward Tomasz Napierala /* 448ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 449ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 450ec125fbbSEdward Tomasz Napierala */ 451ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 452ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 453ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 454ec125fbbSEdward Tomasz Napierala continue; 455*ae34b6ffSEdward Tomasz Napierala 456*ae34b6ffSEdward Tomasz Napierala available = rctl_available_resource(p, rule); 457*ae34b6ffSEdward Tomasz Napierala if (available >= (int64_t)amount) { 458ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 459ec125fbbSEdward Tomasz Napierala continue; 460ec125fbbSEdward Tomasz Napierala } 461ec125fbbSEdward Tomasz Napierala 462ec125fbbSEdward Tomasz Napierala switch (rule->rr_action) { 463ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_DENY: 464ec125fbbSEdward Tomasz Napierala should_deny = 1; 465ec125fbbSEdward Tomasz Napierala continue; 466ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_LOG: 467ec125fbbSEdward Tomasz Napierala /* 468ec125fbbSEdward Tomasz Napierala * If rrl_exceeded != 0, it means we've already 469ec125fbbSEdward Tomasz Napierala * logged a warning for this process. 470ec125fbbSEdward Tomasz Napierala */ 471ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 472ec125fbbSEdward Tomasz Napierala continue; 473ec125fbbSEdward Tomasz Napierala 47472a401d9SEdward Tomasz Napierala /* 47572a401d9SEdward Tomasz Napierala * If the process state is not fully initialized yet, 47672a401d9SEdward Tomasz Napierala * we can't access most of the required fields, e.g. 47772a401d9SEdward Tomasz Napierala * p->p_comm. This happens when called from fork1(). 47872a401d9SEdward Tomasz Napierala * Ignore this rule for now; it will be processed just 47972a401d9SEdward Tomasz Napierala * after fork, when called from racct_proc_fork_done(). 48072a401d9SEdward Tomasz Napierala */ 48172a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 48272a401d9SEdward Tomasz Napierala continue; 48372a401d9SEdward Tomasz Napierala 484f70c075eSEdward Tomasz Napierala if (!ppsratecheck(&log_lasttime, &log_curtime, 485f70c075eSEdward Tomasz Napierala rctl_log_rate_limit)) 486ec125fbbSEdward Tomasz Napierala continue; 487ec125fbbSEdward Tomasz Napierala 488ec125fbbSEdward Tomasz Napierala buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); 489ec125fbbSEdward Tomasz Napierala if (buf == NULL) { 490ec125fbbSEdward Tomasz Napierala printf("rctl_enforce: out of memory\n"); 491ec125fbbSEdward Tomasz Napierala continue; 492ec125fbbSEdward Tomasz Napierala } 493ec125fbbSEdward Tomasz Napierala sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); 494ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(&sb, rule); 495ec125fbbSEdward Tomasz Napierala sbuf_finish(&sb); 496ec125fbbSEdward Tomasz Napierala printf("rctl: rule \"%s\" matched by pid %d " 497ec125fbbSEdward Tomasz Napierala "(%s), uid %d, jail %s\n", sbuf_data(&sb), 498ec125fbbSEdward Tomasz Napierala p->p_pid, p->p_comm, p->p_ucred->cr_uid, 499a7ad07bfSEdward Tomasz Napierala p->p_ucred->cr_prison->pr_prison_racct->prr_name); 500ec125fbbSEdward Tomasz Napierala sbuf_delete(&sb); 501ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 502ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 503ec125fbbSEdward Tomasz Napierala continue; 504ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_DEVCTL: 505ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 506ec125fbbSEdward Tomasz Napierala continue; 507ec125fbbSEdward Tomasz Napierala 50872a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 50972a401d9SEdward Tomasz Napierala continue; 51072a401d9SEdward Tomasz Napierala 511f70c075eSEdward Tomasz Napierala if (!ppsratecheck(&devctl_lasttime, &devctl_curtime, 512f70c075eSEdward Tomasz Napierala rctl_devctl_rate_limit)) 513f70c075eSEdward Tomasz Napierala continue; 514f70c075eSEdward Tomasz Napierala 515ec125fbbSEdward Tomasz Napierala buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); 516ec125fbbSEdward Tomasz Napierala if (buf == NULL) { 517ec125fbbSEdward Tomasz Napierala printf("rctl_enforce: out of memory\n"); 518ec125fbbSEdward Tomasz Napierala continue; 519ec125fbbSEdward Tomasz Napierala } 520ec125fbbSEdward Tomasz Napierala sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); 521ec125fbbSEdward Tomasz Napierala sbuf_printf(&sb, "rule="); 522ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(&sb, rule); 523ec125fbbSEdward Tomasz Napierala sbuf_printf(&sb, " pid=%d ruid=%d jail=%s", 524ec125fbbSEdward Tomasz Napierala p->p_pid, p->p_ucred->cr_ruid, 525a7ad07bfSEdward Tomasz Napierala p->p_ucred->cr_prison->pr_prison_racct->prr_name); 526ec125fbbSEdward Tomasz Napierala sbuf_finish(&sb); 527ec125fbbSEdward Tomasz Napierala devctl_notify_f("RCTL", "rule", "matched", 528ec125fbbSEdward Tomasz Napierala sbuf_data(&sb), M_NOWAIT); 529ec125fbbSEdward Tomasz Napierala sbuf_delete(&sb); 530ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 531ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 532ec125fbbSEdward Tomasz Napierala continue; 533*ae34b6ffSEdward Tomasz Napierala case RCTL_ACTION_THROTTLE: 534*ae34b6ffSEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 535*ae34b6ffSEdward Tomasz Napierala continue; 536*ae34b6ffSEdward Tomasz Napierala 537*ae34b6ffSEdward Tomasz Napierala /* 538*ae34b6ffSEdward Tomasz Napierala * Make the process sleep for a fraction of second 539*ae34b6ffSEdward Tomasz Napierala * proportional to the ratio of process' resource 540*ae34b6ffSEdward Tomasz Napierala * utilization compared to the limit. The point is 541*ae34b6ffSEdward Tomasz Napierala * to penalize resource hogs: processes that consume 542*ae34b6ffSEdward Tomasz Napierala * more of the available resources sleep for longer. 543*ae34b6ffSEdward Tomasz Napierala * 544*ae34b6ffSEdward Tomasz Napierala * We're trying to defer division until the very end, 545*ae34b6ffSEdward Tomasz Napierala * to minimize the rounding effects. The following 546*ae34b6ffSEdward Tomasz Napierala * calculation could have been written in a clearer 547*ae34b6ffSEdward Tomasz Napierala * way like this: 548*ae34b6ffSEdward Tomasz Napierala * 549*ae34b6ffSEdward Tomasz Napierala * sleep_ms = hz * p->p_racct->r_resources[resource] / 550*ae34b6ffSEdward Tomasz Napierala * rule->rr_amount; 551*ae34b6ffSEdward Tomasz Napierala * sleep_ms *= rctl_throttle_pct / 100; 552*ae34b6ffSEdward Tomasz Napierala * if (sleep_ms < rctl_throttle_min) 553*ae34b6ffSEdward Tomasz Napierala * sleep_ms = rctl_throttle_min; 554*ae34b6ffSEdward Tomasz Napierala * 555*ae34b6ffSEdward Tomasz Napierala */ 556*ae34b6ffSEdward Tomasz Napierala sleep_ms = xmul(hz, p->p_racct->r_resources[resource]); 557*ae34b6ffSEdward Tomasz Napierala sleep_ms = xmul(sleep_ms, rctl_throttle_pct) / 100; 558*ae34b6ffSEdward Tomasz Napierala if (sleep_ms < rctl_throttle_min * rule->rr_amount) 559*ae34b6ffSEdward Tomasz Napierala sleep_ms = rctl_throttle_min * rule->rr_amount; 560*ae34b6ffSEdward Tomasz Napierala 561*ae34b6ffSEdward Tomasz Napierala /* 562*ae34b6ffSEdward Tomasz Napierala * Multiply that by the ratio of the resource 563*ae34b6ffSEdward Tomasz Napierala * consumption for the container compared to the limit, 564*ae34b6ffSEdward Tomasz Napierala * squared. In other words, a process in a container 565*ae34b6ffSEdward Tomasz Napierala * that is two times over the limit will be throttled 566*ae34b6ffSEdward Tomasz Napierala * four times as much for hitting the same rule. The 567*ae34b6ffSEdward Tomasz Napierala * point is to penalize processes more if the container 568*ae34b6ffSEdward Tomasz Napierala * itself (eg certain UID or jail) is above the limit. 569*ae34b6ffSEdward Tomasz Napierala */ 570*ae34b6ffSEdward Tomasz Napierala if (available < 0) 571*ae34b6ffSEdward Tomasz Napierala sleep_ratio = -available / rule->rr_amount; 572*ae34b6ffSEdward Tomasz Napierala else 573*ae34b6ffSEdward Tomasz Napierala sleep_ratio = 0; 574*ae34b6ffSEdward Tomasz Napierala sleep_ratio = xmul(sleep_ratio, sleep_ratio); 575*ae34b6ffSEdward Tomasz Napierala sleep_ratio = xmul(sleep_ratio, rctl_throttle_pct2) / 100; 576*ae34b6ffSEdward Tomasz Napierala sleep_ms = xadd(sleep_ms, xmul(sleep_ms, sleep_ratio)); 577*ae34b6ffSEdward Tomasz Napierala 578*ae34b6ffSEdward Tomasz Napierala /* 579*ae34b6ffSEdward Tomasz Napierala * Finally the division. 580*ae34b6ffSEdward Tomasz Napierala */ 581*ae34b6ffSEdward Tomasz Napierala sleep_ms /= rule->rr_amount; 582*ae34b6ffSEdward Tomasz Napierala 583*ae34b6ffSEdward Tomasz Napierala if (sleep_ms > rctl_throttle_max) 584*ae34b6ffSEdward Tomasz Napierala sleep_ms = rctl_throttle_max; 585*ae34b6ffSEdward Tomasz Napierala #if 0 586*ae34b6ffSEdward Tomasz Napierala printf("%s: pid %d (%s), %jd of %jd, will sleep for %ld ms (ratio %ld, available %ld)\n", 587*ae34b6ffSEdward Tomasz Napierala __func__, p->p_pid, p->p_comm, 588*ae34b6ffSEdward Tomasz Napierala p->p_racct->r_resources[resource], 589*ae34b6ffSEdward Tomasz Napierala rule->rr_amount, sleep_ms, sleep_ratio, available); 590*ae34b6ffSEdward Tomasz Napierala #endif 591*ae34b6ffSEdward Tomasz Napierala 592*ae34b6ffSEdward Tomasz Napierala KASSERT(sleep_ms >= rctl_throttle_min, ("%s: %ju < %d\n", 593*ae34b6ffSEdward Tomasz Napierala __func__, (uintmax_t)sleep_ms, rctl_throttle_min)); 594*ae34b6ffSEdward Tomasz Napierala racct_proc_throttle(p, sleep_ms); 595*ae34b6ffSEdward Tomasz Napierala continue; 596ec125fbbSEdward Tomasz Napierala default: 597ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 598ec125fbbSEdward Tomasz Napierala continue; 599ec125fbbSEdward Tomasz Napierala 60072a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 60172a401d9SEdward Tomasz Napierala continue; 60272a401d9SEdward Tomasz Napierala 603ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_action > 0 && 604ec125fbbSEdward Tomasz Napierala rule->rr_action <= RCTL_ACTION_SIGNAL_MAX, 605ec125fbbSEdward Tomasz Napierala ("rctl_enforce: unknown action %d", 606ec125fbbSEdward Tomasz Napierala rule->rr_action)); 607ec125fbbSEdward Tomasz Napierala 608ec125fbbSEdward Tomasz Napierala /* 609ec125fbbSEdward Tomasz Napierala * We're using the fact that RCTL_ACTION_SIG* values 610ec125fbbSEdward Tomasz Napierala * are equal to their counterparts from sys/signal.h. 611ec125fbbSEdward Tomasz Napierala */ 6128451d0ddSKip Macy kern_psignal(p, rule->rr_action); 613ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 614ec125fbbSEdward Tomasz Napierala continue; 615ec125fbbSEdward Tomasz Napierala } 616ec125fbbSEdward Tomasz Napierala } 617ec125fbbSEdward Tomasz Napierala 6184c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 619ec125fbbSEdward Tomasz Napierala 620ec125fbbSEdward Tomasz Napierala if (should_deny) { 621ec125fbbSEdward Tomasz Napierala /* 622ec125fbbSEdward Tomasz Napierala * Return fake error code; the caller should change it 623ec125fbbSEdward Tomasz Napierala * into one proper for the situation - EFSIZ, ENOMEM etc. 624ec125fbbSEdward Tomasz Napierala */ 625ec125fbbSEdward Tomasz Napierala return (EDOOFUS); 626ec125fbbSEdward Tomasz Napierala } 627ec125fbbSEdward Tomasz Napierala 628ec125fbbSEdward Tomasz Napierala return (0); 629ec125fbbSEdward Tomasz Napierala } 630ec125fbbSEdward Tomasz Napierala 631ec125fbbSEdward Tomasz Napierala uint64_t 632ec125fbbSEdward Tomasz Napierala rctl_get_limit(struct proc *p, int resource) 633ec125fbbSEdward Tomasz Napierala { 634ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 635ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 636ec125fbbSEdward Tomasz Napierala uint64_t amount = UINT64_MAX; 637ec125fbbSEdward Tomasz Napierala 6384b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 6394b5c9cf6SEdward Tomasz Napierala 6404c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 641ec125fbbSEdward Tomasz Napierala 642ec125fbbSEdward Tomasz Napierala /* 643ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 644ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 645ec125fbbSEdward Tomasz Napierala */ 646ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 647ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 648ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 649ec125fbbSEdward Tomasz Napierala continue; 650ec125fbbSEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 651ec125fbbSEdward Tomasz Napierala continue; 652ec125fbbSEdward Tomasz Napierala if (rule->rr_amount < amount) 653ec125fbbSEdward Tomasz Napierala amount = rule->rr_amount; 654ec125fbbSEdward Tomasz Napierala } 655ec125fbbSEdward Tomasz Napierala 6564c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 657ec125fbbSEdward Tomasz Napierala 658ec125fbbSEdward Tomasz Napierala return (amount); 659ec125fbbSEdward Tomasz Napierala } 660ec125fbbSEdward Tomasz Napierala 661ec125fbbSEdward Tomasz Napierala uint64_t 662ec125fbbSEdward Tomasz Napierala rctl_get_available(struct proc *p, int resource) 663ec125fbbSEdward Tomasz Napierala { 664ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 665ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 666ec125fbbSEdward Tomasz Napierala int64_t available, minavailable, allocated; 667ec125fbbSEdward Tomasz Napierala 668ec125fbbSEdward Tomasz Napierala minavailable = INT64_MAX; 669ec125fbbSEdward Tomasz Napierala 6704b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 6714b5c9cf6SEdward Tomasz Napierala 6724c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 673ec125fbbSEdward Tomasz Napierala 674ec125fbbSEdward Tomasz Napierala /* 675ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 676ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 677ec125fbbSEdward Tomasz Napierala */ 678ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 679ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 680ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 681ec125fbbSEdward Tomasz Napierala continue; 682ec125fbbSEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 683ec125fbbSEdward Tomasz Napierala continue; 684ec125fbbSEdward Tomasz Napierala available = rctl_available_resource(p, rule); 685ec125fbbSEdward Tomasz Napierala if (available < minavailable) 686ec125fbbSEdward Tomasz Napierala minavailable = available; 687ec125fbbSEdward Tomasz Napierala } 688ec125fbbSEdward Tomasz Napierala 6894c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 690ec125fbbSEdward Tomasz Napierala 691ec125fbbSEdward Tomasz Napierala /* 692ec125fbbSEdward Tomasz Napierala * XXX: Think about this _hard_. 693ec125fbbSEdward Tomasz Napierala */ 694ec125fbbSEdward Tomasz Napierala allocated = p->p_racct->r_resources[resource]; 695ec125fbbSEdward Tomasz Napierala if (minavailable < INT64_MAX - allocated) 696ec125fbbSEdward Tomasz Napierala minavailable += allocated; 697ec125fbbSEdward Tomasz Napierala if (minavailable < 0) 698ec125fbbSEdward Tomasz Napierala minavailable = 0; 699ec125fbbSEdward Tomasz Napierala return (minavailable); 700ec125fbbSEdward Tomasz Napierala } 701ec125fbbSEdward Tomasz Napierala 702ec125fbbSEdward Tomasz Napierala static int 703ec125fbbSEdward Tomasz Napierala rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter) 704ec125fbbSEdward Tomasz Napierala { 705ec125fbbSEdward Tomasz Napierala 7064b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 7074b5c9cf6SEdward Tomasz Napierala 708ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED) { 709ec125fbbSEdward Tomasz Napierala if (rule->rr_subject_type != filter->rr_subject_type) 710ec125fbbSEdward Tomasz Napierala return (0); 711ec125fbbSEdward Tomasz Napierala 712ec125fbbSEdward Tomasz Napierala switch (filter->rr_subject_type) { 713ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 714ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_proc != NULL && 715ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc != 716ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_proc) 717ec125fbbSEdward Tomasz Napierala return (0); 718ec125fbbSEdward Tomasz Napierala break; 719ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 720ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_uip != NULL && 721ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip != 722ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_uip) 723ec125fbbSEdward Tomasz Napierala return (0); 724ec125fbbSEdward Tomasz Napierala break; 725ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 726415896e3SEdward Tomasz Napierala if (filter->rr_subject.rs_loginclass != NULL && 727415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass != 728415896e3SEdward Tomasz Napierala filter->rr_subject.rs_loginclass) 729ec125fbbSEdward Tomasz Napierala return (0); 730ec125fbbSEdward Tomasz Napierala break; 731ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 732a7ad07bfSEdward Tomasz Napierala if (filter->rr_subject.rs_prison_racct != NULL && 733a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct != 734a7ad07bfSEdward Tomasz Napierala filter->rr_subject.rs_prison_racct) 735ec125fbbSEdward Tomasz Napierala return (0); 736ec125fbbSEdward Tomasz Napierala break; 737ec125fbbSEdward Tomasz Napierala default: 738ec125fbbSEdward Tomasz Napierala panic("rctl_rule_matches: unknown subject type %d", 739ec125fbbSEdward Tomasz Napierala filter->rr_subject_type); 740ec125fbbSEdward Tomasz Napierala } 741ec125fbbSEdward Tomasz Napierala } 742ec125fbbSEdward Tomasz Napierala 743ec125fbbSEdward Tomasz Napierala if (filter->rr_resource != RACCT_UNDEFINED) { 744ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != filter->rr_resource) 745ec125fbbSEdward Tomasz Napierala return (0); 746ec125fbbSEdward Tomasz Napierala } 747ec125fbbSEdward Tomasz Napierala 748ec125fbbSEdward Tomasz Napierala if (filter->rr_action != RCTL_ACTION_UNDEFINED) { 749ec125fbbSEdward Tomasz Napierala if (rule->rr_action != filter->rr_action) 750ec125fbbSEdward Tomasz Napierala return (0); 751ec125fbbSEdward Tomasz Napierala } 752ec125fbbSEdward Tomasz Napierala 753ec125fbbSEdward Tomasz Napierala if (filter->rr_amount != RCTL_AMOUNT_UNDEFINED) { 754ec125fbbSEdward Tomasz Napierala if (rule->rr_amount != filter->rr_amount) 755ec125fbbSEdward Tomasz Napierala return (0); 756ec125fbbSEdward Tomasz Napierala } 757ec125fbbSEdward Tomasz Napierala 758ec125fbbSEdward Tomasz Napierala if (filter->rr_per != RCTL_SUBJECT_TYPE_UNDEFINED) { 759ec125fbbSEdward Tomasz Napierala if (rule->rr_per != filter->rr_per) 760ec125fbbSEdward Tomasz Napierala return (0); 761ec125fbbSEdward Tomasz Napierala } 762ec125fbbSEdward Tomasz Napierala 763ec125fbbSEdward Tomasz Napierala return (1); 764ec125fbbSEdward Tomasz Napierala } 765ec125fbbSEdward Tomasz Napierala 766ec125fbbSEdward Tomasz Napierala static int 767ec125fbbSEdward Tomasz Napierala str2value(const char *str, int *value, struct dict *table) 768ec125fbbSEdward Tomasz Napierala { 769ec125fbbSEdward Tomasz Napierala int i; 770ec125fbbSEdward Tomasz Napierala 771ec125fbbSEdward Tomasz Napierala if (value == NULL) 772ec125fbbSEdward Tomasz Napierala return (EINVAL); 773ec125fbbSEdward Tomasz Napierala 774ec125fbbSEdward Tomasz Napierala for (i = 0; table[i].d_name != NULL; i++) { 775ec125fbbSEdward Tomasz Napierala if (strcasecmp(table[i].d_name, str) == 0) { 776ec125fbbSEdward Tomasz Napierala *value = table[i].d_value; 777ec125fbbSEdward Tomasz Napierala return (0); 778ec125fbbSEdward Tomasz Napierala } 779ec125fbbSEdward Tomasz Napierala } 780ec125fbbSEdward Tomasz Napierala 781ec125fbbSEdward Tomasz Napierala return (EINVAL); 782ec125fbbSEdward Tomasz Napierala } 783ec125fbbSEdward Tomasz Napierala 784ec125fbbSEdward Tomasz Napierala static int 785ec125fbbSEdward Tomasz Napierala str2id(const char *str, id_t *value) 786ec125fbbSEdward Tomasz Napierala { 787ec125fbbSEdward Tomasz Napierala char *end; 788ec125fbbSEdward Tomasz Napierala 789ec125fbbSEdward Tomasz Napierala if (str == NULL) 790ec125fbbSEdward Tomasz Napierala return (EINVAL); 791ec125fbbSEdward Tomasz Napierala 792ec125fbbSEdward Tomasz Napierala *value = strtoul(str, &end, 10); 793ec125fbbSEdward Tomasz Napierala if ((size_t)(end - str) != strlen(str)) 794ec125fbbSEdward Tomasz Napierala return (EINVAL); 795ec125fbbSEdward Tomasz Napierala 796ec125fbbSEdward Tomasz Napierala return (0); 797ec125fbbSEdward Tomasz Napierala } 798ec125fbbSEdward Tomasz Napierala 799ec125fbbSEdward Tomasz Napierala static int 800ec125fbbSEdward Tomasz Napierala str2int64(const char *str, int64_t *value) 801ec125fbbSEdward Tomasz Napierala { 802ec125fbbSEdward Tomasz Napierala char *end; 803ec125fbbSEdward Tomasz Napierala 804ec125fbbSEdward Tomasz Napierala if (str == NULL) 805ec125fbbSEdward Tomasz Napierala return (EINVAL); 806ec125fbbSEdward Tomasz Napierala 807ec125fbbSEdward Tomasz Napierala *value = strtoul(str, &end, 10); 808ec125fbbSEdward Tomasz Napierala if ((size_t)(end - str) != strlen(str)) 809ec125fbbSEdward Tomasz Napierala return (EINVAL); 810ec125fbbSEdward Tomasz Napierala 811b450d447SEdward Tomasz Napierala if (*value < 0) 812b450d447SEdward Tomasz Napierala return (ERANGE); 813b450d447SEdward Tomasz Napierala 814ec125fbbSEdward Tomasz Napierala return (0); 815ec125fbbSEdward Tomasz Napierala } 816ec125fbbSEdward Tomasz Napierala 817ec125fbbSEdward Tomasz Napierala /* 818ec125fbbSEdward Tomasz Napierala * Connect the rule to the racct, increasing refcount for the rule. 819ec125fbbSEdward Tomasz Napierala */ 820ec125fbbSEdward Tomasz Napierala static void 821ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(struct racct *racct, struct rctl_rule *rule) 822ec125fbbSEdward Tomasz Napierala { 823ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 824ec125fbbSEdward Tomasz Napierala 8254b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 826ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 827ec125fbbSEdward Tomasz Napierala 828ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(rule); 829ec125fbbSEdward Tomasz Napierala link = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 830ec125fbbSEdward Tomasz Napierala link->rrl_rule = rule; 831ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 832ec125fbbSEdward Tomasz Napierala 8334c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 834ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); 8354c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 836ec125fbbSEdward Tomasz Napierala } 837ec125fbbSEdward Tomasz Napierala 838ec125fbbSEdward Tomasz Napierala static int 839ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule_locked(struct racct *racct, struct rctl_rule *rule) 840ec125fbbSEdward Tomasz Napierala { 841ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 842ec125fbbSEdward Tomasz Napierala 8434b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 844ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 8454c230cdaSEdward Tomasz Napierala RCTL_WLOCK_ASSERT(); 846ec125fbbSEdward Tomasz Napierala 847ec125fbbSEdward Tomasz Napierala link = uma_zalloc(rctl_rule_link_zone, M_NOWAIT); 848ec125fbbSEdward Tomasz Napierala if (link == NULL) 849ec125fbbSEdward Tomasz Napierala return (ENOMEM); 850ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(rule); 851ec125fbbSEdward Tomasz Napierala link->rrl_rule = rule; 852ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 853ec125fbbSEdward Tomasz Napierala 854ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); 855ec125fbbSEdward Tomasz Napierala return (0); 856ec125fbbSEdward Tomasz Napierala } 857ec125fbbSEdward Tomasz Napierala 858ec125fbbSEdward Tomasz Napierala /* 859ec125fbbSEdward Tomasz Napierala * Remove limits for a rules matching the filter and release 860ec125fbbSEdward Tomasz Napierala * the refcounts for the rules, possibly freeing them. Returns 861ec125fbbSEdward Tomasz Napierala * the number of limit structures removed. 862ec125fbbSEdward Tomasz Napierala */ 863ec125fbbSEdward Tomasz Napierala static int 864ec125fbbSEdward Tomasz Napierala rctl_racct_remove_rules(struct racct *racct, 865ec125fbbSEdward Tomasz Napierala const struct rctl_rule *filter) 866ec125fbbSEdward Tomasz Napierala { 867ec125fbbSEdward Tomasz Napierala int removed = 0; 868ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link, *linktmp; 869ec125fbbSEdward Tomasz Napierala 8704b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 8714c230cdaSEdward Tomasz Napierala RCTL_WLOCK_ASSERT(); 872ec125fbbSEdward Tomasz Napierala 873ec125fbbSEdward Tomasz Napierala LIST_FOREACH_SAFE(link, &racct->r_rule_links, rrl_next, linktmp) { 874ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 875ec125fbbSEdward Tomasz Napierala continue; 876ec125fbbSEdward Tomasz Napierala 877ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 878ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 879ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 880ec125fbbSEdward Tomasz Napierala removed++; 881ec125fbbSEdward Tomasz Napierala } 882ec125fbbSEdward Tomasz Napierala return (removed); 883ec125fbbSEdward Tomasz Napierala } 884ec125fbbSEdward Tomasz Napierala 885ec125fbbSEdward Tomasz Napierala static void 886ec125fbbSEdward Tomasz Napierala rctl_rule_acquire_subject(struct rctl_rule *rule) 887ec125fbbSEdward Tomasz Napierala { 888ec125fbbSEdward Tomasz Napierala 8894b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 8904b5c9cf6SEdward Tomasz Napierala 891ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 892ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 893ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 894a7ad07bfSEdward Tomasz Napierala break; 895ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 896a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct != NULL) 897a7ad07bfSEdward Tomasz Napierala prison_racct_hold(rule->rr_subject.rs_prison_racct); 898ec125fbbSEdward Tomasz Napierala break; 899ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 900ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip != NULL) 901ec125fbbSEdward Tomasz Napierala uihold(rule->rr_subject.rs_uip); 902ec125fbbSEdward Tomasz Napierala break; 903ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 904415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass != NULL) 905415896e3SEdward Tomasz Napierala loginclass_hold(rule->rr_subject.rs_loginclass); 906ec125fbbSEdward Tomasz Napierala break; 907ec125fbbSEdward Tomasz Napierala default: 908ec125fbbSEdward Tomasz Napierala panic("rctl_rule_acquire_subject: unknown subject type %d", 909ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 910ec125fbbSEdward Tomasz Napierala } 911ec125fbbSEdward Tomasz Napierala } 912ec125fbbSEdward Tomasz Napierala 913ec125fbbSEdward Tomasz Napierala static void 914ec125fbbSEdward Tomasz Napierala rctl_rule_release_subject(struct rctl_rule *rule) 915ec125fbbSEdward Tomasz Napierala { 916ec125fbbSEdward Tomasz Napierala 9174b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 9184b5c9cf6SEdward Tomasz Napierala 919ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 920ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 921ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 922a7ad07bfSEdward Tomasz Napierala break; 923ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 924a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct != NULL) 925a7ad07bfSEdward Tomasz Napierala prison_racct_free(rule->rr_subject.rs_prison_racct); 926ec125fbbSEdward Tomasz Napierala break; 927ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 928ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip != NULL) 929ec125fbbSEdward Tomasz Napierala uifree(rule->rr_subject.rs_uip); 930ec125fbbSEdward Tomasz Napierala break; 931ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 932415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass != NULL) 933415896e3SEdward Tomasz Napierala loginclass_free(rule->rr_subject.rs_loginclass); 934ec125fbbSEdward Tomasz Napierala break; 935ec125fbbSEdward Tomasz Napierala default: 936ec125fbbSEdward Tomasz Napierala panic("rctl_rule_release_subject: unknown subject type %d", 937ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 938ec125fbbSEdward Tomasz Napierala } 939ec125fbbSEdward Tomasz Napierala } 940ec125fbbSEdward Tomasz Napierala 941ec125fbbSEdward Tomasz Napierala struct rctl_rule * 942ec125fbbSEdward Tomasz Napierala rctl_rule_alloc(int flags) 943ec125fbbSEdward Tomasz Napierala { 944ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 945ec125fbbSEdward Tomasz Napierala 9464b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 9474b5c9cf6SEdward Tomasz Napierala 948ec125fbbSEdward Tomasz Napierala rule = uma_zalloc(rctl_rule_zone, flags); 949ec125fbbSEdward Tomasz Napierala if (rule == NULL) 950ec125fbbSEdward Tomasz Napierala return (NULL); 951ec125fbbSEdward Tomasz Napierala rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED; 952ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = NULL; 953ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = NULL; 954415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = NULL; 955a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = NULL; 956ec125fbbSEdward Tomasz Napierala rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED; 957ec125fbbSEdward Tomasz Napierala rule->rr_resource = RACCT_UNDEFINED; 958ec125fbbSEdward Tomasz Napierala rule->rr_action = RCTL_ACTION_UNDEFINED; 959ec125fbbSEdward Tomasz Napierala rule->rr_amount = RCTL_AMOUNT_UNDEFINED; 960ec125fbbSEdward Tomasz Napierala refcount_init(&rule->rr_refcount, 1); 961ec125fbbSEdward Tomasz Napierala 962ec125fbbSEdward Tomasz Napierala return (rule); 963ec125fbbSEdward Tomasz Napierala } 964ec125fbbSEdward Tomasz Napierala 965ec125fbbSEdward Tomasz Napierala struct rctl_rule * 966ec125fbbSEdward Tomasz Napierala rctl_rule_duplicate(const struct rctl_rule *rule, int flags) 967ec125fbbSEdward Tomasz Napierala { 968ec125fbbSEdward Tomasz Napierala struct rctl_rule *copy; 969ec125fbbSEdward Tomasz Napierala 9704b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 9714b5c9cf6SEdward Tomasz Napierala 972ec125fbbSEdward Tomasz Napierala copy = uma_zalloc(rctl_rule_zone, flags); 973ec125fbbSEdward Tomasz Napierala if (copy == NULL) 974ec125fbbSEdward Tomasz Napierala return (NULL); 975ec125fbbSEdward Tomasz Napierala copy->rr_subject_type = rule->rr_subject_type; 976ec125fbbSEdward Tomasz Napierala copy->rr_subject.rs_proc = rule->rr_subject.rs_proc; 977ec125fbbSEdward Tomasz Napierala copy->rr_subject.rs_uip = rule->rr_subject.rs_uip; 978415896e3SEdward Tomasz Napierala copy->rr_subject.rs_loginclass = rule->rr_subject.rs_loginclass; 979a7ad07bfSEdward Tomasz Napierala copy->rr_subject.rs_prison_racct = rule->rr_subject.rs_prison_racct; 980ec125fbbSEdward Tomasz Napierala copy->rr_per = rule->rr_per; 981ec125fbbSEdward Tomasz Napierala copy->rr_resource = rule->rr_resource; 982ec125fbbSEdward Tomasz Napierala copy->rr_action = rule->rr_action; 983ec125fbbSEdward Tomasz Napierala copy->rr_amount = rule->rr_amount; 984ec125fbbSEdward Tomasz Napierala refcount_init(©->rr_refcount, 1); 985ec125fbbSEdward Tomasz Napierala rctl_rule_acquire_subject(copy); 986ec125fbbSEdward Tomasz Napierala 987ec125fbbSEdward Tomasz Napierala return (copy); 988ec125fbbSEdward Tomasz Napierala } 989ec125fbbSEdward Tomasz Napierala 990ec125fbbSEdward Tomasz Napierala void 991ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(struct rctl_rule *rule) 992ec125fbbSEdward Tomasz Napierala { 993ec125fbbSEdward Tomasz Napierala 9944b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 995ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0")); 996ec125fbbSEdward Tomasz Napierala 997ec125fbbSEdward Tomasz Napierala refcount_acquire(&rule->rr_refcount); 998ec125fbbSEdward Tomasz Napierala } 999ec125fbbSEdward Tomasz Napierala 1000ec125fbbSEdward Tomasz Napierala static void 1001ec125fbbSEdward Tomasz Napierala rctl_rule_free(void *context, int pending) 1002ec125fbbSEdward Tomasz Napierala { 1003ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 1004ec125fbbSEdward Tomasz Napierala 1005ec125fbbSEdward Tomasz Napierala rule = (struct rctl_rule *)context; 1006ec125fbbSEdward Tomasz Napierala 10074b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 1008ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount == 0, ("rule->rr_refcount != 0")); 1009ec125fbbSEdward Tomasz Napierala 1010ec125fbbSEdward Tomasz Napierala /* 1011ec125fbbSEdward Tomasz Napierala * We don't need locking here; rule is guaranteed to be inaccessible. 1012ec125fbbSEdward Tomasz Napierala */ 1013ec125fbbSEdward Tomasz Napierala 1014ec125fbbSEdward Tomasz Napierala rctl_rule_release_subject(rule); 1015ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_zone, rule); 1016ec125fbbSEdward Tomasz Napierala } 1017ec125fbbSEdward Tomasz Napierala 1018ec125fbbSEdward Tomasz Napierala void 1019ec125fbbSEdward Tomasz Napierala rctl_rule_release(struct rctl_rule *rule) 1020ec125fbbSEdward Tomasz Napierala { 1021ec125fbbSEdward Tomasz Napierala 10224b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 1023ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0")); 1024ec125fbbSEdward Tomasz Napierala 1025ec125fbbSEdward Tomasz Napierala if (refcount_release(&rule->rr_refcount)) { 1026ec125fbbSEdward Tomasz Napierala /* 1027ec125fbbSEdward Tomasz Napierala * rctl_rule_release() is often called when iterating 1028ec125fbbSEdward Tomasz Napierala * over all the uidinfo structures in the system, 1029ec125fbbSEdward Tomasz Napierala * holding uihashtbl_lock. Since rctl_rule_free() 1030ec125fbbSEdward Tomasz Napierala * might end up calling uifree(), this would lead 1031ec125fbbSEdward Tomasz Napierala * to lock recursion. Use taskqueue to avoid this. 1032ec125fbbSEdward Tomasz Napierala */ 1033ec125fbbSEdward Tomasz Napierala TASK_INIT(&rule->rr_task, 0, rctl_rule_free, rule); 1034ec125fbbSEdward Tomasz Napierala taskqueue_enqueue(taskqueue_thread, &rule->rr_task); 1035ec125fbbSEdward Tomasz Napierala } 1036ec125fbbSEdward Tomasz Napierala } 1037ec125fbbSEdward Tomasz Napierala 1038ec125fbbSEdward Tomasz Napierala static int 1039ec125fbbSEdward Tomasz Napierala rctl_rule_fully_specified(const struct rctl_rule *rule) 1040ec125fbbSEdward Tomasz Napierala { 1041ec125fbbSEdward Tomasz Napierala 10424b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 10434b5c9cf6SEdward Tomasz Napierala 1044ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1045ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 1046ec125fbbSEdward Tomasz Napierala return (0); 1047ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1048ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) 1049ec125fbbSEdward Tomasz Napierala return (0); 1050ec125fbbSEdward Tomasz Napierala break; 1051ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1052ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip == NULL) 1053ec125fbbSEdward Tomasz Napierala return (0); 1054ec125fbbSEdward Tomasz Napierala break; 1055ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1056415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) 1057ec125fbbSEdward Tomasz Napierala return (0); 1058ec125fbbSEdward Tomasz Napierala break; 1059ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1060a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) 1061ec125fbbSEdward Tomasz Napierala return (0); 1062ec125fbbSEdward Tomasz Napierala break; 1063ec125fbbSEdward Tomasz Napierala default: 1064ec125fbbSEdward Tomasz Napierala panic("rctl_rule_fully_specified: unknown subject type %d", 1065ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1066ec125fbbSEdward Tomasz Napierala } 1067ec125fbbSEdward Tomasz Napierala if (rule->rr_resource == RACCT_UNDEFINED) 1068ec125fbbSEdward Tomasz Napierala return (0); 1069ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_UNDEFINED) 1070ec125fbbSEdward Tomasz Napierala return (0); 1071ec125fbbSEdward Tomasz Napierala if (rule->rr_amount == RCTL_AMOUNT_UNDEFINED) 1072ec125fbbSEdward Tomasz Napierala return (0); 1073ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED) 1074ec125fbbSEdward Tomasz Napierala return (0); 1075ec125fbbSEdward Tomasz Napierala 1076ec125fbbSEdward Tomasz Napierala return (1); 1077ec125fbbSEdward Tomasz Napierala } 1078ec125fbbSEdward Tomasz Napierala 1079ec125fbbSEdward Tomasz Napierala static int 1080ec125fbbSEdward Tomasz Napierala rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep) 1081ec125fbbSEdward Tomasz Napierala { 1082ec125fbbSEdward Tomasz Napierala int error = 0; 1083ec125fbbSEdward Tomasz Napierala char *subjectstr, *subject_idstr, *resourcestr, *actionstr, 1084ec125fbbSEdward Tomasz Napierala *amountstr, *perstr; 1085ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 1086ec125fbbSEdward Tomasz Napierala id_t id; 1087ec125fbbSEdward Tomasz Napierala 10884b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 10894b5c9cf6SEdward Tomasz Napierala 1090ec125fbbSEdward Tomasz Napierala rule = rctl_rule_alloc(M_WAITOK); 1091ec125fbbSEdward Tomasz Napierala 1092ec125fbbSEdward Tomasz Napierala subjectstr = strsep(&rulestr, ":"); 1093ec125fbbSEdward Tomasz Napierala subject_idstr = strsep(&rulestr, ":"); 1094ec125fbbSEdward Tomasz Napierala resourcestr = strsep(&rulestr, ":"); 1095ec125fbbSEdward Tomasz Napierala actionstr = strsep(&rulestr, "=/"); 1096ec125fbbSEdward Tomasz Napierala amountstr = strsep(&rulestr, "/"); 1097ec125fbbSEdward Tomasz Napierala perstr = rulestr; 1098ec125fbbSEdward Tomasz Napierala 1099ec125fbbSEdward Tomasz Napierala if (subjectstr == NULL || subjectstr[0] == '\0') 1100ec125fbbSEdward Tomasz Napierala rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED; 1101ec125fbbSEdward Tomasz Napierala else { 1102ec125fbbSEdward Tomasz Napierala error = str2value(subjectstr, &rule->rr_subject_type, subjectnames); 1103ec125fbbSEdward Tomasz Napierala if (error != 0) 1104ec125fbbSEdward Tomasz Napierala goto out; 1105ec125fbbSEdward Tomasz Napierala } 1106ec125fbbSEdward Tomasz Napierala 1107ec125fbbSEdward Tomasz Napierala if (subject_idstr == NULL || subject_idstr[0] == '\0') { 1108ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = NULL; 1109ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = NULL; 1110415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = NULL; 1111a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = NULL; 1112ec125fbbSEdward Tomasz Napierala } else { 1113ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1114ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 1115ec125fbbSEdward Tomasz Napierala error = EINVAL; 1116ec125fbbSEdward Tomasz Napierala goto out; 1117ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1118ec125fbbSEdward Tomasz Napierala error = str2id(subject_idstr, &id); 1119ec125fbbSEdward Tomasz Napierala if (error != 0) 1120ec125fbbSEdward Tomasz Napierala goto out; 1121ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 1122ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = pfind(id); 1123ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) { 1124ec125fbbSEdward Tomasz Napierala error = ESRCH; 1125ec125fbbSEdward Tomasz Napierala goto out; 1126ec125fbbSEdward Tomasz Napierala } 1127ec125fbbSEdward Tomasz Napierala PROC_UNLOCK(rule->rr_subject.rs_proc); 1128ec125fbbSEdward Tomasz Napierala break; 1129ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1130ec125fbbSEdward Tomasz Napierala error = str2id(subject_idstr, &id); 1131ec125fbbSEdward Tomasz Napierala if (error != 0) 1132ec125fbbSEdward Tomasz Napierala goto out; 1133ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = uifind(id); 1134ec125fbbSEdward Tomasz Napierala break; 1135ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1136415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = 1137ec125fbbSEdward Tomasz Napierala loginclass_find(subject_idstr); 1138415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) { 1139ec125fbbSEdward Tomasz Napierala error = ENAMETOOLONG; 1140ec125fbbSEdward Tomasz Napierala goto out; 1141ec125fbbSEdward Tomasz Napierala } 1142ec125fbbSEdward Tomasz Napierala break; 1143ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1144a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = 1145a7ad07bfSEdward Tomasz Napierala prison_racct_find(subject_idstr); 1146a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) { 1147a7ad07bfSEdward Tomasz Napierala error = ENAMETOOLONG; 1148ec125fbbSEdward Tomasz Napierala goto out; 1149ec125fbbSEdward Tomasz Napierala } 1150ec125fbbSEdward Tomasz Napierala break; 1151ec125fbbSEdward Tomasz Napierala default: 1152ec125fbbSEdward Tomasz Napierala panic("rctl_string_to_rule: unknown subject type %d", 1153ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1154ec125fbbSEdward Tomasz Napierala } 1155ec125fbbSEdward Tomasz Napierala } 1156ec125fbbSEdward Tomasz Napierala 1157ec125fbbSEdward Tomasz Napierala if (resourcestr == NULL || resourcestr[0] == '\0') 1158ec125fbbSEdward Tomasz Napierala rule->rr_resource = RACCT_UNDEFINED; 1159ec125fbbSEdward Tomasz Napierala else { 1160ec125fbbSEdward Tomasz Napierala error = str2value(resourcestr, &rule->rr_resource, 1161ec125fbbSEdward Tomasz Napierala resourcenames); 1162ec125fbbSEdward Tomasz Napierala if (error != 0) 1163ec125fbbSEdward Tomasz Napierala goto out; 1164ec125fbbSEdward Tomasz Napierala } 1165ec125fbbSEdward Tomasz Napierala 1166ec125fbbSEdward Tomasz Napierala if (actionstr == NULL || actionstr[0] == '\0') 1167ec125fbbSEdward Tomasz Napierala rule->rr_action = RCTL_ACTION_UNDEFINED; 1168ec125fbbSEdward Tomasz Napierala else { 1169ec125fbbSEdward Tomasz Napierala error = str2value(actionstr, &rule->rr_action, actionnames); 1170ec125fbbSEdward Tomasz Napierala if (error != 0) 1171ec125fbbSEdward Tomasz Napierala goto out; 1172ec125fbbSEdward Tomasz Napierala } 1173ec125fbbSEdward Tomasz Napierala 1174ec125fbbSEdward Tomasz Napierala if (amountstr == NULL || amountstr[0] == '\0') 1175ec125fbbSEdward Tomasz Napierala rule->rr_amount = RCTL_AMOUNT_UNDEFINED; 1176ec125fbbSEdward Tomasz Napierala else { 1177ec125fbbSEdward Tomasz Napierala error = str2int64(amountstr, &rule->rr_amount); 1178ec125fbbSEdward Tomasz Napierala if (error != 0) 1179ec125fbbSEdward Tomasz Napierala goto out; 1180b450d447SEdward Tomasz Napierala if (RACCT_IS_IN_MILLIONS(rule->rr_resource)) { 1181b450d447SEdward Tomasz Napierala if (rule->rr_amount > INT64_MAX / 1000000) { 1182b450d447SEdward Tomasz Napierala error = ERANGE; 1183b450d447SEdward Tomasz Napierala goto out; 1184b450d447SEdward Tomasz Napierala } 1185cff08ec0SEdward Tomasz Napierala rule->rr_amount *= 1000000; 1186ec125fbbSEdward Tomasz Napierala } 1187b450d447SEdward Tomasz Napierala } 1188ec125fbbSEdward Tomasz Napierala 1189ec125fbbSEdward Tomasz Napierala if (perstr == NULL || perstr[0] == '\0') 1190ec125fbbSEdward Tomasz Napierala rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED; 1191ec125fbbSEdward Tomasz Napierala else { 1192ec125fbbSEdward Tomasz Napierala error = str2value(perstr, &rule->rr_per, subjectnames); 1193ec125fbbSEdward Tomasz Napierala if (error != 0) 1194ec125fbbSEdward Tomasz Napierala goto out; 1195ec125fbbSEdward Tomasz Napierala } 1196ec125fbbSEdward Tomasz Napierala 1197ec125fbbSEdward Tomasz Napierala out: 1198ec125fbbSEdward Tomasz Napierala if (error == 0) 1199ec125fbbSEdward Tomasz Napierala *rulep = rule; 1200ec125fbbSEdward Tomasz Napierala else 1201ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 1202ec125fbbSEdward Tomasz Napierala 1203ec125fbbSEdward Tomasz Napierala return (error); 1204ec125fbbSEdward Tomasz Napierala } 1205ec125fbbSEdward Tomasz Napierala 1206ec125fbbSEdward Tomasz Napierala /* 1207ec125fbbSEdward Tomasz Napierala * Link a rule with all the subjects it applies to. 1208ec125fbbSEdward Tomasz Napierala */ 1209ec125fbbSEdward Tomasz Napierala int 1210ec125fbbSEdward Tomasz Napierala rctl_rule_add(struct rctl_rule *rule) 1211ec125fbbSEdward Tomasz Napierala { 1212ec125fbbSEdward Tomasz Napierala struct proc *p; 1213ec125fbbSEdward Tomasz Napierala struct ucred *cred; 1214ec125fbbSEdward Tomasz Napierala struct uidinfo *uip; 1215ec125fbbSEdward Tomasz Napierala struct prison *pr; 1216a7ad07bfSEdward Tomasz Napierala struct prison_racct *prr; 1217ec125fbbSEdward Tomasz Napierala struct loginclass *lc; 1218ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule2; 1219ec125fbbSEdward Tomasz Napierala int match; 1220ec125fbbSEdward Tomasz Napierala 12214b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 1222ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 1223ec125fbbSEdward Tomasz Napierala 1224ec125fbbSEdward Tomasz Napierala /* 1225*ae34b6ffSEdward Tomasz Napierala * Some rules just don't make sense, like "deny" rule for an undeniable 1226*ae34b6ffSEdward Tomasz Napierala * resource. The exception are the RSS and %CPU resources - they are 1227*ae34b6ffSEdward Tomasz Napierala * not deniable in the racct sense, but the limit is enforced in 1228*ae34b6ffSEdward Tomasz Napierala * a different way. 1229ec125fbbSEdward Tomasz Napierala */ 1230ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_DENY && 1231*ae34b6ffSEdward Tomasz Napierala !RACCT_IS_DENIABLE(rule->rr_resource) && 1232*ae34b6ffSEdward Tomasz Napierala rule->rr_resource != RACCT_RSS && 1233*ae34b6ffSEdward Tomasz Napierala rule->rr_resource != RACCT_PCTCPU) { 1234ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1235*ae34b6ffSEdward Tomasz Napierala } 1236*ae34b6ffSEdward Tomasz Napierala 1237*ae34b6ffSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_THROTTLE && 1238*ae34b6ffSEdward Tomasz Napierala !RACCT_IS_DECAYING(rule->rr_resource)) { 1239*ae34b6ffSEdward Tomasz Napierala return (EOPNOTSUPP); 1240*ae34b6ffSEdward Tomasz Napierala } 1241*ae34b6ffSEdward Tomasz Napierala 1242*ae34b6ffSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_THROTTLE && 1243*ae34b6ffSEdward Tomasz Napierala rule->rr_resource == RACCT_PCTCPU) { 1244*ae34b6ffSEdward Tomasz Napierala return (EOPNOTSUPP); 1245*ae34b6ffSEdward Tomasz Napierala } 1246ec125fbbSEdward Tomasz Napierala 1247ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS && 1248*ae34b6ffSEdward Tomasz Napierala RACCT_IS_SLOPPY(rule->rr_resource)) { 1249ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1250*ae34b6ffSEdward Tomasz Napierala } 1251ec125fbbSEdward Tomasz Napierala 1252ec125fbbSEdward Tomasz Napierala /* 1253ec125fbbSEdward Tomasz Napierala * Make sure there are no duplicated rules. Also, for the "deny" 1254ec125fbbSEdward Tomasz Napierala * rules, remove ones differing only by "amount". 1255ec125fbbSEdward Tomasz Napierala */ 1256ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_DENY) { 1257ec125fbbSEdward Tomasz Napierala rule2 = rctl_rule_duplicate(rule, M_WAITOK); 1258ec125fbbSEdward Tomasz Napierala rule2->rr_amount = RCTL_AMOUNT_UNDEFINED; 1259ec125fbbSEdward Tomasz Napierala rctl_rule_remove(rule2); 1260ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule2); 1261ec125fbbSEdward Tomasz Napierala } else 1262ec125fbbSEdward Tomasz Napierala rctl_rule_remove(rule); 1263ec125fbbSEdward Tomasz Napierala 1264ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1265ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1266ec125fbbSEdward Tomasz Napierala p = rule->rr_subject.rs_proc; 1267ec125fbbSEdward Tomasz Napierala KASSERT(p != NULL, ("rctl_rule_add: NULL proc")); 1268ec125fbbSEdward Tomasz Napierala 1269ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(p->p_racct, rule); 1270ec125fbbSEdward Tomasz Napierala /* 1271ec125fbbSEdward Tomasz Napierala * In case of per-process rule, we don't have anything more 1272ec125fbbSEdward Tomasz Napierala * to do. 1273ec125fbbSEdward Tomasz Napierala */ 1274ec125fbbSEdward Tomasz Napierala return (0); 1275ec125fbbSEdward Tomasz Napierala 1276ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1277ec125fbbSEdward Tomasz Napierala uip = rule->rr_subject.rs_uip; 1278ec125fbbSEdward Tomasz Napierala KASSERT(uip != NULL, ("rctl_rule_add: NULL uip")); 1279ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(uip->ui_racct, rule); 1280ec125fbbSEdward Tomasz Napierala break; 1281ec125fbbSEdward Tomasz Napierala 1282ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1283415896e3SEdward Tomasz Napierala lc = rule->rr_subject.rs_loginclass; 1284ec125fbbSEdward Tomasz Napierala KASSERT(lc != NULL, ("rctl_rule_add: NULL loginclass")); 1285ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(lc->lc_racct, rule); 1286ec125fbbSEdward Tomasz Napierala break; 1287ec125fbbSEdward Tomasz Napierala 1288ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1289a7ad07bfSEdward Tomasz Napierala prr = rule->rr_subject.rs_prison_racct; 1290a7ad07bfSEdward Tomasz Napierala KASSERT(prr != NULL, ("rctl_rule_add: NULL pr")); 1291a7ad07bfSEdward Tomasz Napierala rctl_racct_add_rule(prr->prr_racct, rule); 1292ec125fbbSEdward Tomasz Napierala break; 1293ec125fbbSEdward Tomasz Napierala 1294ec125fbbSEdward Tomasz Napierala default: 1295ec125fbbSEdward Tomasz Napierala panic("rctl_rule_add: unknown subject type %d", 1296ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1297ec125fbbSEdward Tomasz Napierala } 1298ec125fbbSEdward Tomasz Napierala 1299ec125fbbSEdward Tomasz Napierala /* 1300ec125fbbSEdward Tomasz Napierala * Now go through all the processes and add the new rule to the ones 1301ec125fbbSEdward Tomasz Napierala * it applies to. 1302ec125fbbSEdward Tomasz Napierala */ 1303ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 1304ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 1305ec125fbbSEdward Tomasz Napierala cred = p->p_ucred; 1306ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1307ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1308ec125fbbSEdward Tomasz Napierala if (cred->cr_uidinfo == rule->rr_subject.rs_uip || 1309ec125fbbSEdward Tomasz Napierala cred->cr_ruidinfo == rule->rr_subject.rs_uip) 1310ec125fbbSEdward Tomasz Napierala break; 1311ec125fbbSEdward Tomasz Napierala continue; 1312ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1313415896e3SEdward Tomasz Napierala if (cred->cr_loginclass == rule->rr_subject.rs_loginclass) 1314ec125fbbSEdward Tomasz Napierala break; 1315ec125fbbSEdward Tomasz Napierala continue; 1316ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1317ec125fbbSEdward Tomasz Napierala match = 0; 1318ec125fbbSEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) { 1319a7ad07bfSEdward Tomasz Napierala if (pr->pr_prison_racct == rule->rr_subject.rs_prison_racct) { 1320ec125fbbSEdward Tomasz Napierala match = 1; 1321ec125fbbSEdward Tomasz Napierala break; 1322ec125fbbSEdward Tomasz Napierala } 1323ec125fbbSEdward Tomasz Napierala } 1324ec125fbbSEdward Tomasz Napierala if (match) 1325ec125fbbSEdward Tomasz Napierala break; 1326ec125fbbSEdward Tomasz Napierala continue; 1327ec125fbbSEdward Tomasz Napierala default: 1328ec125fbbSEdward Tomasz Napierala panic("rctl_rule_add: unknown subject type %d", 1329ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1330ec125fbbSEdward Tomasz Napierala } 1331ec125fbbSEdward Tomasz Napierala 1332ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(p->p_racct, rule); 1333ec125fbbSEdward Tomasz Napierala } 1334ec125fbbSEdward Tomasz Napierala 1335ec125fbbSEdward Tomasz Napierala return (0); 1336ec125fbbSEdward Tomasz Napierala } 1337ec125fbbSEdward Tomasz Napierala 1338ec125fbbSEdward Tomasz Napierala static void 133915db3c07SEdward Tomasz Napierala rctl_rule_pre_callback(void) 134015db3c07SEdward Tomasz Napierala { 134115db3c07SEdward Tomasz Napierala 13424c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 134315db3c07SEdward Tomasz Napierala } 134415db3c07SEdward Tomasz Napierala 134515db3c07SEdward Tomasz Napierala static void 134615db3c07SEdward Tomasz Napierala rctl_rule_post_callback(void) 134715db3c07SEdward Tomasz Napierala { 134815db3c07SEdward Tomasz Napierala 13494c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 135015db3c07SEdward Tomasz Napierala } 135115db3c07SEdward Tomasz Napierala 135215db3c07SEdward Tomasz Napierala static void 1353ec125fbbSEdward Tomasz Napierala rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3) 1354ec125fbbSEdward Tomasz Napierala { 1355ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter = (struct rctl_rule *)arg2; 1356ec125fbbSEdward Tomasz Napierala int found = 0; 1357ec125fbbSEdward Tomasz Napierala 13584b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 13594c230cdaSEdward Tomasz Napierala RCTL_WLOCK_ASSERT(); 13604b5c9cf6SEdward Tomasz Napierala 1361ec125fbbSEdward Tomasz Napierala found += rctl_racct_remove_rules(racct, filter); 1362ec125fbbSEdward Tomasz Napierala 1363ec125fbbSEdward Tomasz Napierala *((int *)arg3) += found; 1364ec125fbbSEdward Tomasz Napierala } 1365ec125fbbSEdward Tomasz Napierala 1366ec125fbbSEdward Tomasz Napierala /* 1367ec125fbbSEdward Tomasz Napierala * Remove all rules that match the filter. 1368ec125fbbSEdward Tomasz Napierala */ 1369ec125fbbSEdward Tomasz Napierala int 1370ec125fbbSEdward Tomasz Napierala rctl_rule_remove(struct rctl_rule *filter) 1371ec125fbbSEdward Tomasz Napierala { 1372ec125fbbSEdward Tomasz Napierala int found = 0; 1373ec125fbbSEdward Tomasz Napierala struct proc *p; 1374ec125fbbSEdward Tomasz Napierala 13754b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 13764b5c9cf6SEdward Tomasz Napierala 1377ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_PROCESS && 1378ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_proc != NULL) { 1379ec125fbbSEdward Tomasz Napierala p = filter->rr_subject.rs_proc; 13804c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 1381ec125fbbSEdward Tomasz Napierala found = rctl_racct_remove_rules(p->p_racct, filter); 13824c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 1383ec125fbbSEdward Tomasz Napierala if (found) 1384ec125fbbSEdward Tomasz Napierala return (0); 1385ec125fbbSEdward Tomasz Napierala return (ESRCH); 1386ec125fbbSEdward Tomasz Napierala } 1387ec125fbbSEdward Tomasz Napierala 138815db3c07SEdward Tomasz Napierala loginclass_racct_foreach(rctl_rule_remove_callback, 138915db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 139015db3c07SEdward Tomasz Napierala filter, (void *)&found); 139115db3c07SEdward Tomasz Napierala ui_racct_foreach(rctl_rule_remove_callback, 139215db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 139315db3c07SEdward Tomasz Napierala filter, (void *)&found); 139415db3c07SEdward Tomasz Napierala prison_racct_foreach(rctl_rule_remove_callback, 139515db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 139615db3c07SEdward Tomasz Napierala filter, (void *)&found); 1397ec125fbbSEdward Tomasz Napierala 1398ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 13994c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 1400ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 1401ec125fbbSEdward Tomasz Napierala found += rctl_racct_remove_rules(p->p_racct, filter); 1402ec125fbbSEdward Tomasz Napierala } 14034c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 1404ec125fbbSEdward Tomasz Napierala 1405ec125fbbSEdward Tomasz Napierala if (found) 1406ec125fbbSEdward Tomasz Napierala return (0); 1407ec125fbbSEdward Tomasz Napierala return (ESRCH); 1408ec125fbbSEdward Tomasz Napierala } 1409ec125fbbSEdward Tomasz Napierala 1410ec125fbbSEdward Tomasz Napierala /* 1411ec125fbbSEdward Tomasz Napierala * Appends a rule to the sbuf. 1412ec125fbbSEdward Tomasz Napierala */ 1413ec125fbbSEdward Tomasz Napierala static void 1414ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule) 1415ec125fbbSEdward Tomasz Napierala { 1416ec125fbbSEdward Tomasz Napierala int64_t amount; 1417ec125fbbSEdward Tomasz Napierala 14184b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 14194b5c9cf6SEdward Tomasz Napierala 1420ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", rctl_subject_type_name(rule->rr_subject_type)); 1421ec125fbbSEdward Tomasz Napierala 1422ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1423ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1424ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) 1425ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1426ec125fbbSEdward Tomasz Napierala else 1427ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%d:", 1428ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc->p_pid); 1429ec125fbbSEdward Tomasz Napierala break; 1430ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1431ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip == NULL) 1432ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1433ec125fbbSEdward Tomasz Napierala else 1434ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%d:", 1435ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip->ui_uid); 1436ec125fbbSEdward Tomasz Napierala break; 1437ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1438415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) 1439ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1440ec125fbbSEdward Tomasz Napierala else 1441ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", 1442415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass->lc_name); 1443ec125fbbSEdward Tomasz Napierala break; 1444ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1445a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) 1446ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1447ec125fbbSEdward Tomasz Napierala else 1448ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", 1449a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct->prr_name); 1450ec125fbbSEdward Tomasz Napierala break; 1451ec125fbbSEdward Tomasz Napierala default: 1452ec125fbbSEdward Tomasz Napierala panic("rctl_rule_to_sbuf: unknown subject type %d", 1453ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1454ec125fbbSEdward Tomasz Napierala } 1455ec125fbbSEdward Tomasz Napierala 1456ec125fbbSEdward Tomasz Napierala amount = rule->rr_amount; 1457ec125fbbSEdward Tomasz Napierala if (amount != RCTL_AMOUNT_UNDEFINED && 145885a2f1b4SEdward Tomasz Napierala RACCT_IS_IN_MILLIONS(rule->rr_resource)) 145985a2f1b4SEdward Tomasz Napierala amount /= 1000000; 1460ec125fbbSEdward Tomasz Napierala 1461ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:%s=%jd", 1462ec125fbbSEdward Tomasz Napierala rctl_resource_name(rule->rr_resource), 1463ec125fbbSEdward Tomasz Napierala rctl_action_name(rule->rr_action), 1464ec125fbbSEdward Tomasz Napierala amount); 1465ec125fbbSEdward Tomasz Napierala 1466ec125fbbSEdward Tomasz Napierala if (rule->rr_per != rule->rr_subject_type) 1467ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "/%s", rctl_subject_type_name(rule->rr_per)); 1468ec125fbbSEdward Tomasz Napierala } 1469ec125fbbSEdward Tomasz Napierala 1470ec125fbbSEdward Tomasz Napierala /* 1471ec125fbbSEdward Tomasz Napierala * Routine used by RCTL syscalls to read in input string. 1472ec125fbbSEdward Tomasz Napierala */ 1473ec125fbbSEdward Tomasz Napierala static int 1474ec125fbbSEdward Tomasz Napierala rctl_read_inbuf(char **inputstr, const char *inbufp, size_t inbuflen) 1475ec125fbbSEdward Tomasz Napierala { 1476ec125fbbSEdward Tomasz Napierala int error; 1477ec125fbbSEdward Tomasz Napierala char *str; 1478ec125fbbSEdward Tomasz Napierala 14794b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 14804b5c9cf6SEdward Tomasz Napierala 1481ec125fbbSEdward Tomasz Napierala if (inbuflen <= 0) 1482ec125fbbSEdward Tomasz Napierala return (EINVAL); 1483ea228b48SEdward Tomasz Napierala if (inbuflen > RCTL_MAX_INBUFSIZE) 1484786813aaSEdward Tomasz Napierala return (E2BIG); 1485ec125fbbSEdward Tomasz Napierala 1486ec125fbbSEdward Tomasz Napierala str = malloc(inbuflen + 1, M_RCTL, M_WAITOK); 1487ec125fbbSEdward Tomasz Napierala error = copyinstr(inbufp, str, inbuflen, NULL); 1488ec125fbbSEdward Tomasz Napierala if (error != 0) { 1489ec125fbbSEdward Tomasz Napierala free(str, M_RCTL); 1490ec125fbbSEdward Tomasz Napierala return (error); 1491ec125fbbSEdward Tomasz Napierala } 1492ec125fbbSEdward Tomasz Napierala 1493ec125fbbSEdward Tomasz Napierala *inputstr = str; 1494ec125fbbSEdward Tomasz Napierala 1495ec125fbbSEdward Tomasz Napierala return (0); 1496ec125fbbSEdward Tomasz Napierala } 1497ec125fbbSEdward Tomasz Napierala 1498ec125fbbSEdward Tomasz Napierala /* 1499ec125fbbSEdward Tomasz Napierala * Routine used by RCTL syscalls to write out output string. 1500ec125fbbSEdward Tomasz Napierala */ 1501ec125fbbSEdward Tomasz Napierala static int 1502ec125fbbSEdward Tomasz Napierala rctl_write_outbuf(struct sbuf *outputsbuf, char *outbufp, size_t outbuflen) 1503ec125fbbSEdward Tomasz Napierala { 1504ec125fbbSEdward Tomasz Napierala int error; 1505ec125fbbSEdward Tomasz Napierala 15064b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 15074b5c9cf6SEdward Tomasz Napierala 1508ec125fbbSEdward Tomasz Napierala if (outputsbuf == NULL) 1509ec125fbbSEdward Tomasz Napierala return (0); 1510ec125fbbSEdward Tomasz Napierala 1511ec125fbbSEdward Tomasz Napierala sbuf_finish(outputsbuf); 1512ec125fbbSEdward Tomasz Napierala if (outbuflen < sbuf_len(outputsbuf) + 1) { 1513ec125fbbSEdward Tomasz Napierala sbuf_delete(outputsbuf); 1514ec125fbbSEdward Tomasz Napierala return (ERANGE); 1515ec125fbbSEdward Tomasz Napierala } 1516ec125fbbSEdward Tomasz Napierala error = copyout(sbuf_data(outputsbuf), outbufp, 1517ec125fbbSEdward Tomasz Napierala sbuf_len(outputsbuf) + 1); 1518ec125fbbSEdward Tomasz Napierala sbuf_delete(outputsbuf); 1519ec125fbbSEdward Tomasz Napierala return (error); 1520ec125fbbSEdward Tomasz Napierala } 1521ec125fbbSEdward Tomasz Napierala 1522ec125fbbSEdward Tomasz Napierala static struct sbuf * 1523ec125fbbSEdward Tomasz Napierala rctl_racct_to_sbuf(struct racct *racct, int sloppy) 1524ec125fbbSEdward Tomasz Napierala { 1525ec125fbbSEdward Tomasz Napierala int i; 1526ec125fbbSEdward Tomasz Napierala int64_t amount; 1527ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1528ec125fbbSEdward Tomasz Napierala 15294b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 15304b5c9cf6SEdward Tomasz Napierala 1531ec125fbbSEdward Tomasz Napierala sb = sbuf_new_auto(); 1532ec125fbbSEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 15334fe84775SEdward Tomasz Napierala if (sloppy == 0 && RACCT_IS_SLOPPY(i)) 1534ec125fbbSEdward Tomasz Napierala continue; 1535ec125fbbSEdward Tomasz Napierala amount = racct->r_resources[i]; 153685a2f1b4SEdward Tomasz Napierala if (RACCT_IS_IN_MILLIONS(i)) 1537cff08ec0SEdward Tomasz Napierala amount /= 1000000; 1538ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount); 1539ec125fbbSEdward Tomasz Napierala } 1540ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1541ec125fbbSEdward Tomasz Napierala return (sb); 1542ec125fbbSEdward Tomasz Napierala } 1543ec125fbbSEdward Tomasz Napierala 1544ec125fbbSEdward Tomasz Napierala int 15458451d0ddSKip Macy sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) 1546ec125fbbSEdward Tomasz Napierala { 1547ec125fbbSEdward Tomasz Napierala int error; 1548ec125fbbSEdward Tomasz Napierala char *inputstr; 1549ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1550ec125fbbSEdward Tomasz Napierala struct sbuf *outputsbuf = NULL; 1551ec125fbbSEdward Tomasz Napierala struct proc *p; 1552ec125fbbSEdward Tomasz Napierala struct uidinfo *uip; 1553ec125fbbSEdward Tomasz Napierala struct loginclass *lc; 1554a7ad07bfSEdward Tomasz Napierala struct prison_racct *prr; 1555ec125fbbSEdward Tomasz Napierala 15564b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 15574b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 15584b5c9cf6SEdward Tomasz Napierala 1559415896e3SEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_RACCT); 1560ec125fbbSEdward Tomasz Napierala if (error != 0) 1561ec125fbbSEdward Tomasz Napierala return (error); 1562ec125fbbSEdward Tomasz Napierala 1563ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1564ec125fbbSEdward Tomasz Napierala if (error != 0) 1565ec125fbbSEdward Tomasz Napierala return (error); 1566ec125fbbSEdward Tomasz Napierala 1567ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1568ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1569ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1570ec125fbbSEdward Tomasz Napierala if (error != 0) { 1571ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1572ec125fbbSEdward Tomasz Napierala return (error); 1573ec125fbbSEdward Tomasz Napierala } 1574ec125fbbSEdward Tomasz Napierala 1575ec125fbbSEdward Tomasz Napierala switch (filter->rr_subject_type) { 1576ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1577ec125fbbSEdward Tomasz Napierala p = filter->rr_subject.rs_proc; 1578ec125fbbSEdward Tomasz Napierala if (p == NULL) { 1579ec125fbbSEdward Tomasz Napierala error = EINVAL; 1580ec125fbbSEdward Tomasz Napierala goto out; 1581ec125fbbSEdward Tomasz Napierala } 1582ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(p->p_racct, 0); 1583ec125fbbSEdward Tomasz Napierala break; 1584ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1585ec125fbbSEdward Tomasz Napierala uip = filter->rr_subject.rs_uip; 1586ec125fbbSEdward Tomasz Napierala if (uip == NULL) { 1587ec125fbbSEdward Tomasz Napierala error = EINVAL; 1588ec125fbbSEdward Tomasz Napierala goto out; 1589ec125fbbSEdward Tomasz Napierala } 1590ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(uip->ui_racct, 1); 1591ec125fbbSEdward Tomasz Napierala break; 1592ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1593415896e3SEdward Tomasz Napierala lc = filter->rr_subject.rs_loginclass; 1594ec125fbbSEdward Tomasz Napierala if (lc == NULL) { 1595ec125fbbSEdward Tomasz Napierala error = EINVAL; 1596ec125fbbSEdward Tomasz Napierala goto out; 1597ec125fbbSEdward Tomasz Napierala } 1598ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(lc->lc_racct, 1); 1599ec125fbbSEdward Tomasz Napierala break; 1600ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1601a7ad07bfSEdward Tomasz Napierala prr = filter->rr_subject.rs_prison_racct; 1602a7ad07bfSEdward Tomasz Napierala if (prr == NULL) { 1603ec125fbbSEdward Tomasz Napierala error = EINVAL; 1604ec125fbbSEdward Tomasz Napierala goto out; 1605ec125fbbSEdward Tomasz Napierala } 1606a7ad07bfSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(prr->prr_racct, 1); 1607ec125fbbSEdward Tomasz Napierala break; 1608ec125fbbSEdward Tomasz Napierala default: 1609ec125fbbSEdward Tomasz Napierala error = EINVAL; 1610ec125fbbSEdward Tomasz Napierala } 1611ec125fbbSEdward Tomasz Napierala out: 1612ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1613ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1614ec125fbbSEdward Tomasz Napierala if (error != 0) 1615ec125fbbSEdward Tomasz Napierala return (error); 1616ec125fbbSEdward Tomasz Napierala 1617ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(outputsbuf, uap->outbufp, uap->outbuflen); 1618ec125fbbSEdward Tomasz Napierala 1619ec125fbbSEdward Tomasz Napierala return (error); 1620ec125fbbSEdward Tomasz Napierala } 1621ec125fbbSEdward Tomasz Napierala 1622ec125fbbSEdward Tomasz Napierala static void 1623ec125fbbSEdward Tomasz Napierala rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3) 1624ec125fbbSEdward Tomasz Napierala { 1625ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter = (struct rctl_rule *)arg2; 1626ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1627ec125fbbSEdward Tomasz Napierala struct sbuf *sb = (struct sbuf *)arg3; 1628ec125fbbSEdward Tomasz Napierala 16294b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 16304c230cdaSEdward Tomasz Napierala RCTL_LOCK_ASSERT(); 16314b5c9cf6SEdward Tomasz Napierala 1632ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { 1633ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 1634ec125fbbSEdward Tomasz Napierala continue; 1635ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1636ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1637ec125fbbSEdward Tomasz Napierala } 1638ec125fbbSEdward Tomasz Napierala } 1639ec125fbbSEdward Tomasz Napierala 1640ec125fbbSEdward Tomasz Napierala int 16418451d0ddSKip Macy sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) 1642ec125fbbSEdward Tomasz Napierala { 1643ec125fbbSEdward Tomasz Napierala int error; 16442b4035eeSEdward Tomasz Napierala size_t bufsize; 1645ec125fbbSEdward Tomasz Napierala char *inputstr, *buf; 1646ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1647ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1648ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1649ec125fbbSEdward Tomasz Napierala struct proc *p; 1650ec125fbbSEdward Tomasz Napierala 16514b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 16524b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 16534b5c9cf6SEdward Tomasz Napierala 1654ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_RULES); 1655ec125fbbSEdward Tomasz Napierala if (error != 0) 1656ec125fbbSEdward Tomasz Napierala return (error); 1657ec125fbbSEdward Tomasz Napierala 1658ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1659ec125fbbSEdward Tomasz Napierala if (error != 0) 1660ec125fbbSEdward Tomasz Napierala return (error); 1661ec125fbbSEdward Tomasz Napierala 1662ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1663ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1664ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1665ec125fbbSEdward Tomasz Napierala if (error != 0) { 1666ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1667ec125fbbSEdward Tomasz Napierala return (error); 1668ec125fbbSEdward Tomasz Napierala } 1669ec125fbbSEdward Tomasz Napierala 16702b4035eeSEdward Tomasz Napierala bufsize = uap->outbuflen; 16712b4035eeSEdward Tomasz Napierala if (bufsize > rctl_maxbufsize) { 16722b4035eeSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 16732b4035eeSEdward Tomasz Napierala return (E2BIG); 16742b4035eeSEdward Tomasz Napierala } 16752b4035eeSEdward Tomasz Napierala 1676ec125fbbSEdward Tomasz Napierala buf = malloc(bufsize, M_RCTL, M_WAITOK); 1677ec125fbbSEdward Tomasz Napierala sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1678ec125fbbSEdward Tomasz Napierala KASSERT(sb != NULL, ("sbuf_new failed")); 1679ec125fbbSEdward Tomasz Napierala 1680ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 16814c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 1682ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1683ec125fbbSEdward Tomasz Napierala /* 1684ec125fbbSEdward Tomasz Napierala * Non-process rules will be added to the buffer later. 1685ec125fbbSEdward Tomasz Napierala * Adding them here would result in duplicated output. 1686ec125fbbSEdward Tomasz Napierala */ 1687ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type != 1688ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) 1689ec125fbbSEdward Tomasz Napierala continue; 1690ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 1691ec125fbbSEdward Tomasz Napierala continue; 1692ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1693ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1694ec125fbbSEdward Tomasz Napierala } 16954c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 1696ec125fbbSEdward Tomasz Napierala } 1697ec125fbbSEdward Tomasz Napierala 169815db3c07SEdward Tomasz Napierala loginclass_racct_foreach(rctl_get_rules_callback, 169915db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 170015db3c07SEdward Tomasz Napierala filter, sb); 170115db3c07SEdward Tomasz Napierala ui_racct_foreach(rctl_get_rules_callback, 170215db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 170315db3c07SEdward Tomasz Napierala filter, sb); 170415db3c07SEdward Tomasz Napierala prison_racct_foreach(rctl_get_rules_callback, 170515db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 170615db3c07SEdward Tomasz Napierala filter, sb); 1707ec125fbbSEdward Tomasz Napierala if (sbuf_error(sb) == ENOMEM) { 17082b4035eeSEdward Tomasz Napierala error = ERANGE; 17092b4035eeSEdward Tomasz Napierala goto out; 1710ec125fbbSEdward Tomasz Napierala } 1711ec125fbbSEdward Tomasz Napierala 1712ec125fbbSEdward Tomasz Napierala /* 1713ec125fbbSEdward Tomasz Napierala * Remove trailing ",". 1714ec125fbbSEdward Tomasz Napierala */ 1715ec125fbbSEdward Tomasz Napierala if (sbuf_len(sb) > 0) 1716ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1717ec125fbbSEdward Tomasz Napierala 1718ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); 17192b4035eeSEdward Tomasz Napierala out: 1720ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1721ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1722ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 1723ec125fbbSEdward Tomasz Napierala return (error); 1724ec125fbbSEdward Tomasz Napierala } 1725ec125fbbSEdward Tomasz Napierala 1726ec125fbbSEdward Tomasz Napierala int 17278451d0ddSKip Macy sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) 1728ec125fbbSEdward Tomasz Napierala { 1729ec125fbbSEdward Tomasz Napierala int error; 17302b4035eeSEdward Tomasz Napierala size_t bufsize; 1731ec125fbbSEdward Tomasz Napierala char *inputstr, *buf; 1732ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1733ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1734ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1735ec125fbbSEdward Tomasz Napierala 17364b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 17374b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 17384b5c9cf6SEdward Tomasz Napierala 1739ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_LIMITS); 1740ec125fbbSEdward Tomasz Napierala if (error != 0) 1741ec125fbbSEdward Tomasz Napierala return (error); 1742ec125fbbSEdward Tomasz Napierala 1743ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1744ec125fbbSEdward Tomasz Napierala if (error != 0) 1745ec125fbbSEdward Tomasz Napierala return (error); 1746ec125fbbSEdward Tomasz Napierala 1747ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1748ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1749ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1750ec125fbbSEdward Tomasz Napierala if (error != 0) { 1751ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1752ec125fbbSEdward Tomasz Napierala return (error); 1753ec125fbbSEdward Tomasz Napierala } 1754ec125fbbSEdward Tomasz Napierala 1755ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_UNDEFINED) { 1756ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1757ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1758ec125fbbSEdward Tomasz Napierala return (EINVAL); 1759ec125fbbSEdward Tomasz Napierala } 1760ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_PROCESS) { 1761ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1762ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1763ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1764ec125fbbSEdward Tomasz Napierala } 1765ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_proc == NULL) { 1766ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1767ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1768ec125fbbSEdward Tomasz Napierala return (EINVAL); 1769ec125fbbSEdward Tomasz Napierala } 1770ec125fbbSEdward Tomasz Napierala 17712b4035eeSEdward Tomasz Napierala bufsize = uap->outbuflen; 17722b4035eeSEdward Tomasz Napierala if (bufsize > rctl_maxbufsize) { 17732b4035eeSEdward Tomasz Napierala rctl_rule_release(filter); 17742b4035eeSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 17752b4035eeSEdward Tomasz Napierala return (E2BIG); 17762b4035eeSEdward Tomasz Napierala } 17772b4035eeSEdward Tomasz Napierala 1778ec125fbbSEdward Tomasz Napierala buf = malloc(bufsize, M_RCTL, M_WAITOK); 1779ec125fbbSEdward Tomasz Napierala sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1780ec125fbbSEdward Tomasz Napierala KASSERT(sb != NULL, ("sbuf_new failed")); 1781ec125fbbSEdward Tomasz Napierala 17824c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 1783ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &filter->rr_subject.rs_proc->p_racct->r_rule_links, 1784ec125fbbSEdward Tomasz Napierala rrl_next) { 1785ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1786ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1787ec125fbbSEdward Tomasz Napierala } 17884c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 1789ec125fbbSEdward Tomasz Napierala if (sbuf_error(sb) == ENOMEM) { 17902b4035eeSEdward Tomasz Napierala error = ERANGE; 17912b4035eeSEdward Tomasz Napierala goto out; 1792ec125fbbSEdward Tomasz Napierala } 1793ec125fbbSEdward Tomasz Napierala 1794ec125fbbSEdward Tomasz Napierala /* 1795ec125fbbSEdward Tomasz Napierala * Remove trailing ",". 1796ec125fbbSEdward Tomasz Napierala */ 1797ec125fbbSEdward Tomasz Napierala if (sbuf_len(sb) > 0) 1798ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1799ec125fbbSEdward Tomasz Napierala 1800ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); 18012b4035eeSEdward Tomasz Napierala out: 1802ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1803ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1804ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 1805ec125fbbSEdward Tomasz Napierala return (error); 1806ec125fbbSEdward Tomasz Napierala } 1807ec125fbbSEdward Tomasz Napierala 1808ec125fbbSEdward Tomasz Napierala int 18098451d0ddSKip Macy sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) 1810ec125fbbSEdward Tomasz Napierala { 1811ec125fbbSEdward Tomasz Napierala int error; 1812ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 1813ec125fbbSEdward Tomasz Napierala char *inputstr; 1814ec125fbbSEdward Tomasz Napierala 18154b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 18164b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 18174b5c9cf6SEdward Tomasz Napierala 1818ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_ADD_RULE); 1819ec125fbbSEdward Tomasz Napierala if (error != 0) 1820ec125fbbSEdward Tomasz Napierala return (error); 1821ec125fbbSEdward Tomasz Napierala 1822ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1823ec125fbbSEdward Tomasz Napierala if (error != 0) 1824ec125fbbSEdward Tomasz Napierala return (error); 1825ec125fbbSEdward Tomasz Napierala 1826ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1827ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &rule); 1828ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1829ec125fbbSEdward Tomasz Napierala if (error != 0) { 1830ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1831ec125fbbSEdward Tomasz Napierala return (error); 1832ec125fbbSEdward Tomasz Napierala } 1833ec125fbbSEdward Tomasz Napierala /* 1834ec125fbbSEdward Tomasz Napierala * The 'per' part of a rule is optional. 1835ec125fbbSEdward Tomasz Napierala */ 1836ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED && 1837ec125fbbSEdward Tomasz Napierala rule->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED) 1838ec125fbbSEdward Tomasz Napierala rule->rr_per = rule->rr_subject_type; 1839ec125fbbSEdward Tomasz Napierala 1840ec125fbbSEdward Tomasz Napierala if (!rctl_rule_fully_specified(rule)) { 1841ec125fbbSEdward Tomasz Napierala error = EINVAL; 1842ec125fbbSEdward Tomasz Napierala goto out; 1843ec125fbbSEdward Tomasz Napierala } 1844ec125fbbSEdward Tomasz Napierala 1845ec125fbbSEdward Tomasz Napierala error = rctl_rule_add(rule); 1846ec125fbbSEdward Tomasz Napierala 1847ec125fbbSEdward Tomasz Napierala out: 1848ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 1849ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1850ec125fbbSEdward Tomasz Napierala return (error); 1851ec125fbbSEdward Tomasz Napierala } 1852ec125fbbSEdward Tomasz Napierala 1853ec125fbbSEdward Tomasz Napierala int 18548451d0ddSKip Macy sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) 1855ec125fbbSEdward Tomasz Napierala { 1856ec125fbbSEdward Tomasz Napierala int error; 1857ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1858ec125fbbSEdward Tomasz Napierala char *inputstr; 1859ec125fbbSEdward Tomasz Napierala 18604b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 18614b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 18624b5c9cf6SEdward Tomasz Napierala 1863ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_REMOVE_RULE); 1864ec125fbbSEdward Tomasz Napierala if (error != 0) 1865ec125fbbSEdward Tomasz Napierala return (error); 1866ec125fbbSEdward Tomasz Napierala 1867ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1868ec125fbbSEdward Tomasz Napierala if (error != 0) 1869ec125fbbSEdward Tomasz Napierala return (error); 1870ec125fbbSEdward Tomasz Napierala 1871ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1872ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1873ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1874ec125fbbSEdward Tomasz Napierala if (error != 0) { 1875ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1876ec125fbbSEdward Tomasz Napierala return (error); 1877ec125fbbSEdward Tomasz Napierala } 1878ec125fbbSEdward Tomasz Napierala 1879ec125fbbSEdward Tomasz Napierala error = rctl_rule_remove(filter); 1880ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1881ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1882ec125fbbSEdward Tomasz Napierala 1883ec125fbbSEdward Tomasz Napierala return (error); 1884ec125fbbSEdward Tomasz Napierala } 1885ec125fbbSEdward Tomasz Napierala 1886ec125fbbSEdward Tomasz Napierala /* 1887ec125fbbSEdward Tomasz Napierala * Update RCTL rule list after credential change. 1888ec125fbbSEdward Tomasz Napierala */ 1889ec125fbbSEdward Tomasz Napierala void 1890ec125fbbSEdward Tomasz Napierala rctl_proc_ucred_changed(struct proc *p, struct ucred *newcred) 1891ec125fbbSEdward Tomasz Napierala { 1892ec125fbbSEdward Tomasz Napierala int rulecnt, i; 1893ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link, *newlink; 1894ec125fbbSEdward Tomasz Napierala struct uidinfo *newuip; 1895ec125fbbSEdward Tomasz Napierala struct loginclass *newlc; 1896a7ad07bfSEdward Tomasz Napierala struct prison_racct *newprr; 1897ec125fbbSEdward Tomasz Napierala LIST_HEAD(, rctl_rule_link) newrules; 1898ec125fbbSEdward Tomasz Napierala 18994b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 19004b5c9cf6SEdward Tomasz Napierala 1901ec125fbbSEdward Tomasz Napierala newuip = newcred->cr_ruidinfo; 1902ec125fbbSEdward Tomasz Napierala newlc = newcred->cr_loginclass; 1903a7ad07bfSEdward Tomasz Napierala newprr = newcred->cr_prison->pr_prison_racct; 1904ec125fbbSEdward Tomasz Napierala 1905ec125fbbSEdward Tomasz Napierala LIST_INIT(&newrules); 1906ec125fbbSEdward Tomasz Napierala 1907ec125fbbSEdward Tomasz Napierala again: 1908ec125fbbSEdward Tomasz Napierala /* 1909ec125fbbSEdward Tomasz Napierala * First, count the rules that apply to the process with new 1910ec125fbbSEdward Tomasz Napierala * credentials. 1911ec125fbbSEdward Tomasz Napierala */ 1912ec125fbbSEdward Tomasz Napierala rulecnt = 0; 19134c230cdaSEdward Tomasz Napierala RCTL_RLOCK(); 1914ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1915ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 1916ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) 1917ec125fbbSEdward Tomasz Napierala rulecnt++; 1918ec125fbbSEdward Tomasz Napierala } 1919ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) 1920ec125fbbSEdward Tomasz Napierala rulecnt++; 1921ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) 1922ec125fbbSEdward Tomasz Napierala rulecnt++; 1923a7ad07bfSEdward Tomasz Napierala LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) 1924ec125fbbSEdward Tomasz Napierala rulecnt++; 19254c230cdaSEdward Tomasz Napierala RCTL_RUNLOCK(); 1926ec125fbbSEdward Tomasz Napierala 1927ec125fbbSEdward Tomasz Napierala /* 1928ec125fbbSEdward Tomasz Napierala * Create temporary list. We've dropped the rctl_lock in order 1929ec125fbbSEdward Tomasz Napierala * to use M_WAITOK. 1930ec125fbbSEdward Tomasz Napierala */ 1931ec125fbbSEdward Tomasz Napierala for (i = 0; i < rulecnt; i++) { 1932ec125fbbSEdward Tomasz Napierala newlink = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 1933ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = NULL; 1934ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = 0; 1935ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&newrules, newlink, rrl_next); 1936ec125fbbSEdward Tomasz Napierala } 1937ec125fbbSEdward Tomasz Napierala 1938ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 1939ec125fbbSEdward Tomasz Napierala 1940ec125fbbSEdward Tomasz Napierala /* 1941ec125fbbSEdward Tomasz Napierala * Assign rules to the newly allocated list entries. 1942ec125fbbSEdward Tomasz Napierala */ 19434c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 1944ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1945ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 1946ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) { 1947ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1948ec125fbbSEdward Tomasz Napierala goto goaround; 1949ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1950ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1951ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1952ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1953ec125fbbSEdward Tomasz Napierala rulecnt--; 1954ec125fbbSEdward Tomasz Napierala } 1955ec125fbbSEdward Tomasz Napierala } 1956ec125fbbSEdward Tomasz Napierala 1957ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) { 1958ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1959ec125fbbSEdward Tomasz Napierala goto goaround; 1960ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1961ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1962ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1963ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1964ec125fbbSEdward Tomasz Napierala rulecnt--; 1965ec125fbbSEdward Tomasz Napierala } 1966ec125fbbSEdward Tomasz Napierala 1967ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) { 1968ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1969ec125fbbSEdward Tomasz Napierala goto goaround; 1970ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1971ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1972ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1973ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1974ec125fbbSEdward Tomasz Napierala rulecnt--; 1975ec125fbbSEdward Tomasz Napierala } 1976ec125fbbSEdward Tomasz Napierala 1977a7ad07bfSEdward Tomasz Napierala LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) { 1978ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1979ec125fbbSEdward Tomasz Napierala goto goaround; 1980ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1981ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1982ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1983ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1984ec125fbbSEdward Tomasz Napierala rulecnt--; 1985ec125fbbSEdward Tomasz Napierala } 1986ec125fbbSEdward Tomasz Napierala 1987ec125fbbSEdward Tomasz Napierala if (rulecnt == 0) { 1988ec125fbbSEdward Tomasz Napierala /* 1989ec125fbbSEdward Tomasz Napierala * Free the old rule list. 1990ec125fbbSEdward Tomasz Napierala */ 1991ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&p->p_racct->r_rule_links)) { 1992ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&p->p_racct->r_rule_links); 1993ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 1994ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 1995ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 1996ec125fbbSEdward Tomasz Napierala } 1997ec125fbbSEdward Tomasz Napierala 1998ec125fbbSEdward Tomasz Napierala /* 1999ec125fbbSEdward Tomasz Napierala * Replace lists and we're done. 2000ec125fbbSEdward Tomasz Napierala * 2001ec125fbbSEdward Tomasz Napierala * XXX: Is there any way to switch list heads instead 2002ec125fbbSEdward Tomasz Napierala * of iterating here? 2003ec125fbbSEdward Tomasz Napierala */ 2004ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&newrules)) { 2005ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 2006ec125fbbSEdward Tomasz Napierala LIST_REMOVE(newlink, rrl_next); 2007ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&p->p_racct->r_rule_links, 2008ec125fbbSEdward Tomasz Napierala newlink, rrl_next); 2009ec125fbbSEdward Tomasz Napierala } 2010ec125fbbSEdward Tomasz Napierala 20114c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 2012ec125fbbSEdward Tomasz Napierala 2013ec125fbbSEdward Tomasz Napierala return; 2014ec125fbbSEdward Tomasz Napierala } 2015ec125fbbSEdward Tomasz Napierala 2016ec125fbbSEdward Tomasz Napierala goaround: 20174c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 2018ec125fbbSEdward Tomasz Napierala 2019ec125fbbSEdward Tomasz Napierala /* 2020ec125fbbSEdward Tomasz Napierala * Rule list changed while we were not holding the rctl_lock. 2021ec125fbbSEdward Tomasz Napierala * Free the new list and try again. 2022ec125fbbSEdward Tomasz Napierala */ 2023ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&newrules)) { 2024ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 2025ec125fbbSEdward Tomasz Napierala LIST_REMOVE(newlink, rrl_next); 2026ec125fbbSEdward Tomasz Napierala if (newlink->rrl_rule != NULL) 2027ec125fbbSEdward Tomasz Napierala rctl_rule_release(newlink->rrl_rule); 2028ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, newlink); 2029ec125fbbSEdward Tomasz Napierala } 2030ec125fbbSEdward Tomasz Napierala 2031ec125fbbSEdward Tomasz Napierala goto again; 2032ec125fbbSEdward Tomasz Napierala } 2033ec125fbbSEdward Tomasz Napierala 2034ec125fbbSEdward Tomasz Napierala /* 2035ec125fbbSEdward Tomasz Napierala * Assign RCTL rules to the newly created process. 2036ec125fbbSEdward Tomasz Napierala */ 2037ec125fbbSEdward Tomasz Napierala int 2038ec125fbbSEdward Tomasz Napierala rctl_proc_fork(struct proc *parent, struct proc *child) 2039ec125fbbSEdward Tomasz Napierala { 2040ec125fbbSEdward Tomasz Napierala int error; 2041ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 2042ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 2043ec125fbbSEdward Tomasz Napierala 2044ec125fbbSEdward Tomasz Napierala LIST_INIT(&child->p_racct->r_rule_links); 2045ec125fbbSEdward Tomasz Napierala 20464b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 20470b18eb6dSEdward Tomasz Napierala KASSERT(parent->p_racct != NULL, ("process without racct; p = %p", parent)); 2048ec125fbbSEdward Tomasz Napierala 20494c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 2050ec125fbbSEdward Tomasz Napierala 2051ec125fbbSEdward Tomasz Napierala /* 2052ec125fbbSEdward Tomasz Napierala * Go through limits applicable to the parent and assign them 2053ec125fbbSEdward Tomasz Napierala * to the child. Rules with 'process' subject have to be duplicated 2054ec125fbbSEdward Tomasz Napierala * in order to make their rr_subject point to the new process. 2055ec125fbbSEdward Tomasz Napierala */ 2056ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &parent->p_racct->r_rule_links, rrl_next) { 2057ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 2058ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) { 2059ec125fbbSEdward Tomasz Napierala rule = rctl_rule_duplicate(link->rrl_rule, M_NOWAIT); 2060ec125fbbSEdward Tomasz Napierala if (rule == NULL) 2061ec125fbbSEdward Tomasz Napierala goto fail; 2062ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_subject.rs_proc == parent, 2063ec125fbbSEdward Tomasz Napierala ("rule->rr_subject.rs_proc != parent")); 2064ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = child; 2065ec125fbbSEdward Tomasz Napierala error = rctl_racct_add_rule_locked(child->p_racct, 2066ec125fbbSEdward Tomasz Napierala rule); 2067ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 2068ec125fbbSEdward Tomasz Napierala if (error != 0) 2069ec125fbbSEdward Tomasz Napierala goto fail; 2070ec125fbbSEdward Tomasz Napierala } else { 2071ec125fbbSEdward Tomasz Napierala error = rctl_racct_add_rule_locked(child->p_racct, 2072ec125fbbSEdward Tomasz Napierala link->rrl_rule); 2073ec125fbbSEdward Tomasz Napierala if (error != 0) 2074ec125fbbSEdward Tomasz Napierala goto fail; 2075ec125fbbSEdward Tomasz Napierala } 2076ec125fbbSEdward Tomasz Napierala } 2077ec125fbbSEdward Tomasz Napierala 20784c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 2079ec125fbbSEdward Tomasz Napierala return (0); 2080ec125fbbSEdward Tomasz Napierala 2081ec125fbbSEdward Tomasz Napierala fail: 2082ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&child->p_racct->r_rule_links)) { 2083ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&child->p_racct->r_rule_links); 2084ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 2085ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 2086ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 2087ec125fbbSEdward Tomasz Napierala } 20884c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 2089ec125fbbSEdward Tomasz Napierala return (EAGAIN); 2090ec125fbbSEdward Tomasz Napierala } 2091ec125fbbSEdward Tomasz Napierala 2092ec125fbbSEdward Tomasz Napierala /* 2093ec125fbbSEdward Tomasz Napierala * Release rules attached to the racct. 2094ec125fbbSEdward Tomasz Napierala */ 2095ec125fbbSEdward Tomasz Napierala void 2096ec125fbbSEdward Tomasz Napierala rctl_racct_release(struct racct *racct) 2097ec125fbbSEdward Tomasz Napierala { 2098ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 2099ec125fbbSEdward Tomasz Napierala 21004b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 21014b5c9cf6SEdward Tomasz Napierala 21024c230cdaSEdward Tomasz Napierala RCTL_WLOCK(); 2103ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&racct->r_rule_links)) { 2104ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&racct->r_rule_links); 2105ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 2106ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 2107ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 2108ec125fbbSEdward Tomasz Napierala } 21094c230cdaSEdward Tomasz Napierala RCTL_WUNLOCK(); 2110ec125fbbSEdward Tomasz Napierala } 2111ec125fbbSEdward Tomasz Napierala 2112ec125fbbSEdward Tomasz Napierala static void 2113ec125fbbSEdward Tomasz Napierala rctl_init(void) 2114ec125fbbSEdward Tomasz Napierala { 2115ec125fbbSEdward Tomasz Napierala 21164b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 21174b5c9cf6SEdward Tomasz Napierala return; 21184b5c9cf6SEdward Tomasz Napierala 2119ec125fbbSEdward Tomasz Napierala rctl_rule_link_zone = uma_zcreate("rctl_rule_link", 2120ec125fbbSEdward Tomasz Napierala sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL, 2121ec125fbbSEdward Tomasz Napierala UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 2122ec125fbbSEdward Tomasz Napierala rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), 2123ec125fbbSEdward Tomasz Napierala NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 2124*ae34b6ffSEdward Tomasz Napierala 2125*ae34b6ffSEdward Tomasz Napierala if (rctl_throttle_min <= 0) 2126*ae34b6ffSEdward Tomasz Napierala rctl_throttle_min = 1; 2127*ae34b6ffSEdward Tomasz Napierala if (rctl_throttle_max <= 0) 2128*ae34b6ffSEdward Tomasz Napierala rctl_throttle_max = 2 * hz; 2129*ae34b6ffSEdward Tomasz Napierala if (rctl_throttle_pct <= 0) 2130*ae34b6ffSEdward Tomasz Napierala rctl_throttle_pct = 100; 2131*ae34b6ffSEdward Tomasz Napierala if (rctl_throttle_pct2 <= 0) 2132*ae34b6ffSEdward Tomasz Napierala rctl_throttle_pct2 = 100; 2133ec125fbbSEdward Tomasz Napierala } 2134ec125fbbSEdward Tomasz Napierala 2135ec125fbbSEdward Tomasz Napierala #else /* !RCTL */ 2136ec125fbbSEdward Tomasz Napierala 2137ec125fbbSEdward Tomasz Napierala int 21388451d0ddSKip Macy sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) 2139ec125fbbSEdward Tomasz Napierala { 2140ec125fbbSEdward Tomasz Napierala 2141ec125fbbSEdward Tomasz Napierala return (ENOSYS); 2142ec125fbbSEdward Tomasz Napierala } 2143ec125fbbSEdward Tomasz Napierala 2144ec125fbbSEdward Tomasz Napierala int 21458451d0ddSKip Macy sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) 2146ec125fbbSEdward Tomasz Napierala { 2147ec125fbbSEdward Tomasz Napierala 2148ec125fbbSEdward Tomasz Napierala return (ENOSYS); 2149ec125fbbSEdward Tomasz Napierala } 2150ec125fbbSEdward Tomasz Napierala 2151ec125fbbSEdward Tomasz Napierala int 21528451d0ddSKip Macy sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) 2153ec125fbbSEdward Tomasz Napierala { 2154ec125fbbSEdward Tomasz Napierala 2155ec125fbbSEdward Tomasz Napierala return (ENOSYS); 2156ec125fbbSEdward Tomasz Napierala } 2157ec125fbbSEdward Tomasz Napierala 2158ec125fbbSEdward Tomasz Napierala int 21598451d0ddSKip Macy sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) 2160ec125fbbSEdward Tomasz Napierala { 2161ec125fbbSEdward Tomasz Napierala 2162ec125fbbSEdward Tomasz Napierala return (ENOSYS); 2163ec125fbbSEdward Tomasz Napierala } 2164ec125fbbSEdward Tomasz Napierala 2165ec125fbbSEdward Tomasz Napierala int 21668451d0ddSKip Macy sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) 2167ec125fbbSEdward Tomasz Napierala { 2168ec125fbbSEdward Tomasz Napierala 2169ec125fbbSEdward Tomasz Napierala return (ENOSYS); 2170ec125fbbSEdward Tomasz Napierala } 2171ec125fbbSEdward Tomasz Napierala 2172ec125fbbSEdward Tomasz Napierala #endif /* !RCTL */ 2173