[patch 16/38] CKRM e18: Rule Based Classification Engine, basic rcfs support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Part 2 of 5 patches to support Rule Based Classification Engine for CKRM.
This patch provides the functionality needed by the rcfs interface for
ce provided in patch 1. No classification functionality yet.

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_internal.h |  161 +++++++++
 rbce_main.c     |  993 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 rbce_token.c    |  241 +++++++++++++
 4 files changed, 1383 insertions(+), 14 deletions(-)

Index: linux-2.6.12-ckrm1/kernel/ckrm/rbce/Makefile
===================================================================
--- linux-2.6.12-ckrm1.orig/kernel/ckrm/rbce/Makefile	2005-06-20 13:08:42.000000000 -0700
+++ linux-2.6.12-ckrm1/kernel/ckrm/rbce/Makefile	2005-06-20 13:08:44.000000000 -0700
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_CKRM_RBCE)	+= rbce.o
-rbce-objs := rbce_fs.o rbce_main.o
+rbce-objs := rbce_fs.o rbce_main.o rbce_token.o
Index: linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_internal.h
===================================================================
--- linux-2.6.12-ckrm1.orig/kernel/ckrm/rbce/rbce_internal.h	2005-06-20 13:08:42.000000000 -0700
+++ linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_internal.h	2005-06-20 13:08:44.000000000 -0700
@@ -41,8 +41,165 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-extern int rbce_enabled;
+/*
+ * comman data structure used for identification of class and rules
+ * in the RBCE namespace
+ */
+struct named_obj_hdr {
+	struct list_head link;
+	int referenced;
+	char *name;
+};
+
+#define GET_REF(x) ((x)->obj.referenced)
+#define INC_REF(x) (GET_REF(x)++)
+#define DEC_REF(x) (--GET_REF(x))
+
+struct rbce_class {
+	struct named_obj_hdr obj;
+	int classtype;
+	void *classobj;
+};
+
+typedef int __bitwise rbce_rule_op_t;
+enum rbce_rule_op {
+	RBCE_RULE_CMD_PATH = (__force rbce_rule_op_t) 1,
+	RBCE_RULE_CMD = (__force rbce_rule_op_t) 2,
+	RBCE_RULE_ARGS = (__force rbce_rule_op_t) 3,
+	RBCE_RULE_REAL_UID = (__force rbce_rule_op_t) 4,
+	RBCE_RULE_REAL_GID = (__force rbce_rule_op_t) 5,
+	RBCE_RULE_EFFECTIVE_UID = (__force rbce_rule_op_t) 6,
+	RBCE_RULE_EFFECTIVE_GID = (__force rbce_rule_op_t) 7,
+	RBCE_RULE_APP_TAG = (__force rbce_rule_op_t) 8,
+	RBCE_RULE_IPV4 = (__force rbce_rule_op_t) 9,
+	RBCE_RULE_IPV6 = (__force rbce_rule_op_t) 10,
+	RBCE_RULE_DEP_RULE = (__force rbce_rule_op_t) 11,
+	RBCE_RULE_INVALID = (__force rbce_rule_op_t) 12,
+	RBCE_RULE_INVALID2 = (__force rbce_rule_op_t) 13,
+};
+
+typedef int __bitwise rbce_operator_t;
+enum rbce_operator {
+	RBCE_EQUAL = (__force rbce_operator_t) 1,
+	RBCE_NOT = (__force rbce_operator_t) 2,
+	RBCE_LESS_THAN = (__force rbce_operator_t) 3,
+	RBCE_GREATER_THAN = (__force rbce_operator_t) 4,
+};
+
+struct rbce_rule_term {
+	rbce_rule_op_t op;
+	rbce_operator_t operator;
+	union {
+		char *string;	/* path, cmd, arg, tag, ipv4 and ipv6 */
+		long id;	/* uid, gid, euid, egid */
+		struct rbce_rule *deprule;
+	} u;
+};
+
+struct rbce_rule {
+	struct named_obj_hdr obj;
+	struct rbce_class *target_class;
+	int classtype;
+	int num_terms;
+	int *terms;	/* vector of indices into the global term vector */
+	int index;	/* index of this rule into the global term vector */
+	int termflag;	/* which term ids would require a recalculation */
+	int do_opt;	/* do we have to consider this rule during optimize */
+	char *strtab;	/* string table to store the strings of all terms */
+	int order;	/* order of execution of this rule */
+	int state;	/* RBCE_RULE_ENABLED/RBCE_RULE_DISABLED */
+};
+
+/* rules states */
+#define RBCE_RULE_DISABLED 0
+#define RBCE_RULE_ENABLED  1
+
+/*
+ * Data structures and macros used for optimization
+ */
+#define RBCE_TERM_CMD   (0)
+#define RBCE_TERM_UID   (1)
+#define RBCE_TERM_GID   (2)
+#define RBCE_TERM_TAG   (3)
+#define RBCE_TERM_IPV4  (4)
+#define RBCE_TERM_IPV6  (5)
+
+#define NUM_TERM_MASK_VECTOR  (6)
+
+/* Rule flags. 1 bit for each type of rule term */
+#define RBCE_TERMFLAG_CMD   (1 << RBCE_TERM_CMD)
+#define RBCE_TERMFLAG_UID   (1 << RBCE_TERM_UID)
+#define RBCE_TERMFLAG_GID   (1 << RBCE_TERM_GID)
+#define RBCE_TERMFLAG_TAG   (1 << RBCE_TERM_TAG)
+#define RBCE_TERMFLAG_IPV4  (1 << RBCE_TERM_IPV4)
+#define RBCE_TERMFLAG_IPV6  (1 << RBCE_TERM_IPV6)
+#define RBCE_TERMFLAG_ALL      (RBCE_TERMFLAG_CMD | RBCE_TERMFLAG_UID |	\
+				RBCE_TERMFLAG_GID | RBCE_TERMFLAG_TAG |	\
+				RBCE_TERMFLAG_IPV4 | RBCE_TERMFLAG_IPV6)
+
+/* Token operation related data structures, functions etc., */
+typedef int __bitwise rule_token_t;
+enum rule_token {
+	TOKEN_PATH = (__force rule_token_t) 1,
+	TOKEN_CMD = (__force rule_token_t) 2,
+	TOKEN_ARGS = (__force rule_token_t) 3,
+	TOKEN_RUID_EQ = (__force rule_token_t) 4,
+	TOKEN_RUID_LT = (__force rule_token_t) 5,
+	TOKEN_RUID_GT = (__force rule_token_t) 6,
+	TOKEN_RUID_NOT = (__force rule_token_t) 7,
+	TOKEN_RGID_EQ = (__force rule_token_t) 8,
+	TOKEN_RGID_LT = (__force rule_token_t) 9,
+	TOKEN_RGID_GT = (__force rule_token_t) 10,
+	TOKEN_RGID_NOT = (__force rule_token_t) 11,
+	TOKEN_EUID_EQ = (__force rule_token_t) 12,
+	TOKEN_EUID_LT = (__force rule_token_t) 13,
+	TOKEN_EUID_GT = (__force rule_token_t) 14,
+	TOKEN_EUID_NOT = (__force rule_token_t) 15,
+	TOKEN_EGID_EQ = (__force rule_token_t) 16,
+	TOKEN_EGID_LT = (__force rule_token_t) 17,
+	TOKEN_EGID_GT = (__force rule_token_t) 18,
+	TOKEN_EGID_NOT = (__force rule_token_t) 19,
+	TOKEN_TAG = (__force rule_token_t) 20,
+	TOKEN_IPV4 = (__force rule_token_t) 21,
+	TOKEN_IPV6 = (__force rule_token_t) 22,
+	TOKEN_DEP = (__force rule_token_t) 23,
+	TOKEN_DEP_ADD = (__force rule_token_t) 24,
+	TOKEN_DEP_DEL = (__force rule_token_t) 25,
+	TOKEN_ORDER = (__force rule_token_t) 26,
+	TOKEN_CLASS = (__force rule_token_t) 27,
+	TOKEN_STATE = (__force rule_token_t) 28,
+	TOKEN_INVALID = (__force rule_token_t) 29
+};
+
+typedef int __bitwise op_token_t;
+enum op_token {
+	TOKEN_OP_EQUAL = (__force op_token_t) RBCE_EQUAL,
+	TOKEN_OP_NOT = (__force op_token_t) RBCE_NOT,
+	TOKEN_OP_LESS_THAN = (__force op_token_t) RBCE_LESS_THAN,
+	TOKEN_OP_GREATER_THAN = (__force op_token_t) RBCE_GREATER_THAN,
+	TOKEN_OP_DEP = (__force op_token_t) (TOKEN_OP_GREATER_THAN+1),
+	TOKEN_OP_DEP_ADD = (__force op_token_t) (TOKEN_OP_GREATER_THAN+2),
+	TOKEN_OP_DEP_DEL = (__force op_token_t) (TOKEN_OP_GREATER_THAN+3),
+	TOKEN_OP_ORDER = (__force op_token_t) (TOKEN_OP_GREATER_THAN+4),
+	TOKEN_OP_CLASS = (__force op_token_t) (TOKEN_OP_GREATER_THAN+5),
+	TOKEN_OP_STATE = (__force op_token_t) (TOKEN_OP_GREATER_THAN+6),
+};
+
+
+/*
+ * data structure rbce_private_data to hold the app_tag for a task.
+ * Expands later.
+ *
+ */
+struct rbce_private_data {
+	char *app_tag;
+};
+
+#define RBCE_DATA(tsk) ((struct rbce_private_data*)((tsk)->ce_data))
+#define RBCE_DATAP(tsk) ((tsk)->ce_data)
+
 extern struct rbce_eng_callback rbce_rcfs_ecbs;
