From: gh@us.ibm.com
To: linux-kernel@vger.kernel.org, ckrm-tech@lists.sourceforge.net
Subject: [patch 18/21] CKRM: Rule Based Classification Engine, full CE
Date: Thu, 05 May 2005 11:07:49 -0700 [thread overview]
Message-ID: <20050505180935.358378000@us.ibm.com> (raw)
In-Reply-To: 20050505180731.010896000@us.ibm.com
--
Content-Disposition: inline; filename=09-04-rbce_opt-core
Part 4 of 5 patches to support Rule Based Classification Engine for CKRM.
This patch connects RBCE with CKRM core. Full functionality of RBCE
achieved with this patch.
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@us.ibm.com>
Signed-Off-By: Vivek Kashyap <vivk@us.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
Makefile | 2
rbce_core.c | 890 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rbce_internal.h | 23 +
rbce_main.c | 67 ++--
4 files changed, 961 insertions(+), 21 deletions(-)
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/Makefile
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/Makefile 2005-05-05 09:38:03.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/Makefile 2005-05-05 09:38:06.000000000 -0700
@@ -3,4 +3,4 @@
#
obj-$(CONFIG_CKRM_RBCE) += rbce.o
-rbce-objs := rbce_fs.o rbce_main.o rbce_token.o
+rbce-objs := rbce_fs.o rbce_main.o rbce_token.o rbce_core.o
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_core.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_core.c 2005-05-05 09:38:06.000000000 -0700
@@ -0,0 +1,890 @@
+/* Rule-based Classification Engine (RBCE) and
+ * Consolidated RBCE module code (combined)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ * (C) Chandra Seetharaman, IBM Corp. 2003
+ * (C) Vivek Kashyap, IBM Corp. 2004
+ *
+ * Module for loading of classification policies and providing
+ * a user API for Class-based Kernel Resource Management (CKRM)
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include "rbce_internal.h"
+
+/*
+ * Callback from core when a class is deleted.
+ */
+static void
+rbce_class_deletecb(const char *classname, void *classobj, int classtype)
+{
+ static struct rbce_class *cls;
+ struct named_obj_hdr *pos;
+ struct rbce_rule *rule;
+
+ write_lock(&rbce_rwlock);
+ cls = find_class_name(classname);
+ if (cls) {
+ if (cls->classobj != classobj) {
+ printk(KERN_ERR "rbce: class %s changed identity\n",
+ classname);
+ }
+ cls->classobj = NULL;
+ list_for_each_entry(pos, &rules_list[cls->classtype], link) {
+ rule = (struct rbce_rule *)pos;
+ if (rule->target_class) {
+ if (!strcmp
+ (rule->target_class->obj.name, classname)) {
+ put_class(cls);
+ rule->target_class = NULL;
+ rule->classtype = -1;
+ }
+ }
+ }
+ if ((cls = find_class_name(classname)) != NULL) {
+ printk(KERN_ERR
+ "rbce ERROR: class %s exists in rbce after "
+ "removal in core\n", classname);
+ }
+ }
+ write_unlock(&rbce_rwlock);
+ return;
+}
+
+/*====================== Classification Functions =======================*/
+
+/*
+ * Match the given full path name with the command expression.
+ * This function treats the folowing 2 charaters as special if seen in
+ * cmd_exp, all other chanracters are compared as is:
+ * ? - compares to any one single character
+ * * - compares to one or more single characters
+ *
+ * If fullpath is 1, tsk_comm is compared in full. otherwise only the command
+ * name (basename(tsk_comm)) is compared.
+ */
+static inline int
+match_cmd(const char *tsk_comm, const char *cmd_exp, int fullpath)
+{
+ const char *c, *t, *last_ast, *cmd = tsk_comm;
+ char next_c;
+
+ /* get the command name if we don't have to match the fullpath */
+ if (!fullpath && ((c = strrchr(tsk_comm, '/')) != NULL)) {
+ cmd = c + 1;
+ }
+
+ /* now faithfully assume the entire pathname is in cmd */
+
+ /* we now have to effectively implement a regular expression
+ * for now assume
+ * '?' any single character
+ * '*' one or more '?'
+ * rest must match
+ */
+
+ c = cmd_exp;
+ t = cmd;
+ if (t == NULL || c == NULL) {
+ return 0;
+ }
+
+ last_ast = NULL;
+ next_c = '\0';
+
+ while (*c && *t) {
+ switch (*c) {
+ case '?':
+ if (*t == '/') {
+ return 0;
+ }
+ c++;
+ t++;
+ continue;
+ case '*':
+ if (*t == '/') {
+ return 0;
+ }
+ /* eat up all '*' in c */
+ while (*(c + 1) == '*')
+ c++;
+ next_c = '\0';
+ last_ast = c;
+ /*t++; Add this for matching '*' with "one"
+ or more chars. */
+ while (*t && (*t != *(c + 1)) && *t != '/')
+ t++;
+ if (*t == *(c + 1)) {
+ c++;
+ if (*c != '/') {
+ if (*c == '?') {
+ if (*t == '/') {
+ return 0;
+ }
+ t++;
+ c++;
+ }
+ next_c = *c;
+ if (*c) {
+ if (*t == '/') {
+ return 0;
+ }
+ t++;
+ c++;
+ if (!*c && *t)
+ c = last_ast;
+ }
+ } else {
+ last_ast = NULL;
+ }
+ continue;
+ }
+ return 0;
+ case '/':
+ next_c = '\0';
+ /*FALLTHRU*/ default:
+ if (*t == *c && next_c != *t) {
+ c++, t++;
+ continue;
+ } else {
+ /* reset to last asterix and
+ continue from there */
+ if (last_ast) {
+ c = last_ast;
+ } else {
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* check for trailing "*" */
+ while (*c == '*')
+ c++;
+
+ return (!*c && !*t);
+}
+
+static inline void reverse(char *str, int n)
+{
+ char s;
+ int i, j = n - 1;
+
+ for (i = 0; i < j; i++, j--) {
+ s = str[i];
+ str[i] = str[j];
+ str[j] = s;
+ }
+}
+
+static inline int itoa(int n, char *str)
+{
+ int i = 0, sz = 0;
+
+ do {
+ str[i++] = n % 10 + '0';
+ sz++;
+ n = n / 10;
+ } while (n > 0);
+
+ (void)reverse(str, sz);
+ return sz;
+}
+
+static inline int v4toa(__u32 y, char *a)
+{
+ int i;
+ int size = 0;
+
+ for (i = 0; i < 4; i++) {
+ size += itoa(y & 0xff, &a[size]);
+ a[size++] = '.';
+ y >>= 8;
+ }
+ return --size;
+}
+
+static inline int match_ipv4(struct ckrm_net_struct *ns, char **string)
+{
+ char *ptr = *string;
+ int size;
+ char a4[16];
+
+ size = v4toa(ns->ns_daddrv4, a4);
+
+ *string += size;
+ return !strncmp(a4, ptr, size);
+}
+
+static inline int match_port(struct ckrm_net_struct *ns, char *ptr)
+{
+ char a[5];
+ int size = itoa(ns->ns_dport, a);
+
+ return !strncmp(a, ptr, size);
+}
+
+static int __evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
+ struct rbce_rule *rule, bitvector_t * vec_eval,
+ bitvector_t * vec_true, char **filename);
+/*
+ * evaluate the given task against the given rule with the vec_eval and
+ * vec_true in context. Return 1 if the task satisfies the given rule, 0
+ * otherwise.
+ *
+ * If the bit corresponding to the rule is set in the vec_eval, then the
+ * corresponding bit in vec_true is the result. If it is not set, evaluate
+ * the rule and set the bits in both the vectors accordingly.
+ *
+ * On return, filename will have the pointer to the pathname of the task's
+ * executable, if the rule had any command related terms.
+ *
+ * Caller must hold the rbce_rwlock atleast in read mode.
+ */
+static inline int
+evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
+ struct rbce_rule *rule, bitvector_t * vec_eval,
+ bitvector_t * vec_true, char **filename)
+{
+ int tidx = rule->index;
+
+ if (!bitvector_test(tidx, vec_eval)) {
+ if (__evaluate_rule
+ (tsk, ns, rule, vec_eval, vec_true, filename)) {
+ bitvector_set(tidx, vec_true);
+ }
+ bitvector_set(tidx, vec_eval);
+ }
+ return bitvector_test(tidx, vec_true);
+}
+
+/*
+ * evaluate the given task against every term in the given rule with
+ * vec_eval and vec_true in context.
+ *
+ * If the bit corresponding to a rule term is set in the vec_eval, then the
+ * corresponding bit in vec_true is the result for taht particular. If it is
+ * not set, evaluate the rule term and set the bits in both the vectors
+ * accordingly.
+ *
+ * This fucntions returns true only if all terms in the rule evaluate true.
+ *
+ * On return, filename will have the pointer to the pathname of the task's
+ * executable, if the rule had any command related terms.
+ *
+ * Caller must hold the rbce_rwlock atleast in read mode.
+ */
+static int
+__evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
+ struct rbce_rule *rule, bitvector_t * vec_eval,
+ bitvector_t * vec_true, char **filename)
+{
+ int i;
+ int no_ip = 1;
+
+ for (i = rule->num_terms; --i >= 0;) {
+ int rc = 1, tidx = rule->terms[i];
+
+ if (!bitvector_test(tidx, vec_eval)) {
+ struct rbce_rule_term *term = &gl_terms[tidx];
+
+ switch (term->op) {
+
+ case RBCE_RULE_CMD_PATH:
+ case RBCE_RULE_CMD:
+#if __NOT_YET__
+ if (!*filename) { /* get this once */
+ if (((*filename =
+ kmalloc(NAME_MAX,
+ GFP_ATOMIC)) == NULL)
+ ||
+ (get_exe_path_name
+ (tsk, *filename, NAME_MAX) < 0)) {
+ rc = 0;
+ break;
+ }
+ }
+ rc = match_cmd(*filename, term->u.string,
+ (term->op ==
+ RBCE_RULE_CMD_PATH));
+#else
+ rc = match_cmd(tsk->comm, term->u.string,
+ (term->op ==
+ RBCE_RULE_CMD_PATH));
+#endif
+ break;
+ case RBCE_RULE_REAL_UID:
+ if (term->operator == RBCE_LESS_THAN) {
+ rc = (tsk->uid < term->u.id);
+ } else if (term->operator == RBCE_GREATER_THAN){
+ rc = (tsk->uid > term->u.id);
+ } else if (term->operator == RBCE_NOT) {
+ rc = (tsk->uid != term->u.id);
+ } else {
+ rc = (tsk->uid == term->u.id);
+ }
+ break;
+ case RBCE_RULE_REAL_GID:
+ if (term->operator == RBCE_LESS_THAN) {
+ rc = (tsk->gid < term->u.id);
+ } else if (term->operator == RBCE_GREATER_THAN){
+ rc = (tsk->gid > term->u.id);
+ } else if (term->operator == RBCE_NOT) {
+ rc = (tsk->gid != term->u.id);
+ } else {
+ rc = (tsk->gid == term->u.id);
+ }
+ break;
+ case RBCE_RULE_EFFECTIVE_UID:
+ if (term->operator == RBCE_LESS_THAN) {
+ rc = (tsk->euid < term->u.id);
+ } else if (term->operator == RBCE_GREATER_THAN){
+ rc = (tsk->euid > term->u.id);
+ } else if (term->operator == RBCE_NOT) {
+ rc = (tsk->euid != term->u.id);
+ } else {
+ rc = (tsk->euid == term->u.id);
+ }
+ break;
+ case RBCE_RULE_EFFECTIVE_GID:
+ if (term->operator == RBCE_LESS_THAN) {
+ rc = (tsk->egid < term->u.id);
+ } else if (term->operator == RBCE_GREATER_THAN){
+ rc = (tsk->egid > term->u.id);
+ } else if (term->operator == RBCE_NOT) {
+ rc = (tsk->egid != term->u.id);
+ } else {
+ rc = (tsk->egid == term->u.id);
+ }
+ break;
+ case RBCE_RULE_APP_TAG:
+ rc = (RBCE_DATA(tsk)
+ && RBCE_DATA(tsk)->
+ app_tag) ? !strcmp(RBCE_DATA(tsk)->
+ app_tag,
+ term->u.string) : 0;
+ break;
+ case RBCE_RULE_DEP_RULE:
+ rc = evaluate_rule(tsk, NULL, term->u.deprule,
+ vec_eval, vec_true,
+ filename);
+ break;
+
+ case RBCE_RULE_IPV4:
+ /* TBD: add NOT_EQUAL match. At present */
+ /* rbce recognises EQUAL matches only. */
+ if (ns && term->operator == RBCE_EQUAL) {
+ int ma = 0;
+ int mp = 0;
+ char *ptr = term->u.string;
+
+ if (term->u.string[0] == '*')
+ ma = 1;
+ else
+ ma = match_ipv4(ns, &ptr);
+
+ if (*ptr != '\\') {
+ rc = 0;
+ break;
+ } else {
+ ++ptr;
+ if (*ptr == '*')
+ mp = 1;
+ else
+ mp = match_port(ns,
+ ptr);
+ }
+ rc = mp && ma;
+ } else
+ rc = 0;
+ no_ip = 0;
+ break;
+
+ case RBCE_RULE_IPV6: /* no support yet */
+ rc = 0;
+ no_ip = 0;
+ break;
+
+ default:
+ rc = 0;
+ printk(KERN_ERR "Error evaluate term op=%d\n",
+ term->op);
+ break;
+ }
+ if (!rc && no_ip) {
+ bitvector_clear(tidx, vec_true);
+ } else {
+ bitvector_set(tidx, vec_true);
+ }
+ bitvector_set(tidx, vec_eval);
+ } else {
+ rc = bitvector_test(tidx, vec_true);
+ }
+ if (!rc) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * This is some old debug code which needs to be trimmed.
+ */
+
+#define valid_pdata(pdata) (1)
+#define store_pdata(pdata)
+#define unstore_pdata(pdata)
+
+struct rbce_private_data *create_private_data(struct rbce_private_data
+ *src, int copy_sample)
+{
+ int vsize = 0, psize, bsize = 0;
+ struct rbce_private_data *pdata;
+
+ if (use_persistent_state) {
+ vsize = gl_allocated;
+ bsize = vsize / 8 + sizeof(bitvector_t);
+ psize = sizeof(struct rbce_private_data) + 2 * bsize;
+ } else {
+ psize = sizeof(struct rbce_private_data);
+ }
+
+ pdata = kmalloc(psize, GFP_ATOMIC);
+ if (pdata != NULL) {
+ if (use_persistent_state) {
+ pdata->bitmap_version = gl_bitmap_version;
+ pdata->eval = (bitvector_t *) & pdata->data[0];
+ pdata->true = (bitvector_t *) & pdata->data[bsize];
+ if (src && (src->bitmap_version == gl_bitmap_version)) {
+ memcpy(pdata->data, src->data, 2 * bsize);
+ } else {
+ bitvector_init(pdata->eval, vsize);
+ bitvector_init(pdata->true, vsize);
+ }
+ }
+ pdata->evaluate = 1;
+ pdata->rules_version = src ? src->rules_version : 0;
+ pdata->app_tag = NULL;
+ }
+ store_pdata(pdata);
+ return pdata;
+}
+
+static inline void free_private_data(struct rbce_private_data *pdata)
+{
+ if (valid_pdata(pdata)) {
+ unstore_pdata(pdata);
+ kfree(pdata);
+ }
+}
+
+void free_all_private_data(void)
+{
+ struct task_struct *proc, *thread;
+
+ read_lock(&tasklist_lock);
+ do_each_thread(proc, thread) {
+ struct rbce_private_data *pdata;
+
+ pdata = RBCE_DATA(thread);
+ RBCE_DATAP(thread) = NULL;
+ free_private_data(pdata);
+ } while_each_thread(proc, thread);
+ read_unlock(&tasklist_lock);
+ return;
+}
+
+/*
+ * reclassify function, which is called by all the callback functions.
+ *
+ * Takes that task to be reclassified and ruleflags that indicates the
+ * attributes that caused this reclassification request.
+ *
+ * On success, returns the core class pointer to which the given task should
+ * belong to.
+ */
+static struct ckrm_core_class *rbce_classify(struct task_struct *tsk,
+ struct ckrm_net_struct *ns,
+ unsigned long termflag,
+ int classtype)
+{
+ int i;
+ struct rbce_rule *rule;
+ bitvector_t *vec_true = NULL, *vec_eval = NULL;
+ struct rbce_class *tgt = NULL;
+ struct ckrm_core_class *cls = NULL;
+ char *filename = NULL;
+
+ if (!valid_pdata(RBCE_DATA(tsk))) {
+ return NULL;
+ }
+ if (classtype >= CKRM_MAX_CLASSTYPES) {
+ /* can't handle more than CKRM_MAX_CLASSTYPES */
+ return NULL;
+ }
+ /* fast path to avoid locking in case CE is not enabled or */
+ /* if no rules are defined or if no evaluation is needed. */
+ if (!rbce_enabled || !gl_num_rules ||
+ (RBCE_DATA(tsk) && !RBCE_DATA(tsk)->evaluate)) {
+ return NULL;
+ }
+ /* FIXME: optimize_policy should be called from here if */
+ /* gl_action is non-zero. Also, it has to be called with the */
+ /* rbce_rwlock held in write mode. */
+
+ read_lock(&rbce_rwlock);
+
+ vec_eval = vec_true = NULL;
+ if (use_persistent_state) {
+ struct rbce_private_data *pdata = RBCE_DATA(tsk);
+
+ if (!pdata
+ || (pdata
+ && (gl_bitmap_version != pdata->bitmap_version))) {
+ struct rbce_private_data *new_pdata =
+ create_private_data(pdata, 1);
+
+ if (new_pdata) {
+ if (pdata) {
+ new_pdata->rules_version =
+ pdata->rules_version;
+ new_pdata->evaluate = pdata->evaluate;
+ new_pdata->app_tag = pdata->app_tag;
+ free_private_data(pdata);
+ }
+ pdata = RBCE_DATAP(tsk) = new_pdata;
+ termflag = RBCE_TERMFLAG_ALL;
+ /* need to evaluate them all */
+ } else {
+ /*
+ * we shouldn't free the pdata as it has more
+ * details than the vectors. But, this
+ * reclassification should go thru
+ */
+ pdata = NULL;
+ }
+ }
+ if (!pdata) {
+ goto cls_determined;
+ }
+ vec_eval = pdata->eval;
+ vec_true = pdata->true;
+ } else {
+ int bsize = gl_allocated;
+
+ vec_eval = bitvector_alloc(bsize);
+ vec_true = bitvector_alloc(bsize);
+
+ if (vec_eval == NULL || vec_true == NULL) {
+ goto cls_determined;
+ }
+ termflag = RBCE_TERMFLAG_ALL;
+ /* need to evaluate all of them now */
+ }
+
+ /*
+ * using bit ops invalidate all terms related to this termflag
+ * context (only in per task vec)
+ */
+
+ if (termflag == RBCE_TERMFLAG_ALL) {
+ bitvector_zero(vec_eval);
+ } else {
+ for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
+ if (test_bit(i, &termflag)) {
+ bitvector_t *maskvec = get_gl_mask_vecs(i);
+
+ bitvector_and_not(vec_eval, vec_eval, maskvec);
+ }
+ }
+ }
+ bitvector_and(vec_true, vec_true, vec_eval);
+
+ /* run through the rules in order and see what needs evaluation */
+ list_for_each_entry(rule, &rules_list[classtype], obj.link) {
+ if (rule->state == RBCE_RULE_ENABLED &&
+ rule->target_class &&
+ rule->target_class->classobj &&
+ evaluate_rule(tsk, ns, rule, vec_eval, vec_true,
+ &filename)) {
+ tgt = rule->target_class;
+ cls = rule->target_class->classobj;
+ break;
+ }
+ }
+
+ cls_determined:
+ if (!use_persistent_state) {
+ if (vec_eval) {
+ bitvector_free(vec_eval);
+ }
+ if (vec_true) {
+ bitvector_free(vec_true);
+ }
+ }
+ ckrm_core_grab(cls);
+ read_unlock(&rbce_rwlock);
+ if (filename) {
+ kfree(filename);
+ }
+ if (RBCE_DATA(tsk)) {
+ RBCE_DATA(tsk)->rules_version = gl_rules_version;
+ }
+ return cls;
+}
+
+/*****************************************************************************
+ *
+ * Module specific utilization of core RBCE functionality
+ *
+ * Includes support for the various classtypes
+ * New classtypes will require extensions here
+ *
+ *****************************************************************************/
+
+/* helper functions that are required in the extended version */
+
+static inline void rbce_tc_manual(struct task_struct *tsk)
+{
+ read_lock(&rbce_rwlock);
+
+ if (!RBCE_DATA(tsk)) {
+ RBCE_DATAP(tsk) =
+ (void *)create_private_data(RBCE_DATA(tsk->parent), 0);
+ }
+ if (RBCE_DATA(tsk)) {
+ RBCE_DATA(tsk)->evaluate = 0;
+ }
+ read_unlock(&rbce_rwlock);
+ return;
+}
+
+/*****************************************************************************
+ * VARIOUS CLASSTYPES
+ *****************************************************************************/
+
+/* to enable type coercion of the function pointers */
+
+/*============================================================================
+ * TASKCLASS CLASSTYPE
+ *============================================================================*/
+
+int tc_classtype = -1;
+
+/*
+ * fork callback to be registered with core module.
+ */
+static inline void *rbce_tc_forkcb(struct task_struct *tsk)
+{
+ int rule_version_changed = 1;
+ struct ckrm_core_class *cls;
+ read_lock(&rbce_rwlock);
+ /* dup ce_data */
+ RBCE_DATAP(tsk) =
+ (void *)create_private_data(RBCE_DATA(tsk->parent), 0);
+ read_unlock(&rbce_rwlock);
+
+ if (RBCE_DATA(tsk->parent)) {
+ rule_version_changed =
+ (RBCE_DATA(tsk->parent)->rules_version != gl_rules_version);
+ }
+ cls = rule_version_changed ?
+ rbce_classify(tsk, NULL, RBCE_TERMFLAG_ALL, tc_classtype) : NULL;
+
+ /*
+ * note the fork notification to any user client will be sent through
+ * the guaranteed fork-reclassification
+ */
+ return cls;
+}
+
+/*
+ * exit callback to be registered with core module.
+ */
+static void rbce_tc_exitcb(struct task_struct *tsk)
+{
+ struct rbce_private_data *pdata;
+
+ pdata = RBCE_DATA(tsk);
+ RBCE_DATAP(tsk) = NULL;
+ if (pdata) {
+ if (pdata->app_tag) {
+ kfree(pdata->app_tag);
+ }
+ free_private_data(pdata);
+ }
+ return;
+}
+
+static void *rbce_tc_classify(enum ckrm_event event, ...)
+{
+ va_list args;
+ void *cls = NULL;
+ struct task_struct *tsk;
+ struct rbce_private_data *pdata;
+
+ va_start(args, event);
+ tsk = va_arg(args, struct task_struct *);
+ va_end(args);
+
+ /* we only have to deal with events between
+ * [ CKRM_LATCHABLE_EVENTS .. CKRM_NONLATCHABLE_EVENTS )
+ */
+ switch (event) {
+
+ case CKRM_EVENT_FORK:
+ cls = rbce_tc_forkcb(tsk);
+ break;
+
+ case CKRM_EVENT_EXIT:
+ rbce_tc_exitcb(tsk);
+ break;
+
+ case CKRM_EVENT_EXEC:
+ cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_CMD |
+ RBCE_TERMFLAG_UID | RBCE_TERMFLAG_GID,
+ tc_classtype);
+ break;
+
+ case CKRM_EVENT_UID:
+ cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_UID, tc_classtype);
+ break;
+
+ case CKRM_EVENT_GID:
+ cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_GID, tc_classtype);
+ break;
+
+ case CKRM_EVENT_LOGIN:
+ case CKRM_EVENT_USERADD:
+ case CKRM_EVENT_USERDEL:
+ case CKRM_EVENT_LISTEN_START:
+ case CKRM_EVENT_LISTEN_STOP:
+ case CKRM_EVENT_APPTAG:
+ /* no interest in this events .. */
+ break;
+
+ default:
+ /* catch all */
+ break;
+
+ case CKRM_EVENT_RECLASSIFY:
+ if ((pdata = (RBCE_DATA(tsk)))) {
+ pdata->evaluate = 1;
+ }
+ cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_ALL, tc_classtype);
+ break;
+
+ }
+
+ return cls;
+}
+
+static void rbce_tc_notify(int event, void *core, struct task_struct *tsk)
+{
+ if (event != CKRM_EVENT_MANUAL)
+ return;
+ rbce_tc_manual(tsk);
+}
+
+static struct ckrm_eng_callback rbce_taskclass_ecbs = {
+ .c_interest = (unsigned long)(-1), /* set whole bitmap */
+ .classify = (ce_classify_fct) rbce_tc_classify,
+ .class_delete = rbce_class_deletecb,
+ .n_interest = (1 << CKRM_EVENT_MANUAL),
+ .notify = (ce_notify_fct) rbce_tc_notify,
+ .always_callback = 0,
+};
+
+/*============================================================================
+ * ACCEPTQ CLASSTYPE
+ *============================================================================*/
+
+int sc_classtype = -1;
+
+static void *rbce_sc_classify(enum ckrm_event event, ...)
+{
+ /* no special consideratation */
+ void *result;
+ va_list args;
+ struct task_struct *tsk;
+ struct ckrm_net_struct *ns;
+
+ va_start(args, event);
+ ns = va_arg(args, struct ckrm_net_struct *);
+ tsk = va_arg(args, struct task_struct *);
+ va_end(args);
+
+ result = rbce_classify(tsk, ns, RBCE_TERMFLAG_ALL, sc_classtype);
+
+ return result;
+}
+
+static struct ckrm_eng_callback rbce_acceptQclass_ecbs = {
+ .c_interest = (unsigned long)(-1),
+ .always_callback = 0, /* enable during debugging only */
+ .classify = (ce_classify_fct) & rbce_sc_classify,
+ .class_delete = rbce_class_deletecb,
+};
+
+/*============================================================================
+ * Module Initialization ...
+ *============================================================================*/
+
+#define TASKCLASS_NAME "taskclass"
+#define SOCKCLASS_NAME "socket_class"
+
+struct ce_regtable_struct {
+ const char *name;
+ struct ckrm_eng_callback *cbs;
+ int *clsvar;
+};
+
+struct ce_regtable_struct ce_regtable[] = {
+ {TASKCLASS_NAME, &rbce_taskclass_ecbs, &tc_classtype},
+ {SOCKCLASS_NAME, &rbce_acceptQclass_ecbs, &sc_classtype},
+ {NULL}
+};
+
+void unregister_classtype_engines(void)
+{
+ int rc;
+ struct ce_regtable_struct *ceptr = ce_regtable;
+
+ while (ceptr->name) {
+ if (*ceptr->clsvar >= 0) {
+ while ((rc = ckrm_unregister_engine(ceptr->name)) == -EAGAIN)
+ ;
+ *ceptr->clsvar = -1;
+ }
+ ceptr++;
+ }
+}
+
+int register_classtype_engines(void)
+{
+ int rc;
+ struct ce_regtable_struct *ceptr = ce_regtable;
+
+ while (ceptr->name) {
+ rc = ckrm_register_engine(ceptr->name, ceptr->cbs);
+ if ((rc < 0) && (rc != -ENOENT)) {
+ unregister_classtype_engines();
+ return (rc);
+ }
+ if (rc != -ENOENT)
+ *ceptr->clsvar = rc;
+ ceptr++;
+ }
+ return 0;
+}
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_internal.h 2005-05-05 09:38:05.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h 2005-05-05 09:38:06.000000000 -0700
@@ -41,6 +41,8 @@
#include <asm/io.h>
#include <asm/uaccess.h>
+#include "rbce_bitvector.h"
+
/*
* comman data structure used for identification of class and rules
* in the RBCE namespace
@@ -205,14 +207,25 @@ struct rbce_private_data {
bitvector_t *eval;
bitvector_t *true;
char *app_tag;
+ unsigned long bitmap_version;
char data[0]; /* bitvectors eval and true */
};
#define RBCE_DATA(tsk) ((struct rbce_private_data*)((tsk)->ce_data))
#define RBCE_DATAP(tsk) ((tsk)->ce_data)
+/* Other rbce global stuff. */
+
extern struct rbce_eng_callback rbce_rcfs_ecbs;
extern int rbce_enabled;
+extern struct list_head rules_list[];
+extern const int use_persistent_state;
+extern int gl_num_rules;
+extern int gl_bitmap_version;
+extern int gl_allocated;
+extern struct rbce_rule_term *gl_terms;
+extern int gl_rules_version;
+extern rwlock_t rbce_rwlock;
extern int rbce_mkdir(struct inode *, struct dentry *, int);
extern int rbce_rmdir(struct inode *, struct dentry *);
@@ -228,4 +241,14 @@ extern int rbce_rename_rule(const char *
extern int rules_parse(char *, struct rbce_rule_term **, int *);
+extern struct rbce_private_data *create_private_data(struct rbce_private_data
+ *, int);
+extern bitvector_t *get_gl_mask_vecs(int);
+extern struct rbce_class *find_class_name(const char *);
+extern void put_class(struct rbce_class *);
+extern void free_all_private_data(void);
+
+extern void unregister_classtype_engines(void);
+extern int register_classtype_engines(void);
+
#endif /* _RBCE_INTERNAL_H */
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_main.c 2005-05-05 09:38:05.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c 2005-05-05 09:38:06.000000000 -0700
@@ -23,7 +23,6 @@
*/
#include "rbce_internal.h"
-#include "rbce_bitvector.h"
MODULE_DESCRIPTION(RBCE_MOD_DESCR);
MODULE_AUTHOR("Hubertus Franke, Chandra Seetharaman (IBM)");
@@ -57,19 +56,20 @@ int termop_2_vecidx[RBCE_RULE_INVALID] =
extern int errno;
-int rbce_enabled = 1;
-const int use_persistent_state = 1;
-
static LIST_HEAD(class_list);
-static struct list_head rules_list[CKRM_MAX_CLASSTYPES];
-static int gl_num_rules;
+struct list_head rules_list[CKRM_MAX_CLASSTYPES];
static int gl_action, gl_num_terms;
-static int gl_bitmap_version, gl_action, gl_num_terms;
-static int gl_allocated, gl_released;
-static struct rbce_rule_term *gl_terms;
-static int gl_rules_version;
+static int gl_released;
static bitvector_t *gl_mask_vecs[NUM_TERM_MASK_VECTOR];
-static rwlock_t rbce_rwlock = RW_LOCK_UNLOCKED;
+
+int rbce_enabled = 1;
+const int use_persistent_state = 1;
+int gl_num_rules;
+int gl_bitmap_version;
+int gl_allocated;
+struct rbce_rule_term *gl_terms;
+int gl_rules_version;
+rwlock_t rbce_rwlock = RW_LOCK_UNLOCKED;
/*
* One lock to protect them all !!!
* Additions, deletions to rules must
@@ -84,6 +84,12 @@ static rwlock_t rbce_rwlock = RW_LOCK_UN
static void optimize_policy(void);
+bitvector_t *
+get_gl_mask_vecs(int index)
+{
+ return gl_mask_vecs[index];
+}
+
static inline struct rbce_rule *find_rule_name(const char *name)
{
struct named_obj_hdr *pos;
@@ -353,7 +359,7 @@ static inline int __delete_rule(struct r
/*
* Optimize the rule evaluation logic
*
- * Caller must hold global_rwlock in write mode.
+ * Caller must hold rbce_rwlock in write mode.
*/
static void optimize_policy(void)
{
@@ -1127,12 +1133,6 @@ int rbce_rule_exists(const char *rname)
}
/*====================== Magic file handling =======================*/
-struct rbce_private_data *create_private_data(struct rbce_private_data *a,
- int b)
-{
- return NULL;
-}
-
static inline
void reset_evaluation(struct rbce_private_data *pdata,int termflag)
{
@@ -1197,15 +1197,25 @@ out:
int init_rbce(void)
{
- int rc, line;
+ int rc, i, line;
printk(KERN_INFO "Installing \'%s\' module\n", modname);
- rc = rcfs_register_engine(&rbce_rcfs_ecbs);
+ for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
+ INIT_LIST_HEAD(&rules_list[i]);
+ }
+
+ rc = register_classtype_engines();
line = __LINE__;
if (rc)
goto out;
+ /* register any other class type engine here */
+ rc = rcfs_register_engine(&rbce_rcfs_ecbs);
+ line = __LINE__;
+ if (rc)
+ goto out_unreg_classtype;;
+
if (rcfs_mounted) {
rc = rbce_create_config();
line = __LINE__;
@@ -1214,6 +1224,8 @@ int init_rbce(void)
}
rcfs_unregister_engine(&rbce_rcfs_ecbs);
+out_unreg_classtype:
+ unregister_classtype_engines();
out:
printk(KERN_ERR "%s: error installing rc=%d line=%d\n",
__FUNCTION__, rc, line);
@@ -1222,12 +1234,27 @@ out:
void exit_rbce(void)
{
+ int i;
printk(KERN_INFO "Removing \'%s\' module\n", modname);
+ /* Print warnings if lists are not empty, which is a bug */
+ if (!list_empty(&class_list)) {
+ printk(KERN_WARNING "exit_rbce: Class list is not empty\n");
+ }
+
+ for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
+ if (!list_empty(&rules_list[i])) {
+ printk(KERN_WARNING "exit_rbce: Rules list for "
+ "classtype %d is not empty\n", i);
+ }
+ }
+
if (rcfs_mounted)
rbce_clear_config();
rcfs_unregister_engine(&rbce_rcfs_ecbs);
+ unregister_classtype_engines();
+ free_all_private_data();
}
module_init(init_rbce);
--
next prev parent reply other threads:[~2005-05-05 18:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-05 18:07 [patch 00/21] CKRM: Core patch set with Classification Engine, basic controllers gh
2005-05-05 18:07 ` [patch 01/21] CKRM: Core CKRM Event Callbacks gh
2005-05-05 18:07 ` [patch 02/21] CKRM: Processor Delay Accounting gh
2005-05-05 18:07 ` [patch 03/21] CKRM: Core infrastructure gh
2005-05-05 18:07 ` [patch 04/21] CKRM: Resource Control File System (rcfs) gh
2005-05-05 18:07 ` [patch 05/21] CKRM: Classtype definitions for task class gh
2005-05-05 18:07 ` [patch 06/21] CKRM: Classtype definitions for socket class gh
2005-05-05 18:07 ` [patch 07/21] CKRM: Numtasks Controller gh
2005-05-05 18:07 ` [patch 08/21] CKRM: Documentation gh
2005-05-05 18:07 ` [patch 09/21] CKRM: Add missing read_unlock gh
2005-05-05 18:07 ` [patch 10/21] CKRM: Move Callbacks from listenaq to socketclass gh
2005-05-05 18:07 ` [patch 11/21] CKRM: Change ipaddr_port syntax gh
2005-05-05 18:07 ` [patch 12/21] CKRM: Check to see if my guarantee is set to DONTCARE gh
2005-05-05 18:07 ` [patch 13/21] CKRM: Minor cosmetic cleanups in numtasks controller gh
2005-05-05 18:07 ` [patch 14/21] CKRM: undo removal of check in numtasks_put_ref_local gh
2005-05-05 18:07 ` [patch 15/21] CKRM: Rule Based Classification Engine, stub rcfs support gh
2005-05-05 18:07 ` [patch 16/21] CKRM: Rule Based Classification Engine, basic " gh
2005-05-05 18:07 ` [patch 17/21] CKRM: Rule Based Classification Engine, bitvector support for classification info gh
2005-05-05 18:07 ` gh [this message]
2005-05-05 18:07 ` [patch 19/21] CKRM: Rule Based Classification Engine, more advanced classification engine gh
2005-05-05 18:07 ` [patch 20/21] CKRM: Clean up typo in printk message gh
2005-05-05 18:07 ` [patch 21/21] CKRM: Fix for compiler warnings gh
2005-05-08 12:49 ` Domen Puncer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050505180935.358378000@us.ibm.com \
--to=gh@us.ibm.com \
--cc=ckrm-tech@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.