lkml.org 
[lkml]   [2005]   [May]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[patch 18/21] CKRM: Rule Based Classification Engine, full CE
    From
    --
    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);
    --

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-05-05 20:53    [W:0.077 / U:30.340 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site