+extern int rbce_enabled;
 
 extern int rbce_mkdir(struct inode *, struct dentry *, int);
 extern int rbce_rmdir(struct inode *, struct dentry *);
@@ -56,4 +213,6 @@ extern int rbce_delete_rule(const char *
 extern int rbce_set_tasktag(int, char *);
 extern int rbce_rename_rule(const char *, const char *);
 
+extern int rules_parse(char *, struct rbce_rule_term **, int *);
+
 #endif /* _RBCE_INTERNAL_H */
Index: linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_main.c
===================================================================
--- linux-2.6.12-ckrm1.orig/kernel/ckrm/rbce/rbce_main.c	2005-06-20 13:08:42.000000000 -0700
+++ linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_main.c	2005-06-20 13:08:44.000000000 -0700
@@ -30,32 +30,1001 @@ MODULE_LICENSE("GPL");
 
 static char modname[] = RBCE_MOD_NAME;
 
-/* Stub routines for now */
-void rbce_get_rule(const char *a, char *b)
+/* ==================== global variables etc., ==================== */
+
+int termop_2_vecidx[RBCE_RULE_INVALID] = {
+	[RBCE_RULE_CMD_PATH] = RBCE_TERM_CMD,
+	[RBCE_RULE_CMD] = RBCE_TERM_CMD,
+	[RBCE_RULE_ARGS] = RBCE_TERM_CMD,
+	[RBCE_RULE_REAL_UID] = RBCE_TERM_UID,
+	[RBCE_RULE_REAL_GID] = RBCE_TERM_GID,
+	[RBCE_RULE_EFFECTIVE_UID] = RBCE_TERM_UID,
+	[RBCE_RULE_EFFECTIVE_GID] = RBCE_TERM_GID,
+	[RBCE_RULE_APP_TAG] = RBCE_TERM_TAG,
+	[RBCE_RULE_IPV4] = RBCE_TERM_IPV4,
+	[RBCE_RULE_IPV6] = RBCE_TERM_IPV6,
+	[RBCE_RULE_DEP_RULE] = -1
+};
+
+#define TERMOP_2_TERMFLAG(x)	(1 << termop_2_vecidx[x])
+#define TERM_2_TERMFLAG(x)		(1 << x)
+
+#define POLICY_INC_NUMTERMS	(BITS_PER_LONG)	/* No. of terms alloc'd once */
+#define POLICY_ACTION_NEW_VERSION	0x01	/* Force reallocation */
+#define POLICY_ACTION_REDO_ALL		0x02	/* Recompute all rule flags */
+#define POLICY_ACTION_PACK_TERMS	0x04	/* Time to pack the terms */
+
+extern int errno;
+
+int rbce_enabled = 1;
+
+static LIST_HEAD(class_list);
+static struct list_head rules_list[CKRM_MAX_CLASSTYPES];
+static int gl_num_rules;
+static int gl_action, gl_num_terms;
+static int gl_allocated, gl_released;
+static struct rbce_rule_term *gl_terms;
+static int gl_rules_version;
+static rwlock_t rbce_rwlock = RW_LOCK_UNLOCKED;
+	/*
+	 * One lock to protect them all !!!
+	 * Additions, deletions to rules must
+	 * happen with this lock being held in write mode.
+	 * Access(read/write) to any of the data structures must happen
+	 * with this lock held in read mode.
+	 * Since, rule related changes do not happen very often it is ok to
+	 * have single rwlock.
+	 */
+
+/* ======================= Helper Functions ========================= */
+
+static inline struct rbce_rule *find_rule_name(const char *name)
+{
+	struct named_obj_hdr *pos;
+	int i;
+
+	for (i = 0; i < CKRM_MAX_CLASSTYPES; i++)
+		list_for_each_entry(pos, &rules_list[i], link)
+			if (!strcmp(pos->name, name))
+				return ((struct rbce_rule *)pos);
+	return NULL;
+}
+
+struct rbce_class *find_class_name(const char *name)
 {
+	struct named_obj_hdr *pos;
+
+	list_for_each_entry(pos, &class_list, link)
+		if (!strcmp(pos->name, name))
+			return (struct rbce_class *)pos;
+	return NULL;
 }
-int rbce_rule_exists(const char *a)
+
+/* Type of Rule insertion */
+#define INSERT		0	/* new rule */
+#define REINSERT	1	/* existing rule */
+
+/*
+ * Insert the given rule at the specified order
+ * 		order = -1 ==> insert at the tail.
+ *		type == INSERT - insert the rule
+ *		type == REINSERT - remove the rule from its current
+ *				 position and reinsert accoring to order.
+ *
+ * Caller must hold rbce_rwlock in write mode.
+ */
+static int insert_rule(struct rbce_rule *rule, int order, int type)
 {
+#define ORDER_COUNTER_INCR 10
+	static int order_counter;
+	int old_counter;
+	struct list_head *head = &rules_list[rule->classtype];
+	struct list_head *insert = head;
+	struct rbce_rule *tmp;
+
+	if (gl_num_rules == 0)
+		order_counter = 0;
+
+	switch (order) {
+	case -1:
+		rule->order = order_counter;
+		/* FIXME: order_counter overflow/wraparound!! */
+		order_counter += ORDER_COUNTER_INCR;
+		break;
+	default:
+		old_counter = order_counter;
+		if (order_counter < order)
+			order_counter = order;
+		rule->order = order;
+		order_counter += ORDER_COUNTER_INCR;
+		list_for_each_entry(tmp, head, obj.link) {
+			if (rule == tmp)
+				continue;
+			if (rule->order == tmp->order) {
+				order_counter = old_counter;
+				return -EEXIST;
+			}
+			if (rule->order < tmp->order) {
+				insert = &tmp->obj.link;
+				break;
+			}
+		}
+	}
+	if (type == REINSERT)
+		list_del(&rule->obj.link);
+	else {
+		/*  protect the module from removed if a rule exists */
+		try_module_get(THIS_MODULE);
+		gl_num_rules++;
+	}
+	gl_rules_version++;
+	list_add_tail(&rule->obj.link, insert);
 	return 0;
 }
-int rbce_change_rule(const char *a, char *b)
+
+/*
+ * Get a refernece to the class, create one if it doesn't exist
+ *
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+
+struct rbce_class *create_rbce_class(const char *classname,
+					    int classtype, void *classobj)
 {
-	return 1;
+	struct rbce_class *cls;
+
+	if (classtype >= CKRM_MAX_CLASSTYPES) {
+		printk(KERN_ERR
+		       "ckrm_classobj returned %d as classtype which cannot "
+		       " be handled by RBCE\n", classtype);
+		return NULL;
+	}
+
+	cls = kmalloc(sizeof(struct rbce_class), GFP_ATOMIC);
+	if (!cls)
+		return NULL;
+	cls->obj.name = kmalloc(strlen(classname) + 1, GFP_ATOMIC);
+	if (cls->obj.name) {
+		GET_REF(cls) = 1;
+		cls->classobj = classobj;
+		strcpy(cls->obj.name, classname);
+		list_add_tail(&cls->obj.link, &class_list);
+		cls->classtype = classtype;
+	} else {
+		kfree(cls);
+		cls = NULL;
+	}
+	return cls;
 }
-int rbce_delete_rule(const char *a)
+
+static struct rbce_class *get_class(char *classname, int *classtype)
 {
-	return 1;
+	struct rbce_class *cls;
+	void *classobj;
+
+	if (!classname)
+		return NULL;
+	cls = find_class_name(classname);
+	if (cls) {
+		if (cls->classobj) {
+			INC_REF(cls);
+			*classtype = cls->classtype;
+			return cls;
+		}
+		return NULL;
+	}
+	classobj = ckrm_classobj(classname, classtype);
+	if (!classobj)
+		return NULL;
+	return create_rbce_class(classname, *classtype, classobj);
 }
-int rbce_set_tasktag(int i, char *a)
+
+/*
+ * Drop a refernece to the class, create one if it doesn't exist
+ *
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+void put_class(struct rbce_class *cls)
 {
-	return 1;
+	if (cls && (DEC_REF(cls) <= 0)) {
+		list_del(&cls->obj.link);
+		kfree(cls->obj.name);
+		kfree(cls);
+	}
+	return;
 }
-int rbce_rename_rule(const char *a, const char *b)
+
+/*
+ * Allocate an index in the global term vector
+ * On success, returns the index. On failure returns -errno.
+ * Caller must hold the rbce_rwlock in write mode as global data is
+ * written onto.
+ */
+static int alloc_term_index(void)
 {
-	return 1;
+	int size = gl_allocated;
+
+	if (gl_num_terms >= size) {
+		int i;
+		struct rbce_rule_term *oldv, *newv;
+		int newsize = size + POLICY_INC_NUMTERMS;
+
+		oldv = gl_terms;
+		newv =
+		    kmalloc(newsize * sizeof(struct rbce_rule_term),
+			    GFP_ATOMIC);
+		if (!newv)
+			return -ENOMEM;
+		memcpy(newv, oldv, size * sizeof(struct rbce_rule_term));
+		for (i = size; i < newsize; i++)
+			newv[i].op = -1;
+		gl_terms = newv;
+		gl_allocated = newsize;
+		kfree(oldv);
+
+		gl_action |= POLICY_ACTION_NEW_VERSION;
+	}
+	return gl_num_terms++;
+}
+
+/*
+ * Release an index in the global term vector
+ *
+ * Caller must hold the rbce_rwlock in write mode as the global data
+ * is written onto.
+ */
+static void release_term_index(int idx)
+{
+	if ((idx < 0) || (idx > gl_num_terms))
+		return;
+
+	gl_terms[idx].op = -1;
+	gl_released++;
+	if ((gl_released > POLICY_INC_NUMTERMS) &&
+	    (gl_allocated >
+	     (gl_num_terms - gl_released + POLICY_INC_NUMTERMS))) {
+		gl_action |= POLICY_ACTION_PACK_TERMS;
+	}
+	return;
+}
+
+/*
+ * Release the indices, string memory, and terms associated with the given
+ * rule.
+ *
+ * Caller should be holding rbce_rwlock
+ */
+static void __release_rule(struct rbce_rule *rule)
+{
+	int i, *terms = rule->terms;
+
+	/* remove memory and references from other rules */
+	for (i = rule->num_terms; --i >= 0;) {
+		struct rbce_rule_term *term = &gl_terms[terms[i]];
+
+		if (term->op == RBCE_RULE_DEP_RULE)
+			DEC_REF(term->u.deprule);
+		release_term_index(terms[i]);
+	}
+	rule->num_terms = 0;
+	if (rule->strtab) {
+		kfree(rule->strtab);
+		rule->strtab = NULL;
+	}
+	if (rule->terms) {
+		kfree(rule->terms);
+		rule->terms = NULL;
+	}
+	return;
+}
+
+/*
+ * delete the given rule and all memory associated with it.
+ *
+ * Caller is responsible for protecting the global data
+ */
+static inline int __delete_rule(struct rbce_rule *rule)
+{
+	/* make sure we are not referenced by other rules */
+	if (GET_REF(rule))
+		return -EBUSY;
+	__release_rule(rule);
+	put_class(rule->target_class);
+	release_term_index(rule->index);
+	list_del(&rule->obj.link);
+	gl_num_rules--;
+	gl_rules_version++;
+	module_put(THIS_MODULE);
+	kfree(rule->obj.name);
+	kfree(rule);
+	return 0;
+}
+
+/* ======================= Rule related Functions ========================= */
+
+/*
+ * This function takes terms as input and digests the valid rbce terms
+ * and fills the newrule appropriately.
+ *	 Valid terms have op != RBCE_RULE_INVALID
+ * This function returns the number of valid terms found.
+ * In case of error it return -errno
+ */
+static inline int
+digest_terms(struct rbce_rule *newrule,
+	struct rbce_rule_term *terms, int nterms)
+{
+	char *strtab = NULL;
+	struct rbce_rule *deprule;
+	int i, j, real_nterms = 0, strtablen = 0;
+
+	for (i = 0; i < nterms; i++) {
+		if (terms[i].op == RBCE_RULE_INVALID)
+			continue;
+		real_nterms++;
+
+		switch (terms[i].op) {
+		case RBCE_RULE_DEP_RULE:
+			/* check if the depend rule is valid */
+			deprule = find_rule_name(terms[i].u.string);
+			if (!deprule || deprule == newrule) {
+				real_nterms = -EINVAL;
+				goto out;
+			} else {
+				/* make sure _a_ depend rule */
+				/* appears in only one term. */
+				for (j = 0; j < i; j++) {
+					if (terms[j].op ==
+					    RBCE_RULE_DEP_RULE
+					    && terms[j].u.deprule ==
+					    deprule) {
+						real_nterms = -EINVAL;
+						goto out;
+					}
+				}
+				terms[i].u.deprule = deprule;
+			}
+
+			/* +depend is acceptable and -depend is not */
+			if (terms[i].operator != TOKEN_OP_DEP_DEL)
+				terms[i].operator = RBCE_EQUAL;
+			else {
+				real_nterms = -EINVAL;
+				goto out;
+			}
+			break;
+
+		case RBCE_RULE_CMD_PATH:
+		case RBCE_RULE_CMD:
+		case RBCE_RULE_ARGS:
+		case RBCE_RULE_APP_TAG:
+		case RBCE_RULE_IPV4:
+		case RBCE_RULE_IPV6:
+			/* sum up the string length */
+			strtablen += strlen(terms[i].u.string) + 1;
+			break;
+		default:
+			break;
+
+		}
+	}
+	if (strtablen) {
+		strtab = kmalloc(strtablen, GFP_ATOMIC);
+		if (!strtab)
+			real_nterms = -ENOMEM;
+		else {
+			if (newrule->strtab)
+				kfree(newrule->strtab);
+			newrule->strtab = strtab;
+		}
+	}
+out:
+	return real_nterms;
+}
+
+/*
+ * This function takes terms as input and digests the non rbce terms
+ * and fills newrule appropriately.
+ * non rbce teerms are used to get attribute/value that are not part
+ * of the rule terms.
+ *	 non rbce terms have op != RBCE_RULE_INVALID
+ * This function returns 0 on success and -errno in case of error
+ */
+static inline int
+digest_nonterms(struct rbce_rule *newrule,
+	struct rbce_rule_term *terms, int nterms)
+{
+	char *class = NULL;
+	int state = -1, order = -1, rc = 0, i;
+
+	for (i = 0; i < nterms; i++) {
+		if (terms[i].op != RBCE_RULE_INVALID)
+			continue;
+		switch (terms[i].operator) {
+		case TOKEN_OP_ORDER:
+			order = terms[i].u.id;
+			if (order < 0) {
+				rc = -EINVAL;
+				goto out;
+			}
+			break;
+		case TOKEN_OP_STATE:
+			state = terms[i].u.id != 0;
+			break;
+		case TOKEN_OP_CLASS:
+			class = terms[i].u.string;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Check if class was specified */
+	if (class != NULL) {
+		int classtype;
+		struct rbce_class *targetcls;
+		if ((targetcls = get_class(class, &classtype)) == NULL) {
+			rc = -EINVAL;
+			goto out;
+		}
+		if (newrule->target_class)
+			put_class(newrule->target_class);
+
+		newrule->target_class = targetcls;
+		newrule->classtype = classtype;
+	}
+	if (!newrule->target_class) {
+		rc = -EINVAL;
+		goto out;
+	}
+	if (state != -1)
+		newrule->state = state;
+	if (order != -1)
+		newrule->order = order;
+out:
+	return rc;
+}
+
+/*
+ * Allocate and fill the term vectors of the newrule from the terms array.
+ * Only handle the realy terms and ignore the nonterms.
+ */
+static inline int
+fill_term_vector(struct rbce_rule *newrule,
+	struct rbce_rule_term *terms, int real_nterms)
+{
+	int i, rc = 0, strtablen = 0, j, ii;
+	struct rbce_rule_term *term;
+
+	newrule->terms = kmalloc(real_nterms * sizeof(int), GFP_ATOMIC);
+	if (!newrule->terms) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0, j = 0; j < real_nterms; i++, j++) {
+		if (terms[i].op == RBCE_RULE_INVALID)
+			continue;
+
+		newrule->terms[j] = alloc_term_index();
+		if (newrule->terms[j] < 0) {
+			for (ii = 0; ii < j; ii++)
+				release_term_index(newrule->terms[ii]);
+			rc = -ENOMEM;
+			goto out;
+		}
+		term = &gl_terms[newrule->terms[j]];
+		term->op = terms[i].op;
+		term->operator = terms[i].operator;
+		switch (terms[i].op) {
+		case RBCE_RULE_CMD_PATH:
+		case RBCE_RULE_CMD:
+		case RBCE_RULE_ARGS:
+		case RBCE_RULE_APP_TAG:
+		case RBCE_RULE_IPV4:
+		case RBCE_RULE_IPV6:
+			term->u.string = &newrule->strtab[strtablen];
+			strcpy(term->u.string, terms[i].u.string);
+			strtablen = strlen(term->u.string) + 1;
+			break;
+
+		case RBCE_RULE_REAL_UID:
+		case RBCE_RULE_REAL_GID:
+		case RBCE_RULE_EFFECTIVE_UID:
+		case RBCE_RULE_EFFECTIVE_GID:
+			term->u.id = terms[i].u.id;
+			break;
+
+		case RBCE_RULE_DEP_RULE:
+			term->u.deprule = terms[i].u.deprule;
+			INC_REF(term->u.deprule);
+			break;
+		default:
+			break;
+		}
+	}
+out:
+	if (rc) {
+		kfree(newrule->terms);
+		newrule->terms = NULL;
+	}
+	return rc;
+
+}
+
+/*
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+static int
+fill_rule(struct rbce_rule *newrule, struct rbce_rule_term *terms, int nterms)
+{
+	int real_nterms, index = -1, rc = 0;
+	struct rbce_rule_term *term = NULL;
+
+	if (!newrule)
+		return -EINVAL;
+	newrule->num_terms = 0;
+	newrule->termflag = 0;
+
+	/* Digest filled terms. */
+	real_nterms = digest_terms(newrule, terms, nterms);
+	if (real_nterms < 0)
+		return real_nterms;
+	rc = digest_nonterms(newrule, terms, nterms);
+	if (rc < 0)
+		goto out;
+
+	if (newrule->index == -1) {
+		index = alloc_term_index();
+		if (index < 0) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		newrule->index = index;
+		term = &gl_terms[newrule->index];
+		term->op = RBCE_RULE_DEP_RULE;
+		term->u.deprule = newrule;
+	}
+
+	rc = fill_term_vector(newrule, terms, real_nterms);
+out:
+	if (rc) {
+		if (newrule->target_class) {
+			put_class(newrule->target_class);
+			newrule->target_class = NULL;
+		}
+		if (index >= 0) {
+			release_term_index(index);
+			newrule->index = -1;
+		}
+		kfree(newrule->terms);
+		newrule->terms = NULL;
+		kfree(newrule->strtab);
+		newrule->strtab = NULL;
+		newrule->num_terms = 0;
+	} else
+		newrule->num_terms = real_nterms;
+	return rc;
+}
+
+static inline int
+rbce_create_rule(struct rbce_rule_term *new_terms,
+	int nterms, const char *rname)
+{
+	struct rbce_rule *rule;
+	int rc = -ENOMEM;
+
+	rule = kmalloc (sizeof(struct rbce_rule), GFP_ATOMIC);
+	if (rule) {
+		rule->obj.name = kmalloc(strlen(rname) + 1, GFP_ATOMIC);
+		if (rule->obj.name) {
+			strcpy(rule->obj.name, rname);
+			GET_REF(rule) = 0;
+			rule->order = -1;
+			rule->index = -1;
+			rule->num_terms = 0;
+			rule->state = RBCE_RULE_ENABLED;
+			rule->target_class = NULL;
+			rule->strtab = NULL;
+			rule->classtype = -1;
+			rule->terms = NULL;
+			rule->do_opt = 1;
+			INIT_LIST_HEAD(&rule->obj.link);
+			rc = fill_rule(rule, new_terms, nterms);
+			if (rc) {
+				kfree(rule->obj.name);
+				kfree(rule);
+			} else if ((rc = insert_rule(rule,
+					rule->order, INSERT)) != 0)
+				__delete_rule(rule);
+		} else
+			kfree(rule);
+	}
+	return rc;
+}
+
+static inline struct rbce_rule_term *
+merge_terms(struct rbce_rule *rule, struct rbce_rule_term *new_terms,
+	int nterms, int new_term_mask, int *merged_nterms)
+{
+	struct rbce_rule_term *terms, *term;
+	struct rbce_rule *deprule;
+	int i, j, k, oterms, tot_terms, strlocal_len;
+	char *strlocal;
+
+	oterms = rule->num_terms;
+	tot_terms = nterms + oterms;
+	*merged_nterms = 0;
+
+	terms = kmalloc(tot_terms * sizeof(struct rbce_rule_term), GFP_ATOMIC);
+
+	if (!terms) {
+		return NULL;
+	}
+
+	/* Assume we are going to copy all strings from the original rule. */
+	strlocal_len = 0;
+	for (i = 0; i < oterms; i++) {
+		term = &gl_terms[rule->terms[i]];
+		switch (term->op) {
+		case RBCE_RULE_CMD_PATH:
+		case RBCE_RULE_CMD:
+		case RBCE_RULE_ARGS:
+		case RBCE_RULE_APP_TAG:
+		case RBCE_RULE_IPV4:
+		case RBCE_RULE_IPV6:
+			strlocal_len += strlen(term->u.string) + 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	strlocal = kmalloc(strlocal_len, GFP_ATOMIC);
+	if (!strlocal) {
+		kfree(terms);
+		return NULL;
+	}
+
+	strlocal_len = 0;
+	new_term_mask &= ~(1 << RBCE_RULE_DEP_RULE);
+	/* ignore the new deprule terms for the first iteration. */
+	/* taken care of later. */
+	for (i = 0; i < oterms; i++) {
+		term = &gl_terms[rule->terms[i]];	/* old term */
+
+		if ((1 << term->op) & new_term_mask) {
+			/* newrule has this attr/value */
+			for (j = 0; j < nterms; j++)
+				if (term->op == new_terms[j].op) {
+					terms[i].op = new_terms[j].op;
+					terms[i].operator = new_terms[j].
+					    operator;
+					terms[i].u.string =
+					    new_terms[j].u.string;
+					new_terms[j].op = RBCE_RULE_INVALID2;
+					break;
+				}
+		} else {
+			terms[i].op = term->op;
+			terms[i].operator = term->operator;
+			switch (term->op) {
+			case RBCE_RULE_CMD_PATH:
+			case RBCE_RULE_CMD:
+			case RBCE_RULE_ARGS:
+			case RBCE_RULE_APP_TAG:
+			case RBCE_RULE_IPV4:
+			case RBCE_RULE_IPV6:
+				terms[i].u.string = &strlocal[strlocal_len];
+				strcpy(terms[i].u.string, term->u.string);
+				strlocal_len = strlen(terms[i].u.string) + 1;
+				break;
+			default:
+				terms[i].u.string = term->u.string;
+				break;
+			}
+		}
+	}
+
+	i = oterms;		/* for readability */
+
+	for (j = 0; j < nterms; j++) {
+		/* handled in the previous iteration */
+		if (new_terms[j].op == RBCE_RULE_INVALID2)
+			continue;
+		if (new_terms[j].op == RBCE_RULE_DEP_RULE) {
+			if (new_terms[j].operator == TOKEN_OP_DEP) {
+				/*
+				 * "depend=rule" deletes all depends in the
+				 * original rule so, delete all depend rule
+				 * terms in the original rule
+				 */
+				for (k = 0; k < oterms; k++)
+					if (terms[k].op == RBCE_RULE_DEP_RULE)
+						terms[k].op = RBCE_RULE_INVALID;
+				/* must copy the new deprule term */
+			} else {
+				/*
+				 * delete the depend rule term if was defined
+				 * in the original rule for both +depend
+				 * and -depend
+				 */
+				deprule = find_rule_name(new_terms[j].u.string);
+				if (deprule)
+					for (k = 0; k < oterms; k++) {
+						if (terms[k].op ==
+						    RBCE_RULE_DEP_RULE
+						    && terms[k].u.deprule ==
+						    deprule) {
+							terms[k].op =
+							    RBCE_RULE_INVALID;
+							break;
+						}
+					}
+				if (new_terms[j].operator == TOKEN_OP_DEP_DEL)
+					/* No need to copy the new deprule */
+					continue;
+			}
+		}
+		terms[i].op = new_terms[j].op;
+		terms[i].operator = new_terms[j].operator;
+		terms[i].u.string = new_terms[j].u.string;
+		i++;
+		new_terms[j].op = RBCE_RULE_INVALID2;
+	}
+
+	tot_terms = i;
+
+	/* convert old deprule pointers to name pointers. */
+	for (i = 0; i < oterms; i++) {
+		if (terms[i].op != RBCE_RULE_DEP_RULE)
+			continue;
+		terms[i].u.string = terms[i].u.deprule->obj.name;
+	}
+
+	*merged_nterms = tot_terms;
+	return terms;
+}
+
+int rbce_change_rule(const char *rname, char *rdefn)
+{
+	struct rbce_rule *rule;
+	struct rbce_rule_term *new_terms = NULL, *merged_terms;
+	int nterms, new_term_mask = 0, merged_nterms, rc = -ENOMEM;
+
+	if ((nterms = rules_parse(rdefn, &new_terms, &new_term_mask)) <= 0)
+		return !nterms ? -EINVAL : nterms;
+
+	write_lock(&rbce_rwlock);
+	rule = find_rule_name(rname);
+	if (rule == NULL) {
+		rc = rbce_create_rule(new_terms, nterms, rname);
+		kfree(new_terms);
+		write_unlock(&rbce_rwlock);
+		return rc;
+	}
+
+	merged_terms = merge_terms(rule, new_terms, nterms, new_term_mask,
+			&merged_nterms);
+
+	if (merged_terms) {
+		/* release the rule */
+		__release_rule(rule);
+
+		rule->do_opt = 1;
+		rc = fill_rule(rule, merged_terms, merged_nterms);
+		if (rc == 0)
+			rc = insert_rule(rule, rule->order, REINSERT);
+		if (rc != 0)	/* rule creation/insertion failed */
+			__delete_rule(rule);
+	}
+
+	write_unlock(&rbce_rwlock);
+	kfree(merged_terms);
+	kfree(new_terms);
+	return rc;
+}
+
+/*
+ * Delete the specified rule.
+ *
+ */
+int rbce_delete_rule(const char *rname)
+{
+	int rc = 0;
+	struct rbce_rule *rule;
+
+	write_lock(&rbce_rwlock);
+
+	if ((rule = find_rule_name(rname)) != NULL)
+		rc = __delete_rule(rule);
+	write_unlock(&rbce_rwlock);
+	return rc;
+}
+
+/*
+ * copy the rule specified by rname and to the given result string.
+ *
+ */
+void rbce_get_rule(const char *rname, char *result)
+{
+	int i;
+	struct rbce_rule *rule;
+	struct rbce_rule_term *term;
+	char *cp = result, oper, idtype[3], str[5];
+
+	read_lock(&rbce_rwlock);
+
+	rule = find_rule_name(rname);
+	if (rule != NULL) {
+		for (i = 0; i < rule->num_terms; i++) {
+			term = gl_terms + rule->terms[i];
+			switch (term->op) {
+			case RBCE_RULE_REAL_UID:
+				strcpy(idtype, "u");
+				goto handleid;
+			case RBCE_RULE_REAL_GID:
+				strcpy(idtype, "g");
+				goto handleid;
+			case RBCE_RULE_EFFECTIVE_UID:
+				strcpy(idtype, "eu");
+				goto handleid;
+			case RBCE_RULE_EFFECTIVE_GID:
+				strcpy(idtype, "eg");
+			handleid:
+				switch (term->operator) {
+				case RBCE_LESS_THAN:
+					oper = '<';
+					break;
+				case RBCE_GREATER_THAN:
+					oper = '>';
+					break;
+				case RBCE_NOT:
+					oper = '!';
+					break;
+				default:
+					oper = '=';
+					break;
+				}
+				cp +=
+				    sprintf(cp, "%sid%c%ld,", idtype, oper,
+					    term->u.id);
+				break;
+			case RBCE_RULE_CMD_PATH:
+				strcpy(str, "path");
+				goto handle_str;
+			case RBCE_RULE_CMD:
+				strcpy(str, "cmd");
+				goto handle_str;
+			case RBCE_RULE_ARGS:
+				strcpy(str, "args");
+				goto handle_str;
+			case RBCE_RULE_APP_TAG:
+				strcpy(str, "tag");
+				goto handle_str;
+			case RBCE_RULE_IPV4:
+				strcpy(str, "ipv4");
+				goto handle_str;
+			case RBCE_RULE_IPV6:
+				strcpy(str, "ipv6");
+			      handle_str:
+				cp +=
+				    sprintf(cp, "%s=%s,", str, term->u.string);
+				break;
+			case RBCE_RULE_DEP_RULE:
+				cp +=
+				    sprintf(cp, "depend=%s,",
+					    term->u.deprule->obj.name);
+				break;
+			default:
+				break;
+			}
+		}
+
+		cp +=
+		    sprintf(cp, "order=%d,state=%d,", rule->order, rule->state);
+		cp +=
+		    sprintf(cp, "class=%s",
+			    rule->target_class ? rule->target_class->obj.
+			    name : "*****REMOVED*****");
+		*cp = '\0';
+	} else
+		sprintf(result, "***** Rule %s doesn't exist *****", rname);
+
+	read_unlock(&rbce_rwlock);
+	return;
+}
+
+/*
+ * Change the name of the given rule "from_rname" to "to_rname"
+ *
+ */
+int rbce_rename_rule(const char *from_rname, const char *to_rname)
+{
+	struct rbce_rule *rule;
+	int nlen, rc = -EINVAL;
+
+	if (!to_rname || !*to_rname)
+		return rc;
+	write_lock(&rbce_rwlock);
+
+	rule = find_rule_name(from_rname);
+	if (rule != NULL) {
+		if ((nlen = strlen(to_rname)) > strlen(rule->obj.name)) {
+			char *name = kmalloc(nlen + 1, GFP_ATOMIC);
+			if (!name)
+				return -ENOMEM;
+			kfree(rule->obj.name);
+			rule->obj.name = name;
+		}
+		strcpy(rule->obj.name, to_rname);
+		rc = 0;
+	}
+	write_unlock(&rbce_rwlock);
+	return rc;
+}
+
+/*
+ * Return TRUE if the given rule exists, FALSE otherwise
+ *
+ */
+int rbce_rule_exists(const char *rname)
+{
+	struct rbce_rule *rule;
+
+	read_lock(&rbce_rwlock);
+	rule = find_rule_name(rname);
+	read_unlock(&rbce_rwlock);
+	return rule != NULL;
+}
+
+/*====================== Magic file handling =======================*/
+struct rbce_private_data *create_private_data(struct rbce_private_data *a,
+						     int b)
+{
+	return NULL;
+}
+
+int rbce_set_tasktag(int pid, char *tag)
+{
+	char *tp;
+	int rc = 0;
+	struct task_struct *tsk;
+	struct rbce_private_data *pdata;
+	int len;
+
+	if (!tag)
+		return -EINVAL;
+	len = strlen(tag) + 1;
+	tp = kmalloc(len, GFP_ATOMIC);
+	if (!tp)
+		return -ENOMEM;
+	strncpy(tp,tag,len);
+
+	read_lock(&tasklist_lock);
+	if ((tsk = find_task_by_pid(pid)) == NULL) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (!RBCE_DATA(tsk)) {
+		RBCE_DATAP(tsk) = create_private_data(NULL, 0);
+		if (!RBCE_DATA(tsk)) {
+			rc = -ENOMEM;
+			goto out;
+		}
+	}
+	pdata = RBCE_DATA(tsk);
+	if (pdata->app_tag)
+		kfree(pdata->app_tag);
+	pdata->app_tag = tp;
+
+out:
+	read_unlock(&tasklist_lock);
+	if (rc != 0)
+		kfree(tp);
+	return rc;
 }
 
-int rbce_enabled = 1;
 /* ======================= Module definition Functions ====================== */
 
 int init_rbce(void)
Index: linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_token.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-ckrm1/kernel/ckrm/rbce/rbce_token.c	2005-06-20 13:08:44.000000000 -0700
@@ -0,0 +1,241 @@
+/* Tokens for 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
+ *
+ * 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 <linux/parser.h>
+#include <linux/ctype.h>
+#include "rbce_internal.h"
+
+int token_to_ruleop[TOKEN_INVALID + 1] = {
+	[TOKEN_PATH] = RBCE_RULE_CMD_PATH,
+	[TOKEN_CMD] = RBCE_RULE_CMD,
+	[TOKEN_ARGS] = RBCE_RULE_ARGS,
+	[TOKEN_RUID_EQ] = RBCE_RULE_REAL_UID,
+	[TOKEN_RUID_LT] = RBCE_RULE_REAL_UID,
+	[TOKEN_RUID_GT] = RBCE_RULE_REAL_UID,
+	[TOKEN_RUID_NOT] = RBCE_RULE_REAL_UID,
+	[TOKEN_RGID_EQ] = RBCE_RULE_REAL_GID,
+	[TOKEN_RGID_LT] = RBCE_RULE_REAL_GID,
+	[TOKEN_RGID_GT] = RBCE_RULE_REAL_GID,
+	[TOKEN_RGID_NOT] = RBCE_RULE_REAL_GID,
+	[TOKEN_EUID_EQ] = RBCE_RULE_EFFECTIVE_UID,
+	[TOKEN_EUID_LT] = RBCE_RULE_EFFECTIVE_UID,
+	[TOKEN_EUID_GT] = RBCE_RULE_EFFECTIVE_UID,
+	[TOKEN_EUID_NOT] = RBCE_RULE_EFFECTIVE_UID,
+	[TOKEN_EGID_EQ] = RBCE_RULE_EFFECTIVE_GID,
+	[TOKEN_EGID_LT] = RBCE_RULE_EFFECTIVE_GID,
+	[TOKEN_EGID_GT] = RBCE_RULE_EFFECTIVE_GID,
+	[TOKEN_EGID_NOT] = RBCE_RULE_EFFECTIVE_GID,
+	[TOKEN_TAG] = RBCE_RULE_APP_TAG,
+	[TOKEN_IPV4] = RBCE_RULE_IPV4,
+	[TOKEN_IPV6] = RBCE_RULE_IPV6,
+	[TOKEN_DEP] = RBCE_RULE_DEP_RULE,
+	[TOKEN_DEP_ADD] = RBCE_RULE_DEP_RULE,
+	[TOKEN_DEP_DEL] = RBCE_RULE_DEP_RULE,
+	[TOKEN_ORDER] = RBCE_RULE_INVALID,
+	[TOKEN_CLASS] = RBCE_RULE_INVALID,
+	[TOKEN_STATE] = RBCE_RULE_INVALID,
+};
+
+enum op_token token_to_operator[TOKEN_INVALID + 1] = {
+	[TOKEN_PATH] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_CMD] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_ARGS] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_RUID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_RUID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+	[TOKEN_RUID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+	[TOKEN_RUID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+	[TOKEN_RGID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_RGID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+	[TOKEN_RGID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+	[TOKEN_RGID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+	[TOKEN_EUID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_EUID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+	[TOKEN_EUID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+	[TOKEN_EUID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+	[TOKEN_EGID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_EGID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+	[TOKEN_EGID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+	[TOKEN_EGID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+	[TOKEN_TAG] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_IPV4] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_IPV6] = (__force op_token_t) TOKEN_OP_EQUAL,
+	[TOKEN_DEP] = (__force op_token_t) TOKEN_OP_DEP,
+	[TOKEN_DEP_ADD] = (__force op_token_t) TOKEN_OP_DEP_ADD,
+	[TOKEN_DEP_DEL] = (__force op_token_t) TOKEN_OP_DEP_DEL,
+	[TOKEN_ORDER] = (__force op_token_t) TOKEN_OP_ORDER,
+	[TOKEN_CLASS] = (__force op_token_t) TOKEN_OP_CLASS,
+	[TOKEN_STATE] = (__force op_token_t) TOKEN_OP_STATE
+};
+
+static match_table_t tokens = {
+	{TOKEN_PATH, "path=%s"},
+	{TOKEN_CMD, "cmd=%s"},
+	{TOKEN_ARGS, "args=%s"},
+	{TOKEN_RUID_EQ, "uid=%d"},
+	{TOKEN_RUID_LT, "uid<%d"},
+	{TOKEN_RUID_GT, "uid>%d"},
+	{TOKEN_RUID_NOT, "uid!%d"},
+	{TOKEN_RGID_EQ, "gid=%d"},
+	{TOKEN_RGID_LT, "gid<%d"},
+	{TOKEN_RGID_GT, "gid>%d"},
+	{TOKEN_RGID_NOT, "gid!d"},
+	{TOKEN_EUID_EQ, "euid=%d"},
+	{TOKEN_EUID_LT, "euid<%d"},
+	{TOKEN_EUID_GT, "euid>%d"},
+	{TOKEN_EUID_NOT, "euid!%d"},
+	{TOKEN_EGID_EQ, "egid=%d"},
+	{TOKEN_EGID_LT, "egid<%d"},
+	{TOKEN_EGID_GT, "egid>%d"},
+	{TOKEN_EGID_NOT, "egid!%d"},
+	{TOKEN_TAG, "tag=%s"},
+	{TOKEN_IPV4, "ipv4=%s"},
+	{TOKEN_IPV6, "ipv6=%s"},
+	{TOKEN_DEP, "depend=%s"},
+	{TOKEN_DEP_ADD, "+depend=%s"},
+	{TOKEN_DEP_DEL, "-depend=%s"},
+	{TOKEN_ORDER, "order=%d"},
+	{TOKEN_CLASS, "class=%s"},
+	{TOKEN_STATE, "state=%d"},
+	{TOKEN_INVALID, NULL}
+};
+
+/*
+ * return -EINVAL in case of failures
+ * returns number of terms in terms on success.
+ * never returns 0.
+ */
+
+int
+rules_parse(char *rule_defn, struct rbce_rule_term **rterms, int *term_mask)
+{
+	char *p, *rp = rule_defn;
+	int option, i = 0, nterms;
+	struct rbce_rule_term *terms;
+
+	*rterms = NULL;
+	*term_mask = 0;
+	if (!rule_defn)
+		return -EINVAL;
+
+	nterms = 0;
+	while (*rp++)
+		if (*rp == '>' || *rp == '<' || *rp == '=' || *rp == '!')
+			nterms++;
+
+	if (!nterms)
+		return -EINVAL;
+
+	terms = kmalloc(nterms * sizeof(struct rbce_rule_term), GFP_KERNEL);
+	if (!terms)
+		return -ENOMEM;
+
+	while ((p = strsep(&rule_defn, ",")) != NULL) {
+
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+
+		while (*p && isspace(*p))
+			p++;
+		if (!*p)
+			continue;
+
+		token = match_token(p, tokens, args);
+
+		terms[i].op = token_to_ruleop[token];
+		terms[i].operator = token_to_operator[token];
+		switch (token) {
+
+		case TOKEN_PATH:
+		case TOKEN_CMD:
+		case TOKEN_ARGS:
+		case TOKEN_TAG:
+		case TOKEN_IPV4:
+		case TOKEN_IPV6:
+			/* all these tokens can be specified only once */
+			if (*term_mask & (1 << terms[i].op)) {
+				nterms = -EINVAL;
+				goto out;
+			}
+		/*FALLTHRU*/
+		case TOKEN_CLASS:
+		case TOKEN_DEP:
+		case TOKEN_DEP_ADD:
+		case TOKEN_DEP_DEL:
+			terms[i].u.string = args->from;
+			break;
+
+		case TOKEN_RUID_EQ:
+		case TOKEN_RUID_LT:
+		case TOKEN_RUID_GT:
+		case TOKEN_RUID_NOT:
+		case TOKEN_RGID_EQ:
+		case TOKEN_RGID_LT:
+		case TOKEN_RGID_GT:
+		case TOKEN_RGID_NOT:
+		case TOKEN_EUID_EQ:
+		case TOKEN_EUID_LT:
+		case TOKEN_EUID_GT:
+		case TOKEN_EUID_NOT:
+		case TOKEN_EGID_EQ:
+		case TOKEN_EGID_LT:
+		case TOKEN_EGID_GT:
+		case TOKEN_EGID_NOT:
+			/* all these tokens can be specified only once */
+			if (*term_mask & (1 << terms[i].op)) {
+				nterms = -EINVAL;
+				goto out;
+			}
+		/*FALLTHRU*/
+		case TOKEN_ORDER:
+		case TOKEN_STATE:
+			if (match_int(args, &option)) {
+				nterms = -EINVAL;
+				goto out;
+			}
+			terms[i].u.id = option;
+			break;
+		default:
+			nterms = -EINVAL;
+			goto out;
+		}
+		/* Check range of term value */
+		switch(token){
+		case TOKEN_STATE:
+			if ((terms[i].u.id != 0) && (terms[i].u.id != 1)){
+				nterms = -EINVAL;
+				goto out;
+			}
+			break;
+		default: /* Non-numerical value */
+			break;
+		}
+		*term_mask |= (1 << terms[i].op);
+		i++;
+	}
+	*rterms = terms;
+
+      out:
+	if (nterms < 0) {
+		kfree(terms);
+		*term_mask = 0;
+	}
+	return nterms;
+}

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

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux