Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Jun 2009 14:50:43 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 165311 for review
Message-ID:  <200906271450.n5REohmr040848@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=165311

Change 165311 by trasz@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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906271450.n5REohmr040848>