--
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 <[EMAIL PROTECTED]>
Signed-Off-By: Chandra Seetharaman <[EMAIL PROTECTED]>
Signed-Off-By: Shailabh Nagar <[EMAIL PROTECTED]>
Signed-Off-By: Vivek Kashyap <[EMAIL PROTECTED]>
Signed-Off-By: Gerrit Huizenga <[EMAIL PROTECTED]>

 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);

--



-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to