FreeBSD/sys/kern/kern_rctl.c
/*
 * Link a rule with all the subjects it applies to.
 */
Link a rule with all the subjects it applies to.
Link a rule with all the subjects it applies to .
int
rctl_rule_add(struct rctl_rule *rule)
{
	struct proc *p;
	struct ucred *cred;
	struct uidinfo *uip;
	struct prison *pr;
	struct prison_racct *prr;
	struct loginclass *lc;
	struct rctl_rule *rule2;
	int match;
	ASSERT_RACCT_ENABLED();
	KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
	if (rule->rr_action == RCTL_ACTION_DENY &&
	    !RACCT_IS_DENIABLE(rule->rr_resource) &&
	    rule->rr_resource != RACCT_RSS &&
	    rule->rr_resource != RACCT_PCTCPU) {
		return (EOPNOTSUPP);
	}
	if (rule->rr_action == RCTL_ACTION_THROTTLE &&
	    !RACCT_IS_DECAYING(rule->rr_resource)) {
		return (EOPNOTSUPP);
	}
	if (rule->rr_action == RCTL_ACTION_THROTTLE &&
	    rule->rr_resource == RACCT_PCTCPU) {
		return (EOPNOTSUPP);
	}
	if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS &&
	    RACCT_IS_SLOPPY(rule->rr_resource)) {
		return (EOPNOTSUPP);
	}
	if (rule->rr_action == RCTL_ACTION_DENY) {
		rule2 = rctl_rule_duplicate(rule, M_WAITOK);
		rule2->rr_amount = RCTL_AMOUNT_UNDEFINED;
		rctl_rule_remove(rule2);
		rctl_rule_release(rule2);
	} else
		rctl_rule_remove(rule);
	switch (rule->rr_subject_type) {
	case RCTL_SUBJECT_TYPE_PROCESS:
		p = rule->rr_subject.rs_proc;
		KASSERT(p != NULL, ("rctl_rule_add: NULL proc"));
		rctl_racct_add_rule(p->p_racct, rule);
		return (0);
	case RCTL_SUBJECT_TYPE_USER:
		uip = rule->rr_subject.rs_uip;
		KASSERT(uip != NULL, ("rctl_rule_add: NULL uip"));
		rctl_racct_add_rule(uip->ui_racct, rule);
		break;
	case RCTL_SUBJECT_TYPE_LOGINCLASS:
		lc = rule->rr_subject.rs_loginclass;
		KASSERT(lc != NULL, ("rctl_rule_add: NULL loginclass"));
		rctl_racct_add_rule(lc->lc_racct, rule);
		break;
	case RCTL_SUBJECT_TYPE_JAIL:
		prr = rule->rr_subject.rs_prison_racct;
		KASSERT(prr != NULL, ("rctl_rule_add: NULL pr"));
		rctl_racct_add_rule(prr->prr_racct, rule);
		break;
	default:
		panic("rctl_rule_add: unknown subject type %d",
		    rule->rr_subject_type);
	}
	sx_assert(&allproc_lock, SA_LOCKED);
	FOREACH_PROC_IN_SYSTEM(p) {
		cred = p->p_ucred;
		switch (rule->rr_subject_type) {
		case RCTL_SUBJECT_TYPE_USER:
			if (cred->cr_uidinfo == rule->rr_subject.rs_uip ||
			    cred->cr_ruidinfo == rule->rr_subject.rs_uip)
				break;
			continue;
		case RCTL_SUBJECT_TYPE_LOGINCLASS:
			if (cred->cr_loginclass == rule->rr_subject.rs_loginclass)
				break;
			continue;
		case RCTL_SUBJECT_TYPE_JAIL:
			match = 0;
			for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) {
				if (pr->pr_prison_racct == rule->rr_subject.rs_prison_racct) {
					match = 1;
					break;
				}
			}
			if (match)
				break;
			continue;
		default:
			panic("rctl_rule_add: unknown subject type %d",
			    rule->rr_subject_type);
		}
		rctl_racct_add_rule(p->p_racct, rule);
	}
	return (0);
}
int rctl_rule_add ( struct rctl_rule * rule ) { struct proc * p ; struct ucred * cred ; struct uidinfo * uip ; struct prison * pr ; struct prison_racct * prr ; struct loginclass * lc ; struct rctl_rule * rule2 ; int match ; ASSERT_RACCT_ENABLED ( ) ; KASSERT ( rctl_rule_fully_specified ( rule ) , ( " " ) ) ; if ( rule -> rr_action == RCTL_ACTION_DENY && ! RACCT_IS_DENIABLE ( rule -> rr_resource ) && rule -> rr_resource != RACCT_RSS && rule -> rr_resource != RACCT_PCTCPU ) { return ( EOPNOTSUPP ) ; } if ( rule -> rr_action == RCTL_ACTION_THROTTLE && ! RACCT_IS_DECAYING ( rule -> rr_resource ) ) { return ( EOPNOTSUPP ) ; } if ( rule -> rr_action == RCTL_ACTION_THROTTLE && rule -> rr_resource == RACCT_PCTCPU ) { return ( EOPNOTSUPP ) ; } if ( rule -> rr_per == RCTL_SUBJECT_TYPE_PROCESS && RACCT_IS_SLOPPY ( rule -> rr_resource ) ) { return ( EOPNOTSUPP ) ; } if ( rule -> rr_action == RCTL_ACTION_DENY ) { rule2 = rctl_rule_duplicate ( rule , M_WAITOK ) ; rule2 -> rr_amount = RCTL_AMOUNT_UNDEFINED ; rctl_rule_remove ( rule2 ) ; rctl_rule_release ( rule2 ) ; } else rctl_rule_remove ( rule ) ; switch ( rule -> rr_subject_type ) { case RCTL_SUBJECT_TYPE_PROCESS : p = rule -> rr_subject . rs_proc ; KASSERT ( p != NULL , ( " " ) ) ; rctl_racct_add_rule ( p -> p_racct , rule ) ; return ( 0 ) ; case RCTL_SUBJECT_TYPE_USER : uip = rule -> rr_subject . rs_uip ; KASSERT ( uip != NULL , ( " " ) ) ; rctl_racct_add_rule ( uip -> ui_racct , rule ) ; break ; case RCTL_SUBJECT_TYPE_LOGINCLASS : lc = rule -> rr_subject . rs_loginclass ; KASSERT ( lc != NULL , ( " " ) ) ; rctl_racct_add_rule ( lc -> lc_racct , rule ) ; break ; case RCTL_SUBJECT_TYPE_JAIL : prr = rule -> rr_subject . rs_prison_racct ; KASSERT ( prr != NULL , ( " " ) ) ; rctl_racct_add_rule ( prr -> prr_racct , rule ) ; break ; default : panic ( " " , rule -> rr_subject_type ) ; } sx_assert ( & allproc_lock , SA_LOCKED ) ; FOREACH_PROC_IN_SYSTEM ( p ) { cred = p -> p_ucred ; switch ( rule -> rr_subject_type ) { case RCTL_SUBJECT_TYPE_USER : if ( cred -> cr_uidinfo == rule -> rr_subject . rs_uip || cred -> cr_ruidinfo == rule -> rr_subject . rs_uip ) break ; continue ; case RCTL_SUBJECT_TYPE_LOGINCLASS : if ( cred -> cr_loginclass == rule -> rr_subject . rs_loginclass ) break ; continue ; case RCTL_SUBJECT_TYPE_JAIL : match = 0 ; for ( pr = cred -> cr_prison ; pr != NULL ; pr = pr -> pr_parent ) { if ( pr -> pr_prison_racct == rule -> rr_subject . rs_prison_racct ) { match = 1 ; break ; } } if ( match ) break ; continue ; default : panic ( " " , rule -> rr_subject_type ) ; } rctl_racct_add_rule ( p -> p_racct , rule ) ; } return ( 0 ) ; }
Link a rule with all the subjects it applies to.
Link a rule with all the subjects it applies to .
/*
	 * Some rules just don't make sense, like "deny" rule for an undeniable
	 * resource.  The exception are the RSS and %CPU resources - they are
	 * not deniable in the racct sense, but the limit is enforced in
	 * a different way.
	 */ /*
	 * Make sure there are no duplicated rules.  Also, for the "deny"
	 * rules, remove ones differing only by "amount".
	 */ /*
		 * In case of per-process rule, we don't have anything more
		 * to do.
		 */ /*
	 * Now go through all the processes and add the new rule to the ones
	 * it applies to.
	 */