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 80ea228b48SEdward Tomasz Napierala unsigned int rctl_maxbufsize = RCTL_MAX_OUTBUFSIZE; 812b4035eeSEdward Tomasz Napierala 822b4035eeSEdward Tomasz Napierala SYSCTL_NODE(_kern_racct, OID_AUTO, rctl, CTLFLAG_RW, 0, "Resource Limits"); 832b4035eeSEdward Tomasz Napierala SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, maxbufsize, CTLFLAG_RWTUN, 842b4035eeSEdward Tomasz Napierala &rctl_maxbufsize, 0, "Maximum output buffer size"); 852b4035eeSEdward Tomasz Napierala 86ec125fbbSEdward Tomasz Napierala /* 87ec125fbbSEdward Tomasz Napierala * 'rctl_rule_link' connects a rule with every racct it's related to. 88ec125fbbSEdward Tomasz Napierala * For example, rule 'user:X:openfiles:deny=N/process' is linked 89ec125fbbSEdward Tomasz Napierala * with uidinfo for user X, and to each process of that user. 90ec125fbbSEdward Tomasz Napierala */ 91ec125fbbSEdward Tomasz Napierala struct rctl_rule_link { 92ec125fbbSEdward Tomasz Napierala LIST_ENTRY(rctl_rule_link) rrl_next; 93ec125fbbSEdward Tomasz Napierala struct rctl_rule *rrl_rule; 94ec125fbbSEdward Tomasz Napierala int rrl_exceeded; 95ec125fbbSEdward Tomasz Napierala }; 96ec125fbbSEdward Tomasz Napierala 97ec125fbbSEdward Tomasz Napierala struct dict { 98ec125fbbSEdward Tomasz Napierala const char *d_name; 99ec125fbbSEdward Tomasz Napierala int d_value; 100ec125fbbSEdward Tomasz Napierala }; 101ec125fbbSEdward Tomasz Napierala 102ec125fbbSEdward Tomasz Napierala static struct dict subjectnames[] = { 103ec125fbbSEdward Tomasz Napierala { "process", RCTL_SUBJECT_TYPE_PROCESS }, 104ec125fbbSEdward Tomasz Napierala { "user", RCTL_SUBJECT_TYPE_USER }, 105ec125fbbSEdward Tomasz Napierala { "loginclass", RCTL_SUBJECT_TYPE_LOGINCLASS }, 106ec125fbbSEdward Tomasz Napierala { "jail", RCTL_SUBJECT_TYPE_JAIL }, 107ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 108ec125fbbSEdward Tomasz Napierala 109ec125fbbSEdward Tomasz Napierala static struct dict resourcenames[] = { 11085a2f1b4SEdward Tomasz Napierala { "cputime", RACCT_CPU }, 11185a2f1b4SEdward Tomasz Napierala { "datasize", RACCT_DATA }, 11285a2f1b4SEdward Tomasz Napierala { "stacksize", RACCT_STACK }, 11385a2f1b4SEdward Tomasz Napierala { "coredumpsize", RACCT_CORE }, 11485a2f1b4SEdward Tomasz Napierala { "memoryuse", RACCT_RSS }, 11585a2f1b4SEdward Tomasz Napierala { "memorylocked", RACCT_MEMLOCK }, 11685a2f1b4SEdward Tomasz Napierala { "maxproc", RACCT_NPROC }, 11785a2f1b4SEdward Tomasz Napierala { "openfiles", RACCT_NOFILE }, 11885a2f1b4SEdward Tomasz Napierala { "vmemoryuse", RACCT_VMEM }, 11985a2f1b4SEdward Tomasz Napierala { "pseudoterminals", RACCT_NPTS }, 12085a2f1b4SEdward Tomasz Napierala { "swapuse", RACCT_SWAP }, 121ec125fbbSEdward Tomasz Napierala { "nthr", RACCT_NTHR }, 122ec125fbbSEdward Tomasz Napierala { "msgqqueued", RACCT_MSGQQUEUED }, 123ec125fbbSEdward Tomasz Napierala { "msgqsize", RACCT_MSGQSIZE }, 124ec125fbbSEdward Tomasz Napierala { "nmsgq", RACCT_NMSGQ }, 125ec125fbbSEdward Tomasz Napierala { "nsem", RACCT_NSEM }, 126ec125fbbSEdward Tomasz Napierala { "nsemop", RACCT_NSEMOP }, 127ec125fbbSEdward Tomasz Napierala { "nshm", RACCT_NSHM }, 128ec125fbbSEdward Tomasz Napierala { "shmsize", RACCT_SHMSIZE }, 129ec125fbbSEdward Tomasz Napierala { "wallclock", RACCT_WALLCLOCK }, 13036af9869SEdward Tomasz Napierala { "pcpu", RACCT_PCTCPU }, 131ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 132ec125fbbSEdward Tomasz Napierala 133ec125fbbSEdward Tomasz Napierala static struct dict actionnames[] = { 134ec125fbbSEdward Tomasz Napierala { "sighup", RCTL_ACTION_SIGHUP }, 135ec125fbbSEdward Tomasz Napierala { "sigint", RCTL_ACTION_SIGINT }, 136ec125fbbSEdward Tomasz Napierala { "sigquit", RCTL_ACTION_SIGQUIT }, 137ec125fbbSEdward Tomasz Napierala { "sigill", RCTL_ACTION_SIGILL }, 138ec125fbbSEdward Tomasz Napierala { "sigtrap", RCTL_ACTION_SIGTRAP }, 139ec125fbbSEdward Tomasz Napierala { "sigabrt", RCTL_ACTION_SIGABRT }, 140ec125fbbSEdward Tomasz Napierala { "sigemt", RCTL_ACTION_SIGEMT }, 141ec125fbbSEdward Tomasz Napierala { "sigfpe", RCTL_ACTION_SIGFPE }, 142ec125fbbSEdward Tomasz Napierala { "sigkill", RCTL_ACTION_SIGKILL }, 143ec125fbbSEdward Tomasz Napierala { "sigbus", RCTL_ACTION_SIGBUS }, 144ec125fbbSEdward Tomasz Napierala { "sigsegv", RCTL_ACTION_SIGSEGV }, 145ec125fbbSEdward Tomasz Napierala { "sigsys", RCTL_ACTION_SIGSYS }, 146ec125fbbSEdward Tomasz Napierala { "sigpipe", RCTL_ACTION_SIGPIPE }, 147ec125fbbSEdward Tomasz Napierala { "sigalrm", RCTL_ACTION_SIGALRM }, 148ec125fbbSEdward Tomasz Napierala { "sigterm", RCTL_ACTION_SIGTERM }, 149ec125fbbSEdward Tomasz Napierala { "sigurg", RCTL_ACTION_SIGURG }, 150ec125fbbSEdward Tomasz Napierala { "sigstop", RCTL_ACTION_SIGSTOP }, 151ec125fbbSEdward Tomasz Napierala { "sigtstp", RCTL_ACTION_SIGTSTP }, 152ec125fbbSEdward Tomasz Napierala { "sigchld", RCTL_ACTION_SIGCHLD }, 153ec125fbbSEdward Tomasz Napierala { "sigttin", RCTL_ACTION_SIGTTIN }, 154ec125fbbSEdward Tomasz Napierala { "sigttou", RCTL_ACTION_SIGTTOU }, 155ec125fbbSEdward Tomasz Napierala { "sigio", RCTL_ACTION_SIGIO }, 156ec125fbbSEdward Tomasz Napierala { "sigxcpu", RCTL_ACTION_SIGXCPU }, 157ec125fbbSEdward Tomasz Napierala { "sigxfsz", RCTL_ACTION_SIGXFSZ }, 158ec125fbbSEdward Tomasz Napierala { "sigvtalrm", RCTL_ACTION_SIGVTALRM }, 159ec125fbbSEdward Tomasz Napierala { "sigprof", RCTL_ACTION_SIGPROF }, 160ec125fbbSEdward Tomasz Napierala { "sigwinch", RCTL_ACTION_SIGWINCH }, 161ec125fbbSEdward Tomasz Napierala { "siginfo", RCTL_ACTION_SIGINFO }, 162ec125fbbSEdward Tomasz Napierala { "sigusr1", RCTL_ACTION_SIGUSR1 }, 163ec125fbbSEdward Tomasz Napierala { "sigusr2", RCTL_ACTION_SIGUSR2 }, 164ec125fbbSEdward Tomasz Napierala { "sigthr", RCTL_ACTION_SIGTHR }, 165ec125fbbSEdward Tomasz Napierala { "deny", RCTL_ACTION_DENY }, 166ec125fbbSEdward Tomasz Napierala { "log", RCTL_ACTION_LOG }, 167ec125fbbSEdward Tomasz Napierala { "devctl", RCTL_ACTION_DEVCTL }, 168ec125fbbSEdward Tomasz Napierala { NULL, -1 }}; 169ec125fbbSEdward Tomasz Napierala 170ec125fbbSEdward Tomasz Napierala static void rctl_init(void); 171ec125fbbSEdward Tomasz Napierala SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL); 172ec125fbbSEdward Tomasz Napierala 173ec125fbbSEdward Tomasz Napierala static uma_zone_t rctl_rule_link_zone; 174ec125fbbSEdward Tomasz Napierala static uma_zone_t rctl_rule_zone; 175ec125fbbSEdward Tomasz Napierala static struct rwlock rctl_lock; 176ec125fbbSEdward Tomasz Napierala RW_SYSINIT(rctl_lock, &rctl_lock, "RCTL lock"); 177ec125fbbSEdward Tomasz Napierala 178ec125fbbSEdward Tomasz Napierala static int rctl_rule_fully_specified(const struct rctl_rule *rule); 179ec125fbbSEdward Tomasz Napierala static void rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule); 180ec125fbbSEdward Tomasz Napierala 181d745c852SEd Schouten static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits"); 182ec125fbbSEdward Tomasz Napierala 183ec125fbbSEdward Tomasz Napierala static const char * 184ec125fbbSEdward Tomasz Napierala rctl_subject_type_name(int subject) 185ec125fbbSEdward Tomasz Napierala { 186ec125fbbSEdward Tomasz Napierala int i; 187ec125fbbSEdward Tomasz Napierala 188ec125fbbSEdward Tomasz Napierala for (i = 0; subjectnames[i].d_name != NULL; i++) { 189ec125fbbSEdward Tomasz Napierala if (subjectnames[i].d_value == subject) 190ec125fbbSEdward Tomasz Napierala return (subjectnames[i].d_name); 191ec125fbbSEdward Tomasz Napierala } 192ec125fbbSEdward Tomasz Napierala 193ec125fbbSEdward Tomasz Napierala panic("rctl_subject_type_name: unknown subject type %d", subject); 194ec125fbbSEdward Tomasz Napierala } 195ec125fbbSEdward Tomasz Napierala 196ec125fbbSEdward Tomasz Napierala static const char * 197ec125fbbSEdward Tomasz Napierala rctl_action_name(int action) 198ec125fbbSEdward Tomasz Napierala { 199ec125fbbSEdward Tomasz Napierala int i; 200ec125fbbSEdward Tomasz Napierala 201ec125fbbSEdward Tomasz Napierala for (i = 0; actionnames[i].d_name != NULL; i++) { 202ec125fbbSEdward Tomasz Napierala if (actionnames[i].d_value == action) 203ec125fbbSEdward Tomasz Napierala return (actionnames[i].d_name); 204ec125fbbSEdward Tomasz Napierala } 205ec125fbbSEdward Tomasz Napierala 206ec125fbbSEdward Tomasz Napierala panic("rctl_action_name: unknown action %d", action); 207ec125fbbSEdward Tomasz Napierala } 208ec125fbbSEdward Tomasz Napierala 209ec125fbbSEdward Tomasz Napierala const char * 210ec125fbbSEdward Tomasz Napierala rctl_resource_name(int resource) 211ec125fbbSEdward Tomasz Napierala { 212ec125fbbSEdward Tomasz Napierala int i; 213ec125fbbSEdward Tomasz Napierala 214ec125fbbSEdward Tomasz Napierala for (i = 0; resourcenames[i].d_name != NULL; i++) { 215ec125fbbSEdward Tomasz Napierala if (resourcenames[i].d_value == resource) 216ec125fbbSEdward Tomasz Napierala return (resourcenames[i].d_name); 217ec125fbbSEdward Tomasz Napierala } 218ec125fbbSEdward Tomasz Napierala 219ec125fbbSEdward Tomasz Napierala panic("rctl_resource_name: unknown resource %d", resource); 220ec125fbbSEdward Tomasz Napierala } 221ec125fbbSEdward Tomasz Napierala 222*ac3c9819SEdward Tomasz Napierala static struct racct * 223*ac3c9819SEdward Tomasz Napierala rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule) 224*ac3c9819SEdward Tomasz Napierala { 225*ac3c9819SEdward Tomasz Napierala struct ucred *cred = p->p_ucred; 226*ac3c9819SEdward Tomasz Napierala 227*ac3c9819SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 228*ac3c9819SEdward Tomasz Napierala rw_assert(&rctl_lock, RA_LOCKED); 229*ac3c9819SEdward Tomasz Napierala 230*ac3c9819SEdward Tomasz Napierala switch (rule->rr_per) { 231*ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 232*ac3c9819SEdward Tomasz Napierala return (p->p_racct); 233*ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 234*ac3c9819SEdward Tomasz Napierala return (cred->cr_ruidinfo->ui_racct); 235*ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 236*ac3c9819SEdward Tomasz Napierala return (cred->cr_loginclass->lc_racct); 237*ac3c9819SEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 238*ac3c9819SEdward Tomasz Napierala return (cred->cr_prison->pr_prison_racct->prr_racct); 239*ac3c9819SEdward Tomasz Napierala default: 240*ac3c9819SEdward Tomasz Napierala panic("%s: unknown per %d", __func__, rule->rr_per); 241*ac3c9819SEdward Tomasz Napierala } 242*ac3c9819SEdward Tomasz Napierala } 243*ac3c9819SEdward Tomasz Napierala 244ec125fbbSEdward Tomasz Napierala /* 245ec125fbbSEdward Tomasz Napierala * Return the amount of resource that can be allocated by 'p' before 246ec125fbbSEdward Tomasz Napierala * hitting 'rule'. 247ec125fbbSEdward Tomasz Napierala */ 248ec125fbbSEdward Tomasz Napierala static int64_t 249ec125fbbSEdward Tomasz Napierala rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) 250ec125fbbSEdward Tomasz Napierala { 251*ac3c9819SEdward Tomasz Napierala int64_t available; 252*ac3c9819SEdward Tomasz Napierala const struct racct *racct; 253ec125fbbSEdward Tomasz Napierala 2544b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 255ec125fbbSEdward Tomasz Napierala rw_assert(&rctl_lock, RA_LOCKED); 256ec125fbbSEdward Tomasz Napierala 257*ac3c9819SEdward Tomasz Napierala racct = rctl_proc_rule_to_racct(p, rule); 258*ac3c9819SEdward Tomasz Napierala available = rule->rr_amount - racct->r_resources[rule->rr_resource]; 259ec125fbbSEdward Tomasz Napierala 260ec125fbbSEdward Tomasz Napierala return (available); 261ec125fbbSEdward Tomasz Napierala } 262ec125fbbSEdward Tomasz Napierala 263ec125fbbSEdward Tomasz Napierala /* 264ec125fbbSEdward Tomasz Napierala * Return non-zero if allocating 'amount' by proc 'p' would exceed 265ec125fbbSEdward Tomasz Napierala * resource limit specified by 'rule'. 266ec125fbbSEdward Tomasz Napierala */ 267ec125fbbSEdward Tomasz Napierala static int 268ec125fbbSEdward Tomasz Napierala rctl_would_exceed(const struct proc *p, const struct rctl_rule *rule, 269ec125fbbSEdward Tomasz Napierala int64_t amount) 270ec125fbbSEdward Tomasz Napierala { 271ec125fbbSEdward Tomasz Napierala int64_t available; 272ec125fbbSEdward Tomasz Napierala 2734b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 2744b5c9cf6SEdward Tomasz Napierala 275ec125fbbSEdward Tomasz Napierala rw_assert(&rctl_lock, RA_LOCKED); 276ec125fbbSEdward Tomasz Napierala 277ec125fbbSEdward Tomasz Napierala available = rctl_available_resource(p, rule); 278ec125fbbSEdward Tomasz Napierala if (available >= amount) 279ec125fbbSEdward Tomasz Napierala return (0); 280ec125fbbSEdward Tomasz Napierala 281ec125fbbSEdward Tomasz Napierala return (1); 282ec125fbbSEdward Tomasz Napierala } 283ec125fbbSEdward Tomasz Napierala 284ec125fbbSEdward Tomasz Napierala /* 285af1a7b25SEdward Tomasz Napierala * Special version of rctl_get_available() for the %CPU resource. 28636af9869SEdward Tomasz Napierala * We slightly cheat here and return less than we normally would. 28736af9869SEdward Tomasz Napierala */ 28836af9869SEdward Tomasz Napierala int64_t 28936af9869SEdward Tomasz Napierala rctl_pcpu_available(const struct proc *p) { 29036af9869SEdward Tomasz Napierala struct rctl_rule *rule; 29136af9869SEdward Tomasz Napierala struct rctl_rule_link *link; 29236af9869SEdward Tomasz Napierala int64_t available, minavailable, limit; 29336af9869SEdward Tomasz Napierala 2944b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 2954b5c9cf6SEdward Tomasz Napierala 29636af9869SEdward Tomasz Napierala minavailable = INT64_MAX; 29736af9869SEdward Tomasz Napierala limit = 0; 29836af9869SEdward Tomasz Napierala 29936af9869SEdward Tomasz Napierala rw_rlock(&rctl_lock); 30036af9869SEdward Tomasz Napierala 30136af9869SEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 30236af9869SEdward Tomasz Napierala rule = link->rrl_rule; 30336af9869SEdward Tomasz Napierala if (rule->rr_resource != RACCT_PCTCPU) 30436af9869SEdward Tomasz Napierala continue; 30536af9869SEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 30636af9869SEdward Tomasz Napierala continue; 30736af9869SEdward Tomasz Napierala available = rctl_available_resource(p, rule); 30836af9869SEdward Tomasz Napierala if (available < minavailable) { 30936af9869SEdward Tomasz Napierala minavailable = available; 31036af9869SEdward Tomasz Napierala limit = rule->rr_amount; 31136af9869SEdward Tomasz Napierala } 31236af9869SEdward Tomasz Napierala } 31336af9869SEdward Tomasz Napierala 31436af9869SEdward Tomasz Napierala rw_runlock(&rctl_lock); 31536af9869SEdward Tomasz Napierala 31636af9869SEdward Tomasz Napierala /* 31736af9869SEdward Tomasz Napierala * Return slightly less than actual value of the available 31836af9869SEdward Tomasz Napierala * %cpu resource. This makes %cpu throttling more agressive 31936af9869SEdward Tomasz Napierala * and lets us act sooner than the limits are already exceeded. 32036af9869SEdward Tomasz Napierala */ 32136af9869SEdward Tomasz Napierala if (limit != 0) { 32236af9869SEdward Tomasz Napierala if (limit > 2 * RCTL_PCPU_SHIFT) 32336af9869SEdward Tomasz Napierala minavailable -= RCTL_PCPU_SHIFT; 32436af9869SEdward Tomasz Napierala else 32536af9869SEdward Tomasz Napierala minavailable -= (limit / 2); 32636af9869SEdward Tomasz Napierala } 32736af9869SEdward Tomasz Napierala 32836af9869SEdward Tomasz Napierala return (minavailable); 32936af9869SEdward Tomasz Napierala } 33036af9869SEdward Tomasz Napierala 33136af9869SEdward Tomasz Napierala /* 332ec125fbbSEdward Tomasz Napierala * Check whether the proc 'p' can allocate 'amount' of 'resource' in addition 333ec125fbbSEdward Tomasz Napierala * to what it keeps allocated now. Returns non-zero if the allocation should 334ec125fbbSEdward Tomasz Napierala * be denied, 0 otherwise. 335ec125fbbSEdward Tomasz Napierala */ 336ec125fbbSEdward Tomasz Napierala int 337ec125fbbSEdward Tomasz Napierala rctl_enforce(struct proc *p, int resource, uint64_t amount) 338ec125fbbSEdward Tomasz Napierala { 339ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 340ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 341ec125fbbSEdward Tomasz Napierala struct sbuf sb; 342ec125fbbSEdward Tomasz Napierala int should_deny = 0; 343ec125fbbSEdward Tomasz Napierala char *buf; 344ec125fbbSEdward Tomasz Napierala static int curtime = 0; 345ec125fbbSEdward Tomasz Napierala static struct timeval lasttime; 346ec125fbbSEdward Tomasz Napierala 3474b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 3484b5c9cf6SEdward Tomasz Napierala 349ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 350ec125fbbSEdward Tomasz Napierala 351ec125fbbSEdward Tomasz Napierala /* 352ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 353ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 354ec125fbbSEdward Tomasz Napierala */ 355ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 356ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 357ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 358ec125fbbSEdward Tomasz Napierala continue; 359ec125fbbSEdward Tomasz Napierala if (!rctl_would_exceed(p, rule, amount)) { 360ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 361ec125fbbSEdward Tomasz Napierala continue; 362ec125fbbSEdward Tomasz Napierala } 363ec125fbbSEdward Tomasz Napierala 364ec125fbbSEdward Tomasz Napierala switch (rule->rr_action) { 365ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_DENY: 366ec125fbbSEdward Tomasz Napierala should_deny = 1; 367ec125fbbSEdward Tomasz Napierala continue; 368ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_LOG: 369ec125fbbSEdward Tomasz Napierala /* 370ec125fbbSEdward Tomasz Napierala * If rrl_exceeded != 0, it means we've already 371ec125fbbSEdward Tomasz Napierala * logged a warning for this process. 372ec125fbbSEdward Tomasz Napierala */ 373ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 374ec125fbbSEdward Tomasz Napierala continue; 375ec125fbbSEdward Tomasz Napierala 37672a401d9SEdward Tomasz Napierala /* 37772a401d9SEdward Tomasz Napierala * If the process state is not fully initialized yet, 37872a401d9SEdward Tomasz Napierala * we can't access most of the required fields, e.g. 37972a401d9SEdward Tomasz Napierala * p->p_comm. This happens when called from fork1(). 38072a401d9SEdward Tomasz Napierala * Ignore this rule for now; it will be processed just 38172a401d9SEdward Tomasz Napierala * after fork, when called from racct_proc_fork_done(). 38272a401d9SEdward Tomasz Napierala */ 38372a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 38472a401d9SEdward Tomasz Napierala continue; 38572a401d9SEdward Tomasz Napierala 386ec125fbbSEdward Tomasz Napierala if (!ppsratecheck(&lasttime, &curtime, 10)) 387ec125fbbSEdward Tomasz Napierala continue; 388ec125fbbSEdward Tomasz Napierala 389ec125fbbSEdward Tomasz Napierala buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); 390ec125fbbSEdward Tomasz Napierala if (buf == NULL) { 391ec125fbbSEdward Tomasz Napierala printf("rctl_enforce: out of memory\n"); 392ec125fbbSEdward Tomasz Napierala continue; 393ec125fbbSEdward Tomasz Napierala } 394ec125fbbSEdward Tomasz Napierala sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); 395ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(&sb, rule); 396ec125fbbSEdward Tomasz Napierala sbuf_finish(&sb); 397ec125fbbSEdward Tomasz Napierala printf("rctl: rule \"%s\" matched by pid %d " 398ec125fbbSEdward Tomasz Napierala "(%s), uid %d, jail %s\n", sbuf_data(&sb), 399ec125fbbSEdward Tomasz Napierala p->p_pid, p->p_comm, p->p_ucred->cr_uid, 400a7ad07bfSEdward Tomasz Napierala p->p_ucred->cr_prison->pr_prison_racct->prr_name); 401ec125fbbSEdward Tomasz Napierala sbuf_delete(&sb); 402ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 403ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 404ec125fbbSEdward Tomasz Napierala continue; 405ec125fbbSEdward Tomasz Napierala case RCTL_ACTION_DEVCTL: 406ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 407ec125fbbSEdward Tomasz Napierala continue; 408ec125fbbSEdward Tomasz Napierala 40972a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 41072a401d9SEdward Tomasz Napierala continue; 41172a401d9SEdward Tomasz Napierala 412ec125fbbSEdward Tomasz Napierala buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); 413ec125fbbSEdward Tomasz Napierala if (buf == NULL) { 414ec125fbbSEdward Tomasz Napierala printf("rctl_enforce: out of memory\n"); 415ec125fbbSEdward Tomasz Napierala continue; 416ec125fbbSEdward Tomasz Napierala } 417ec125fbbSEdward Tomasz Napierala sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); 418ec125fbbSEdward Tomasz Napierala sbuf_printf(&sb, "rule="); 419ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(&sb, rule); 420ec125fbbSEdward Tomasz Napierala sbuf_printf(&sb, " pid=%d ruid=%d jail=%s", 421ec125fbbSEdward Tomasz Napierala p->p_pid, p->p_ucred->cr_ruid, 422a7ad07bfSEdward Tomasz Napierala p->p_ucred->cr_prison->pr_prison_racct->prr_name); 423ec125fbbSEdward Tomasz Napierala sbuf_finish(&sb); 424ec125fbbSEdward Tomasz Napierala devctl_notify_f("RCTL", "rule", "matched", 425ec125fbbSEdward Tomasz Napierala sbuf_data(&sb), M_NOWAIT); 426ec125fbbSEdward Tomasz Napierala sbuf_delete(&sb); 427ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 428ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 429ec125fbbSEdward Tomasz Napierala continue; 430ec125fbbSEdward Tomasz Napierala default: 431ec125fbbSEdward Tomasz Napierala if (link->rrl_exceeded != 0) 432ec125fbbSEdward Tomasz Napierala continue; 433ec125fbbSEdward Tomasz Napierala 43472a401d9SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 43572a401d9SEdward Tomasz Napierala continue; 43672a401d9SEdward Tomasz Napierala 437ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_action > 0 && 438ec125fbbSEdward Tomasz Napierala rule->rr_action <= RCTL_ACTION_SIGNAL_MAX, 439ec125fbbSEdward Tomasz Napierala ("rctl_enforce: unknown action %d", 440ec125fbbSEdward Tomasz Napierala rule->rr_action)); 441ec125fbbSEdward Tomasz Napierala 442ec125fbbSEdward Tomasz Napierala /* 443ec125fbbSEdward Tomasz Napierala * We're using the fact that RCTL_ACTION_SIG* values 444ec125fbbSEdward Tomasz Napierala * are equal to their counterparts from sys/signal.h. 445ec125fbbSEdward Tomasz Napierala */ 4468451d0ddSKip Macy kern_psignal(p, rule->rr_action); 447ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 1; 448ec125fbbSEdward Tomasz Napierala continue; 449ec125fbbSEdward Tomasz Napierala } 450ec125fbbSEdward Tomasz Napierala } 451ec125fbbSEdward Tomasz Napierala 452ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 453ec125fbbSEdward Tomasz Napierala 454ec125fbbSEdward Tomasz Napierala if (should_deny) { 455ec125fbbSEdward Tomasz Napierala /* 456ec125fbbSEdward Tomasz Napierala * Return fake error code; the caller should change it 457ec125fbbSEdward Tomasz Napierala * into one proper for the situation - EFSIZ, ENOMEM etc. 458ec125fbbSEdward Tomasz Napierala */ 459ec125fbbSEdward Tomasz Napierala return (EDOOFUS); 460ec125fbbSEdward Tomasz Napierala } 461ec125fbbSEdward Tomasz Napierala 462ec125fbbSEdward Tomasz Napierala return (0); 463ec125fbbSEdward Tomasz Napierala } 464ec125fbbSEdward Tomasz Napierala 465ec125fbbSEdward Tomasz Napierala uint64_t 466ec125fbbSEdward Tomasz Napierala rctl_get_limit(struct proc *p, int resource) 467ec125fbbSEdward Tomasz Napierala { 468ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 469ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 470ec125fbbSEdward Tomasz Napierala uint64_t amount = UINT64_MAX; 471ec125fbbSEdward Tomasz Napierala 4724b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 4734b5c9cf6SEdward Tomasz Napierala 474ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 475ec125fbbSEdward Tomasz Napierala 476ec125fbbSEdward Tomasz Napierala /* 477ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 478ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 479ec125fbbSEdward Tomasz Napierala */ 480ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 481ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 482ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 483ec125fbbSEdward Tomasz Napierala continue; 484ec125fbbSEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 485ec125fbbSEdward Tomasz Napierala continue; 486ec125fbbSEdward Tomasz Napierala if (rule->rr_amount < amount) 487ec125fbbSEdward Tomasz Napierala amount = rule->rr_amount; 488ec125fbbSEdward Tomasz Napierala } 489ec125fbbSEdward Tomasz Napierala 490ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 491ec125fbbSEdward Tomasz Napierala 492ec125fbbSEdward Tomasz Napierala return (amount); 493ec125fbbSEdward Tomasz Napierala } 494ec125fbbSEdward Tomasz Napierala 495ec125fbbSEdward Tomasz Napierala uint64_t 496ec125fbbSEdward Tomasz Napierala rctl_get_available(struct proc *p, int resource) 497ec125fbbSEdward Tomasz Napierala { 498ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 499ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 500ec125fbbSEdward Tomasz Napierala int64_t available, minavailable, allocated; 501ec125fbbSEdward Tomasz Napierala 502ec125fbbSEdward Tomasz Napierala minavailable = INT64_MAX; 503ec125fbbSEdward Tomasz Napierala 5044b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 5054b5c9cf6SEdward Tomasz Napierala 506ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 507ec125fbbSEdward Tomasz Napierala 508ec125fbbSEdward Tomasz Napierala /* 509ec125fbbSEdward Tomasz Napierala * There may be more than one matching rule; go through all of them. 510ec125fbbSEdward Tomasz Napierala * Denial should be done last, after logging and sending signals. 511ec125fbbSEdward Tomasz Napierala */ 512ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 513ec125fbbSEdward Tomasz Napierala rule = link->rrl_rule; 514ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != resource) 515ec125fbbSEdward Tomasz Napierala continue; 516ec125fbbSEdward Tomasz Napierala if (rule->rr_action != RCTL_ACTION_DENY) 517ec125fbbSEdward Tomasz Napierala continue; 518ec125fbbSEdward Tomasz Napierala available = rctl_available_resource(p, rule); 519ec125fbbSEdward Tomasz Napierala if (available < minavailable) 520ec125fbbSEdward Tomasz Napierala minavailable = available; 521ec125fbbSEdward Tomasz Napierala } 522ec125fbbSEdward Tomasz Napierala 523ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 524ec125fbbSEdward Tomasz Napierala 525ec125fbbSEdward Tomasz Napierala /* 526ec125fbbSEdward Tomasz Napierala * XXX: Think about this _hard_. 527ec125fbbSEdward Tomasz Napierala */ 528ec125fbbSEdward Tomasz Napierala allocated = p->p_racct->r_resources[resource]; 529ec125fbbSEdward Tomasz Napierala if (minavailable < INT64_MAX - allocated) 530ec125fbbSEdward Tomasz Napierala minavailable += allocated; 531ec125fbbSEdward Tomasz Napierala if (minavailable < 0) 532ec125fbbSEdward Tomasz Napierala minavailable = 0; 533ec125fbbSEdward Tomasz Napierala return (minavailable); 534ec125fbbSEdward Tomasz Napierala } 535ec125fbbSEdward Tomasz Napierala 536ec125fbbSEdward Tomasz Napierala static int 537ec125fbbSEdward Tomasz Napierala rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter) 538ec125fbbSEdward Tomasz Napierala { 539ec125fbbSEdward Tomasz Napierala 5404b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 5414b5c9cf6SEdward Tomasz Napierala 542ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED) { 543ec125fbbSEdward Tomasz Napierala if (rule->rr_subject_type != filter->rr_subject_type) 544ec125fbbSEdward Tomasz Napierala return (0); 545ec125fbbSEdward Tomasz Napierala 546ec125fbbSEdward Tomasz Napierala switch (filter->rr_subject_type) { 547ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 548ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_proc != NULL && 549ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc != 550ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_proc) 551ec125fbbSEdward Tomasz Napierala return (0); 552ec125fbbSEdward Tomasz Napierala break; 553ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 554ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_uip != NULL && 555ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip != 556ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_uip) 557ec125fbbSEdward Tomasz Napierala return (0); 558ec125fbbSEdward Tomasz Napierala break; 559ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 560415896e3SEdward Tomasz Napierala if (filter->rr_subject.rs_loginclass != NULL && 561415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass != 562415896e3SEdward Tomasz Napierala filter->rr_subject.rs_loginclass) 563ec125fbbSEdward Tomasz Napierala return (0); 564ec125fbbSEdward Tomasz Napierala break; 565ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 566a7ad07bfSEdward Tomasz Napierala if (filter->rr_subject.rs_prison_racct != NULL && 567a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct != 568a7ad07bfSEdward Tomasz Napierala filter->rr_subject.rs_prison_racct) 569ec125fbbSEdward Tomasz Napierala return (0); 570ec125fbbSEdward Tomasz Napierala break; 571ec125fbbSEdward Tomasz Napierala default: 572ec125fbbSEdward Tomasz Napierala panic("rctl_rule_matches: unknown subject type %d", 573ec125fbbSEdward Tomasz Napierala filter->rr_subject_type); 574ec125fbbSEdward Tomasz Napierala } 575ec125fbbSEdward Tomasz Napierala } 576ec125fbbSEdward Tomasz Napierala 577ec125fbbSEdward Tomasz Napierala if (filter->rr_resource != RACCT_UNDEFINED) { 578ec125fbbSEdward Tomasz Napierala if (rule->rr_resource != filter->rr_resource) 579ec125fbbSEdward Tomasz Napierala return (0); 580ec125fbbSEdward Tomasz Napierala } 581ec125fbbSEdward Tomasz Napierala 582ec125fbbSEdward Tomasz Napierala if (filter->rr_action != RCTL_ACTION_UNDEFINED) { 583ec125fbbSEdward Tomasz Napierala if (rule->rr_action != filter->rr_action) 584ec125fbbSEdward Tomasz Napierala return (0); 585ec125fbbSEdward Tomasz Napierala } 586ec125fbbSEdward Tomasz Napierala 587ec125fbbSEdward Tomasz Napierala if (filter->rr_amount != RCTL_AMOUNT_UNDEFINED) { 588ec125fbbSEdward Tomasz Napierala if (rule->rr_amount != filter->rr_amount) 589ec125fbbSEdward Tomasz Napierala return (0); 590ec125fbbSEdward Tomasz Napierala } 591ec125fbbSEdward Tomasz Napierala 592ec125fbbSEdward Tomasz Napierala if (filter->rr_per != RCTL_SUBJECT_TYPE_UNDEFINED) { 593ec125fbbSEdward Tomasz Napierala if (rule->rr_per != filter->rr_per) 594ec125fbbSEdward Tomasz Napierala return (0); 595ec125fbbSEdward Tomasz Napierala } 596ec125fbbSEdward Tomasz Napierala 597ec125fbbSEdward Tomasz Napierala return (1); 598ec125fbbSEdward Tomasz Napierala } 599ec125fbbSEdward Tomasz Napierala 600ec125fbbSEdward Tomasz Napierala static int 601ec125fbbSEdward Tomasz Napierala str2value(const char *str, int *value, struct dict *table) 602ec125fbbSEdward Tomasz Napierala { 603ec125fbbSEdward Tomasz Napierala int i; 604ec125fbbSEdward Tomasz Napierala 605ec125fbbSEdward Tomasz Napierala if (value == NULL) 606ec125fbbSEdward Tomasz Napierala return (EINVAL); 607ec125fbbSEdward Tomasz Napierala 608ec125fbbSEdward Tomasz Napierala for (i = 0; table[i].d_name != NULL; i++) { 609ec125fbbSEdward Tomasz Napierala if (strcasecmp(table[i].d_name, str) == 0) { 610ec125fbbSEdward Tomasz Napierala *value = table[i].d_value; 611ec125fbbSEdward Tomasz Napierala return (0); 612ec125fbbSEdward Tomasz Napierala } 613ec125fbbSEdward Tomasz Napierala } 614ec125fbbSEdward Tomasz Napierala 615ec125fbbSEdward Tomasz Napierala return (EINVAL); 616ec125fbbSEdward Tomasz Napierala } 617ec125fbbSEdward Tomasz Napierala 618ec125fbbSEdward Tomasz Napierala static int 619ec125fbbSEdward Tomasz Napierala str2id(const char *str, id_t *value) 620ec125fbbSEdward Tomasz Napierala { 621ec125fbbSEdward Tomasz Napierala char *end; 622ec125fbbSEdward Tomasz Napierala 623ec125fbbSEdward Tomasz Napierala if (str == NULL) 624ec125fbbSEdward Tomasz Napierala return (EINVAL); 625ec125fbbSEdward Tomasz Napierala 626ec125fbbSEdward Tomasz Napierala *value = strtoul(str, &end, 10); 627ec125fbbSEdward Tomasz Napierala if ((size_t)(end - str) != strlen(str)) 628ec125fbbSEdward Tomasz Napierala return (EINVAL); 629ec125fbbSEdward Tomasz Napierala 630ec125fbbSEdward Tomasz Napierala return (0); 631ec125fbbSEdward Tomasz Napierala } 632ec125fbbSEdward Tomasz Napierala 633ec125fbbSEdward Tomasz Napierala static int 634ec125fbbSEdward Tomasz Napierala str2int64(const char *str, int64_t *value) 635ec125fbbSEdward Tomasz Napierala { 636ec125fbbSEdward Tomasz Napierala char *end; 637ec125fbbSEdward Tomasz Napierala 638ec125fbbSEdward Tomasz Napierala if (str == NULL) 639ec125fbbSEdward Tomasz Napierala return (EINVAL); 640ec125fbbSEdward Tomasz Napierala 641ec125fbbSEdward Tomasz Napierala *value = strtoul(str, &end, 10); 642ec125fbbSEdward Tomasz Napierala if ((size_t)(end - str) != strlen(str)) 643ec125fbbSEdward Tomasz Napierala return (EINVAL); 644ec125fbbSEdward Tomasz Napierala 645b450d447SEdward Tomasz Napierala if (*value < 0) 646b450d447SEdward Tomasz Napierala return (ERANGE); 647b450d447SEdward Tomasz Napierala 648ec125fbbSEdward Tomasz Napierala return (0); 649ec125fbbSEdward Tomasz Napierala } 650ec125fbbSEdward Tomasz Napierala 651ec125fbbSEdward Tomasz Napierala /* 652ec125fbbSEdward Tomasz Napierala * Connect the rule to the racct, increasing refcount for the rule. 653ec125fbbSEdward Tomasz Napierala */ 654ec125fbbSEdward Tomasz Napierala static void 655ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(struct racct *racct, struct rctl_rule *rule) 656ec125fbbSEdward Tomasz Napierala { 657ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 658ec125fbbSEdward Tomasz Napierala 6594b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 660ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 661ec125fbbSEdward Tomasz Napierala 662ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(rule); 663ec125fbbSEdward Tomasz Napierala link = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 664ec125fbbSEdward Tomasz Napierala link->rrl_rule = rule; 665ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 666ec125fbbSEdward Tomasz Napierala 667ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 668ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); 669ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 670ec125fbbSEdward Tomasz Napierala } 671ec125fbbSEdward Tomasz Napierala 672ec125fbbSEdward Tomasz Napierala static int 673ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule_locked(struct racct *racct, struct rctl_rule *rule) 674ec125fbbSEdward Tomasz Napierala { 675ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 676ec125fbbSEdward Tomasz Napierala 6774b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 678ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 679ec125fbbSEdward Tomasz Napierala rw_assert(&rctl_lock, RA_WLOCKED); 680ec125fbbSEdward Tomasz Napierala 681ec125fbbSEdward Tomasz Napierala link = uma_zalloc(rctl_rule_link_zone, M_NOWAIT); 682ec125fbbSEdward Tomasz Napierala if (link == NULL) 683ec125fbbSEdward Tomasz Napierala return (ENOMEM); 684ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(rule); 685ec125fbbSEdward Tomasz Napierala link->rrl_rule = rule; 686ec125fbbSEdward Tomasz Napierala link->rrl_exceeded = 0; 687ec125fbbSEdward Tomasz Napierala 688ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); 689ec125fbbSEdward Tomasz Napierala return (0); 690ec125fbbSEdward Tomasz Napierala } 691ec125fbbSEdward Tomasz Napierala 692ec125fbbSEdward Tomasz Napierala /* 693ec125fbbSEdward Tomasz Napierala * Remove limits for a rules matching the filter and release 694ec125fbbSEdward Tomasz Napierala * the refcounts for the rules, possibly freeing them. Returns 695ec125fbbSEdward Tomasz Napierala * the number of limit structures removed. 696ec125fbbSEdward Tomasz Napierala */ 697ec125fbbSEdward Tomasz Napierala static int 698ec125fbbSEdward Tomasz Napierala rctl_racct_remove_rules(struct racct *racct, 699ec125fbbSEdward Tomasz Napierala const struct rctl_rule *filter) 700ec125fbbSEdward Tomasz Napierala { 701ec125fbbSEdward Tomasz Napierala int removed = 0; 702ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link, *linktmp; 703ec125fbbSEdward Tomasz Napierala 7044b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 705ec125fbbSEdward Tomasz Napierala rw_assert(&rctl_lock, RA_WLOCKED); 706ec125fbbSEdward Tomasz Napierala 707ec125fbbSEdward Tomasz Napierala LIST_FOREACH_SAFE(link, &racct->r_rule_links, rrl_next, linktmp) { 708ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 709ec125fbbSEdward Tomasz Napierala continue; 710ec125fbbSEdward Tomasz Napierala 711ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 712ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 713ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 714ec125fbbSEdward Tomasz Napierala removed++; 715ec125fbbSEdward Tomasz Napierala } 716ec125fbbSEdward Tomasz Napierala return (removed); 717ec125fbbSEdward Tomasz Napierala } 718ec125fbbSEdward Tomasz Napierala 719ec125fbbSEdward Tomasz Napierala static void 720ec125fbbSEdward Tomasz Napierala rctl_rule_acquire_subject(struct rctl_rule *rule) 721ec125fbbSEdward Tomasz Napierala { 722ec125fbbSEdward Tomasz Napierala 7234b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 7244b5c9cf6SEdward Tomasz Napierala 725ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 726ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 727ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 728a7ad07bfSEdward Tomasz Napierala break; 729ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 730a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct != NULL) 731a7ad07bfSEdward Tomasz Napierala prison_racct_hold(rule->rr_subject.rs_prison_racct); 732ec125fbbSEdward Tomasz Napierala break; 733ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 734ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip != NULL) 735ec125fbbSEdward Tomasz Napierala uihold(rule->rr_subject.rs_uip); 736ec125fbbSEdward Tomasz Napierala break; 737ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 738415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass != NULL) 739415896e3SEdward Tomasz Napierala loginclass_hold(rule->rr_subject.rs_loginclass); 740ec125fbbSEdward Tomasz Napierala break; 741ec125fbbSEdward Tomasz Napierala default: 742ec125fbbSEdward Tomasz Napierala panic("rctl_rule_acquire_subject: unknown subject type %d", 743ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 744ec125fbbSEdward Tomasz Napierala } 745ec125fbbSEdward Tomasz Napierala } 746ec125fbbSEdward Tomasz Napierala 747ec125fbbSEdward Tomasz Napierala static void 748ec125fbbSEdward Tomasz Napierala rctl_rule_release_subject(struct rctl_rule *rule) 749ec125fbbSEdward Tomasz Napierala { 750ec125fbbSEdward Tomasz Napierala 7514b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 7524b5c9cf6SEdward Tomasz Napierala 753ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 754ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 755ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 756a7ad07bfSEdward Tomasz Napierala break; 757ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 758a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct != NULL) 759a7ad07bfSEdward Tomasz Napierala prison_racct_free(rule->rr_subject.rs_prison_racct); 760ec125fbbSEdward Tomasz Napierala break; 761ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 762ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip != NULL) 763ec125fbbSEdward Tomasz Napierala uifree(rule->rr_subject.rs_uip); 764ec125fbbSEdward Tomasz Napierala break; 765ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 766415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass != NULL) 767415896e3SEdward Tomasz Napierala loginclass_free(rule->rr_subject.rs_loginclass); 768ec125fbbSEdward Tomasz Napierala break; 769ec125fbbSEdward Tomasz Napierala default: 770ec125fbbSEdward Tomasz Napierala panic("rctl_rule_release_subject: unknown subject type %d", 771ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 772ec125fbbSEdward Tomasz Napierala } 773ec125fbbSEdward Tomasz Napierala } 774ec125fbbSEdward Tomasz Napierala 775ec125fbbSEdward Tomasz Napierala struct rctl_rule * 776ec125fbbSEdward Tomasz Napierala rctl_rule_alloc(int flags) 777ec125fbbSEdward Tomasz Napierala { 778ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 779ec125fbbSEdward Tomasz Napierala 7804b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 7814b5c9cf6SEdward Tomasz Napierala 782ec125fbbSEdward Tomasz Napierala rule = uma_zalloc(rctl_rule_zone, flags); 783ec125fbbSEdward Tomasz Napierala if (rule == NULL) 784ec125fbbSEdward Tomasz Napierala return (NULL); 785ec125fbbSEdward Tomasz Napierala rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED; 786ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = NULL; 787ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = NULL; 788415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = NULL; 789a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = NULL; 790ec125fbbSEdward Tomasz Napierala rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED; 791ec125fbbSEdward Tomasz Napierala rule->rr_resource = RACCT_UNDEFINED; 792ec125fbbSEdward Tomasz Napierala rule->rr_action = RCTL_ACTION_UNDEFINED; 793ec125fbbSEdward Tomasz Napierala rule->rr_amount = RCTL_AMOUNT_UNDEFINED; 794ec125fbbSEdward Tomasz Napierala refcount_init(&rule->rr_refcount, 1); 795ec125fbbSEdward Tomasz Napierala 796ec125fbbSEdward Tomasz Napierala return (rule); 797ec125fbbSEdward Tomasz Napierala } 798ec125fbbSEdward Tomasz Napierala 799ec125fbbSEdward Tomasz Napierala struct rctl_rule * 800ec125fbbSEdward Tomasz Napierala rctl_rule_duplicate(const struct rctl_rule *rule, int flags) 801ec125fbbSEdward Tomasz Napierala { 802ec125fbbSEdward Tomasz Napierala struct rctl_rule *copy; 803ec125fbbSEdward Tomasz Napierala 8044b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 8054b5c9cf6SEdward Tomasz Napierala 806ec125fbbSEdward Tomasz Napierala copy = uma_zalloc(rctl_rule_zone, flags); 807ec125fbbSEdward Tomasz Napierala if (copy == NULL) 808ec125fbbSEdward Tomasz Napierala return (NULL); 809ec125fbbSEdward Tomasz Napierala copy->rr_subject_type = rule->rr_subject_type; 810ec125fbbSEdward Tomasz Napierala copy->rr_subject.rs_proc = rule->rr_subject.rs_proc; 811ec125fbbSEdward Tomasz Napierala copy->rr_subject.rs_uip = rule->rr_subject.rs_uip; 812415896e3SEdward Tomasz Napierala copy->rr_subject.rs_loginclass = rule->rr_subject.rs_loginclass; 813a7ad07bfSEdward Tomasz Napierala copy->rr_subject.rs_prison_racct = rule->rr_subject.rs_prison_racct; 814ec125fbbSEdward Tomasz Napierala copy->rr_per = rule->rr_per; 815ec125fbbSEdward Tomasz Napierala copy->rr_resource = rule->rr_resource; 816ec125fbbSEdward Tomasz Napierala copy->rr_action = rule->rr_action; 817ec125fbbSEdward Tomasz Napierala copy->rr_amount = rule->rr_amount; 818ec125fbbSEdward Tomasz Napierala refcount_init(©->rr_refcount, 1); 819ec125fbbSEdward Tomasz Napierala rctl_rule_acquire_subject(copy); 820ec125fbbSEdward Tomasz Napierala 821ec125fbbSEdward Tomasz Napierala return (copy); 822ec125fbbSEdward Tomasz Napierala } 823ec125fbbSEdward Tomasz Napierala 824ec125fbbSEdward Tomasz Napierala void 825ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(struct rctl_rule *rule) 826ec125fbbSEdward Tomasz Napierala { 827ec125fbbSEdward Tomasz Napierala 8284b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 829ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0")); 830ec125fbbSEdward Tomasz Napierala 831ec125fbbSEdward Tomasz Napierala refcount_acquire(&rule->rr_refcount); 832ec125fbbSEdward Tomasz Napierala } 833ec125fbbSEdward Tomasz Napierala 834ec125fbbSEdward Tomasz Napierala static void 835ec125fbbSEdward Tomasz Napierala rctl_rule_free(void *context, int pending) 836ec125fbbSEdward Tomasz Napierala { 837ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 838ec125fbbSEdward Tomasz Napierala 839ec125fbbSEdward Tomasz Napierala rule = (struct rctl_rule *)context; 840ec125fbbSEdward Tomasz Napierala 8414b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 842ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount == 0, ("rule->rr_refcount != 0")); 843ec125fbbSEdward Tomasz Napierala 844ec125fbbSEdward Tomasz Napierala /* 845ec125fbbSEdward Tomasz Napierala * We don't need locking here; rule is guaranteed to be inaccessible. 846ec125fbbSEdward Tomasz Napierala */ 847ec125fbbSEdward Tomasz Napierala 848ec125fbbSEdward Tomasz Napierala rctl_rule_release_subject(rule); 849ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_zone, rule); 850ec125fbbSEdward Tomasz Napierala } 851ec125fbbSEdward Tomasz Napierala 852ec125fbbSEdward Tomasz Napierala void 853ec125fbbSEdward Tomasz Napierala rctl_rule_release(struct rctl_rule *rule) 854ec125fbbSEdward Tomasz Napierala { 855ec125fbbSEdward Tomasz Napierala 8564b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 857ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_refcount > 0, ("rule->rr_refcount <= 0")); 858ec125fbbSEdward Tomasz Napierala 859ec125fbbSEdward Tomasz Napierala if (refcount_release(&rule->rr_refcount)) { 860ec125fbbSEdward Tomasz Napierala /* 861ec125fbbSEdward Tomasz Napierala * rctl_rule_release() is often called when iterating 862ec125fbbSEdward Tomasz Napierala * over all the uidinfo structures in the system, 863ec125fbbSEdward Tomasz Napierala * holding uihashtbl_lock. Since rctl_rule_free() 864ec125fbbSEdward Tomasz Napierala * might end up calling uifree(), this would lead 865ec125fbbSEdward Tomasz Napierala * to lock recursion. Use taskqueue to avoid this. 866ec125fbbSEdward Tomasz Napierala */ 867ec125fbbSEdward Tomasz Napierala TASK_INIT(&rule->rr_task, 0, rctl_rule_free, rule); 868ec125fbbSEdward Tomasz Napierala taskqueue_enqueue(taskqueue_thread, &rule->rr_task); 869ec125fbbSEdward Tomasz Napierala } 870ec125fbbSEdward Tomasz Napierala } 871ec125fbbSEdward Tomasz Napierala 872ec125fbbSEdward Tomasz Napierala static int 873ec125fbbSEdward Tomasz Napierala rctl_rule_fully_specified(const struct rctl_rule *rule) 874ec125fbbSEdward Tomasz Napierala { 875ec125fbbSEdward Tomasz Napierala 8764b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 8774b5c9cf6SEdward Tomasz Napierala 878ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 879ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 880ec125fbbSEdward Tomasz Napierala return (0); 881ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 882ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) 883ec125fbbSEdward Tomasz Napierala return (0); 884ec125fbbSEdward Tomasz Napierala break; 885ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 886ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip == NULL) 887ec125fbbSEdward Tomasz Napierala return (0); 888ec125fbbSEdward Tomasz Napierala break; 889ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 890415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) 891ec125fbbSEdward Tomasz Napierala return (0); 892ec125fbbSEdward Tomasz Napierala break; 893ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 894a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) 895ec125fbbSEdward Tomasz Napierala return (0); 896ec125fbbSEdward Tomasz Napierala break; 897ec125fbbSEdward Tomasz Napierala default: 898ec125fbbSEdward Tomasz Napierala panic("rctl_rule_fully_specified: unknown subject type %d", 899ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 900ec125fbbSEdward Tomasz Napierala } 901ec125fbbSEdward Tomasz Napierala if (rule->rr_resource == RACCT_UNDEFINED) 902ec125fbbSEdward Tomasz Napierala return (0); 903ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_UNDEFINED) 904ec125fbbSEdward Tomasz Napierala return (0); 905ec125fbbSEdward Tomasz Napierala if (rule->rr_amount == RCTL_AMOUNT_UNDEFINED) 906ec125fbbSEdward Tomasz Napierala return (0); 907ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED) 908ec125fbbSEdward Tomasz Napierala return (0); 909ec125fbbSEdward Tomasz Napierala 910ec125fbbSEdward Tomasz Napierala return (1); 911ec125fbbSEdward Tomasz Napierala } 912ec125fbbSEdward Tomasz Napierala 913ec125fbbSEdward Tomasz Napierala static int 914ec125fbbSEdward Tomasz Napierala rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep) 915ec125fbbSEdward Tomasz Napierala { 916ec125fbbSEdward Tomasz Napierala int error = 0; 917ec125fbbSEdward Tomasz Napierala char *subjectstr, *subject_idstr, *resourcestr, *actionstr, 918ec125fbbSEdward Tomasz Napierala *amountstr, *perstr; 919ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 920ec125fbbSEdward Tomasz Napierala id_t id; 921ec125fbbSEdward Tomasz Napierala 9224b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 9234b5c9cf6SEdward Tomasz Napierala 924ec125fbbSEdward Tomasz Napierala rule = rctl_rule_alloc(M_WAITOK); 925ec125fbbSEdward Tomasz Napierala 926ec125fbbSEdward Tomasz Napierala subjectstr = strsep(&rulestr, ":"); 927ec125fbbSEdward Tomasz Napierala subject_idstr = strsep(&rulestr, ":"); 928ec125fbbSEdward Tomasz Napierala resourcestr = strsep(&rulestr, ":"); 929ec125fbbSEdward Tomasz Napierala actionstr = strsep(&rulestr, "=/"); 930ec125fbbSEdward Tomasz Napierala amountstr = strsep(&rulestr, "/"); 931ec125fbbSEdward Tomasz Napierala perstr = rulestr; 932ec125fbbSEdward Tomasz Napierala 933ec125fbbSEdward Tomasz Napierala if (subjectstr == NULL || subjectstr[0] == '\0') 934ec125fbbSEdward Tomasz Napierala rule->rr_subject_type = RCTL_SUBJECT_TYPE_UNDEFINED; 935ec125fbbSEdward Tomasz Napierala else { 936ec125fbbSEdward Tomasz Napierala error = str2value(subjectstr, &rule->rr_subject_type, subjectnames); 937ec125fbbSEdward Tomasz Napierala if (error != 0) 938ec125fbbSEdward Tomasz Napierala goto out; 939ec125fbbSEdward Tomasz Napierala } 940ec125fbbSEdward Tomasz Napierala 941ec125fbbSEdward Tomasz Napierala if (subject_idstr == NULL || subject_idstr[0] == '\0') { 942ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = NULL; 943ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = NULL; 944415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = NULL; 945a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = NULL; 946ec125fbbSEdward Tomasz Napierala } else { 947ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 948ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_UNDEFINED: 949ec125fbbSEdward Tomasz Napierala error = EINVAL; 950ec125fbbSEdward Tomasz Napierala goto out; 951ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 952ec125fbbSEdward Tomasz Napierala error = str2id(subject_idstr, &id); 953ec125fbbSEdward Tomasz Napierala if (error != 0) 954ec125fbbSEdward Tomasz Napierala goto out; 955ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 956ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = pfind(id); 957ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) { 958ec125fbbSEdward Tomasz Napierala error = ESRCH; 959ec125fbbSEdward Tomasz Napierala goto out; 960ec125fbbSEdward Tomasz Napierala } 961ec125fbbSEdward Tomasz Napierala PROC_UNLOCK(rule->rr_subject.rs_proc); 962ec125fbbSEdward Tomasz Napierala break; 963ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 964ec125fbbSEdward Tomasz Napierala error = str2id(subject_idstr, &id); 965ec125fbbSEdward Tomasz Napierala if (error != 0) 966ec125fbbSEdward Tomasz Napierala goto out; 967ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip = uifind(id); 968ec125fbbSEdward Tomasz Napierala break; 969ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 970415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass = 971ec125fbbSEdward Tomasz Napierala loginclass_find(subject_idstr); 972415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) { 973ec125fbbSEdward Tomasz Napierala error = ENAMETOOLONG; 974ec125fbbSEdward Tomasz Napierala goto out; 975ec125fbbSEdward Tomasz Napierala } 976ec125fbbSEdward Tomasz Napierala break; 977ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 978a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct = 979a7ad07bfSEdward Tomasz Napierala prison_racct_find(subject_idstr); 980a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) { 981a7ad07bfSEdward Tomasz Napierala error = ENAMETOOLONG; 982ec125fbbSEdward Tomasz Napierala goto out; 983ec125fbbSEdward Tomasz Napierala } 984ec125fbbSEdward Tomasz Napierala break; 985ec125fbbSEdward Tomasz Napierala default: 986ec125fbbSEdward Tomasz Napierala panic("rctl_string_to_rule: unknown subject type %d", 987ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 988ec125fbbSEdward Tomasz Napierala } 989ec125fbbSEdward Tomasz Napierala } 990ec125fbbSEdward Tomasz Napierala 991ec125fbbSEdward Tomasz Napierala if (resourcestr == NULL || resourcestr[0] == '\0') 992ec125fbbSEdward Tomasz Napierala rule->rr_resource = RACCT_UNDEFINED; 993ec125fbbSEdward Tomasz Napierala else { 994ec125fbbSEdward Tomasz Napierala error = str2value(resourcestr, &rule->rr_resource, 995ec125fbbSEdward Tomasz Napierala resourcenames); 996ec125fbbSEdward Tomasz Napierala if (error != 0) 997ec125fbbSEdward Tomasz Napierala goto out; 998ec125fbbSEdward Tomasz Napierala } 999ec125fbbSEdward Tomasz Napierala 1000ec125fbbSEdward Tomasz Napierala if (actionstr == NULL || actionstr[0] == '\0') 1001ec125fbbSEdward Tomasz Napierala rule->rr_action = RCTL_ACTION_UNDEFINED; 1002ec125fbbSEdward Tomasz Napierala else { 1003ec125fbbSEdward Tomasz Napierala error = str2value(actionstr, &rule->rr_action, actionnames); 1004ec125fbbSEdward Tomasz Napierala if (error != 0) 1005ec125fbbSEdward Tomasz Napierala goto out; 1006ec125fbbSEdward Tomasz Napierala } 1007ec125fbbSEdward Tomasz Napierala 1008ec125fbbSEdward Tomasz Napierala if (amountstr == NULL || amountstr[0] == '\0') 1009ec125fbbSEdward Tomasz Napierala rule->rr_amount = RCTL_AMOUNT_UNDEFINED; 1010ec125fbbSEdward Tomasz Napierala else { 1011ec125fbbSEdward Tomasz Napierala error = str2int64(amountstr, &rule->rr_amount); 1012ec125fbbSEdward Tomasz Napierala if (error != 0) 1013ec125fbbSEdward Tomasz Napierala goto out; 1014b450d447SEdward Tomasz Napierala if (RACCT_IS_IN_MILLIONS(rule->rr_resource)) { 1015b450d447SEdward Tomasz Napierala if (rule->rr_amount > INT64_MAX / 1000000) { 1016b450d447SEdward Tomasz Napierala error = ERANGE; 1017b450d447SEdward Tomasz Napierala goto out; 1018b450d447SEdward Tomasz Napierala } 1019cff08ec0SEdward Tomasz Napierala rule->rr_amount *= 1000000; 1020ec125fbbSEdward Tomasz Napierala } 1021b450d447SEdward Tomasz Napierala } 1022ec125fbbSEdward Tomasz Napierala 1023ec125fbbSEdward Tomasz Napierala if (perstr == NULL || perstr[0] == '\0') 1024ec125fbbSEdward Tomasz Napierala rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED; 1025ec125fbbSEdward Tomasz Napierala else { 1026ec125fbbSEdward Tomasz Napierala error = str2value(perstr, &rule->rr_per, subjectnames); 1027ec125fbbSEdward Tomasz Napierala if (error != 0) 1028ec125fbbSEdward Tomasz Napierala goto out; 1029ec125fbbSEdward Tomasz Napierala } 1030ec125fbbSEdward Tomasz Napierala 1031ec125fbbSEdward Tomasz Napierala out: 1032ec125fbbSEdward Tomasz Napierala if (error == 0) 1033ec125fbbSEdward Tomasz Napierala *rulep = rule; 1034ec125fbbSEdward Tomasz Napierala else 1035ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 1036ec125fbbSEdward Tomasz Napierala 1037ec125fbbSEdward Tomasz Napierala return (error); 1038ec125fbbSEdward Tomasz Napierala } 1039ec125fbbSEdward Tomasz Napierala 1040ec125fbbSEdward Tomasz Napierala /* 1041ec125fbbSEdward Tomasz Napierala * Link a rule with all the subjects it applies to. 1042ec125fbbSEdward Tomasz Napierala */ 1043ec125fbbSEdward Tomasz Napierala int 1044ec125fbbSEdward Tomasz Napierala rctl_rule_add(struct rctl_rule *rule) 1045ec125fbbSEdward Tomasz Napierala { 1046ec125fbbSEdward Tomasz Napierala struct proc *p; 1047ec125fbbSEdward Tomasz Napierala struct ucred *cred; 1048ec125fbbSEdward Tomasz Napierala struct uidinfo *uip; 1049ec125fbbSEdward Tomasz Napierala struct prison *pr; 1050a7ad07bfSEdward Tomasz Napierala struct prison_racct *prr; 1051ec125fbbSEdward Tomasz Napierala struct loginclass *lc; 1052ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule2; 1053ec125fbbSEdward Tomasz Napierala int match; 1054ec125fbbSEdward Tomasz Napierala 10554b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 1056ec125fbbSEdward Tomasz Napierala KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 1057ec125fbbSEdward Tomasz Napierala 1058ec125fbbSEdward Tomasz Napierala /* 1059ec125fbbSEdward Tomasz Napierala * Some rules just don't make sense. Note that the one below 10604fe84775SEdward Tomasz Napierala * cannot be rewritten using RACCT_IS_DENIABLE(); the RACCT_PCTCPU, 1061ec125fbbSEdward Tomasz Napierala * for example, is not deniable in the racct sense, but the 1062ec125fbbSEdward Tomasz Napierala * limit is enforced in a different way, so "deny" rules for %CPU 1063ec125fbbSEdward Tomasz Napierala * do make sense. 1064ec125fbbSEdward Tomasz Napierala */ 1065ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_DENY && 1066ec125fbbSEdward Tomasz Napierala (rule->rr_resource == RACCT_CPU || 1067ec125fbbSEdward Tomasz Napierala rule->rr_resource == RACCT_WALLCLOCK)) 1068ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1069ec125fbbSEdward Tomasz Napierala 1070ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS && 10714fe84775SEdward Tomasz Napierala RACCT_IS_SLOPPY(rule->rr_resource)) 1072ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1073ec125fbbSEdward Tomasz Napierala 1074ec125fbbSEdward Tomasz Napierala /* 1075ec125fbbSEdward Tomasz Napierala * Make sure there are no duplicated rules. Also, for the "deny" 1076ec125fbbSEdward Tomasz Napierala * rules, remove ones differing only by "amount". 1077ec125fbbSEdward Tomasz Napierala */ 1078ec125fbbSEdward Tomasz Napierala if (rule->rr_action == RCTL_ACTION_DENY) { 1079ec125fbbSEdward Tomasz Napierala rule2 = rctl_rule_duplicate(rule, M_WAITOK); 1080ec125fbbSEdward Tomasz Napierala rule2->rr_amount = RCTL_AMOUNT_UNDEFINED; 1081ec125fbbSEdward Tomasz Napierala rctl_rule_remove(rule2); 1082ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule2); 1083ec125fbbSEdward Tomasz Napierala } else 1084ec125fbbSEdward Tomasz Napierala rctl_rule_remove(rule); 1085ec125fbbSEdward Tomasz Napierala 1086ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1087ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1088ec125fbbSEdward Tomasz Napierala p = rule->rr_subject.rs_proc; 1089ec125fbbSEdward Tomasz Napierala KASSERT(p != NULL, ("rctl_rule_add: NULL proc")); 1090ec125fbbSEdward Tomasz Napierala 1091ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(p->p_racct, rule); 1092ec125fbbSEdward Tomasz Napierala /* 1093ec125fbbSEdward Tomasz Napierala * In case of per-process rule, we don't have anything more 1094ec125fbbSEdward Tomasz Napierala * to do. 1095ec125fbbSEdward Tomasz Napierala */ 1096ec125fbbSEdward Tomasz Napierala return (0); 1097ec125fbbSEdward Tomasz Napierala 1098ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1099ec125fbbSEdward Tomasz Napierala uip = rule->rr_subject.rs_uip; 1100ec125fbbSEdward Tomasz Napierala KASSERT(uip != NULL, ("rctl_rule_add: NULL uip")); 1101ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(uip->ui_racct, rule); 1102ec125fbbSEdward Tomasz Napierala break; 1103ec125fbbSEdward Tomasz Napierala 1104ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1105415896e3SEdward Tomasz Napierala lc = rule->rr_subject.rs_loginclass; 1106ec125fbbSEdward Tomasz Napierala KASSERT(lc != NULL, ("rctl_rule_add: NULL loginclass")); 1107ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(lc->lc_racct, rule); 1108ec125fbbSEdward Tomasz Napierala break; 1109ec125fbbSEdward Tomasz Napierala 1110ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1111a7ad07bfSEdward Tomasz Napierala prr = rule->rr_subject.rs_prison_racct; 1112a7ad07bfSEdward Tomasz Napierala KASSERT(prr != NULL, ("rctl_rule_add: NULL pr")); 1113a7ad07bfSEdward Tomasz Napierala rctl_racct_add_rule(prr->prr_racct, rule); 1114ec125fbbSEdward Tomasz Napierala break; 1115ec125fbbSEdward Tomasz Napierala 1116ec125fbbSEdward Tomasz Napierala default: 1117ec125fbbSEdward Tomasz Napierala panic("rctl_rule_add: unknown subject type %d", 1118ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1119ec125fbbSEdward Tomasz Napierala } 1120ec125fbbSEdward Tomasz Napierala 1121ec125fbbSEdward Tomasz Napierala /* 1122ec125fbbSEdward Tomasz Napierala * Now go through all the processes and add the new rule to the ones 1123ec125fbbSEdward Tomasz Napierala * it applies to. 1124ec125fbbSEdward Tomasz Napierala */ 1125ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 1126ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 1127ec125fbbSEdward Tomasz Napierala cred = p->p_ucred; 1128ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1129ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1130ec125fbbSEdward Tomasz Napierala if (cred->cr_uidinfo == rule->rr_subject.rs_uip || 1131ec125fbbSEdward Tomasz Napierala cred->cr_ruidinfo == rule->rr_subject.rs_uip) 1132ec125fbbSEdward Tomasz Napierala break; 1133ec125fbbSEdward Tomasz Napierala continue; 1134ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1135415896e3SEdward Tomasz Napierala if (cred->cr_loginclass == rule->rr_subject.rs_loginclass) 1136ec125fbbSEdward Tomasz Napierala break; 1137ec125fbbSEdward Tomasz Napierala continue; 1138ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1139ec125fbbSEdward Tomasz Napierala match = 0; 1140ec125fbbSEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) { 1141a7ad07bfSEdward Tomasz Napierala if (pr->pr_prison_racct == rule->rr_subject.rs_prison_racct) { 1142ec125fbbSEdward Tomasz Napierala match = 1; 1143ec125fbbSEdward Tomasz Napierala break; 1144ec125fbbSEdward Tomasz Napierala } 1145ec125fbbSEdward Tomasz Napierala } 1146ec125fbbSEdward Tomasz Napierala if (match) 1147ec125fbbSEdward Tomasz Napierala break; 1148ec125fbbSEdward Tomasz Napierala continue; 1149ec125fbbSEdward Tomasz Napierala default: 1150ec125fbbSEdward Tomasz Napierala panic("rctl_rule_add: unknown subject type %d", 1151ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1152ec125fbbSEdward Tomasz Napierala } 1153ec125fbbSEdward Tomasz Napierala 1154ec125fbbSEdward Tomasz Napierala rctl_racct_add_rule(p->p_racct, rule); 1155ec125fbbSEdward Tomasz Napierala } 1156ec125fbbSEdward Tomasz Napierala 1157ec125fbbSEdward Tomasz Napierala return (0); 1158ec125fbbSEdward Tomasz Napierala } 1159ec125fbbSEdward Tomasz Napierala 1160ec125fbbSEdward Tomasz Napierala static void 116115db3c07SEdward Tomasz Napierala rctl_rule_pre_callback(void) 116215db3c07SEdward Tomasz Napierala { 116315db3c07SEdward Tomasz Napierala 116415db3c07SEdward Tomasz Napierala rw_wlock(&rctl_lock); 116515db3c07SEdward Tomasz Napierala } 116615db3c07SEdward Tomasz Napierala 116715db3c07SEdward Tomasz Napierala static void 116815db3c07SEdward Tomasz Napierala rctl_rule_post_callback(void) 116915db3c07SEdward Tomasz Napierala { 117015db3c07SEdward Tomasz Napierala 117115db3c07SEdward Tomasz Napierala rw_wunlock(&rctl_lock); 117215db3c07SEdward Tomasz Napierala } 117315db3c07SEdward Tomasz Napierala 117415db3c07SEdward Tomasz Napierala static void 1175ec125fbbSEdward Tomasz Napierala rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3) 1176ec125fbbSEdward Tomasz Napierala { 1177ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter = (struct rctl_rule *)arg2; 1178ec125fbbSEdward Tomasz Napierala int found = 0; 1179ec125fbbSEdward Tomasz Napierala 11804b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 118115db3c07SEdward Tomasz Napierala rw_assert(&rctl_lock, RA_WLOCKED); 11824b5c9cf6SEdward Tomasz Napierala 1183ec125fbbSEdward Tomasz Napierala found += rctl_racct_remove_rules(racct, filter); 1184ec125fbbSEdward Tomasz Napierala 1185ec125fbbSEdward Tomasz Napierala *((int *)arg3) += found; 1186ec125fbbSEdward Tomasz Napierala } 1187ec125fbbSEdward Tomasz Napierala 1188ec125fbbSEdward Tomasz Napierala /* 1189ec125fbbSEdward Tomasz Napierala * Remove all rules that match the filter. 1190ec125fbbSEdward Tomasz Napierala */ 1191ec125fbbSEdward Tomasz Napierala int 1192ec125fbbSEdward Tomasz Napierala rctl_rule_remove(struct rctl_rule *filter) 1193ec125fbbSEdward Tomasz Napierala { 1194ec125fbbSEdward Tomasz Napierala int found = 0; 1195ec125fbbSEdward Tomasz Napierala struct proc *p; 1196ec125fbbSEdward Tomasz Napierala 11974b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 11984b5c9cf6SEdward Tomasz Napierala 1199ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_PROCESS && 1200ec125fbbSEdward Tomasz Napierala filter->rr_subject.rs_proc != NULL) { 1201ec125fbbSEdward Tomasz Napierala p = filter->rr_subject.rs_proc; 1202ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 1203ec125fbbSEdward Tomasz Napierala found = rctl_racct_remove_rules(p->p_racct, filter); 1204ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1205ec125fbbSEdward Tomasz Napierala if (found) 1206ec125fbbSEdward Tomasz Napierala return (0); 1207ec125fbbSEdward Tomasz Napierala return (ESRCH); 1208ec125fbbSEdward Tomasz Napierala } 1209ec125fbbSEdward Tomasz Napierala 121015db3c07SEdward Tomasz Napierala loginclass_racct_foreach(rctl_rule_remove_callback, 121115db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 121215db3c07SEdward Tomasz Napierala filter, (void *)&found); 121315db3c07SEdward Tomasz Napierala ui_racct_foreach(rctl_rule_remove_callback, 121415db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 121515db3c07SEdward Tomasz Napierala filter, (void *)&found); 121615db3c07SEdward Tomasz Napierala prison_racct_foreach(rctl_rule_remove_callback, 121715db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 121815db3c07SEdward Tomasz Napierala filter, (void *)&found); 1219ec125fbbSEdward Tomasz Napierala 1220ec125fbbSEdward Tomasz Napierala sx_assert(&allproc_lock, SA_LOCKED); 1221ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 1222ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 1223ec125fbbSEdward Tomasz Napierala found += rctl_racct_remove_rules(p->p_racct, filter); 1224ec125fbbSEdward Tomasz Napierala } 1225ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1226ec125fbbSEdward Tomasz Napierala 1227ec125fbbSEdward Tomasz Napierala if (found) 1228ec125fbbSEdward Tomasz Napierala return (0); 1229ec125fbbSEdward Tomasz Napierala return (ESRCH); 1230ec125fbbSEdward Tomasz Napierala } 1231ec125fbbSEdward Tomasz Napierala 1232ec125fbbSEdward Tomasz Napierala /* 1233ec125fbbSEdward Tomasz Napierala * Appends a rule to the sbuf. 1234ec125fbbSEdward Tomasz Napierala */ 1235ec125fbbSEdward Tomasz Napierala static void 1236ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule) 1237ec125fbbSEdward Tomasz Napierala { 1238ec125fbbSEdward Tomasz Napierala int64_t amount; 1239ec125fbbSEdward Tomasz Napierala 12404b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 12414b5c9cf6SEdward Tomasz Napierala 1242ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", rctl_subject_type_name(rule->rr_subject_type)); 1243ec125fbbSEdward Tomasz Napierala 1244ec125fbbSEdward Tomasz Napierala switch (rule->rr_subject_type) { 1245ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1246ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_proc == NULL) 1247ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1248ec125fbbSEdward Tomasz Napierala else 1249ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%d:", 1250ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc->p_pid); 1251ec125fbbSEdward Tomasz Napierala break; 1252ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1253ec125fbbSEdward Tomasz Napierala if (rule->rr_subject.rs_uip == NULL) 1254ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1255ec125fbbSEdward Tomasz Napierala else 1256ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%d:", 1257ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_uip->ui_uid); 1258ec125fbbSEdward Tomasz Napierala break; 1259ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1260415896e3SEdward Tomasz Napierala if (rule->rr_subject.rs_loginclass == NULL) 1261ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1262ec125fbbSEdward Tomasz Napierala else 1263ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", 1264415896e3SEdward Tomasz Napierala rule->rr_subject.rs_loginclass->lc_name); 1265ec125fbbSEdward Tomasz Napierala break; 1266ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1267a7ad07bfSEdward Tomasz Napierala if (rule->rr_subject.rs_prison_racct == NULL) 1268ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ":"); 1269ec125fbbSEdward Tomasz Napierala else 1270ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:", 1271a7ad07bfSEdward Tomasz Napierala rule->rr_subject.rs_prison_racct->prr_name); 1272ec125fbbSEdward Tomasz Napierala break; 1273ec125fbbSEdward Tomasz Napierala default: 1274ec125fbbSEdward Tomasz Napierala panic("rctl_rule_to_sbuf: unknown subject type %d", 1275ec125fbbSEdward Tomasz Napierala rule->rr_subject_type); 1276ec125fbbSEdward Tomasz Napierala } 1277ec125fbbSEdward Tomasz Napierala 1278ec125fbbSEdward Tomasz Napierala amount = rule->rr_amount; 1279ec125fbbSEdward Tomasz Napierala if (amount != RCTL_AMOUNT_UNDEFINED && 128085a2f1b4SEdward Tomasz Napierala RACCT_IS_IN_MILLIONS(rule->rr_resource)) 128185a2f1b4SEdward Tomasz Napierala amount /= 1000000; 1282ec125fbbSEdward Tomasz Napierala 1283ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s:%s=%jd", 1284ec125fbbSEdward Tomasz Napierala rctl_resource_name(rule->rr_resource), 1285ec125fbbSEdward Tomasz Napierala rctl_action_name(rule->rr_action), 1286ec125fbbSEdward Tomasz Napierala amount); 1287ec125fbbSEdward Tomasz Napierala 1288ec125fbbSEdward Tomasz Napierala if (rule->rr_per != rule->rr_subject_type) 1289ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "/%s", rctl_subject_type_name(rule->rr_per)); 1290ec125fbbSEdward Tomasz Napierala } 1291ec125fbbSEdward Tomasz Napierala 1292ec125fbbSEdward Tomasz Napierala /* 1293ec125fbbSEdward Tomasz Napierala * Routine used by RCTL syscalls to read in input string. 1294ec125fbbSEdward Tomasz Napierala */ 1295ec125fbbSEdward Tomasz Napierala static int 1296ec125fbbSEdward Tomasz Napierala rctl_read_inbuf(char **inputstr, const char *inbufp, size_t inbuflen) 1297ec125fbbSEdward Tomasz Napierala { 1298ec125fbbSEdward Tomasz Napierala int error; 1299ec125fbbSEdward Tomasz Napierala char *str; 1300ec125fbbSEdward Tomasz Napierala 13014b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 13024b5c9cf6SEdward Tomasz Napierala 1303ec125fbbSEdward Tomasz Napierala if (inbuflen <= 0) 1304ec125fbbSEdward Tomasz Napierala return (EINVAL); 1305ea228b48SEdward Tomasz Napierala if (inbuflen > RCTL_MAX_INBUFSIZE) 1306786813aaSEdward Tomasz Napierala return (E2BIG); 1307ec125fbbSEdward Tomasz Napierala 1308ec125fbbSEdward Tomasz Napierala str = malloc(inbuflen + 1, M_RCTL, M_WAITOK); 1309ec125fbbSEdward Tomasz Napierala error = copyinstr(inbufp, str, inbuflen, NULL); 1310ec125fbbSEdward Tomasz Napierala if (error != 0) { 1311ec125fbbSEdward Tomasz Napierala free(str, M_RCTL); 1312ec125fbbSEdward Tomasz Napierala return (error); 1313ec125fbbSEdward Tomasz Napierala } 1314ec125fbbSEdward Tomasz Napierala 1315ec125fbbSEdward Tomasz Napierala *inputstr = str; 1316ec125fbbSEdward Tomasz Napierala 1317ec125fbbSEdward Tomasz Napierala return (0); 1318ec125fbbSEdward Tomasz Napierala } 1319ec125fbbSEdward Tomasz Napierala 1320ec125fbbSEdward Tomasz Napierala /* 1321ec125fbbSEdward Tomasz Napierala * Routine used by RCTL syscalls to write out output string. 1322ec125fbbSEdward Tomasz Napierala */ 1323ec125fbbSEdward Tomasz Napierala static int 1324ec125fbbSEdward Tomasz Napierala rctl_write_outbuf(struct sbuf *outputsbuf, char *outbufp, size_t outbuflen) 1325ec125fbbSEdward Tomasz Napierala { 1326ec125fbbSEdward Tomasz Napierala int error; 1327ec125fbbSEdward Tomasz Napierala 13284b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 13294b5c9cf6SEdward Tomasz Napierala 1330ec125fbbSEdward Tomasz Napierala if (outputsbuf == NULL) 1331ec125fbbSEdward Tomasz Napierala return (0); 1332ec125fbbSEdward Tomasz Napierala 1333ec125fbbSEdward Tomasz Napierala sbuf_finish(outputsbuf); 1334ec125fbbSEdward Tomasz Napierala if (outbuflen < sbuf_len(outputsbuf) + 1) { 1335ec125fbbSEdward Tomasz Napierala sbuf_delete(outputsbuf); 1336ec125fbbSEdward Tomasz Napierala return (ERANGE); 1337ec125fbbSEdward Tomasz Napierala } 1338ec125fbbSEdward Tomasz Napierala error = copyout(sbuf_data(outputsbuf), outbufp, 1339ec125fbbSEdward Tomasz Napierala sbuf_len(outputsbuf) + 1); 1340ec125fbbSEdward Tomasz Napierala sbuf_delete(outputsbuf); 1341ec125fbbSEdward Tomasz Napierala return (error); 1342ec125fbbSEdward Tomasz Napierala } 1343ec125fbbSEdward Tomasz Napierala 1344ec125fbbSEdward Tomasz Napierala static struct sbuf * 1345ec125fbbSEdward Tomasz Napierala rctl_racct_to_sbuf(struct racct *racct, int sloppy) 1346ec125fbbSEdward Tomasz Napierala { 1347ec125fbbSEdward Tomasz Napierala int i; 1348ec125fbbSEdward Tomasz Napierala int64_t amount; 1349ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1350ec125fbbSEdward Tomasz Napierala 13514b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 13524b5c9cf6SEdward Tomasz Napierala 1353ec125fbbSEdward Tomasz Napierala sb = sbuf_new_auto(); 1354ec125fbbSEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 13554fe84775SEdward Tomasz Napierala if (sloppy == 0 && RACCT_IS_SLOPPY(i)) 1356ec125fbbSEdward Tomasz Napierala continue; 1357ec125fbbSEdward Tomasz Napierala amount = racct->r_resources[i]; 135885a2f1b4SEdward Tomasz Napierala if (RACCT_IS_IN_MILLIONS(i)) 1359cff08ec0SEdward Tomasz Napierala amount /= 1000000; 1360ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount); 1361ec125fbbSEdward Tomasz Napierala } 1362ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1363ec125fbbSEdward Tomasz Napierala return (sb); 1364ec125fbbSEdward Tomasz Napierala } 1365ec125fbbSEdward Tomasz Napierala 1366ec125fbbSEdward Tomasz Napierala int 13678451d0ddSKip Macy sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) 1368ec125fbbSEdward Tomasz Napierala { 1369ec125fbbSEdward Tomasz Napierala int error; 1370ec125fbbSEdward Tomasz Napierala char *inputstr; 1371ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1372ec125fbbSEdward Tomasz Napierala struct sbuf *outputsbuf = NULL; 1373ec125fbbSEdward Tomasz Napierala struct proc *p; 1374ec125fbbSEdward Tomasz Napierala struct uidinfo *uip; 1375ec125fbbSEdward Tomasz Napierala struct loginclass *lc; 1376a7ad07bfSEdward Tomasz Napierala struct prison_racct *prr; 1377ec125fbbSEdward Tomasz Napierala 13784b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 13794b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 13804b5c9cf6SEdward Tomasz Napierala 1381415896e3SEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_RACCT); 1382ec125fbbSEdward Tomasz Napierala if (error != 0) 1383ec125fbbSEdward Tomasz Napierala return (error); 1384ec125fbbSEdward Tomasz Napierala 1385ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1386ec125fbbSEdward Tomasz Napierala if (error != 0) 1387ec125fbbSEdward Tomasz Napierala return (error); 1388ec125fbbSEdward Tomasz Napierala 1389ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1390ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1391ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1392ec125fbbSEdward Tomasz Napierala if (error != 0) { 1393ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1394ec125fbbSEdward Tomasz Napierala return (error); 1395ec125fbbSEdward Tomasz Napierala } 1396ec125fbbSEdward Tomasz Napierala 1397ec125fbbSEdward Tomasz Napierala switch (filter->rr_subject_type) { 1398ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_PROCESS: 1399ec125fbbSEdward Tomasz Napierala p = filter->rr_subject.rs_proc; 1400ec125fbbSEdward Tomasz Napierala if (p == NULL) { 1401ec125fbbSEdward Tomasz Napierala error = EINVAL; 1402ec125fbbSEdward Tomasz Napierala goto out; 1403ec125fbbSEdward Tomasz Napierala } 1404ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(p->p_racct, 0); 1405ec125fbbSEdward Tomasz Napierala break; 1406ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_USER: 1407ec125fbbSEdward Tomasz Napierala uip = filter->rr_subject.rs_uip; 1408ec125fbbSEdward Tomasz Napierala if (uip == NULL) { 1409ec125fbbSEdward Tomasz Napierala error = EINVAL; 1410ec125fbbSEdward Tomasz Napierala goto out; 1411ec125fbbSEdward Tomasz Napierala } 1412ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(uip->ui_racct, 1); 1413ec125fbbSEdward Tomasz Napierala break; 1414ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_LOGINCLASS: 1415415896e3SEdward Tomasz Napierala lc = filter->rr_subject.rs_loginclass; 1416ec125fbbSEdward Tomasz Napierala if (lc == NULL) { 1417ec125fbbSEdward Tomasz Napierala error = EINVAL; 1418ec125fbbSEdward Tomasz Napierala goto out; 1419ec125fbbSEdward Tomasz Napierala } 1420ec125fbbSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(lc->lc_racct, 1); 1421ec125fbbSEdward Tomasz Napierala break; 1422ec125fbbSEdward Tomasz Napierala case RCTL_SUBJECT_TYPE_JAIL: 1423a7ad07bfSEdward Tomasz Napierala prr = filter->rr_subject.rs_prison_racct; 1424a7ad07bfSEdward Tomasz Napierala if (prr == NULL) { 1425ec125fbbSEdward Tomasz Napierala error = EINVAL; 1426ec125fbbSEdward Tomasz Napierala goto out; 1427ec125fbbSEdward Tomasz Napierala } 1428a7ad07bfSEdward Tomasz Napierala outputsbuf = rctl_racct_to_sbuf(prr->prr_racct, 1); 1429ec125fbbSEdward Tomasz Napierala break; 1430ec125fbbSEdward Tomasz Napierala default: 1431ec125fbbSEdward Tomasz Napierala error = EINVAL; 1432ec125fbbSEdward Tomasz Napierala } 1433ec125fbbSEdward Tomasz Napierala out: 1434ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1435ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1436ec125fbbSEdward Tomasz Napierala if (error != 0) 1437ec125fbbSEdward Tomasz Napierala return (error); 1438ec125fbbSEdward Tomasz Napierala 1439ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(outputsbuf, uap->outbufp, uap->outbuflen); 1440ec125fbbSEdward Tomasz Napierala 1441ec125fbbSEdward Tomasz Napierala return (error); 1442ec125fbbSEdward Tomasz Napierala } 1443ec125fbbSEdward Tomasz Napierala 1444ec125fbbSEdward Tomasz Napierala static void 1445ec125fbbSEdward Tomasz Napierala rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3) 1446ec125fbbSEdward Tomasz Napierala { 1447ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter = (struct rctl_rule *)arg2; 1448ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1449ec125fbbSEdward Tomasz Napierala struct sbuf *sb = (struct sbuf *)arg3; 1450ec125fbbSEdward Tomasz Napierala 14514b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 145215db3c07SEdward Tomasz Napierala rw_assert(&rctl_lock, RA_LOCKED); 14534b5c9cf6SEdward Tomasz Napierala 1454ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { 1455ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 1456ec125fbbSEdward Tomasz Napierala continue; 1457ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1458ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1459ec125fbbSEdward Tomasz Napierala } 1460ec125fbbSEdward Tomasz Napierala } 1461ec125fbbSEdward Tomasz Napierala 1462ec125fbbSEdward Tomasz Napierala int 14638451d0ddSKip Macy sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) 1464ec125fbbSEdward Tomasz Napierala { 1465ec125fbbSEdward Tomasz Napierala int error; 14662b4035eeSEdward Tomasz Napierala size_t bufsize; 1467ec125fbbSEdward Tomasz Napierala char *inputstr, *buf; 1468ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1469ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1470ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1471ec125fbbSEdward Tomasz Napierala struct proc *p; 1472ec125fbbSEdward Tomasz Napierala 14734b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 14744b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 14754b5c9cf6SEdward Tomasz Napierala 1476ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_RULES); 1477ec125fbbSEdward Tomasz Napierala if (error != 0) 1478ec125fbbSEdward Tomasz Napierala return (error); 1479ec125fbbSEdward Tomasz Napierala 1480ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1481ec125fbbSEdward Tomasz Napierala if (error != 0) 1482ec125fbbSEdward Tomasz Napierala return (error); 1483ec125fbbSEdward Tomasz Napierala 1484ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1485ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1486ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1487ec125fbbSEdward Tomasz Napierala if (error != 0) { 1488ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1489ec125fbbSEdward Tomasz Napierala return (error); 1490ec125fbbSEdward Tomasz Napierala } 1491ec125fbbSEdward Tomasz Napierala 14922b4035eeSEdward Tomasz Napierala bufsize = uap->outbuflen; 14932b4035eeSEdward Tomasz Napierala if (bufsize > rctl_maxbufsize) { 14942b4035eeSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 14952b4035eeSEdward Tomasz Napierala return (E2BIG); 14962b4035eeSEdward Tomasz Napierala } 14972b4035eeSEdward Tomasz Napierala 1498ec125fbbSEdward Tomasz Napierala buf = malloc(bufsize, M_RCTL, M_WAITOK); 1499ec125fbbSEdward Tomasz Napierala sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1500ec125fbbSEdward Tomasz Napierala KASSERT(sb != NULL, ("sbuf_new failed")); 1501ec125fbbSEdward Tomasz Napierala 1502ec125fbbSEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 1503ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 1504ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1505ec125fbbSEdward Tomasz Napierala /* 1506ec125fbbSEdward Tomasz Napierala * Non-process rules will be added to the buffer later. 1507ec125fbbSEdward Tomasz Napierala * Adding them here would result in duplicated output. 1508ec125fbbSEdward Tomasz Napierala */ 1509ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type != 1510ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) 1511ec125fbbSEdward Tomasz Napierala continue; 1512ec125fbbSEdward Tomasz Napierala if (!rctl_rule_matches(link->rrl_rule, filter)) 1513ec125fbbSEdward Tomasz Napierala continue; 1514ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1515ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1516ec125fbbSEdward Tomasz Napierala } 1517ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 1518ec125fbbSEdward Tomasz Napierala } 1519ec125fbbSEdward Tomasz Napierala 152015db3c07SEdward Tomasz Napierala loginclass_racct_foreach(rctl_get_rules_callback, 152115db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 152215db3c07SEdward Tomasz Napierala filter, sb); 152315db3c07SEdward Tomasz Napierala ui_racct_foreach(rctl_get_rules_callback, 152415db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 152515db3c07SEdward Tomasz Napierala filter, sb); 152615db3c07SEdward Tomasz Napierala prison_racct_foreach(rctl_get_rules_callback, 152715db3c07SEdward Tomasz Napierala rctl_rule_pre_callback, rctl_rule_post_callback, 152815db3c07SEdward Tomasz Napierala filter, sb); 1529ec125fbbSEdward Tomasz Napierala if (sbuf_error(sb) == ENOMEM) { 15302b4035eeSEdward Tomasz Napierala error = ERANGE; 15312b4035eeSEdward Tomasz Napierala goto out; 1532ec125fbbSEdward Tomasz Napierala } 1533ec125fbbSEdward Tomasz Napierala 1534ec125fbbSEdward Tomasz Napierala /* 1535ec125fbbSEdward Tomasz Napierala * Remove trailing ",". 1536ec125fbbSEdward Tomasz Napierala */ 1537ec125fbbSEdward Tomasz Napierala if (sbuf_len(sb) > 0) 1538ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1539ec125fbbSEdward Tomasz Napierala 1540ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); 15412b4035eeSEdward Tomasz Napierala out: 1542ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1543ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1544ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 1545ec125fbbSEdward Tomasz Napierala return (error); 1546ec125fbbSEdward Tomasz Napierala } 1547ec125fbbSEdward Tomasz Napierala 1548ec125fbbSEdward Tomasz Napierala int 15498451d0ddSKip Macy sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) 1550ec125fbbSEdward Tomasz Napierala { 1551ec125fbbSEdward Tomasz Napierala int error; 15522b4035eeSEdward Tomasz Napierala size_t bufsize; 1553ec125fbbSEdward Tomasz Napierala char *inputstr, *buf; 1554ec125fbbSEdward Tomasz Napierala struct sbuf *sb; 1555ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1556ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1557ec125fbbSEdward Tomasz Napierala 15584b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 15594b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 15604b5c9cf6SEdward Tomasz Napierala 1561ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_GET_LIMITS); 1562ec125fbbSEdward Tomasz Napierala if (error != 0) 1563ec125fbbSEdward Tomasz Napierala return (error); 1564ec125fbbSEdward Tomasz Napierala 1565ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1566ec125fbbSEdward Tomasz Napierala if (error != 0) 1567ec125fbbSEdward Tomasz Napierala return (error); 1568ec125fbbSEdward Tomasz Napierala 1569ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1570ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1571ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1572ec125fbbSEdward Tomasz Napierala if (error != 0) { 1573ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1574ec125fbbSEdward Tomasz Napierala return (error); 1575ec125fbbSEdward Tomasz Napierala } 1576ec125fbbSEdward Tomasz Napierala 1577ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_UNDEFINED) { 1578ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1579ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1580ec125fbbSEdward Tomasz Napierala return (EINVAL); 1581ec125fbbSEdward Tomasz Napierala } 1582ec125fbbSEdward Tomasz Napierala if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_PROCESS) { 1583ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1584ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1585ec125fbbSEdward Tomasz Napierala return (EOPNOTSUPP); 1586ec125fbbSEdward Tomasz Napierala } 1587ec125fbbSEdward Tomasz Napierala if (filter->rr_subject.rs_proc == NULL) { 1588ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1589ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1590ec125fbbSEdward Tomasz Napierala return (EINVAL); 1591ec125fbbSEdward Tomasz Napierala } 1592ec125fbbSEdward Tomasz Napierala 15932b4035eeSEdward Tomasz Napierala bufsize = uap->outbuflen; 15942b4035eeSEdward Tomasz Napierala if (bufsize > rctl_maxbufsize) { 15952b4035eeSEdward Tomasz Napierala rctl_rule_release(filter); 15962b4035eeSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 15972b4035eeSEdward Tomasz Napierala return (E2BIG); 15982b4035eeSEdward Tomasz Napierala } 15992b4035eeSEdward Tomasz Napierala 1600ec125fbbSEdward Tomasz Napierala buf = malloc(bufsize, M_RCTL, M_WAITOK); 1601ec125fbbSEdward Tomasz Napierala sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1602ec125fbbSEdward Tomasz Napierala KASSERT(sb != NULL, ("sbuf_new failed")); 1603ec125fbbSEdward Tomasz Napierala 1604ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 1605ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &filter->rr_subject.rs_proc->p_racct->r_rule_links, 1606ec125fbbSEdward Tomasz Napierala rrl_next) { 1607ec125fbbSEdward Tomasz Napierala rctl_rule_to_sbuf(sb, link->rrl_rule); 1608ec125fbbSEdward Tomasz Napierala sbuf_printf(sb, ","); 1609ec125fbbSEdward Tomasz Napierala } 1610ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 1611ec125fbbSEdward Tomasz Napierala if (sbuf_error(sb) == ENOMEM) { 16122b4035eeSEdward Tomasz Napierala error = ERANGE; 16132b4035eeSEdward Tomasz Napierala goto out; 1614ec125fbbSEdward Tomasz Napierala } 1615ec125fbbSEdward Tomasz Napierala 1616ec125fbbSEdward Tomasz Napierala /* 1617ec125fbbSEdward Tomasz Napierala * Remove trailing ",". 1618ec125fbbSEdward Tomasz Napierala */ 1619ec125fbbSEdward Tomasz Napierala if (sbuf_len(sb) > 0) 1620ec125fbbSEdward Tomasz Napierala sbuf_setpos(sb, sbuf_len(sb) - 1); 1621ec125fbbSEdward Tomasz Napierala 1622ec125fbbSEdward Tomasz Napierala error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); 16232b4035eeSEdward Tomasz Napierala out: 1624ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1625ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1626ec125fbbSEdward Tomasz Napierala free(buf, M_RCTL); 1627ec125fbbSEdward Tomasz Napierala return (error); 1628ec125fbbSEdward Tomasz Napierala } 1629ec125fbbSEdward Tomasz Napierala 1630ec125fbbSEdward Tomasz Napierala int 16318451d0ddSKip Macy sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) 1632ec125fbbSEdward Tomasz Napierala { 1633ec125fbbSEdward Tomasz Napierala int error; 1634ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 1635ec125fbbSEdward Tomasz Napierala char *inputstr; 1636ec125fbbSEdward Tomasz Napierala 16374b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 16384b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 16394b5c9cf6SEdward Tomasz Napierala 1640ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_ADD_RULE); 1641ec125fbbSEdward Tomasz Napierala if (error != 0) 1642ec125fbbSEdward Tomasz Napierala return (error); 1643ec125fbbSEdward Tomasz Napierala 1644ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1645ec125fbbSEdward Tomasz Napierala if (error != 0) 1646ec125fbbSEdward Tomasz Napierala return (error); 1647ec125fbbSEdward Tomasz Napierala 1648ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1649ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &rule); 1650ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1651ec125fbbSEdward Tomasz Napierala if (error != 0) { 1652ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1653ec125fbbSEdward Tomasz Napierala return (error); 1654ec125fbbSEdward Tomasz Napierala } 1655ec125fbbSEdward Tomasz Napierala /* 1656ec125fbbSEdward Tomasz Napierala * The 'per' part of a rule is optional. 1657ec125fbbSEdward Tomasz Napierala */ 1658ec125fbbSEdward Tomasz Napierala if (rule->rr_per == RCTL_SUBJECT_TYPE_UNDEFINED && 1659ec125fbbSEdward Tomasz Napierala rule->rr_subject_type != RCTL_SUBJECT_TYPE_UNDEFINED) 1660ec125fbbSEdward Tomasz Napierala rule->rr_per = rule->rr_subject_type; 1661ec125fbbSEdward Tomasz Napierala 1662ec125fbbSEdward Tomasz Napierala if (!rctl_rule_fully_specified(rule)) { 1663ec125fbbSEdward Tomasz Napierala error = EINVAL; 1664ec125fbbSEdward Tomasz Napierala goto out; 1665ec125fbbSEdward Tomasz Napierala } 1666ec125fbbSEdward Tomasz Napierala 1667ec125fbbSEdward Tomasz Napierala error = rctl_rule_add(rule); 1668ec125fbbSEdward Tomasz Napierala 1669ec125fbbSEdward Tomasz Napierala out: 1670ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 1671ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1672ec125fbbSEdward Tomasz Napierala return (error); 1673ec125fbbSEdward Tomasz Napierala } 1674ec125fbbSEdward Tomasz Napierala 1675ec125fbbSEdward Tomasz Napierala int 16768451d0ddSKip Macy sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) 1677ec125fbbSEdward Tomasz Napierala { 1678ec125fbbSEdward Tomasz Napierala int error; 1679ec125fbbSEdward Tomasz Napierala struct rctl_rule *filter; 1680ec125fbbSEdward Tomasz Napierala char *inputstr; 1681ec125fbbSEdward Tomasz Napierala 16824b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 16834b5c9cf6SEdward Tomasz Napierala return (ENOSYS); 16844b5c9cf6SEdward Tomasz Napierala 1685ec125fbbSEdward Tomasz Napierala error = priv_check(td, PRIV_RCTL_REMOVE_RULE); 1686ec125fbbSEdward Tomasz Napierala if (error != 0) 1687ec125fbbSEdward Tomasz Napierala return (error); 1688ec125fbbSEdward Tomasz Napierala 1689ec125fbbSEdward Tomasz Napierala error = rctl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen); 1690ec125fbbSEdward Tomasz Napierala if (error != 0) 1691ec125fbbSEdward Tomasz Napierala return (error); 1692ec125fbbSEdward Tomasz Napierala 1693ec125fbbSEdward Tomasz Napierala sx_slock(&allproc_lock); 1694ec125fbbSEdward Tomasz Napierala error = rctl_string_to_rule(inputstr, &filter); 1695ec125fbbSEdward Tomasz Napierala free(inputstr, M_RCTL); 1696ec125fbbSEdward Tomasz Napierala if (error != 0) { 1697ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1698ec125fbbSEdward Tomasz Napierala return (error); 1699ec125fbbSEdward Tomasz Napierala } 1700ec125fbbSEdward Tomasz Napierala 1701ec125fbbSEdward Tomasz Napierala error = rctl_rule_remove(filter); 1702ec125fbbSEdward Tomasz Napierala rctl_rule_release(filter); 1703ec125fbbSEdward Tomasz Napierala sx_sunlock(&allproc_lock); 1704ec125fbbSEdward Tomasz Napierala 1705ec125fbbSEdward Tomasz Napierala return (error); 1706ec125fbbSEdward Tomasz Napierala } 1707ec125fbbSEdward Tomasz Napierala 1708ec125fbbSEdward Tomasz Napierala /* 1709ec125fbbSEdward Tomasz Napierala * Update RCTL rule list after credential change. 1710ec125fbbSEdward Tomasz Napierala */ 1711ec125fbbSEdward Tomasz Napierala void 1712ec125fbbSEdward Tomasz Napierala rctl_proc_ucred_changed(struct proc *p, struct ucred *newcred) 1713ec125fbbSEdward Tomasz Napierala { 1714ec125fbbSEdward Tomasz Napierala int rulecnt, i; 1715ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link, *newlink; 1716ec125fbbSEdward Tomasz Napierala struct uidinfo *newuip; 1717ec125fbbSEdward Tomasz Napierala struct loginclass *newlc; 1718a7ad07bfSEdward Tomasz Napierala struct prison_racct *newprr; 1719ec125fbbSEdward Tomasz Napierala LIST_HEAD(, rctl_rule_link) newrules; 1720ec125fbbSEdward Tomasz Napierala 17214b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 17224b5c9cf6SEdward Tomasz Napierala 1723ec125fbbSEdward Tomasz Napierala newuip = newcred->cr_ruidinfo; 1724ec125fbbSEdward Tomasz Napierala newlc = newcred->cr_loginclass; 1725a7ad07bfSEdward Tomasz Napierala newprr = newcred->cr_prison->pr_prison_racct; 1726ec125fbbSEdward Tomasz Napierala 1727ec125fbbSEdward Tomasz Napierala LIST_INIT(&newrules); 1728ec125fbbSEdward Tomasz Napierala 1729ec125fbbSEdward Tomasz Napierala again: 1730ec125fbbSEdward Tomasz Napierala /* 1731ec125fbbSEdward Tomasz Napierala * First, count the rules that apply to the process with new 1732ec125fbbSEdward Tomasz Napierala * credentials. 1733ec125fbbSEdward Tomasz Napierala */ 1734ec125fbbSEdward Tomasz Napierala rulecnt = 0; 1735ec125fbbSEdward Tomasz Napierala rw_rlock(&rctl_lock); 1736ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1737ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 1738ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) 1739ec125fbbSEdward Tomasz Napierala rulecnt++; 1740ec125fbbSEdward Tomasz Napierala } 1741ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) 1742ec125fbbSEdward Tomasz Napierala rulecnt++; 1743ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) 1744ec125fbbSEdward Tomasz Napierala rulecnt++; 1745a7ad07bfSEdward Tomasz Napierala LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) 1746ec125fbbSEdward Tomasz Napierala rulecnt++; 1747ec125fbbSEdward Tomasz Napierala rw_runlock(&rctl_lock); 1748ec125fbbSEdward Tomasz Napierala 1749ec125fbbSEdward Tomasz Napierala /* 1750ec125fbbSEdward Tomasz Napierala * Create temporary list. We've dropped the rctl_lock in order 1751ec125fbbSEdward Tomasz Napierala * to use M_WAITOK. 1752ec125fbbSEdward Tomasz Napierala */ 1753ec125fbbSEdward Tomasz Napierala for (i = 0; i < rulecnt; i++) { 1754ec125fbbSEdward Tomasz Napierala newlink = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 1755ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = NULL; 1756ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = 0; 1757ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&newrules, newlink, rrl_next); 1758ec125fbbSEdward Tomasz Napierala } 1759ec125fbbSEdward Tomasz Napierala 1760ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 1761ec125fbbSEdward Tomasz Napierala 1762ec125fbbSEdward Tomasz Napierala /* 1763ec125fbbSEdward Tomasz Napierala * Assign rules to the newly allocated list entries. 1764ec125fbbSEdward Tomasz Napierala */ 1765ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 1766ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1767ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 1768ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) { 1769ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1770ec125fbbSEdward Tomasz Napierala goto goaround; 1771ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1772ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1773ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1774ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1775ec125fbbSEdward Tomasz Napierala rulecnt--; 1776ec125fbbSEdward Tomasz Napierala } 1777ec125fbbSEdward Tomasz Napierala } 1778ec125fbbSEdward Tomasz Napierala 1779ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) { 1780ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1781ec125fbbSEdward Tomasz Napierala goto goaround; 1782ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1783ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1784ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1785ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1786ec125fbbSEdward Tomasz Napierala rulecnt--; 1787ec125fbbSEdward Tomasz Napierala } 1788ec125fbbSEdward Tomasz Napierala 1789ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) { 1790ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1791ec125fbbSEdward Tomasz Napierala goto goaround; 1792ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1793ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1794ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1795ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1796ec125fbbSEdward Tomasz Napierala rulecnt--; 1797ec125fbbSEdward Tomasz Napierala } 1798ec125fbbSEdward Tomasz Napierala 1799a7ad07bfSEdward Tomasz Napierala LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) { 1800ec125fbbSEdward Tomasz Napierala if (newlink == NULL) 1801ec125fbbSEdward Tomasz Napierala goto goaround; 1802ec125fbbSEdward Tomasz Napierala rctl_rule_acquire(link->rrl_rule); 1803ec125fbbSEdward Tomasz Napierala newlink->rrl_rule = link->rrl_rule; 1804ed810200SEdward Tomasz Napierala newlink->rrl_exceeded = link->rrl_exceeded; 1805ec125fbbSEdward Tomasz Napierala newlink = LIST_NEXT(newlink, rrl_next); 1806ec125fbbSEdward Tomasz Napierala rulecnt--; 1807ec125fbbSEdward Tomasz Napierala } 1808ec125fbbSEdward Tomasz Napierala 1809ec125fbbSEdward Tomasz Napierala if (rulecnt == 0) { 1810ec125fbbSEdward Tomasz Napierala /* 1811ec125fbbSEdward Tomasz Napierala * Free the old rule list. 1812ec125fbbSEdward Tomasz Napierala */ 1813ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&p->p_racct->r_rule_links)) { 1814ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&p->p_racct->r_rule_links); 1815ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 1816ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 1817ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 1818ec125fbbSEdward Tomasz Napierala } 1819ec125fbbSEdward Tomasz Napierala 1820ec125fbbSEdward Tomasz Napierala /* 1821ec125fbbSEdward Tomasz Napierala * Replace lists and we're done. 1822ec125fbbSEdward Tomasz Napierala * 1823ec125fbbSEdward Tomasz Napierala * XXX: Is there any way to switch list heads instead 1824ec125fbbSEdward Tomasz Napierala * of iterating here? 1825ec125fbbSEdward Tomasz Napierala */ 1826ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&newrules)) { 1827ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 1828ec125fbbSEdward Tomasz Napierala LIST_REMOVE(newlink, rrl_next); 1829ec125fbbSEdward Tomasz Napierala LIST_INSERT_HEAD(&p->p_racct->r_rule_links, 1830ec125fbbSEdward Tomasz Napierala newlink, rrl_next); 1831ec125fbbSEdward Tomasz Napierala } 1832ec125fbbSEdward Tomasz Napierala 1833ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1834ec125fbbSEdward Tomasz Napierala 1835ec125fbbSEdward Tomasz Napierala return; 1836ec125fbbSEdward Tomasz Napierala } 1837ec125fbbSEdward Tomasz Napierala 1838ec125fbbSEdward Tomasz Napierala goaround: 1839ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1840ec125fbbSEdward Tomasz Napierala 1841ec125fbbSEdward Tomasz Napierala /* 1842ec125fbbSEdward Tomasz Napierala * Rule list changed while we were not holding the rctl_lock. 1843ec125fbbSEdward Tomasz Napierala * Free the new list and try again. 1844ec125fbbSEdward Tomasz Napierala */ 1845ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&newrules)) { 1846ec125fbbSEdward Tomasz Napierala newlink = LIST_FIRST(&newrules); 1847ec125fbbSEdward Tomasz Napierala LIST_REMOVE(newlink, rrl_next); 1848ec125fbbSEdward Tomasz Napierala if (newlink->rrl_rule != NULL) 1849ec125fbbSEdward Tomasz Napierala rctl_rule_release(newlink->rrl_rule); 1850ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, newlink); 1851ec125fbbSEdward Tomasz Napierala } 1852ec125fbbSEdward Tomasz Napierala 1853ec125fbbSEdward Tomasz Napierala goto again; 1854ec125fbbSEdward Tomasz Napierala } 1855ec125fbbSEdward Tomasz Napierala 1856ec125fbbSEdward Tomasz Napierala /* 1857ec125fbbSEdward Tomasz Napierala * Assign RCTL rules to the newly created process. 1858ec125fbbSEdward Tomasz Napierala */ 1859ec125fbbSEdward Tomasz Napierala int 1860ec125fbbSEdward Tomasz Napierala rctl_proc_fork(struct proc *parent, struct proc *child) 1861ec125fbbSEdward Tomasz Napierala { 1862ec125fbbSEdward Tomasz Napierala int error; 1863ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1864ec125fbbSEdward Tomasz Napierala struct rctl_rule *rule; 1865ec125fbbSEdward Tomasz Napierala 1866ec125fbbSEdward Tomasz Napierala LIST_INIT(&child->p_racct->r_rule_links); 1867ec125fbbSEdward Tomasz Napierala 18684b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 18690b18eb6dSEdward Tomasz Napierala KASSERT(parent->p_racct != NULL, ("process without racct; p = %p", parent)); 1870ec125fbbSEdward Tomasz Napierala 1871ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 1872ec125fbbSEdward Tomasz Napierala 1873ec125fbbSEdward Tomasz Napierala /* 1874ec125fbbSEdward Tomasz Napierala * Go through limits applicable to the parent and assign them 1875ec125fbbSEdward Tomasz Napierala * to the child. Rules with 'process' subject have to be duplicated 1876ec125fbbSEdward Tomasz Napierala * in order to make their rr_subject point to the new process. 1877ec125fbbSEdward Tomasz Napierala */ 1878ec125fbbSEdward Tomasz Napierala LIST_FOREACH(link, &parent->p_racct->r_rule_links, rrl_next) { 1879ec125fbbSEdward Tomasz Napierala if (link->rrl_rule->rr_subject_type == 1880ec125fbbSEdward Tomasz Napierala RCTL_SUBJECT_TYPE_PROCESS) { 1881ec125fbbSEdward Tomasz Napierala rule = rctl_rule_duplicate(link->rrl_rule, M_NOWAIT); 1882ec125fbbSEdward Tomasz Napierala if (rule == NULL) 1883ec125fbbSEdward Tomasz Napierala goto fail; 1884ec125fbbSEdward Tomasz Napierala KASSERT(rule->rr_subject.rs_proc == parent, 1885ec125fbbSEdward Tomasz Napierala ("rule->rr_subject.rs_proc != parent")); 1886ec125fbbSEdward Tomasz Napierala rule->rr_subject.rs_proc = child; 1887ec125fbbSEdward Tomasz Napierala error = rctl_racct_add_rule_locked(child->p_racct, 1888ec125fbbSEdward Tomasz Napierala rule); 1889ec125fbbSEdward Tomasz Napierala rctl_rule_release(rule); 1890ec125fbbSEdward Tomasz Napierala if (error != 0) 1891ec125fbbSEdward Tomasz Napierala goto fail; 1892ec125fbbSEdward Tomasz Napierala } else { 1893ec125fbbSEdward Tomasz Napierala error = rctl_racct_add_rule_locked(child->p_racct, 1894ec125fbbSEdward Tomasz Napierala link->rrl_rule); 1895ec125fbbSEdward Tomasz Napierala if (error != 0) 1896ec125fbbSEdward Tomasz Napierala goto fail; 1897ec125fbbSEdward Tomasz Napierala } 1898ec125fbbSEdward Tomasz Napierala } 1899ec125fbbSEdward Tomasz Napierala 1900ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1901ec125fbbSEdward Tomasz Napierala return (0); 1902ec125fbbSEdward Tomasz Napierala 1903ec125fbbSEdward Tomasz Napierala fail: 1904ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&child->p_racct->r_rule_links)) { 1905ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&child->p_racct->r_rule_links); 1906ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 1907ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 1908ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 1909ec125fbbSEdward Tomasz Napierala } 1910ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1911ec125fbbSEdward Tomasz Napierala return (EAGAIN); 1912ec125fbbSEdward Tomasz Napierala } 1913ec125fbbSEdward Tomasz Napierala 1914ec125fbbSEdward Tomasz Napierala /* 1915ec125fbbSEdward Tomasz Napierala * Release rules attached to the racct. 1916ec125fbbSEdward Tomasz Napierala */ 1917ec125fbbSEdward Tomasz Napierala void 1918ec125fbbSEdward Tomasz Napierala rctl_racct_release(struct racct *racct) 1919ec125fbbSEdward Tomasz Napierala { 1920ec125fbbSEdward Tomasz Napierala struct rctl_rule_link *link; 1921ec125fbbSEdward Tomasz Napierala 19224b5c9cf6SEdward Tomasz Napierala ASSERT_RACCT_ENABLED(); 19234b5c9cf6SEdward Tomasz Napierala 1924ec125fbbSEdward Tomasz Napierala rw_wlock(&rctl_lock); 1925ec125fbbSEdward Tomasz Napierala while (!LIST_EMPTY(&racct->r_rule_links)) { 1926ec125fbbSEdward Tomasz Napierala link = LIST_FIRST(&racct->r_rule_links); 1927ec125fbbSEdward Tomasz Napierala LIST_REMOVE(link, rrl_next); 1928ec125fbbSEdward Tomasz Napierala rctl_rule_release(link->rrl_rule); 1929ec125fbbSEdward Tomasz Napierala uma_zfree(rctl_rule_link_zone, link); 1930ec125fbbSEdward Tomasz Napierala } 1931ec125fbbSEdward Tomasz Napierala rw_wunlock(&rctl_lock); 1932ec125fbbSEdward Tomasz Napierala } 1933ec125fbbSEdward Tomasz Napierala 1934ec125fbbSEdward Tomasz Napierala static void 1935ec125fbbSEdward Tomasz Napierala rctl_init(void) 1936ec125fbbSEdward Tomasz Napierala { 1937ec125fbbSEdward Tomasz Napierala 19384b5c9cf6SEdward Tomasz Napierala if (!racct_enable) 19394b5c9cf6SEdward Tomasz Napierala return; 19404b5c9cf6SEdward Tomasz Napierala 1941ec125fbbSEdward Tomasz Napierala rctl_rule_link_zone = uma_zcreate("rctl_rule_link", 1942ec125fbbSEdward Tomasz Napierala sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL, 1943ec125fbbSEdward Tomasz Napierala UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 1944ec125fbbSEdward Tomasz Napierala rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), 1945ec125fbbSEdward Tomasz Napierala NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 1946ec125fbbSEdward Tomasz Napierala } 1947ec125fbbSEdward Tomasz Napierala 1948ec125fbbSEdward Tomasz Napierala #else /* !RCTL */ 1949ec125fbbSEdward Tomasz Napierala 1950ec125fbbSEdward Tomasz Napierala int 19518451d0ddSKip Macy sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) 1952ec125fbbSEdward Tomasz Napierala { 1953ec125fbbSEdward Tomasz Napierala 1954ec125fbbSEdward Tomasz Napierala return (ENOSYS); 1955ec125fbbSEdward Tomasz Napierala } 1956ec125fbbSEdward Tomasz Napierala 1957ec125fbbSEdward Tomasz Napierala int 19588451d0ddSKip Macy sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) 1959ec125fbbSEdward Tomasz Napierala { 1960ec125fbbSEdward Tomasz Napierala 1961ec125fbbSEdward Tomasz Napierala return (ENOSYS); 1962ec125fbbSEdward Tomasz Napierala } 1963ec125fbbSEdward Tomasz Napierala 1964ec125fbbSEdward Tomasz Napierala int 19658451d0ddSKip Macy sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) 1966ec125fbbSEdward Tomasz Napierala { 1967ec125fbbSEdward Tomasz Napierala 1968ec125fbbSEdward Tomasz Napierala return (ENOSYS); 1969ec125fbbSEdward Tomasz Napierala } 1970ec125fbbSEdward Tomasz Napierala 1971ec125fbbSEdward Tomasz Napierala int 19728451d0ddSKip Macy sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) 1973ec125fbbSEdward Tomasz Napierala { 1974ec125fbbSEdward Tomasz Napierala 1975ec125fbbSEdward Tomasz Napierala return (ENOSYS); 1976ec125fbbSEdward Tomasz Napierala } 1977ec125fbbSEdward Tomasz Napierala 1978ec125fbbSEdward Tomasz Napierala int 19798451d0ddSKip Macy sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) 1980ec125fbbSEdward Tomasz Napierala { 1981ec125fbbSEdward Tomasz Napierala 1982ec125fbbSEdward Tomasz Napierala return (ENOSYS); 1983ec125fbbSEdward Tomasz Napierala } 1984ec125fbbSEdward Tomasz Napierala 1985ec125fbbSEdward Tomasz Napierala #endif /* !RCTL */ 1986