PERFORCE change 165311 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Sat Jun 27 14:50:45 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=165311
Change 165311 by trasz at trasz_victim on 2009/06/27 14:50:38
Rework rule addition/removal to use text strings instead of binary
structs.
Affected files ...
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#16 edit
.. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/Makefile#3 edit
.. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#9 edit
Differences ...
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#16 (text+ko) ====
@@ -57,6 +57,45 @@
RB_ENTRY(hrl_node) hn_next;
};
+struct dict {
+ const char *d_name;
+ int d_value;
+};
+
+struct dict subjectnames[] = {
+ { "process", HRL_SUBJECT_PROCESS },
+ { "user", HRL_SUBJECT_USER },
+ { "group", HRL_SUBJECT_GROUP },
+ { "loginclass", HRL_SUBJECT_LOGINCLASS },
+ { "jail", HRL_SUBJECT_JAIL },
+ { NULL, -1 }};
+
+struct dict resourcenames[] = {
+ { "cputime", HRL_RESOURCE_CPUTIME },
+ { "filesize", HRL_RESOURCE_FILESIZE },
+ { "datasize", HRL_RESOURCE_DATASIZE },
+ { "stacksize", HRL_RESOURCE_STACKSIZE },
+ { "coredumpsize", HRL_RESOURCE_COREDUMPSIZE },
+ { "memoryuse", HRL_RESOURCE_MEMORYUSE },
+ { "memorylocked", HRL_RESOURCE_MEMORYLOCKED },
+ { "maxprocesses", HRL_RESOURCE_MAXPROCESSES },
+ { "openfiles", HRL_RESOURCE_OPENFILES },
+ { "sbsize", HRL_RESOURCE_SBSIZE },
+ { "vmemoryuse", HRL_RESOURCE_VMEMORYUSE },
+ { NULL, -1 }};
+
+struct dict actionnames[] = {
+ { "deny", HRL_ACTION_DENY },
+ { "delay", HRL_ACTION_DELAY },
+ { "log", HRL_ACTION_LOG },
+ { "sighup", HRL_ACTION_SIGHUP },
+ { "sigint", HRL_ACTION_SIGINT },
+ { "sigkill", HRL_ACTION_SIGKILL },
+ { "sigsegv", HRL_ACTION_SIGSEGV },
+ { "sigxcpu", HRL_ACTION_SIGXCPU },
+ { "sigxfsz", HRL_ACTION_SIGXFSZ },
+ { NULL, -1 }};
+
/*
* XXX: This is silly. Some better way of organising these
* will be required.
@@ -181,34 +220,14 @@
static const char *
hrl_resource_name(int resource)
{
- switch (resource) {
- case HRL_RESOURCE_CPUTIME:
- return ("cputime");
- case HRL_RESOURCE_FILESIZE:
- return ("filesize");
- case HRL_RESOURCE_DATASIZE:
- return ("datasize");
- case HRL_RESOURCE_STACKSIZE:
- return ("stacksize");
- case HRL_RESOURCE_COREDUMPSIZE:
- return ("coredumpsize");
- case HRL_RESOURCE_MEMORYUSE:
- return ("memoryuse");
- case HRL_RESOURCE_MEMORYLOCKED:
- return ("memorylocked");
- case HRL_RESOURCE_MAXPROCESSES:
- return ("maxprocesses");
- case HRL_RESOURCE_OPENFILES:
- return ("openfiles");
- case HRL_RESOURCE_SBSIZE:
- return ("sbsize");
- case HRL_RESOURCE_VMEMORYUSE:
- return ("vmemoryuse");
- case HRL_RESOURCE_PTY:
- return ("vmemoryuse");
- default:
- panic("hrl_resource_name: unknown resource");
+ int i;
+
+ for (i = 0; resourcenames[i].d_name != NULL; i++) {
+ if (resourcenames[i].d_value == resource)
+ return (resourcenames[i].d_name);
}
+
+ panic("hrl_resource_name: unknown resource");
}
void
@@ -530,66 +549,119 @@
}
static int
-hrl_rule_add(struct hrl_rule *rule)
+str2value(const char *str, int *value, struct dict *table)
+{
+ int i;
+
+ if (value == NULL)
+ return (EINVAL);
+
+ printf("str2value: '%s'\n", str);
+
+ for (i = 0; table[i].d_name != NULL; i++) {
+ if (strcasecmp(table[i].d_name, str) == 0) {
+ *value = table[i].d_value;
+ return (0);
+ }
+ }
+
+ return (EINVAL);
+}
+
+static int
+str2id(const char *str, id_t *value)
{
- struct hrl_node *node, *existing;
+ char *end;
- node = uma_zalloc(hrl_zone, M_WAITOK);
- node->hn_rule = *rule;
+ if (str == NULL)
+ return (EINVAL);
- mtx_lock(&hrl_lock);
- existing = RB_INSERT(hrl_tree, &hrls, node);
- if (existing != NULL)
- existing->hn_rule.hr_amount = rule->hr_amount;
- mtx_unlock(&hrl_lock);
+ printf("str2id: '%s'\n", str);
- if (existing != NULL)
- uma_zfree(hrl_zone, node);
+ *value = strtoul(str, &end, 10);
+ if ((size_t)(end - str) != strlen(str))
+ return (EINVAL);
return (0);
}
static int
-hrl_rule_remove(struct hrl_rule *rule)
+str2int64(const char *str, int64_t *value)
{
- struct hrl_node searched, *node;
+ char *end;
- node = uma_zalloc(hrl_zone, M_WAITOK);
- searched.hn_rule = *rule;
+ if (str == NULL)
+ return (EINVAL);
- mtx_lock(&hrl_lock);
- node = RB_FIND(hrl_tree, &hrls, &searched);
- if (node != NULL) {
- node = RB_REMOVE(hrl_tree, &hrls, node);
- KASSERT(node != NULL, ("hrl_adjust: node removal failed"));
- }
- mtx_unlock(&hrl_lock);
+ printf("str2int64: '%s'\n", str);
- uma_zfree(hrl_zone, node);
+ *value = strtoul(str, &end, 10);
+ if ((size_t)(end - str) != strlen(str))
+ return (EINVAL);
return (0);
}
static int
-hrl_rule_check(struct hrl_rule *rule)
+hrl_rule_parse(struct hrl_rule *rule, char *rulestr)
{
+ int error;
+ char *subjectstr, *subject_idstr, *resourcestr, *actionstr, *amountstr, *perstr;
+
+ subjectstr = strsep(&rulestr, ":");
+ subject_idstr = strsep(&rulestr, ":");
+ resourcestr = strsep(&rulestr, ":");
+ actionstr = strsep(&rulestr, "=");
+ amountstr = strsep(&rulestr, "/");
+ perstr = rulestr;
- if (rule.hr_subject <= 0 || rule.hr_subject > HRL_SUBJECT_MAX)
+ error = str2value(subjectstr, &rule->hr_subject, subjectnames);
+ if (error)
return (EINVAL);
- if (rule.hr_per <= 0 || rule.hr_per > HRL_SUBJECT_MAX)
+ error = str2id(subject_idstr, &rule->hr_subject_id);
+ if (error)
return (EINVAL);
- if (rule.hr_resource <= 0 || rule.hr_resource > HRL_RESOURCE_MAX)
+ error = str2value(resourcestr, &rule->hr_resource, resourcenames);
+ if (error)
return (EINVAL);
- if (rule.hr_action <= 0 || rule.hr_action > HRL_ACTION_MAX)
+ error = str2value(actionstr, &rule->hr_action, actionnames);
+ if (error)
return (EINVAL);
- if (rule.hr_amount <= 0)
+ error = str2int64(amountstr, &rule->hr_amount);
+ if (error)
return (EINVAL);
+ if (perstr != NULL && perstr[0] != '\0') {
+ error = str2value(perstr, &rule->hr_per, subjectnames);
+ if (error)
+ return (EINVAL);
+ } else
+ rule->hr_per = rule->hr_subject;
+
+ return (0);
+}
+
+static int
+hrl_rule_add(struct hrl_rule *rule)
+{
+ struct hrl_node *node, *existing;
+
+ node = uma_zalloc(hrl_zone, M_WAITOK);
+ node->hn_rule = *rule;
+
+ mtx_lock(&hrl_lock);
+ existing = RB_INSERT(hrl_tree, &hrls, node);
+ if (existing != NULL)
+ existing->hn_rule.hr_amount = rule->hr_amount;
+ mtx_unlock(&hrl_lock);
+ if (existing != NULL)
+ uma_zfree(hrl_zone, node);
+
return (0);
}
static int
-hrl_add_rule(struct thread *td, const void *bufp, size_t buflen)
+hrl_add_rule(struct thread *td, char *inputstr)
{
int error;
struct hrl_rule rule;
@@ -597,25 +669,38 @@
error = priv_check(td, PRIV_HRL_SET);
if (error)
return (error);
+ error = hrl_rule_parse(&rule, inputstr);
+ if (error)
+ return (error);
+ error = hrl_rule_add(&rule);
+ return (error);
+}
- if (buflen != sizeof(rule))
- return (EINVAL);
+static int
+hrl_rule_remove(struct hrl_rule *rule)
+{
+ struct hrl_node searched, *node;
- error = copyin(bufp, &rule, buflen);
- if (error)
- return (error);
+ searched.hn_rule = *rule;
- error = hrl_rule_check(&rule);
- if (error)
- return (error);
+ mtx_lock(&hrl_lock);
+ node = RB_FIND(hrl_tree, &hrls, &searched);
+ if (node != NULL) {
+ node = RB_REMOVE(hrl_tree, &hrls, node);
+ KASSERT(node != NULL, ("hrl_adjust: node removal failed"));
+ }
+ mtx_unlock(&hrl_lock);
- error = hrl_rule_add(&rule);
+ if (node != NULL)
+ uma_zfree(hrl_zone, node);
+ else
+ return (ENOENT);
return (0);
}
static int
-hrl_remove_rule(struct thread *td, const void *bufp, size_t buflen)
+hrl_remove_rule(struct thread *td, char *inputstr)
{
int error;
struct hrl_rule rule;
@@ -623,25 +708,23 @@
error = priv_check(td, PRIV_HRL_SET);
if (error)
return (error);
-
- if (buflen != sizeof(rule))
- return (EINVAL);
-
- error = copyin(bufp, &rule, buflen);
+ error = hrl_rule_parse(&rule, inputstr);
if (error)
return (error);
-
error = hrl_rule_remove(&rule);
-
- return (0);
+ return (error);
}
static int
-hrl_get_acc_pid(struct thread *td, id_t pid, void *bufp, size_t buflen)
+hrl_get_acc_pid(struct thread *td, char *inputstr, void *bufp, size_t buflen)
{
int error;
+ id_t pid;
struct proc *p;
+ error = str2id(inputstr, &pid);
+ if (error)
+ return (error);
if ((p = pfind(pid)) == NULL) {
if ((p = zpfind(pid)) == NULL)
return (ESRCH);
@@ -653,11 +736,15 @@
}
static int
-hrl_get_acc_uid(struct thread *td, id_t uid, void *bufp, size_t buflen)
+hrl_get_acc_uid(struct thread *td, char *inputstr, void *bufp, size_t buflen)
{
int error;
+ id_t uid;
struct uidinfo *uip;
+ error = str2id(inputstr, &uid);
+ if (error)
+ return (error);
uip = uifind_existing(uid);
if (uip == NULL)
return (ESRCH);
@@ -668,11 +755,15 @@
}
static int
-hrl_get_acc_gid(struct thread *td, id_t gid, void *bufp, size_t buflen)
+hrl_get_acc_gid(struct thread *td, char *inputstr, void *bufp, size_t buflen)
{
int error;
+ id_t gid;
struct gidinfo *gip;
+ error = str2id(inputstr, &gid);
+ if (error)
+ return (error);
gip = gifind_existing(gid);
if (gip == NULL)
return (ESRCH);
@@ -683,11 +774,16 @@
}
static int
-hrl_get_acc_jid(struct thread *td, id_t jid, void *bufp, size_t buflen)
+hrl_get_acc_jid(struct thread *td, char *inputstr, void *bufp, size_t buflen)
{
int error;
+ id_t jid;
struct prison *pr;
+ error = str2id(inputstr, &jid);
+ if (error)
+ return (error);
+
sx_xlock(&allprison_lock);
pr = prison_find(jid);
if (pr == NULL) {
@@ -705,39 +801,53 @@
hrl(struct thread *td, struct hrl_args *uap)
{
int error;
- id_t id;
+ char *inputstr = NULL;
- if (uap->op != HRL_OP_GET_RULES) {
- if (uap->inbuflen != sizeof(id_t))
+ if (uap->inbufp != NULL && uap->inbuflen != 0) {
+ if (uap->inbuflen <= 0)
return (EINVAL);
- error = copyin(uap->inbufp, &id, sizeof(id_t));
+
+ inputstr = malloc(uap->inbuflen + 1, M_HRL, M_WAITOK);
+ error = copyinstr(uap->inbufp, inputstr, uap->inbuflen, NULL);
if (error)
- return (error);
- if (id < 0)
- return (EINVAL);
- if (uap->outbuflen < sizeof(struct hrl_acc))
- return (EFBIG);
+ goto out;
}
switch (uap->op) {
case HRL_OP_GET_RULES:
- return (hrl_get_rules(td, uap->outbufp, uap->outbuflen));
+ error = hrl_get_rules(td, uap->outbufp, uap->outbuflen);
+ break;
case HRL_OP_ADD_RULE:
- return (hrl_add_rule(td, uap->inbufp, uap->inbuflen));
+ error = hrl_add_rule(td, inputstr);
+ break;
case HRL_OP_REMOVE_RULE:
- return (hrl_remove_rule(td, uap->inbufp, uap->inbuflen));
+ error = hrl_remove_rule(td, inputstr);
+ break;
case HRL_OP_GET_ACC_PID:
- return (hrl_get_acc_pid(td, id, uap->outbufp, uap->outbuflen));
+ error = hrl_get_acc_pid(td, inputstr, uap->outbufp, uap->outbuflen);
+ break;
case HRL_OP_GET_ACC_UID:
- return (hrl_get_acc_uid(td, id, uap->outbufp, uap->outbuflen));
+ error = hrl_get_acc_uid(td, inputstr, uap->outbufp, uap->outbuflen);
+ break;
case HRL_OP_GET_ACC_GID:
- return (hrl_get_acc_gid(td, id, uap->outbufp, uap->outbuflen));
+ error = hrl_get_acc_gid(td, inputstr, uap->outbufp, uap->outbuflen);
+ break;
case HRL_OP_GET_ACC_JAILID:
- return (hrl_get_acc_jid(td, id, uap->outbufp, uap->outbuflen));
+ error = hrl_get_acc_jid(td, inputstr, uap->outbufp, uap->outbuflen);
+ break;
default:
- return (EINVAL);
+ error = EINVAL;
}
- /* NOTREACHED */
+
+ /*
+ * XXX: Move copyouts into this place.
+ */
+
+out:
+ if (inputstr != NULL)
+ free(inputstr, M_HRL);
+
+ return (error);
}
static void
==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/Makefile#3 (text+ko) ====
==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#9 (text+ko) ====
@@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
@@ -190,7 +191,7 @@
id_t id;
char *end;
- id = strtod(s, &end);
+ id = strtoul(s, &end, 10);
if ((size_t)(end - s) != strlen(s))
errx(1, "trailing characters after numerical id");
@@ -208,6 +209,9 @@
if (pwd != NULL)
return (pwd->pw_uid);
+ if (!isnumber(s[0]))
+ errx(1, "uknown user '%s'", s);
+
id = strtod(s, &end);
if ((size_t)(end - s) != strlen(s))
errx(1, "trailing characters after numerical id");
@@ -226,6 +230,9 @@
if (grp != NULL)
return (grp->gr_gid);
+ if (!isnumber(s[0]))
+ errx(1, "uknown group '%s'", s);
+
id = strtod(s, &end);
if ((size_t)(end - s) != strlen(s))
errx(1, "trailing characters after numerical id");
@@ -284,8 +291,13 @@
{
int error, i;
struct hrl_acc acc;
+ char *str;
+
+ asprintf(&str, "%d", (int)id);
+ if (str == NULL)
+ err(1, "asprintf");
- error = hrl(op, &id, sizeof(id), &acc, sizeof(acc));
+ error = hrl(op, str, strlen(str) + 1, &acc, sizeof(acc));
if (error)
err(1, "hrl");
@@ -298,34 +310,74 @@
}
}
+/*
+ * This routine replaces user/group name with numeric id.
+ */
+static char *
+resolve_id(char *str)
+{
+ id_t id;
+ char *subject, *textid, *resolved;
+
+ subject = strsep(&str, ":");
+ textid = strsep(&str, ":");
+ if (textid == NULL)
+ errx(1, "error in rule specification: no subject");
+ if (str == NULL)
+ errx(1, "error in rule specification: no subject id");
+
+ if (strcasecmp(subject, "user") == 0) {
+ id = parse_user(textid);
+ asprintf(&resolved, "%s:%d:%s", subject, (int)id, str);
+ } else if (strcasecmp(subject, "group") == 0) {
+ id = parse_group(textid);
+ asprintf(&resolved, "%s:%d:%s", subject, (int)id, str);
+ } else
+ asprintf(&resolved, "%s:%s:%s", subject, textid, str);
+
+ if (resolved == NULL)
+ err(1, "asprintf");
+
+ return (resolved);
+}
+
static void
+add_or_remove_rule(int op, char *rule)
+{
+ int error;
+ char *resolved;
+
+ resolved = resolve_id(rule);
+ error = hrl(op, resolved, strlen(resolved) + 1, NULL, 0);
+ if (error)
+ err(1, "hrl");
+ free(resolved);
+}
+
+static void
usage(void)
{
- fprintf(stderr, "usage: hrl [-u user | -g group | -p pid | -j jailid]\n");
+ fprintf(stderr, "usage: hrl [-a rule | -r rule | -u user | -g group | -p pid | -j jailid]\n");
exit(1);
}
int
main(int argc __unused, char **argv __unused)
{
- int ch, op, pflag = 0, uflag = 0, gflag = 0, jflag = 0;
+ int ch, op, aflag = 0, gflag = 0, jflag = 0, pflag = 0, rflag = 0, uflag = 0;
id_t id = 0;
+ char *rule = NULL;
op = HRL_OP_GET_RULES;
- while ((ch = getopt(argc, argv, "p:u:g:j:")) != -1) {
+ while ((ch = getopt(argc, argv, "a:g:j:p:r:u:")) != -1) {
switch (ch) {
- case 'p':
- pflag = 1;
- op = HRL_OP_GET_ACC_PID;
- id = parse_pid(optarg);
+ case 'a':
+ aflag = 1;
+ op = HRL_OP_ADD_RULE;
+ rule = strdup(optarg);
break;
- case 'u':
- uflag = 1;
- op = HRL_OP_GET_ACC_UID;
- id = parse_user(optarg);
- break;
case 'g':
gflag = 1;
op = HRL_OP_GET_ACC_GID;
@@ -336,14 +388,29 @@
op = HRL_OP_GET_ACC_JAILID;
id = parse_group(optarg);
break;
+ case 'p':
+ pflag = 1;
+ op = HRL_OP_GET_ACC_PID;
+ id = parse_pid(optarg);
+ break;
+ case 'r':
+ rflag = 1;
+ op = HRL_OP_REMOVE_RULE;
+ rule = strdup(optarg);
+ break;
+ case 'u':
+ uflag = 1;
+ op = HRL_OP_GET_ACC_UID;
+ id = parse_user(optarg);
+ break;
case '?':
default:
usage();
}
}
- if (pflag + uflag + gflag + jflag > 1)
- errx(1, "only one of the -p, -u, -g and -j may be specified "
+ if (aflag + gflag + jflag + pflag + rflag + uflag > 1)
+ errx(1, "only one flag may be specified "
"at the same time");
switch (op) {
@@ -357,6 +424,14 @@
case HRL_OP_GET_ACC_JAILID:
print_accounting(op, id);
break;
+
+ case HRL_OP_ADD_RULE:
+ case HRL_OP_REMOVE_RULE:
+ if (rule == NULL)
+ err(1, "strdup");
+ add_or_remove_rule(op, rule);
+ free(rule);
+ break;
}
return (0);
More information about the p4-projects
mailing list