From owner-p4-projects@FreeBSD.ORG Sat Jun 27 14:50:44 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 399B61065673; Sat, 27 Jun 2009 14:50:44 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id ED4A8106566C for ; Sat, 27 Jun 2009 14:50:43 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id D98CC8FC08 for ; Sat, 27 Jun 2009 14:50:43 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5REohB8040850 for ; Sat, 27 Jun 2009 14:50:43 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5REohmr040848 for perforce@freebsd.org; Sat, 27 Jun 2009 14:50:43 GMT (envelope-from trasz@freebsd.org) Date: Sat, 27 Jun 2009 14:50:43 GMT Message-Id: <200906271450.n5REohmr040848@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Cc: Subject: PERFORCE change 165311 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Jun 2009 14:50:45 -0000 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 __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -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);