-/* Rule-based Classification Engine (RBCE) module
+/* Rule-based Classification Engine (RBCE) and
+ * Consolidated RBCE module code (combined)
*
* Copyright (C) Hubertus Franke, IBM Corp. 2003
* (C) Chandra Seetharaman, IBM Corp. 2003
* 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.
+ *
*/
/* Changes
#include <linux/ckrm_ce.h>
#include <linux/ckrm_net.h>
#include "bitvector.h"
-#include "rbce.h"
+#include <linux/rbce.h>
#define DEBUG
RBCE_RULE_APP_TAG, // task's application tag
RBCE_RULE_IPV4, // IP address of listen(), ipv4 format
RBCE_RULE_IPV6, // IP address of listen(), ipv6 format
+ RBCE_RULE_XID, // VSERVER
RBCE_RULE_DEP_RULE, // dependent rule; must be the first term
RBCE_RULE_INVALID, // invalid, for filler
RBCE_RULE_INVALID2, // invalid, for filler
#define RBCE_TERM_TAG (3)
#define RBCE_TERM_IPV4 (4)
#define RBCE_TERM_IPV6 (5)
+#define RBCE_TERM_XID (6)
-#define NUM_TERM_MASK_VECTOR (6)
+#define NUM_TERM_MASK_VECTOR (7) // must be one more the last RBCE_TERM_...
// Rule flags. 1 bit for each type of rule term
#define RBCE_TERMFLAG_CMD (1 << RBCE_TERM_CMD)
#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)
+#define RBCE_TERMFLAG_XID (1 << RBCE_TERM_XID)
+#define RBCE_TERMFLAG_ALL (RBCE_TERMFLAG_CMD | RBCE_TERMFLAG_UID | \
+ RBCE_TERMFLAG_GID | RBCE_TERMFLAG_TAG | RBCE_TERMFLAG_XID | \
+ RBCE_TERMFLAG_IPV4 | RBCE_TERMFLAG_IPV6)
int termop_2_vecidx[RBCE_RULE_INVALID] = {
[RBCE_RULE_CMD_PATH] = RBCE_TERM_CMD,
[RBCE_RULE_REAL_GID] = RBCE_TERM_GID,
[RBCE_RULE_EFFECTIVE_UID] = RBCE_TERM_UID,
[RBCE_RULE_EFFECTIVE_GID] = RBCE_TERM_GID,
+ [RBCE_RULE_XID] = RBCE_TERM_XID,
[RBCE_RULE_APP_TAG] = RBCE_TERM_TAG,
[RBCE_RULE_IPV4] = RBCE_TERM_IPV4,
[RBCE_RULE_IPV6] = RBCE_TERM_IPV6,
#define POLICY_ACTION_REDO_ALL 0x02 // Recompute all rule flags
#define POLICY_ACTION_PACK_TERMS 0x04 // Time to pack the terms
+const int use_persistent_state = 1;
+
struct ckrm_eng_callback ckrm_ecbs;
// Term vector state
#define DBG_RULE ( 0x20 )
#define DBG_POLICY ( 0x40 )
-#define DPRINTK(x, y...) if (rbcedebug & (x)) printk(y)
+#define DPRINTK(x, y...) if (rbcedebug & (x)) printk(KERN_DEBUG y)
// debugging selectively enabled through /proc/sys/debug/rbce
static void print_context_vectors(void)
return;
}
for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
- printk("%d: ", i);
+ printk(KERN_DEBUG "%d: ", i);
bitvector_print(DBG_OPTIMIZATION, gl_mask_vecs[i]);
- printk("\n");
+ printk(KERN_DEBUG "\n");
}
}
#else
#define print_context_vectors(x)
#endif
+/* ====================== VSERVER support ========================== */
+#define CONFIG_VSERVER
+#ifdef CONFIG_VSERVER
+#include <linux/vs_base.h>
+#else
+typedef unsigned int xid_t;
+#define vx_task_xid(t) (0)
+#endif
+
/* ======================= Helper Functions ========================= */
#include "token.c"
}
notify_class_action(cls, 0);
cls->classobj = NULL;
- list_for_each_entry(pos, &rules_list[cls->classtype], link) {
+ list_for_each_entry(pos, &rules_list[classtype], link) {
rule = (struct rbce_rule *)pos;
if (rule->target_class) {
if (!strcmp
}
}
}
- put_class(cls);
if ((cls = find_class_name(classname)) != NULL) {
printk(KERN_ERR
"rbce ERROR: class %s exists in rbce after "
case RBCE_RULE_REAL_GID:
case RBCE_RULE_EFFECTIVE_UID:
case RBCE_RULE_EFFECTIVE_GID:
+ case RBCE_RULE_XID:
term->u.id = terms[i].u.id;
break;
goto handleid;
case RBCE_RULE_EFFECTIVE_GID:
strcpy(idtype, "eg");
+ goto handleid;
+ case RBCE_RULE_XID:
+ strcpy(idtype, "x");
handleid:
if (term->operator == RBCE_LESS_THAN) {
oper = '<';
static struct rbce_private_data *create_private_data(struct rbce_private_data *,
int);
-int rbce_ckrm_reclassify(int pid)
+static inline
+void reset_evaluation(struct rbce_private_data *pdata,int termflag)
{
- printk("ckrm_reclassify_pid ignored\n");
- return -EINVAL;
-}
-
-int reclassify_pid(int pid)
-{
- struct task_struct *tsk;
-
- // FIXME: Need to treat -pid as process group
- if (pid < 0) {
- return -EINVAL;
- }
-
- if (pid == 0) {
- rbce_ckrm_reclassify(0); // just reclassify all tasks.
- }
- // if pid is +ve take control of the task, start evaluating it
- if ((tsk = find_task_by_pid(pid)) == NULL) {
- return -EINVAL;
- }
-
- if (unlikely(!RBCE_DATA(tsk))) {
- RBCE_DATAP(tsk) = create_private_data(NULL, 0);
- if (!RBCE_DATA(tsk)) {
- return -ENOMEM;
- }
- }
- RBCE_DATA(tsk)->evaluate = 1;
- rbce_ckrm_reclassify(pid);
- return 0;
+ /* reset TAG ruleterm evaluation results to pick up
+ * on next classification event
+ */
+ if (use_persistent_state && gl_mask_vecs[termflag]) {
+ bitvector_and_not( pdata->eval, pdata->eval,
+ gl_mask_vecs[termflag] );
+ bitvector_and_not( pdata->true, pdata->true,
+ gl_mask_vecs[termflag] );
+ }
}
-
+
int 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;
}
-
- if ((tsk = find_task_by_pid(pid)) == NULL) {
- return -EINVAL;
- }
-
- tp = kmalloc(strlen(tag) + 1, GFP_ATOMIC);
-
+ 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 (unlikely(!RBCE_DATA(tsk))) {
RBCE_DATAP(tsk) = create_private_data(NULL, 0);
if (!RBCE_DATA(tsk)) {
- kfree(tp);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out;
}
}
pdata = RBCE_DATA(tsk);
kfree(pdata->app_tag);
}
pdata->app_tag = tp;
- strcpy(pdata->app_tag, tag);
- rbce_ckrm_reclassify(pid);
-
- return 0;
+ reset_evaluation(pdata,RBCE_TERMFLAG_TAG);
+
+ out:
+ read_unlock(&tasklist_lock);
+ if (rc != 0)
+ kfree(tp);
+ return rc;
}
/*====================== Classification Functions =======================*/
no_ip = 0;
break;
+ case RBCE_RULE_XID:
+ {
+ xid_t xid = vx_task_xid(tsk);
+
+ if (term->operator == RBCE_LESS_THAN) {
+ rc = (xid < term->u.id);
+ } else if (term->operator == RBCE_GREATER_THAN) {
+ rc = (xid > term->u.id);
+ } else if (term->operator == RBCE_NOT) {
+ rc = (xid != term->u.id);
+ } else {
+ rc = (xid == term->u.id);
+ }
+ break;
+ }
+
default:
rc = 0;
printk(KERN_ERR "Error evaluate term op=%d\n",
}
}
spin_unlock(&pdata_lock);
- printk("INVALID/CORRUPT PDATA %p\n", pdata);
+ printk(KERN_WARNING "INVALID/CORRUPT PDATA %p\n", pdata);
return 0;
}
while (i < MAX_PDATA) {
if (pdata_arr[pdata_next] == NULL) {
- printk("storing %p at %d, count %d\n", pdata,
+ printk(KERN_DEBUG "storing %p at %d, count %d\n", pdata,
pdata_next, pdata_count);
pdata_arr[pdata_next++] = pdata;
if (pdata_next == MAX_PDATA) {
spin_unlock(&pdata_lock);
}
if (i == MAX_PDATA) {
- printk("PDATA BUFFER FULL pdata_count %d pdata %p\n",
+ printk(KERN_DEBUG "PDATA BUFFER FULL pdata_count %d pdata %p\n",
pdata_count, pdata);
}
}
spin_lock(&pdata_lock);
for (i = 0; i < MAX_PDATA; i++) {
if (pdata_arr[i] == pdata) {
- printk("unstoring %p at %d, count %d\n", pdata,
+ printk(KERN_DEBUG "unstoring %p at %d, count %d\n", pdata,
i, pdata_count);
pdata_arr[i] = NULL;
pdata_count--;
}
spin_unlock(&pdata_lock);
if (i == MAX_PDATA) {
- printk("pdata %p not found in the stored array\n",
+ printk(KERN_DEBUG "pdata %p not found in the stored array\n",
pdata);
}
}
#endif // PDATA_DEBUG
-const int use_persistent_state = 1;
-
/*
* Allocate and initialize a rbce_private_data data structure.
*
// pdata->evaluate = src->evaluate;
// if(src->app_tag) {
// int len = strlen(src->app_tag)+1;
- // printk("CREATE_PRIVATE: apptag %s len %d\n",
+ // printk(KERN_DEBUG "CREATE_PRIVATE: apptag %s len %d\n",
// src->app_tag,len);
// pdata->app_tag = kmalloc(len, GFP_ATOMIC);
// if (pdata->app_tag) {
AENT(EXEC),
AENT(UID),
AENT(GID),
+ AENT(XID),
AENT(LOGIN),
AENT(USERADD),
AENT(USERDEL),
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 *);
* [ CKRM_LATCHABLE_EVENTS .. CKRM_NONLATCHABLE_EVENTS )
*/
- // printk("tc_classify %p:%d:%s '%s'\n",tsk,tsk->pid,
+ // printk(KERN_DEBUG "tc_classify %p:%d:%s '%s'\n",tsk,tsk->pid,
// tsk->comm,event_names[event]);
switch (event) {
cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_GID, tc_classtype);
break;
+ case CKRM_EVENT_XID:
+ cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_XID, tc_classtype);
+ break;
+
case CKRM_EVENT_LOGIN:
case CKRM_EVENT_USERADD:
case CKRM_EVENT_USERDEL:
break;
case CKRM_EVENT_RECLASSIFY:
+ if ((pdata = (RBCE_DATA(tsk)))) {
+ pdata->evaluate = 1;
+ }
cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_ALL, tc_classtype);
break;
}
- // printk("tc_classify %p:%d:%s '%s' ==> %p\n",tsk,tsk->pid,
+ // printk(KERN_DEBUG "tc_classify %p:%d:%s '%s' ==> %p\n",tsk,tsk->pid,
// tsk->comm,event_names[event],cls);
return cls;
#ifndef RBCE_EXTENSION
static void rbce_tc_notify(int event, void *core, struct task_struct *tsk)
{
- printk("tc_manual %p:%d:%s '%s'\n", tsk, tsk->pid, tsk->comm,
+ printk(KERN_DEBUG "tc_manual %p:%d:%s '%s'\n", tsk, tsk->pid, tsk->comm,
event_names[event]);
if (event != CKRM_EVENT_MANUAL)
return;
{NULL}
};
-static int register_classtype_engines(void)
-{
+static void unregister_classtype_engines(void)
+ {
int rc;
struct ce_regtable_struct *ceptr = ce_regtable;
while (ceptr->name) {
- rc = ckrm_register_engine(ceptr->name, ceptr->cbs);
- printk("ce register with <%s> typeId=%d\n", ceptr->name, rc);
- if ((rc < 0) && (rc != -ENOENT))
- return (rc);
- if (rc != -ENOENT)
- *ceptr->clsvar = rc;
+ if (*ceptr->clsvar >= 0) {
+ printk(KERN_DEBUG "ce unregister with <%s>\n",ceptr->name);
+ while ((rc = ckrm_unregister_engine(ceptr->name)) == -EAGAIN)
+ ;
+ printk(KERN_DEBUG "ce unregister with <%s> rc=%d\n",ceptr->name,rc);
+ *ceptr->clsvar = -1;
+ }
ceptr++;
}
- return 0;
-}
+ }
-static void unregister_classtype_engines(void)
+static int register_classtype_engines(void)
{
int rc;
struct ce_regtable_struct *ceptr = ce_regtable;
while (ceptr->name) {
- if (*ceptr->clsvar >= 0) {
- printk("ce unregister with <%s>\n", ceptr->name);
- rc = ckrm_unregister_engine(ceptr->name);
- printk("ce unregister with <%s> rc=%d\n", ceptr->name,
- rc);
- *ceptr->clsvar = -1;
+ rc = ckrm_register_engine(ceptr->name, ceptr->cbs);
+ printk(KERN_DEBUG "ce register with <%s> typeId=%d\n",ceptr->name,rc);
+ if ((rc < 0) && (rc != -ENOENT)) {
+ unregister_classtype_engines();
+ return (rc);
}
+ if (rc != -ENOENT)
+ *ceptr->clsvar = rc;
ceptr++;
}
+ return 0;
}
// =========== /proc/sysctl/debug/rbce debug stuff =============
{
int rc, i, line;
- printk("<1>\nInstalling \'%s\' module\n", modname);
+ printk(KERN_DEBUG "<1>\nInstalling \'%s\' module\n", modname);
for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
INIT_LIST_HEAD(&rules_list[i]);
exit_rbce_ext();
out:
- printk("<1>%s: error installing rc=%d line=%d\n", __FUNCTION__, rc,
+ printk(KERN_DEBUG "<1>%s: error installing rc=%d line=%d\n", __FUNCTION__, rc,
line);
return rc;
}
{
int i;
- printk("<1>Removing \'%s\' module\n", modname);
+ printk(KERN_DEBUG "<1>Removing \'%s\' module\n", modname);
stop_debug();
exit_rbce_ext();
// Print warnings if lists are not empty, which is a bug
if (!list_empty(&class_list)) {
- printk("exit_rbce: Class list is not empty\n");
+ printk(KERN_DEBUG "exit_rbce: Class list is not empty\n");
}
for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
if (!list_empty(&rules_list[i])) {
- printk("exit_rbce: Rules list for classtype %d"
+ printk(KERN_DEBUG "exit_rbce: Rules list for classtype %d"
" is not empty\n", i);
}
}
EXPORT_SYMBOL(change_rule);
EXPORT_SYMBOL(delete_rule);
EXPORT_SYMBOL(rename_rule);
-EXPORT_SYMBOL(reclassify_pid);
EXPORT_SYMBOL(set_tasktag);
module_init(init_rbce);
module_exit(exit_rbce);
+
+