PERFORCE change 169139 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Fri Oct 2 17:20:43 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=169139
Change 169139 by trasz at trasz_victim on 2009/10/02 17:20:24
Rework rule storage to store pointers to subjects instead of their
id's.
Affected files ...
.. //depot/projects/soc2009/trasz_limits/TODO#11 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#61 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_jail.c#14 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#12 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_proc.c#8 integrate
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_prot.c#22 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#24 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#34 edit
Differences ...
==== //depot/projects/soc2009/trasz_limits/TODO#11 (text+ko) ====
@@ -1,7 +1,4 @@
- - In hrl_rule, instead of keeping subject ids, keep links to a process,
- uidinfo and gidinfo, the same way we do with loginclasses.
-
- Why did I put the loginclass pointer into the proc and not into the cred?
- Make the limits lists protected by the subjects lock (e.g. process lock)
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#61 (text+ko) ====
@@ -71,11 +71,11 @@
};
struct dict subjectnames[] = {
- { "process", HRL_SUBJECT_PROCESS },
- { "user", HRL_SUBJECT_USER },
- { "group", HRL_SUBJECT_GROUP },
- { "loginclass", HRL_SUBJECT_LOGINCLASS },
- { "jail", HRL_SUBJECT_JAIL },
+ { "process", HRL_SUBJECT_TYPE_PROCESS },
+ { "user", HRL_SUBJECT_TYPE_USER },
+ { "group", HRL_SUBJECT_TYPE_GROUP },
+ { "loginclass", HRL_SUBJECT_TYPE_LOGINCLASS },
+ { "jail", HRL_SUBJECT_TYPE_JAIL },
{ NULL, -1 }};
struct dict resourcenames[] = {
@@ -195,7 +195,7 @@
}
static const char *
-hrl_subject_name(int subject)
+hrl_subject_type_name(int subject)
{
int i;
@@ -204,7 +204,7 @@
return (subjectnames[i].d_name);
}
- panic("hrl_subject_name: unknown subject");
+ panic("hrl_subject_type_name: unknown subject type %d", subject);
}
static const char *
@@ -217,7 +217,7 @@
return (actionnames[i].d_name);
}
- panic("hrl_action_name: unknown action");
+ panic("hrl_action_name: unknown action %d", action);
}
static const char *
@@ -230,7 +230,7 @@
return (resourcenames[i].d_name);
}
- panic("hrl_resource_name: unknown resource");
+ panic("hrl_resource_name: unknown resource %d", resource);
}
static void
@@ -259,26 +259,26 @@
hrl_available_resource(const struct proc *p, const struct hrl_rule *rule)
{
int resource, i;
- int64_t available, found = 0;
+ int64_t available = INT64_MAX, found = 0;
struct ucred *cred = p->p_ucred;
mtx_assert(&hrl_lock, MA_OWNED);
resource = rule->hr_resource;
switch (rule->hr_per) {
- case HRL_SUBJECT_PROCESS:
+ case HRL_SUBJECT_TYPE_PROCESS:
available = rule->hr_amount -
p->p_usage.hu_resources[resource];
break;
- case HRL_SUBJECT_USER:
+ case HRL_SUBJECT_TYPE_USER:
available = rule->hr_amount -
cred->cr_ruidinfo->ui_usage.hu_resources[resource];
break;
- case HRL_SUBJECT_GROUP:
+ case HRL_SUBJECT_TYPE_GROUP:
if (hrl_group_accounting) {
for (i = 0; i < cred->cr_ngroups; i++) {
- if (cred->cr_gidinfos[i]->gi_gid !=
- rule->hr_subject_id)
+ if (cred->cr_gidinfos[i] !=
+ rule->hr_subject.hs_gip)
continue;
found = 1;
@@ -288,12 +288,12 @@
KASSERT(found, ("hrl_available_resource: group not found"));
}
break;
- case HRL_SUBJECT_LOGINCLASS:
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
available = rule->hr_amount -
p->p_loginclass->lc_usage.hu_resources[resource];
- available = INT64_MAX;
+ available = INT64_MAX; /* XXX */
break;
- case HRL_SUBJECT_JAIL:
+ case HRL_SUBJECT_TYPE_JAIL:
available = rule->hr_amount -
cred->cr_prison->pr_usage.hu_resources[resource];
break;
@@ -479,11 +479,11 @@
struct ucred *cred;
struct prison *pr;
- KASSERT(amount > 0, ("hrl_alloc: invalid amount for %s: %lld",
+ KASSERT(amount > 0, ("hrl_alloc: invalid amount for %s: %ju",
hrl_resource_name(resource), amount));
#if 0
- printf("hrl_alloc: allocating %lld of %s for %s (pid %d)\n", amount, hrl_resource_name(resource), p->p_comm, p->p_pid);
+ printf("hrl_alloc: allocating %ju of %s for %s (pid %d)\n", amount, hrl_resource_name(resource), p->p_comm, p->p_pid);
#endif
mtx_lock(&hrl_lock);
@@ -540,7 +540,7 @@
struct ucred *cred;
struct prison *pr;
- KASSERT(amount >= 0, ("hrl_allocated: invalid amount for %s: %lld",
+ KASSERT(amount >= 0, ("hrl_allocated: invalid amount for %s: %ju",
hrl_resource_name(resource), amount));
#if 0
@@ -599,7 +599,7 @@
struct ucred *cred;
struct prison *pr;
- KASSERT(amount > 0, ("hrl_free: invalid amount for %s: %lld",
+ KASSERT(amount > 0, ("hrl_free: invalid amount for %s: %ju",
hrl_resource_name(resource), amount));
#if 0
@@ -608,8 +608,8 @@
mtx_lock(&hrl_lock);
KASSERT(amount <= p->p_usage.hu_resources[resource],
- ("hrl_free: freeing %lld of %s, which is more than allocated "
- "%lld for %s (pid %d)", amount, hrl_resource_name(resource),
+ ("hrl_free: freeing %ju of %s, which is more than allocated "
+ "%ld for %s (pid %d)", amount, hrl_resource_name(resource),
p->p_usage.hu_resources[resource], p->p_comm, p->p_pid));
p->p_usage.hu_resources[resource] -= amount;
p->p_loginclass->lc_usage.hu_resources[resource] -= amount;
@@ -684,14 +684,40 @@
hrl_rule_matches(const struct hrl_rule *rule, const struct hrl_rule *filter)
{
- if (filter->hr_subject != HRL_SUBJECT_UNDEFINED) {
- if (rule->hr_subject != filter->hr_subject)
+ if (filter->hr_subject_type != HRL_SUBJECT_TYPE_UNDEFINED) {
+ if (rule->hr_subject_type != filter->hr_subject_type)
return (0);
- }
- if (filter->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED) {
- if (rule->hr_subject_id != filter->hr_subject_id)
- return (0);
+ switch (filter->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_PROCESS:
+ if (filter->hr_subject.hs_proc !=
+ filter->hr_subject.hs_proc)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ if (filter->hr_subject.hs_uip !=
+ filter->hr_subject.hs_uip)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (filter->hr_subject.hs_gip !=
+ filter->hr_subject.hs_gip)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (filter->hr_subject.hs_loginclass !=
+ filter->hr_subject.hs_loginclass)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ if (filter->hr_subject.hs_prison !=
+ filter->hr_subject.hs_prison)
+ return (0);
+ break;
+ default:
+ panic("hrl_rule_matches: unknown subject type %d",
+ filter->hr_subject_type);
+ }
}
if (filter->hr_resource != HRL_RESOURCE_UNDEFINED) {
@@ -709,7 +735,7 @@
return (0);
}
- if (filter->hr_per != HRL_SUBJECT_UNDEFINED) {
+ if (filter->hr_per != HRL_SUBJECT_TYPE_UNDEFINED) {
if (rule->hr_per != filter->hr_per)
return (0);
}
@@ -828,6 +854,69 @@
return (removed);
}
+static void
+hrl_rule_acquire_subject(struct hrl_rule *rule)
+{
+
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_UNDEFINED:
+ case HRL_SUBJECT_TYPE_PROCESS:
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ if (rule->hr_subject.hs_uip != NULL)
+ uihold(rule->hr_subject.hs_uip);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (rule->hr_subject.hs_gip != NULL)
+ gihold(rule->hr_subject.hs_gip);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (rule->hr_subject.hs_loginclass != NULL)
+ loginclass_acquire(rule->hr_subject.hs_loginclass);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ if (rule->hr_subject.hs_loginclass != NULL)
+ prison_hold(rule->hr_subject.hs_prison);
+ break;
+ default:
+ panic("hrl_rule_acquire_subject: unknown subject type %d",
+ rule->hr_subject_type);
+ }
+}
+
+static void
+hrl_rule_release_subject(struct hrl_rule *rule)
+{
+
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_UNDEFINED:
+ case HRL_SUBJECT_TYPE_PROCESS:
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ if (rule->hr_subject.hs_uip != NULL)
+ uifree(rule->hr_subject.hs_uip);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (rule->hr_subject.hs_gip != NULL)
+ gifree(rule->hr_subject.hs_gip);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (rule->hr_subject.hs_loginclass != NULL)
+ loginclass_release(rule->hr_subject.hs_loginclass);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ if (rule->hr_subject.hs_prison != NULL) {
+ prison_free(rule->hr_subject.hs_prison);
+ sx_xunlock(&allprison_lock);
+ }
+ break;
+ default:
+ panic("hrl_rule_release_subject: unknown subject type %d",
+ rule->hr_subject_type);
+ }
+}
+
+
struct hrl_rule *
hrl_rule_alloc(int flags)
{
@@ -836,9 +925,13 @@
rule = uma_zalloc(hrl_rule_zone, flags);
if (rule == NULL)
return (NULL);
- rule->hr_subject = HRL_SUBJECT_UNDEFINED;
- rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
- rule->hr_per = HRL_SUBJECT_UNDEFINED;
+ rule->hr_subject_type = HRL_SUBJECT_TYPE_UNDEFINED;
+ rule->hr_subject.hs_proc = NULL;
+ rule->hr_subject.hs_uip = NULL;
+ rule->hr_subject.hs_gip = NULL;
+ rule->hr_subject.hs_loginclass = NULL;
+ rule->hr_subject.hs_prison = NULL;
+ rule->hr_per = HRL_SUBJECT_TYPE_UNDEFINED;
rule->hr_resource = HRL_RESOURCE_UNDEFINED;
rule->hr_action = HRL_ACTION_UNDEFINED;
rule->hr_amount = HRL_AMOUNT_UNDEFINED;
@@ -855,13 +948,18 @@
copy = uma_zalloc(hrl_rule_zone, flags);
if (copy == NULL)
return (NULL);
- copy->hr_subject = rule->hr_subject;
- copy->hr_subject_id = rule->hr_subject_id;
+ copy->hr_subject_type = rule->hr_subject_type;
+ copy->hr_subject.hs_proc = rule->hr_subject.hs_proc;
+ copy->hr_subject.hs_uip = rule->hr_subject.hs_uip;
+ copy->hr_subject.hs_gip = rule->hr_subject.hs_gip;
+ copy->hr_subject.hs_loginclass = rule->hr_subject.hs_loginclass;
+ copy->hr_subject.hs_prison = rule->hr_subject.hs_prison;
copy->hr_per = rule->hr_per;
copy->hr_resource = rule->hr_resource;
copy->hr_action = rule->hr_action;
copy->hr_amount = rule->hr_amount;
refcount_init(©->hr_refcount, 1);
+ hrl_rule_acquire_subject(copy);
return (copy);
}
@@ -882,10 +980,7 @@
KASSERT(rule->hr_refcount > 0, ("rule->hr_refcount > 0"));
if (refcount_release(&rule->hr_refcount)) {
- if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS &&
- rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED)
- loginclass_release((struct loginclass *)(long)
- rule->hr_subject_id);
+ hrl_rule_release_subject(rule);
uma_zfree(hrl_rule_zone, rule);
}
}
@@ -894,17 +989,40 @@
hrl_rule_fully_specified(const struct hrl_rule *rule)
{
- if (rule->hr_subject == HRL_SUBJECT_UNDEFINED)
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_UNDEFINED:
return (0);
- if (rule->hr_subject_id == HRL_SUBJECT_ID_UNDEFINED)
- return (0);
+ case HRL_SUBJECT_TYPE_PROCESS:
+ if (rule->hr_subject.hs_proc == NULL)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ if (rule->hr_subject.hs_uip == NULL)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (rule->hr_subject.hs_gip == NULL)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (rule->hr_subject.hs_loginclass == NULL)
+ return (0);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ if (rule->hr_subject.hs_prison == NULL)
+ return (0);
+ break;
+ default:
+ panic("hrl_rule_fully_specified: unknown subject type %d",
+ rule->hr_subject_type);
+ }
if (rule->hr_resource == HRL_RESOURCE_UNDEFINED)
return (0);
if (rule->hr_action == HRL_ACTION_UNDEFINED)
return (0);
if (rule->hr_amount == HRL_AMOUNT_UNDEFINED)
return (0);
- if (rule->hr_per == HRL_SUBJECT_UNDEFINED)
+ if (rule->hr_per == HRL_SUBJECT_TYPE_UNDEFINED)
return (0);
return (1);
@@ -913,11 +1031,11 @@
static struct hrl_rule *
hrl_rule_from_string(char *rulestr)
{
- int error;
+ int error = 0;
char *subjectstr, *subject_idstr, *resourcestr, *actionstr,
*amountstr, *perstr;
- struct loginclass *lc;
struct hrl_rule *rule;
+ id_t id;
rule = hrl_rule_alloc(M_WAITOK);
@@ -929,32 +1047,64 @@
perstr = rulestr;
if (subjectstr == NULL || subjectstr[0] == '\0')
- rule->hr_subject = HRL_SUBJECT_UNDEFINED;
+ rule->hr_subject_type = HRL_SUBJECT_TYPE_UNDEFINED;
else {
- error = str2value(subjectstr, &rule->hr_subject, subjectnames);
+ error = str2value(subjectstr, &rule->hr_subject_type, subjectnames);
if (error)
goto out;
}
- /*
- * Login classes don't have any ID. Instead, we just put a pointer
- * to the 'struct loginclass' into the hr_subject_id field.
- */
- if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS) {
- if (subject_idstr == NULL || subject_idstr[0] == '\0') {
- rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
- } else {
- lc = loginclass_find(subject_idstr);
- rule->hr_subject_id = (long)lc;
- }
+ if (subject_idstr == NULL || subject_idstr[0] == '\0') {
+ rule->hr_subject.hs_proc = NULL;
+ rule->hr_subject.hs_uip = NULL;
+ rule->hr_subject.hs_gip = NULL;
+ rule->hr_subject.hs_loginclass = NULL;
+ rule->hr_subject.hs_prison = NULL;
} else {
- if (subject_idstr == NULL || subject_idstr[0] == '\0')
- rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
- else {
- error = str2id(subject_idstr, &rule->hr_subject_id);
+
+ /*
+ * Loginclasses don't have any numerical ID's.
+ */
+ if (rule->hr_subject_type != HRL_SUBJECT_TYPE_LOGINCLASS) {
+ error = str2id(subject_idstr, &id);
if (error)
goto out;
}
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_UNDEFINED:
+ error = EINVAL;
+ goto out;
+ case HRL_SUBJECT_TYPE_PROCESS:
+ sx_assert(&allproc_lock, SA_LOCKED);
+ rule->hr_subject.hs_proc = pfind(id);
+ if (rule->hr_subject.hs_proc == NULL) {
+ error = ESRCH;
+ goto out;
+ }
+ PROC_UNLOCK(rule->hr_subject.hs_proc);
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ rule->hr_subject.hs_uip = uifind(id);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ rule->hr_subject.hs_gip = gifind(id);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ rule->hr_subject.hs_loginclass = loginclass_find(subject_idstr);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ sx_xlock(&allprison_lock);
+ rule->hr_subject.hs_prison = prison_find(id);
+ if (rule->hr_subject.hs_prison == NULL) {
+ sx_xunlock(&allprison_lock);
+ error = ESRCH;
+ goto out;
+ }
+ break;
+ default:
+ panic("hrl_rule_from_string: unknown subject type %d",
+ rule->hr_subject_type);
+ }
}
if (resourcestr == NULL || resourcestr[0] == '\0')
@@ -983,17 +1133,13 @@
}
if (perstr == NULL || perstr[0] == '\0')
- rule->hr_per = HRL_SUBJECT_UNDEFINED;
+ rule->hr_per = HRL_SUBJECT_TYPE_UNDEFINED;
else {
error = str2value(perstr, &rule->hr_per, subjectnames);
if (error)
goto out;
}
- if (rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED &&
- rule->hr_subject == HRL_SUBJECT_UNDEFINED)
- goto out;
-
out:
if (error) {
hrl_rule_release(rule);
@@ -1019,8 +1165,8 @@
KASSERT(hrl_rule_fully_specified(rule), ("rule not fully specified"));
- if ((rule->hr_subject == HRL_SUBJECT_GROUP ||
- rule->hr_per == HRL_SUBJECT_GROUP) && !hrl_group_accounting)
+ if ((rule->hr_subject_type == HRL_SUBJECT_TYPE_GROUP ||
+ rule->hr_per == HRL_SUBJECT_TYPE_GROUP) && !hrl_group_accounting)
return (EOPNOTSUPP);
if (rule->hr_action == HRL_ACTION_DELAY)
@@ -1031,101 +1177,79 @@
*/
hrl_rule_remove(rule);
- switch (rule->hr_subject) {
- case HRL_SUBJECT_PROCESS:
- /*
- * The sx lock is to keep the process from going away.
- */
- sx_slock(&proctree_lock);
- p = pfind(rule->hr_subject_id);
- if (p == NULL) {
- sx_sunlock(&proctree_lock);
- return (ESRCH);
- }
-
- PROC_UNLOCK(p);
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_PROCESS:
+ p = rule->hr_subject.hs_proc;
+ KASSERT(p != NULL, ("hrl_rule_add: NULL proc"));
hrl_limit_add(&p->p_limits, rule);
- sx_sunlock(&proctree_lock);
/*
* In case of per-process rule, we don't have anything more
* to do.
*/
return (0);
- case HRL_SUBJECT_USER:
- uip = uifind(rule->hr_subject_id);
- KASSERT(uip != NULL, ("hrl_rule_add: uifind failed"));
+ case HRL_SUBJECT_TYPE_USER:
+ uip = rule->hr_subject.hs_uip;
+ KASSERT(uip != NULL, ("hrl_rule_add: NULL uip"));
hrl_limit_add(&uip->ui_limits, rule);
- /*
- * Don't call uifree(2); we don't want the uidinfo
- * to go away, because the rule should stay there even
- * if there are no processes with that uid. The same
- * applies to the cases below.
- */
break;
- case HRL_SUBJECT_GROUP:
- gip = gifind_existing(rule->hr_subject_id);
- KASSERT(gip != NULL, ("hrl_rule_add: gifind failed"));
+ case HRL_SUBJECT_TYPE_GROUP:
+ gip = rule->hr_subject.hs_gip;
+ KASSERT(gip != NULL, ("hrl_rule_add: NULL gip"));
hrl_limit_add(&gip->gi_limits, rule);
break;
- case HRL_SUBJECT_LOGINCLASS:
- lc = (struct loginclass *)(long)rule->hr_subject_id;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ lc = rule->hr_subject.hs_loginclass;
+ KASSERT(lc != NULL, ("hrl_rule_add: NULL loginclass"));
hrl_limit_add(&lc->lc_limits, rule);
break;
- case HRL_SUBJECT_JAIL:
- sx_xlock(&allprison_lock);
- pr = prison_find(rule->hr_subject_id);
- if (pr == NULL) {
- sx_xunlock(&allprison_lock);
- return (ESRCH);
- }
+ case HRL_SUBJECT_TYPE_JAIL:
+ pr = rule->hr_subject.hs_prison;
+ KASSERT(pr != NULL, ("hrl_rule_add: NULL pr"));
hrl_limit_add(&pr->pr_limits, rule);
- sx_xunlock(&allprison_lock);
break;
default:
- panic("hrl_rule_add_limits: unknown subject %d",
- rule->hr_subject);
+ panic("hrl_rule_add_limits: unknown subject type %d",
+ rule->hr_subject_type);
}
/*
* Now go through all the processes and add the new rule to the ones
* it applies to.
*/
- sx_slock(&proctree_lock);
+ sx_assert(&allproc_lock, SA_LOCKED);
FOREACH_PROC_IN_SYSTEM(p) {
cred = p->p_ucred;
- switch (rule->hr_subject) {
- case HRL_SUBJECT_USER:
- if (cred->cr_uid == rule->hr_subject_id ||
- cred->cr_ruid == rule->hr_subject_id)
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_USER:
+ if (cred->cr_uidinfo == rule->hr_subject.hs_uip ||
+ cred->cr_ruidinfo == rule->hr_subject.hs_uip)
break;
continue;
- case HRL_SUBJECT_GROUP:
- if (groupmember(rule->hr_subject_id, cred))
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (groupmember(rule->hr_subject.hs_gip->gi_gid, cred))
break;
continue;
- case HRL_SUBJECT_LOGINCLASS:
- lc = (struct loginclass *)(long)rule->hr_subject_id; /* XXX: This line is here to remove cc warning; investigate. */
- if (p->p_loginclass == lc)
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (p->p_loginclass == rule->hr_subject.hs_loginclass)
break;
continue;
- case HRL_SUBJECT_JAIL:
+ case HRL_SUBJECT_TYPE_JAIL:
for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
- if (pr->pr_id == rule->hr_subject_id)
+ if (pr->pr_id == rule->hr_subject.hs_prison->pr_id)
break;
continue;
default:
- panic("hrl_rule_add_limits: unknown subject %d",
- rule->hr_subject);
+ panic("hrl_rule_add_limits: unknown subject type %d",
+ rule->hr_subject_type);
}
hrl_limit_add(&p->p_limits, rule);
}
- sx_sunlock(&proctree_lock);
return (0);
}
@@ -1148,15 +1272,10 @@
int error, found = 0;
struct proc *p;
- if (filter->hr_subject == HRL_SUBJECT_PROCESS &&
- filter->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED) {
- sx_slock(&proctree_lock);
- p = pfind(filter->hr_subject_id);
- if (p == NULL)
- return (ESRCH);
- PROC_UNLOCK(p);
+ if (filter->hr_subject_type == HRL_SUBJECT_TYPE_PROCESS &&
+ filter->hr_subject.hs_proc != NULL) {
+ p = filter->hr_subject.hs_proc;
found = hrl_limit_remove_matching(&p->p_limits, filter);
- sx_sunlock(&proctree_lock);
if (found)
return (0);
return (ESRCH);
@@ -1172,13 +1291,12 @@
(void *)&found);
KASSERT(error == 0, ("gi_limits_foreach failed"));
- sx_slock(&proctree_lock);
+ sx_assert(&allproc_lock, SA_LOCKED);
FOREACH_PROC_IN_SYSTEM(p) {
found += hrl_limit_remove_matching(&p->p_limits, filter);
if (error == 0)
found = 1;
}
- sx_sunlock(&proctree_lock);
if (found)
return (0);
@@ -1191,25 +1309,52 @@
static void
hrl_rule_to_sbuf(struct sbuf *sb, const struct hrl_rule *rule)
{
- if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS) {
- KASSERT(rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED,
- ("rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED"));
- sbuf_printf(sb, "%s:%s:%s:%s=%jd",
- hrl_subject_name(rule->hr_subject),
- ((struct loginclass *)(long)rule->hr_subject_id)->lc_name,
- hrl_resource_name(rule->hr_resource),
- hrl_action_name(rule->hr_action),
- rule->hr_amount);
- } else {
- sbuf_printf(sb, "%s:%d:%s:%s=%jd",
- hrl_subject_name(rule->hr_subject),
- (int)rule->hr_subject_id,
- hrl_resource_name(rule->hr_resource),
- hrl_action_name(rule->hr_action),
- rule->hr_amount);
+
+ sbuf_printf(sb, "%s:", hrl_subject_type_name(rule->hr_subject_type));
+
+ switch (rule->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_PROCESS:
+ if (rule->hr_subject.hs_proc == NULL)
+ sbuf_printf(sb, ":");
+ else
+ sbuf_printf(sb, "%d:", rule->hr_subject.hs_proc->p_pid);
+ break;
+ case HRL_SUBJECT_TYPE_USER:
+ if (rule->hr_subject.hs_uip == NULL)
+ sbuf_printf(sb, ":");
+ else
+ sbuf_printf(sb, "%d:", rule->hr_subject.hs_uip->ui_uid);
+ break;
+ case HRL_SUBJECT_TYPE_GROUP:
+ if (rule->hr_subject.hs_gip == NULL)
+ sbuf_printf(sb, ":");
+ else
+ sbuf_printf(sb, "%d:", rule->hr_subject.hs_gip->gi_gid);
+ break;
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ if (rule->hr_subject.hs_loginclass == NULL)
+ sbuf_printf(sb, ":");
+ else
+ sbuf_printf(sb, "%s:", rule->hr_subject.hs_loginclass->lc_name);
+ break;
+ case HRL_SUBJECT_TYPE_JAIL:
+ if (rule->hr_subject.hs_prison == NULL)
+ sbuf_printf(sb, ":");
+ else
+ sbuf_printf(sb, "%d:", rule->hr_subject.hs_prison->pr_id);
+ break;
+ default:
+ panic("hrl_rule_to_sbuf: unknown subject type %d",
+ rule->hr_subject_type);
}
- if (rule->hr_per != rule->hr_subject)
- sbuf_printf(sb, "/%s", hrl_subject_name(rule->hr_per));
+
+ sbuf_printf(sb, "%s:%s=%jd",
+ hrl_resource_name(rule->hr_resource),
+ hrl_action_name(rule->hr_action),
+ rule->hr_amount);
+
+ if (rule->hr_per != rule->hr_subject_type)
+ sbuf_printf(sb, "/%s", hrl_subject_type_name(rule->hr_per));
}
/*
@@ -1273,87 +1418,6 @@
return (sb);
}
-static int
-hrl_get_usage_pid(struct thread *td, id_t pid, struct sbuf **outputsbuf)
-{
- struct proc *p;
- struct hrl_usage usage;
-
- if ((p = pfind(pid)) == NULL) {
- if ((p = zpfind(pid)) == NULL)
- return (ESRCH);
- }
- usage = p->p_usage;
- PROC_UNLOCK(p);
-
- *outputsbuf = hrl_usage_to_sbuf(&usage);
-
- return (0);
-}
-
-static int
-hrl_get_usage_uid(struct thread *td, id_t uid, struct sbuf **outputsbuf)
-{
- struct uidinfo *uip;
-
- uip = uifind_existing(uid);
- if (uip == NULL)
- return (ESRCH);
- *outputsbuf = hrl_usage_to_sbuf(&uip->ui_usage);
- uifree(uip);
-
- return (0);
-}
-
-static int
-hrl_get_usage_gid(struct thread *td, id_t gid, struct sbuf **outputsbuf)
-{
- struct gidinfo *gip;
-
- if (!hrl_group_accounting)
- return (EOPNOTSUPP);
-
- gip = gifind_existing(gid);
- if (gip == NULL)
- return (ESRCH);
- *outputsbuf = hrl_usage_to_sbuf(&gip->gi_usage);
- gifree(gip);
-
- return (0);
-}
-
-static int
-hrl_get_usage_lc(struct thread *td, int lcp, struct sbuf **outputsbuf)
-{
- struct loginclass *lc;
-
- if (lcp == HRL_SUBJECT_ID_UNDEFINED)
- return (EINVAL);
-
- lc = (struct loginclass *)lcp;
- *outputsbuf = hrl_usage_to_sbuf(&lc->lc_usage);
-
- return (0);
-}
-
-static int
-hrl_get_usage_jid(struct thread *td, id_t jid, struct sbuf **outputsbuf)
-{
- struct prison *pr;
-
- sx_xlock(&allprison_lock);
- pr = prison_find(jid);
- if (pr == NULL) {
- sx_xunlock(&allprison_lock);
- return (ENOENT);
- }
- *outputsbuf = hrl_usage_to_sbuf(&pr->pr_usage);
- prison_free(pr);
- sx_xunlock(&allprison_lock);
-
- return (0);
-}
-
int
hrl_get_usage(struct thread *td, struct hrl_get_usage_args *uap)
{
@@ -1361,6 +1425,11 @@
char *inputstr;
struct hrl_rule *filter;
struct sbuf *outputsbuf = NULL;
+ struct proc *p;
+ struct uidinfo *uip;
+ struct gidinfo *gip;
+ struct loginclass *lc;
+ struct prison *pr;
error = hrl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
if (error)
@@ -1371,30 +1440,51 @@
if (filter == NULL)
return (EINVAL);
- switch (filter->hr_subject) {
- case HRL_SUBJECT_PROCESS:
- error = hrl_get_usage_pid(td, filter->hr_subject_id,
- &outputsbuf);
+ switch (filter->hr_subject_type) {
+ case HRL_SUBJECT_TYPE_PROCESS:
+ p = filter->hr_subject.hs_proc;
+ if (p == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ outputsbuf = hrl_usage_to_sbuf(&p->p_usage);
break;
- case HRL_SUBJECT_USER:
- error = hrl_get_usage_uid(td, filter->hr_subject_id,
- &outputsbuf);
+ case HRL_SUBJECT_TYPE_USER:
+ uip = filter->hr_subject.hs_uip;
+ if (uip == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ outputsbuf = hrl_usage_to_sbuf(&uip->ui_usage);
break;
- case HRL_SUBJECT_GROUP:
- error = hrl_get_usage_gid(td, filter->hr_subject_id,
- &outputsbuf);
+ case HRL_SUBJECT_TYPE_GROUP:
+ gip = filter->hr_subject.hs_gip;
+ if (gip == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ outputsbuf = hrl_usage_to_sbuf(&gip->gi_usage);
break;
- case HRL_SUBJECT_LOGINCLASS:
- error = hrl_get_usage_lc(td, filter->hr_subject_id,
- &outputsbuf);
+ case HRL_SUBJECT_TYPE_LOGINCLASS:
+ lc = filter->hr_subject.hs_loginclass;
+ if (lc == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ outputsbuf = hrl_usage_to_sbuf(&lc->lc_usage);
break;
- case HRL_SUBJECT_JAIL:
- error = hrl_get_usage_jid(td, filter->hr_subject_id,
- &outputsbuf);
+ case HRL_SUBJECT_TYPE_JAIL:
+ pr = filter->hr_subject.hs_prison;
+ if (pr == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ outputsbuf = hrl_usage_to_sbuf(&pr->pr_usage);
break;
default:
error = EINVAL;
}
+out:
hrl_rule_release(filter);
if (error)
return (error);
@@ -1438,17 +1528,20 @@
if (error)
return (error);
+ sx_slock(&allproc_lock);
filter = hrl_rule_from_string(inputstr);
free(inputstr, M_HRL);
- if (filter == NULL)
+ if (filter == NULL) {
+ sx_sunlock(&allproc_lock);
return (EINVAL);
+ }
again:
buf = malloc(bufsize, M_HRL, M_WAITOK);
sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
KASSERT(sb != NULL, ("sbuf_new failed"));
- sx_slock(&proctree_lock);
+ sx_assert(&allproc_lock, SA_LOCKED);
FOREACH_PROC_IN_SYSTEM(p) {
mtx_lock(&hrl_lock);
LIST_FOREACH(limit, &p->p_limits, hl_next) {
@@ -1456,7 +1549,7 @@
* Non-process rules will be added to the buffer later.
* Adding them here would result in duplicated output.
*/
- if (limit->hl_rule->hr_subject != HRL_SUBJECT_PROCESS)
+ if (limit->hl_rule->hr_subject_type != HRL_SUBJECT_TYPE_PROCESS)
continue;
if (!hrl_rule_matches(limit->hl_rule, filter))
continue;
@@ -1465,7 +1558,6 @@
}
mtx_unlock(&hrl_lock);
}
- sx_sunlock(&proctree_lock);
mtx_lock(&hrl_lock);
loginclass_limits_foreach(hrl_get_rules_callback, filter, sb);
@@ -1488,6 +1580,7 @@
error = hrl_write_outbuf(sb, uap->outbufp, uap->outbuflen);
hrl_rule_release(filter);
+ sx_sunlock(&allproc_lock);
free(buf, M_HRL);
return (error);
}
@@ -1501,30 +1594,33 @@
struct sbuf *sb;
struct hrl_rule *filter;
struct hrl_limit *limit;
- struct proc *p;
error = hrl_read_inbuf(&inputstr, uap->inbufp, uap->inbuflen);
if (error)
return (error);
+ sx_slock(&allproc_lock);
filter = hrl_rule_from_string(inputstr);
free(inputstr, M_HRL);
- if (filter == NULL)
+ if (filter == NULL) {
+ sx_sunlock(&allproc_lock);
return (EINVAL);
+ }
- if (filter->hr_subject == HRL_SUBJECT_UNDEFINED) {
+ if (filter->hr_subject_type == HRL_SUBJECT_TYPE_UNDEFINED) {
hrl_rule_release(filter);
+ sx_sunlock(&allproc_lock);
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list