555ba0a4e393777036af1e59e0415a7eab424475
[linux-2.6.git] / kernel / ckrm / rbce / rbcemod.c
1 /* Rule-based Classification Engine (RBCE) and
2  * Consolidated RBCE module code (combined)
3  *
4  * Copyright (C) Hubertus Franke, IBM Corp. 2003
5  *           (C) Chandra Seetharaman, IBM Corp. 2003
6  *           (C) Vivek Kashyap, IBM Corp. 2004 
7  * 
8  * Module for loading of classification policies and providing
9  * a user API for Class-based Kernel Resource Management (CKRM)
10  *
11  * Latest version, more details at http://ckrm.sf.net
12  * 
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it would be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21  *
22  */
23
24 /* Changes
25  *
26  * 28 Aug 2003
27  *        Created. First cut with much scope for cleanup !
28  * 07 Nov 2003
29  *        Made modifications to suit the new RBCE module.
30  *        Made modifications to address sampling and delivery
31  * 16 Mar 2004
32  *        Integrated changes from original RBCE module
33  * 25 Mar 2004
34  *        Merged RBCE and CRBCE into common code base
35  * 29 Mar 2004
36  *        Incorporated listen call back and IPv4 match support
37  * 23 Apr 2004
38  *        Added Multi-Classtype Support
39  */
40
41 #include <linux/init.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <asm/io.h>
45 #include <asm/uaccess.h>
46 #include <linux/mm.h>
47 #include <linux/mount.h>
48 #include <linux/proc_fs.h>
49 #include <linux/limits.h>
50 #include <linux/pid.h>
51 #include <linux/sysctl.h>
52
53 #include <linux/ckrm_rc.h>
54 #include <linux/ckrm_ce.h>
55 #include <linux/ckrm_net.h>
56 #include "bitvector.h"
57 #include <linux/rbce.h>
58
59 #define DEBUG
60
61 MODULE_DESCRIPTION(RBCE_MOD_DESCR);
62 MODULE_AUTHOR("Hubertus Franke, Chandra Seetharaman (IBM)");
63 MODULE_LICENSE("GPL");
64
65 static char modname[] = RBCE_MOD_NAME;
66
67 /* ==================== typedef, global variables etc., ==================== */
68 struct named_obj_hdr {
69         struct list_head link;
70         int referenced;
71         char *name;
72 };
73
74 #define GET_REF(x) ((x)->obj.referenced)
75 #define INC_REF(x) (GET_REF(x)++)
76 #define DEC_REF(x) (--GET_REF(x))
77 struct rbce_class {
78         struct named_obj_hdr obj;
79         int classtype;
80         void *classobj;
81 };
82
83 typedef enum {
84         RBCE_RULE_CMD_PATH = 1, // full qualified path
85         RBCE_RULE_CMD,          // basename of the command
86         RBCE_RULE_ARGS,         // arguments of the command
87         RBCE_RULE_REAL_UID,     // task's real uid
88         RBCE_RULE_REAL_GID,     // task's real gid
89         RBCE_RULE_EFFECTIVE_UID,        // task's effective uid
90         RBCE_RULE_EFFECTIVE_GID,        // task's effective gid
91         RBCE_RULE_APP_TAG,      // task's application tag
92         RBCE_RULE_IPV4,         // IP address of listen(), ipv4 format
93         RBCE_RULE_IPV6,         // IP address of listen(), ipv6 format
94         RBCE_RULE_XID,          // VSERVER 
95         RBCE_RULE_DEP_RULE,     // dependent rule; must be the first term
96         RBCE_RULE_INVALID,      // invalid, for filler
97         RBCE_RULE_INVALID2,     // invalid, for filler
98 } rbce_rule_op_t;
99
100 typedef enum {
101         RBCE_EQUAL = 1,
102         RBCE_NOT,
103         RBCE_LESS_THAN,
104         RBCE_GREATER_THAN,
105 } rbce_operator_t;
106
107 struct rbce_rule_term {
108         rbce_rule_op_t op;
109         rbce_operator_t operator;
110         union {
111                 char *string;   // path, cmd, arg, tag, ipv4 and ipv6
112                 long id;        // uid, gid, euid, egid
113                 struct rbce_rule *deprule;
114         } u;
115 };
116
117 struct rbce_rule {
118         struct named_obj_hdr obj;
119         struct rbce_class *target_class;
120         int classtype;
121         int num_terms;
122         int *terms;     // vector of indices into the global term vector
123         int index;      // index of this rule into the global term vector
124         int termflag;   // which term ids would require a recalculation
125         int do_opt;     // do we have to consider this rule during optimize
126         char *strtab;   // string table to store the strings of all terms
127         int order;      // order of execution of this rule
128         int state;      // RBCE_RULE_ENABLED/RBCE_RULE_DISABLED
129 };
130
131 // rules states
132 #define RBCE_RULE_DISABLED 0
133 #define RBCE_RULE_ENABLED  1
134
135 ///
136 // Data structures and macros used for optimization
137 #define RBCE_TERM_CMD   (0)
138 #define RBCE_TERM_UID   (1)
139 #define RBCE_TERM_GID   (2)
140 #define RBCE_TERM_TAG   (3)
141 #define RBCE_TERM_IPV4  (4)
142 #define RBCE_TERM_IPV6  (5)
143 #define RBCE_TERM_XID   (6)
144
145 #define NUM_TERM_MASK_VECTOR  (7)     // must be one more the last RBCE_TERM_...
146
147 // Rule flags. 1 bit for each type of rule term
148 #define RBCE_TERMFLAG_CMD   (1 << RBCE_TERM_CMD)
149 #define RBCE_TERMFLAG_UID   (1 << RBCE_TERM_UID)
150 #define RBCE_TERMFLAG_GID   (1 << RBCE_TERM_GID)
151 #define RBCE_TERMFLAG_TAG   (1 << RBCE_TERM_TAG)
152 #define RBCE_TERMFLAG_IPV4  (1 << RBCE_TERM_IPV4)
153 #define RBCE_TERMFLAG_IPV6  (1 << RBCE_TERM_IPV6)
154 #define RBCE_TERMFLAG_XID   (1 << RBCE_TERM_XID)
155 #define RBCE_TERMFLAG_ALL (RBCE_TERMFLAG_CMD | RBCE_TERMFLAG_UID |                      \
156                            RBCE_TERMFLAG_GID | RBCE_TERMFLAG_TAG | RBCE_TERMFLAG_XID |  \
157                            RBCE_TERMFLAG_IPV4 | RBCE_TERMFLAG_IPV6)
158
159 int termop_2_vecidx[RBCE_RULE_INVALID] = {
160         [RBCE_RULE_CMD_PATH] = RBCE_TERM_CMD,
161         [RBCE_RULE_CMD] = RBCE_TERM_CMD,
162         [RBCE_RULE_ARGS] = RBCE_TERM_CMD,
163         [RBCE_RULE_REAL_UID] = RBCE_TERM_UID,
164         [RBCE_RULE_REAL_GID] = RBCE_TERM_GID,
165         [RBCE_RULE_EFFECTIVE_UID] = RBCE_TERM_UID,
166         [RBCE_RULE_EFFECTIVE_GID] = RBCE_TERM_GID,
167         [RBCE_RULE_XID] = RBCE_TERM_XID,
168         [RBCE_RULE_APP_TAG] = RBCE_TERM_TAG,
169         [RBCE_RULE_IPV4] = RBCE_TERM_IPV4,
170         [RBCE_RULE_IPV6] = RBCE_TERM_IPV6,
171         [RBCE_RULE_DEP_RULE] = -1
172 };
173
174 #define TERMOP_2_TERMFLAG(x)    (1 << termop_2_vecidx[x])
175 #define TERM_2_TERMFLAG(x)              (1 << x)
176
177 #define POLICY_INC_NUMTERMS     (BITS_PER_LONG) // No. of terms added at a time
178 #define POLICY_ACTION_NEW_VERSION       0x01    // Force reallocation
179 #define POLICY_ACTION_REDO_ALL          0x02    // Recompute all rule flags
180 #define POLICY_ACTION_PACK_TERMS        0x04    // Time to pack the terms
181
182 const int use_persistent_state = 1;
183
184 struct ckrm_eng_callback ckrm_ecbs;
185
186 // Term vector state
187 //
188 static int gl_bitmap_version, gl_action, gl_num_terms;
189 static int gl_allocated, gl_released;
190 struct rbce_rule_term *gl_terms;
191 bitvector_t *gl_mask_vecs[NUM_TERM_MASK_VECTOR];
192
193 extern int errno;
194 static void optimize_policy(void);
195
196 #ifndef CKRM_MAX_CLASSTYPES
197 #define CKRM_MAX_CLASSTYPES 32
198 #endif
199
200 struct list_head rules_list[CKRM_MAX_CLASSTYPES];
201 LIST_HEAD(class_list);          // List of classes used
202
203 static int gl_num_rules;
204 static int gl_rules_version;
205 int rbce_enabled = 1;
206 static rwlock_t global_rwlock = RW_LOCK_UNLOCKED;
207         /*
208          * One lock to protect them all !!!
209          * Additions, deletions to rules must
210          * happen with this lock being held in write mode.
211          * Access(read/write) to any of the data structures must happen 
212          * with this lock held in read mode.
213          * Since, rule related changes do not happen very often it is ok to
214          * have single rwlock.
215          */
216
217 /*
218  * data structure rbce_private_data holds the bit vector 'eval' which 
219  * specifies if rules and terms of rules are evaluated against the task
220  * and if they were evaluated, bit vector 'true' holds the result of that
221  * evaluation.
222  *
223  * This data structure is maintained in a task, and the bitvectors are
224  * updated only when needed.
225  *
226  * Each rule and each term of a rule has a corresponding bit in the vector.
227  *
228  */
229 struct rbce_private_data {
230         struct rbce_ext_private_data ext_data;
231         int evaluate;           // whether to evaluate rules or not ?
232         int rules_version;      // whether to evaluate rules or not ?
233         char *app_tag;
234         unsigned long bitmap_version;
235         bitvector_t *eval;
236         bitvector_t *true;
237         char data[0];           // eval points to this variable size data array
238 };
239
240 #define RBCE_DATA(tsk) ((struct rbce_private_data*)((tsk)->ce_data))
241 #define RBCE_DATAP(tsk) ((tsk)->ce_data)
242
243 /* ======================= DEBUG  Functions ========================= */
244
245 #ifdef DEBUG
246
247 int rbcedebug = 0x00;
248
249 #define DBG_CLASSIFY_RES     ( 0x01 )
250 #define DBG_CLASSIFY_DETAILS ( 0x02 )
251 #define DBG_OPTIMIZATION     ( 0x04 )
252 #define DBG_SHOW_RESCTL      ( 0x08 )
253 #define DBG_CLASS            ( 0x10 )
254 #define DBG_RULE             ( 0x20 )
255 #define DBG_POLICY           ( 0x40 )
256
257 #define DPRINTK(x, y...)   if (rbcedebug & (x)) printk(KERN_DEBUG y)
258         // debugging selectively enabled through /proc/sys/debug/rbce
259
260 static void print_context_vectors(void)
261 {
262         int i;
263
264         if ((rbcedebug & DBG_OPTIMIZATION) == 0) {
265                 return;
266         }
267         for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
268                 printk(KERN_DEBUG "%d: ", i);
269                 bitvector_print(DBG_OPTIMIZATION, gl_mask_vecs[i]);
270                 printk(KERN_DEBUG "\n");
271         }
272 }
273 #else
274
275 #define DPRINTK(x, y...)
276 #define print_context_vectors(x)
277 #endif
278
279 /* ====================== VSERVER support ========================== */
280 #define CONFIG_VSERVER
281 #ifdef CONFIG_VSERVER 
282 #include <linux/vs_base.h>
283 #else
284 typedef unsigned int xid_t;
285 #define vx_task_xid(t)  (0)
286 #endif 
287
288 /* ======================= Helper Functions ========================= */
289
290 #include "token.c"
291
292 static struct ckrm_core_class *rbce_classify(struct task_struct *,
293                                              struct ckrm_net_struct *,
294                                              unsigned long, int classtype);
295
296 static inline struct rbce_rule *find_rule_name(const char *name)
297 {
298         struct named_obj_hdr *pos;
299         int i;
300
301         for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
302                 list_for_each_entry(pos, &rules_list[i], link) {
303                         if (!strcmp(pos->name, name)) {
304                                 return ((struct rbce_rule *)pos);
305                         }
306                 }
307         }
308         return NULL;
309 }
310
311 static inline struct rbce_class *find_class_name(const char *name)
312 {
313         struct named_obj_hdr *pos;
314
315         list_for_each_entry(pos, &class_list, link) {
316                 if (!strcmp(pos->name, name))
317                         return (struct rbce_class *)pos;
318         }
319         return NULL;
320 }
321
322 /*
323  * Insert the given rule at the specified order
324  *              order = -1 ==> insert at the tail.
325  *
326  * Caller must hold global_rwlock in write mode.
327  */
328 static int insert_rule(struct rbce_rule *rule, int order)
329 {
330 #define ORDER_COUNTER_INCR 10
331         static int order_counter;
332         int old_counter;
333         struct list_head *head = &rules_list[rule->classtype];
334         struct list_head *insert = head;
335         struct rbce_rule *tmp;
336
337         if (gl_num_rules == 0) {
338                 order_counter = 0;
339         }
340
341         switch (order) {
342         case -1:
343                 rule->order = order_counter;
344                 // FIXME: order_counter overflow/wraparound!!
345                 order_counter += ORDER_COUNTER_INCR;
346                 break;
347         default:
348                 old_counter = order_counter;
349                 if (order_counter < order) {
350                         order_counter = order;
351                 }
352                 rule->order = order;
353                 order_counter += ORDER_COUNTER_INCR;
354                 list_for_each_entry(tmp, head, obj.link) {
355                         if (rule->order == tmp->order) {
356                                 order_counter = old_counter;
357                                 return -EEXIST;
358                         }
359                         if (rule->order < tmp->order) {
360                                 insert = &tmp->obj.link;
361                                 break;
362                         }
363                 }
364         }
365         list_add_tail(&rule->obj.link, insert);
366         // protect the module from removed when any rule is
367         // defined
368         try_module_get(THIS_MODULE);
369         gl_num_rules++;
370         gl_rules_version++;
371         return 0;
372 }
373
374 /*
375  * Remove the rule and reinsert at the specified order.
376  *
377  * Caller must hold global_rwlock in write mode.
378  */
379 static int reinsert_rule(struct rbce_rule *rule, int order)
380 {
381         list_del(&rule->obj.link);
382         gl_num_rules--;
383         gl_rules_version++;
384         module_put(THIS_MODULE);
385         return insert_rule(rule, order);
386 }
387
388 /*
389  * Get a refernece to the class, create one if it doesn't exist
390  *
391  * Caller need to hold global_rwlock in write mode.
392  * __GFP_WAIT
393  */
394
395 static struct rbce_class *create_rbce_class(const char *classname,
396                                             int classtype, void *classobj)
397 {
398         struct rbce_class *cls;
399
400         if (classtype >= CKRM_MAX_CLASSTYPES) {
401                 printk(KERN_ERR
402                        "ckrm_classobj returned %d as classtype which cannot "
403                        " be handled by RBCE\n", classtype);
404                 return NULL;
405         }
406
407         cls = kmalloc(sizeof(struct rbce_class), GFP_ATOMIC);
408         if (!cls) {
409                 return NULL;
410         }
411         cls->obj.name = kmalloc(strlen(classname) + 1, GFP_ATOMIC);
412         if (cls->obj.name) {
413                 GET_REF(cls) = 1;
414                 cls->classobj = classobj;
415                 strcpy(cls->obj.name, classname);
416                 list_add_tail(&cls->obj.link, &class_list);
417                 cls->classtype = classtype;
418         } else {
419                 kfree(cls);
420                 cls = NULL;
421         }
422         return cls;
423 }
424
425 static struct rbce_class *get_class(char *classname, int *classtype)
426 {
427         struct rbce_class *cls;
428         void *classobj;
429
430         if (!classname) {
431                 return NULL;
432         }
433         cls = find_class_name(classname);
434         if (cls) {
435                 if (cls->classobj) {
436                         INC_REF(cls);
437                         *classtype = cls->classtype;
438                         return cls;
439                 }
440                 return NULL;
441         }
442         classobj = ckrm_classobj(classname, classtype);
443         if (!classobj) {
444                 return NULL;
445         }
446
447         return create_rbce_class(classname, *classtype, classobj);
448 }
449
450 /*
451  * Drop a refernece to the class, create one if it doesn't exist
452  *
453  * Caller need to hold global_rwlock in write mode.
454  */
455 static void put_class(struct rbce_class *cls)
456 {
457         if (cls) {
458                 if (DEC_REF(cls) <= 0) {
459                         list_del(&cls->obj.link);
460                         kfree(cls->obj.name);
461                         kfree(cls);
462                 }
463         }
464         return;
465 }
466
467 /*
468  * Callback from core when a class is added
469  */
470
471 #ifdef RBCE_EXTENSION
472 static void rbce_class_addcb(const char *classname, void *clsobj, int classtype)
473 {
474         struct rbce_class *cls;
475
476         write_lock(&global_rwlock);
477         cls = find_class_name((char *)classname);
478         if (cls) {
479                 cls->classobj = clsobj;
480         } else {
481                 cls = create_rbce_class(classname, classtype, clsobj);
482         }
483         if (cls)
484                 notify_class_action(cls, 1);
485         write_unlock(&global_rwlock);
486         return;
487 }
488 #endif
489
490 /*
491  * Callback from core when a class is deleted.
492  */
493 static void
494 rbce_class_deletecb(const char *classname, void *classobj, int classtype)
495 {
496         static struct rbce_class *cls;
497         struct named_obj_hdr *pos;
498         struct rbce_rule *rule;
499
500         write_lock(&global_rwlock);
501         cls = find_class_name(classname);
502         if (cls) {
503                 if (cls->classobj != classobj) {
504                         printk(KERN_ERR "rbce: class %s changed identity\n",
505                                classname);
506                 }
507                 notify_class_action(cls, 0);
508                 cls->classobj = NULL;
509                 list_for_each_entry(pos, &rules_list[classtype], link) {
510                         rule = (struct rbce_rule *)pos;
511                         if (rule->target_class) {
512                                 if (!strcmp
513                                     (rule->target_class->obj.name, classname)) {
514                                         put_class(cls);
515                                         rule->target_class = NULL;
516                                         rule->classtype = -1;
517                                 }
518                         }
519                 }
520                 if ((cls = find_class_name(classname)) != NULL) {
521                         printk(KERN_ERR
522                                "rbce ERROR: class %s exists in rbce after "
523                                "removal in core\n", classname);
524                 }
525         }
526         write_unlock(&global_rwlock);
527         return;
528 }
529
530 /*
531  * Allocate an index in the global term vector
532  * On success, returns the index. On failure returns -errno.
533  * Caller must hold the global_rwlock in write mode as global data is
534  * written onto.
535  */
536 static int alloc_term_index(void)
537 {
538         int size = gl_allocated;
539
540         if (gl_num_terms >= size) {
541                 int i;
542                 struct rbce_rule_term *oldv, *newv;
543                 int newsize = size + POLICY_INC_NUMTERMS;
544
545                 oldv = gl_terms;
546                 newv =
547                     kmalloc(newsize * sizeof(struct rbce_rule_term),
548                             GFP_ATOMIC);
549                 if (!newv) {
550                         return -ENOMEM;
551                 }
552                 memcpy(newv, oldv, size * sizeof(struct rbce_rule_term));
553                 for (i = size; i < newsize; i++) {
554                         newv[i].op = -1;
555                 }
556                 gl_terms = newv;
557                 gl_allocated = newsize;
558                 kfree(oldv);
559
560                 gl_action |= POLICY_ACTION_NEW_VERSION;
561                 DPRINTK(DBG_OPTIMIZATION,
562                         "alloc_term_index: Expanding size from %d to %d\n",
563                         size, newsize);
564         }
565         return gl_num_terms++;
566 }
567
568 /*
569  * Release an index in the global term vector
570  *
571  * Caller must hold the global_rwlock in write mode as the global data
572  * is written onto.
573  */
574 static void release_term_index(int idx)
575 {
576         if ((idx < 0) || (idx > gl_num_terms))
577                 return;
578
579         gl_terms[idx].op = -1;
580         gl_released++;
581         if ((gl_released > POLICY_INC_NUMTERMS) &&
582             (gl_allocated >
583              (gl_num_terms - gl_released + POLICY_INC_NUMTERMS))) {
584                 gl_action |= POLICY_ACTION_PACK_TERMS;
585         }
586         return;
587 }
588
589 /*
590  * Release the indices, string memory, and terms associated with the given
591  * rule.
592  *
593  * Caller should be holding global_rwlock
594  */
595 static void __release_rule(struct rbce_rule *rule)
596 {
597         int i, *terms = rule->terms;
598
599         // remove memory and references from other rules
600         for (i = rule->num_terms; --i >= 0;) {
601                 struct rbce_rule_term *term = &gl_terms[terms[i]];
602
603                 if (term->op == RBCE_RULE_DEP_RULE) {
604                         DEC_REF(term->u.deprule);
605                 }
606                 release_term_index(terms[i]);
607         }
608         rule->num_terms = 0;
609         if (rule->strtab) {
610                 kfree(rule->strtab);
611                 rule->strtab = NULL;
612         }
613         if (rule->terms) {
614                 kfree(rule->terms);
615                 rule->terms = NULL;
616         }
617         return;
618 }
619
620 /*
621  * delete the given rule and all memory associated with it.
622  *
623  * Caller is responsible for protecting the global data
624  */
625 static inline int __delete_rule(struct rbce_rule *rule)
626 {
627         // make sure we are not referenced by other rules
628         if (GET_REF(rule)) {
629                 return -EBUSY;
630         }
631         __release_rule(rule);
632         put_class(rule->target_class);
633         release_term_index(rule->index);
634         list_del(&rule->obj.link);
635         gl_num_rules--;
636         gl_rules_version++;
637         module_put(THIS_MODULE);
638         kfree(rule->obj.name);
639         kfree(rule);
640         return 0;
641 }
642
643 /*
644  * Optimize the rule evaluation logic
645  *
646  * Caller must hold global_rwlock in write mode.
647  */
648 static void optimize_policy(void)
649 {
650         int i, ii;
651         struct rbce_rule *rule;
652         struct rbce_rule_term *terms;
653         int num_terms;
654         int bsize;
655         bitvector_t **mask_vecs;
656         int pack_terms = 0;
657         int redoall;
658
659         /*
660          * Due to dynamic rule addition/deletion of rules the term
661          * vector can get sparse. As a result the bitvectors grow as we don't
662          * reuse returned indices. If it becomes sparse enough we pack them
663          * closer.
664          */
665
666         pack_terms = (gl_action & POLICY_ACTION_PACK_TERMS);
667         DPRINTK(DBG_OPTIMIZATION,
668                 "----- Optimize Policy ----- act=%x pt=%d (a=%d n=%d r=%d)\n",
669                 gl_action, pack_terms, gl_allocated, gl_num_terms, gl_released);
670
671         if (pack_terms) {
672                 int nsz = ALIGN((gl_num_terms - gl_released),
673                                 POLICY_INC_NUMTERMS);
674                 int newidx = 0;
675                 struct rbce_rule_term *newterms;
676
677                 terms = gl_terms;
678                 newterms =
679                     kmalloc(nsz * sizeof(struct rbce_rule_term), GFP_ATOMIC);
680                 if (newterms) {
681                         for (ii = 0; ii < CKRM_MAX_CLASSTYPES; ii++) {
682                                 // FIXME: check only for task class types
683                                 list_for_each_entry_reverse(rule,
684                                                             &rules_list[ii],
685                                                             obj.link) {
686                                         rule->index = newidx++;
687                                         for (i = rule->num_terms; --i >= 0;) {
688                                                 int idx = rule->terms[i];
689                                                 newterms[newidx] = terms[idx];
690                                                 rule->terms[i] = newidx++;
691                                         }
692                                 }
693                         }
694                         kfree(terms);
695                         gl_allocated = nsz;
696                         gl_released = 0;
697                         gl_num_terms = newidx;
698                         gl_terms = newterms;
699
700                         gl_action &= ~POLICY_ACTION_PACK_TERMS;
701                         gl_action |= POLICY_ACTION_NEW_VERSION;
702                 }
703         }
704
705         num_terms = gl_num_terms;
706         bsize = gl_allocated / 8 + sizeof(bitvector_t);
707         mask_vecs = gl_mask_vecs;
708         terms = gl_terms;
709
710         if (gl_action & POLICY_ACTION_NEW_VERSION) {
711                 /* allocate new mask vectors */
712                 char *temp = kmalloc(NUM_TERM_MASK_VECTOR * bsize, GFP_ATOMIC);
713
714                 DPRINTK(DBG_OPTIMIZATION,
715                         "------ allocmasks act=%x -------  ver=%d\n", gl_action,
716                         gl_bitmap_version);
717                 if (!temp) {
718                         return;
719                 }
720                 if (mask_vecs[0]) {// index 0 has the alloc returned address
721                         kfree(mask_vecs[0]);
722                 }
723                 for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
724                         mask_vecs[i] = (bitvector_t *) (temp + i * bsize);
725                         bitvector_init(mask_vecs[i], gl_allocated);
726                 }
727                 gl_action &= ~POLICY_ACTION_NEW_VERSION;
728                 gl_action |= POLICY_ACTION_REDO_ALL;
729                 gl_bitmap_version++;
730         }
731
732         /* We do two things here at once
733          * 1) recompute the rulemask for each required rule
734          *      we guarantee proper dependency order during creation time and
735          *      by reversely running through this list. 
736          * 2) recompute the mask for each term and rule, if required
737          */
738
739         redoall = gl_action & POLICY_ACTION_REDO_ALL;
740         gl_action &= ~POLICY_ACTION_REDO_ALL;
741
742         DPRINTK(DBG_OPTIMIZATION, "------- run act=%x --------  redoall=%d\n",
743                 gl_action, redoall);
744         for (ii = 0; ii < CKRM_MAX_CLASSTYPES; ii++) {
745                 // FIXME: check only for task class types
746                 list_for_each_entry_reverse(rule, &rules_list[ii], obj.link) {
747                         unsigned long termflag;
748
749                         if (!redoall && !rule->do_opt)
750                                 continue;
751                         termflag = 0;
752                         for (i = rule->num_terms; --i >= 0;) {
753                                 int j, idx = rule->terms[i];
754                                 struct rbce_rule_term *term = &terms[idx];
755                                 int vecidx = termop_2_vecidx[term->op];
756                                 
757                                 if (vecidx == -1) {
758                                         termflag |= term->u.deprule->termflag;
759                                         /* mark this term belonging to all 
760                                            contexts of deprule */
761                                         for (j = 0; j < NUM_TERM_MASK_VECTOR;
762                                              j++) {
763                                                 if (term->u.deprule->termflag 
764                                                     & (1 << j)) {
765                                                         bitvector_set(idx,
766                                                                       mask_vecs
767                                                                       [j]);
768                                                 }
769                                         }
770                                 } else {
771                                         termflag |= TERM_2_TERMFLAG(vecidx);
772                                         /* mark this term belonging to 
773                                            a particular context */
774                                         bitvector_set(idx, mask_vecs[vecidx]);
775                                 }
776                         }
777                         for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
778                                 if (termflag & (1 << i)) {
779                                         bitvector_set(rule->index,
780                                                       mask_vecs[i]);
781                                 }
782                         }
783                         rule->termflag = termflag;
784                         rule->do_opt = 0;
785                         DPRINTK(DBG_OPTIMIZATION, "r-%s: %x %d\n",
786                                 rule->obj.name, rule->termflag, rule->index);
787                 }
788         }
789         print_context_vectors();
790         return;
791 }
792
793 /* ======================= Rule related Functions ========================= */
794
795 /*
796  * Caller need to hold global_rwlock in write mode.
797  */
798 static int
799 fill_rule(struct rbce_rule *newrule, struct rbce_rule_term *terms, int nterms)
800 {
801         char *class, *strtab;
802         int i, j, order, state, real_nterms, index;
803         int strtablen, rc = 0, counter;
804         struct rbce_rule_term *term = NULL;
805         struct rbce_class *targetcls = NULL;
806         struct rbce_rule *deprule;
807
808         if (!newrule) {
809                 return -EINVAL;
810         }
811         // Digest filled terms.
812         real_nterms = 0;
813         strtab = class = NULL;
814         strtablen = 0;
815         state = -1;
816         order = -1;
817         index = -1;
818         for (i = 0; i < nterms; i++) {
819                 if (terms[i].op != RBCE_RULE_INVALID) {
820                         real_nterms++;
821
822                         switch (terms[i].op) {
823                         case RBCE_RULE_DEP_RULE:
824                                 // check if the depend rule is valid
825                                 //
826                                 deprule = find_rule_name(terms[i].u.string);
827                                 if (!deprule || deprule == newrule) {
828                                         rc = -EINVAL;
829                                         goto out;
830                                 } else {
831                                         // make sure _a_ depend rule 
832                                         // appears in only one term.
833                                         for (j = 0; j < i; j++) {
834                                                 if (terms[j].op ==
835                                                     RBCE_RULE_DEP_RULE
836                                                     && terms[j].u.deprule ==
837                                                     deprule) {
838                                                         rc = -EINVAL;
839                                                         goto out;
840                                                 }
841                                         }
842                                         terms[i].u.deprule = deprule;
843                                 }
844
845                                 // +depend is acceptable and -depend is not
846                                 if (terms[i].operator != TOKEN_OP_DEP_DEL) {
847                                         terms[i].operator = RBCE_EQUAL;
848                                 } else {
849                                         rc = -EINVAL;
850                                         goto out;
851                                 }
852                                 break;
853
854                         case RBCE_RULE_CMD_PATH:
855                         case RBCE_RULE_CMD:
856                         case RBCE_RULE_ARGS:
857                         case RBCE_RULE_APP_TAG:
858                         case RBCE_RULE_IPV4:
859                         case RBCE_RULE_IPV6:
860                                 // sum up the string length
861                                 strtablen += strlen(terms[i].u.string) + 1;
862                                 break;
863                         default:
864                                 break;
865
866                         }
867                 } else {
868                         switch (terms[i].operator) {
869                         case TOKEN_OP_ORDER:
870                                 order = terms[i].u.id;
871                                 if (order < 0) {
872                                         rc = -EINVAL;
873                                         goto out;
874                                 }
875                                 break;
876                         case TOKEN_OP_STATE:
877                                 state = terms[i].u.id != 0;
878                                 break;
879                         case TOKEN_OP_CLASS:
880                                 class = terms[i].u.string;
881                                 break;
882                         default:
883                                 break;
884                         }
885                 }
886         }
887
888         // Check if class was specified
889         if (class != NULL) {
890                 int classtype;
891                 if ((targetcls = get_class(class, &classtype)) == NULL) {
892                         rc = -EINVAL;
893                         goto out;
894                 }
895                 put_class(newrule->target_class);
896
897                 newrule->target_class = targetcls;
898                 newrule->classtype = classtype;
899         }
900         if (!newrule->target_class) {
901                 rc = -EINVAL;
902                 goto out;
903         }
904
905         if (state != -1) {
906                 newrule->state = state;
907         }
908         if (order != -1) {
909                 newrule->order = order;
910         }
911         newrule->terms = kmalloc(real_nterms * sizeof(int), GFP_ATOMIC);
912         if (!newrule->terms) {
913                 rc = -ENOMEM;
914                 goto out;
915         }
916         newrule->num_terms = real_nterms;
917         if (strtablen && ((strtab = kmalloc(strtablen, GFP_ATOMIC)) == NULL)) {
918                 rc = -ENOMEM;
919                 goto out;
920         }
921
922         if (newrule->index == -1) {
923                 index = alloc_term_index();
924                 if (index < 0) {
925                         rc = -ENOMEM;
926                         goto out;
927                 }
928                 newrule->index = index;
929                 term = &gl_terms[newrule->index];
930                 term->op = RBCE_RULE_DEP_RULE;
931                 term->u.deprule = newrule;
932         }
933         newrule->strtab = strtab;
934         newrule->termflag = 0;
935
936         // Fill the term vector
937         strtablen = 0;
938         counter = 0;
939         for (i = 0; i < nterms; i++) {
940                 if (terms[i].op == RBCE_RULE_INVALID) {
941                         continue;
942                 }
943
944                 newrule->terms[counter] = alloc_term_index();
945                 if (newrule->terms[counter] < 0) {
946                         for (j = 0; j < counter; j++) {
947                                 release_term_index(newrule->terms[j]);
948                         }
949                         rc = -ENOMEM;
950                         goto out;
951                 }
952                 term = &gl_terms[newrule->terms[counter]];
953                 term->op = terms[i].op;
954                 term->operator = terms[i].operator;
955                 switch (terms[i].op) {
956                 case RBCE_RULE_CMD_PATH:
957                 case RBCE_RULE_CMD:
958                 case RBCE_RULE_ARGS:
959                 case RBCE_RULE_APP_TAG:
960                 case RBCE_RULE_IPV4:
961                 case RBCE_RULE_IPV6:
962                         term->u.string = &strtab[strtablen];
963                         strcpy(term->u.string, terms[i].u.string);
964                         strtablen = strlen(term->u.string) + 1;
965                         break;
966
967                 case RBCE_RULE_REAL_UID:
968                 case RBCE_RULE_REAL_GID:
969                 case RBCE_RULE_EFFECTIVE_UID:
970                 case RBCE_RULE_EFFECTIVE_GID:
971                 case RBCE_RULE_XID:
972                         term->u.id = terms[i].u.id;
973                         break;
974
975                 case RBCE_RULE_DEP_RULE:
976                         term->u.deprule = terms[i].u.deprule;
977                         INC_REF(term->u.deprule);
978                         break;
979                 default:
980                         break;
981                 }
982                 counter++;
983         }
984
985       out:
986         if (rc) {
987                 if (targetcls) {
988                         put_class(targetcls);
989                 }
990                 if (index >= 0) {
991                         release_term_index(index);
992                 }
993                 kfree(newrule->terms);
994                 kfree(strtab);
995
996         }
997         return rc;
998 }
999
1000 int change_rule(const char *rname, char *rdefn)
1001 {
1002         struct rbce_rule *rule = NULL, *deprule;
1003         struct rbce_rule_term *new_terms = NULL, *term, *terms;
1004         int nterms, new_term_mask = 0, oterms, tot_terms;
1005         int i, j, k, rc, new_order = 0;
1006
1007         if ((nterms = rules_parse(rdefn, &new_terms, &new_term_mask)) <= 0) {
1008                 return !nterms ? -EINVAL : nterms;
1009         }
1010
1011         write_lock(&global_rwlock);
1012         rule = find_rule_name(rname);
1013         if (rule == NULL) {
1014                 rule = kmalloc(sizeof(struct rbce_rule), GFP_ATOMIC);
1015                 if (rule) {
1016                         rule->obj.name = kmalloc(strlen(rname) + 1, GFP_ATOMIC);
1017                         if (rule->obj.name) {
1018                                 strcpy(rule->obj.name, rname);
1019                                 GET_REF(rule) = 0;
1020                                 rule->order = -1;
1021                                 rule->index = -1;
1022                                 rule->state = RBCE_RULE_ENABLED;
1023                                 rule->target_class = NULL;
1024                                 rule->classtype = -1;
1025                                 rule->terms = NULL;
1026                                 rule->do_opt = 1;
1027                                 INIT_LIST_HEAD(&rule->obj.link);
1028                                 rc = fill_rule(rule, new_terms, nterms);
1029                                 if (rc) {
1030                                         kfree(rule);
1031                                 } else {
1032                                         if ((rc =
1033                                              insert_rule(rule,
1034                                                          rule->order)) == 0) {
1035                                                 if (rbce_enabled) {
1036                                                         optimize_policy();
1037                                                 }
1038                                         } else {
1039                                                 __delete_rule(rule);
1040                                         }
1041                                 }
1042                         } else {
1043                                 kfree(rule);
1044                                 rc = -ENOMEM;
1045                         }
1046                         kfree(new_terms);
1047                 } else {
1048                         rc = -ENOMEM;
1049                 }
1050                 write_unlock(&global_rwlock);
1051                 return rc;
1052         }
1053
1054         oterms = rule->num_terms;
1055         tot_terms = nterms + oterms;
1056
1057         terms = kmalloc(tot_terms * sizeof(struct rbce_rule_term), GFP_ATOMIC);
1058
1059         if (!terms) {
1060                 kfree(new_terms);
1061                 write_unlock(&global_rwlock);
1062                 return -ENOMEM;
1063         }
1064
1065         new_term_mask &= ~(1 << RBCE_RULE_DEP_RULE);
1066         //ignore the new deprule terms for the first iteration.
1067         // taken care of later.
1068         for (i = 0; i < oterms; i++) {
1069                 term = &gl_terms[rule->terms[i]];       // old term
1070
1071                 if ((1 << term->op) & new_term_mask) {  
1072                         // newrule has this attr/value
1073                         for (j = 0; j < nterms; j++) {
1074                                 if (term->op == new_terms[j].op) {
1075                                         terms[i].op = new_terms[j].op;
1076                                         terms[i].operator = new_terms[j].
1077                                             operator;
1078                                         terms[i].u.string =
1079                                             new_terms[j].u.string;
1080                                         new_terms[j].op = RBCE_RULE_INVALID2;
1081                                         break;
1082                                 }
1083                         }
1084                 } else {
1085                         terms[i].op = term->op;
1086                         terms[i].operator = term->operator;
1087                         terms[i].u.string = term->u.string;
1088                 }
1089         }
1090
1091         i = oterms;             // for readability
1092
1093         for (j = 0; j < nterms; j++) {
1094                 // handled in the previous iteration
1095                 if (new_terms[j].op == RBCE_RULE_INVALID2) {
1096                         continue;
1097                 }
1098
1099                 if (new_terms[j].op == RBCE_RULE_DEP_RULE) {
1100                         if (new_terms[j].operator == TOKEN_OP_DEP) {
1101                                 // "depend=rule" deletes all depends in the 
1102                                 // original rule so, delete all depend rule 
1103                                 // terms in the original rule
1104                                 for (k = 0; k < oterms; k++) {
1105                                         if (terms[k].op == RBCE_RULE_DEP_RULE) {
1106                                                 terms[k].op = RBCE_RULE_INVALID;
1107                                         }
1108                                 }
1109                                 // must copy the new deprule term
1110                         } else {
1111                                 // delete the depend rule term if was defined 
1112                                 // in the original rule for both +depend 
1113                                 // and -depend
1114                                 deprule = find_rule_name(new_terms[j].u.string);
1115                                 if (deprule) {
1116                                         for (k = 0; k < oterms; k++) {
1117                                                 if (terms[k].op ==
1118                                                     RBCE_RULE_DEP_RULE
1119                                                     && terms[k].u.deprule ==
1120                                                     deprule) {
1121                                                         terms[k].op =
1122                                                             RBCE_RULE_INVALID;
1123                                                         break;
1124                                                 }
1125                                         }
1126                                 }
1127                                 if (new_terms[j].operator == TOKEN_OP_DEP_DEL) {
1128                                         // No need to copy the new deprule term
1129                                         continue;
1130                                 }
1131                         }
1132                 } else {
1133                         if ((new_terms[j].op == RBCE_RULE_INVALID) &&
1134                             (new_terms[j].operator == TOKEN_OP_ORDER)) {
1135                                 new_order++;
1136                         }
1137                 }
1138                 terms[i].op = new_terms[j].op;
1139                 terms[i].operator = new_terms[j].operator;
1140                 terms[i].u.string = new_terms[j].u.string;
1141                 i++;
1142                 new_terms[j].op = RBCE_RULE_INVALID2;
1143         }
1144
1145         tot_terms = i;
1146
1147         // convert old deprule pointers to name pointers.
1148         for (i = 0; i < oterms; i++) {
1149                 if (terms[i].op != RBCE_RULE_DEP_RULE)
1150                         continue;
1151                 terms[i].u.string = terms[i].u.deprule->obj.name;
1152         }
1153
1154         // release the rule
1155         __release_rule(rule);
1156
1157         rule->do_opt = 1;
1158         rc = fill_rule(rule, terms, tot_terms);
1159         if (rc == 0 && new_order) {
1160                 rc = reinsert_rule(rule, rule->order);
1161         }
1162         if (rc != 0) {          // rule creation/insertion failed
1163                 __delete_rule(rule);
1164         }
1165         if (rbce_enabled) {
1166                 optimize_policy();
1167         }
1168         write_unlock(&global_rwlock);
1169         kfree(new_terms);
1170         kfree(terms);
1171         return rc;
1172 }
1173
1174 /*
1175  * Delete the specified rule.
1176  *
1177  */
1178 int delete_rule(const char *rname)
1179 {
1180         int rc = 0;
1181         struct rbce_rule *rule;
1182
1183         write_lock(&global_rwlock);
1184
1185         if ((rule = find_rule_name(rname)) == NULL) {
1186                 write_unlock(&global_rwlock);
1187                 goto out;
1188         }
1189         rc = __delete_rule(rule);
1190         if (rbce_enabled && (gl_action & POLICY_ACTION_PACK_TERMS)) {
1191                 optimize_policy();
1192         }
1193         write_unlock(&global_rwlock);
1194       out:
1195         DPRINTK(DBG_RULE, "delete rule %s\n", rname);
1196         return rc;
1197 }
1198
1199 /*
1200  * copy the rule specified by rname and to the given result string.
1201  *
1202  */
1203 void get_rule(const char *rname, char *result)
1204 {
1205         int i;
1206         struct rbce_rule *rule;
1207         struct rbce_rule_term *term;
1208         char *cp = result, oper, idtype[3], str[5];
1209
1210         read_lock(&global_rwlock);
1211
1212         rule = find_rule_name(rname);
1213         if (rule != NULL) {
1214                 for (i = 0; i < rule->num_terms; i++) {
1215                         term = gl_terms + rule->terms[i];
1216                         switch (term->op) {
1217                         case RBCE_RULE_REAL_UID:
1218                                 strcpy(idtype, "u");
1219                                 goto handleid;
1220                         case RBCE_RULE_REAL_GID:
1221                                 strcpy(idtype, "g");
1222                                 goto handleid;
1223                         case RBCE_RULE_EFFECTIVE_UID:
1224                                 strcpy(idtype, "eu");
1225                                 goto handleid;
1226                         case RBCE_RULE_EFFECTIVE_GID:
1227                                 strcpy(idtype, "eg");
1228                                 goto handleid;
1229                         case RBCE_RULE_XID:
1230                                 strcpy(idtype, "x");
1231                               handleid:
1232                                 if (term->operator == RBCE_LESS_THAN) {
1233                                         oper = '<';
1234                                 } else if (term->operator == RBCE_GREATER_THAN) {
1235                                         oper = '>';
1236                                 } else if (term->operator == RBCE_NOT) {
1237                                         oper = '!';
1238                                 } else {
1239                                         oper = '=';
1240                                 }
1241                                 cp +=
1242                                     sprintf(cp, "%sid%c%ld,", idtype, oper,
1243                                             term->u.id);
1244                                 break;
1245                         case RBCE_RULE_CMD_PATH:
1246                                 strcpy(str, "path");
1247                                 goto handle_str;
1248                         case RBCE_RULE_CMD:
1249                                 strcpy(str, "cmd");
1250                                 goto handle_str;
1251                         case RBCE_RULE_ARGS:
1252                                 strcpy(str, "args");
1253                                 goto handle_str;
1254                         case RBCE_RULE_APP_TAG:
1255                                 strcpy(str, "tag");
1256                                 goto handle_str;
1257                         case RBCE_RULE_IPV4:
1258                                 strcpy(str, "ipv4");
1259                                 goto handle_str;
1260                         case RBCE_RULE_IPV6:
1261                                 strcpy(str, "ipv6");
1262                               handle_str:
1263                                 cp +=
1264                                     sprintf(cp, "%s=%s,", str, term->u.string);
1265                                 break;
1266                         case RBCE_RULE_DEP_RULE:
1267                                 cp +=
1268                                     sprintf(cp, "depend=%s,",
1269                                             term->u.deprule->obj.name);
1270                                 break;
1271                         default:
1272                                 break;
1273                         }
1274                 }
1275                 if (!rule->num_terms) {
1276                         cp += sprintf(cp, "***** no terms defined ***** ");
1277                 }
1278
1279                 cp +=
1280                     sprintf(cp, "order=%d,state=%d,", rule->order, rule->state);
1281                 cp +=
1282                     sprintf(cp, "class=%s",
1283                             rule->target_class ? rule->target_class->obj.
1284                             name : "***** REMOVED *****");
1285                 *cp = '\0';
1286         } else {
1287                 sprintf(result, "***** Rule %s doesn't exist *****", rname);
1288         }
1289
1290         read_unlock(&global_rwlock);
1291         return;
1292 }
1293
1294 /*
1295  * Change the name of the given rule "from_rname" to "to_rname"
1296  *
1297  */
1298 int rename_rule(const char *from_rname, const char *to_rname)
1299 {
1300         struct rbce_rule *rule;
1301         int nlen, rc = -EINVAL;
1302
1303         if (!to_rname || !*to_rname) {
1304                 return rc;
1305         }
1306         write_lock(&global_rwlock);
1307
1308         rule = find_rule_name(from_rname);
1309         if (rule != NULL) {
1310                 if ((nlen = strlen(to_rname)) > strlen(rule->obj.name)) {
1311                         char *name = kmalloc(nlen + 1, GFP_ATOMIC);
1312                         if (!name) {
1313                                 return -ENOMEM;
1314                         }
1315                         kfree(rule->obj.name);
1316                         rule->obj.name = name;
1317                 }
1318                 strcpy(rule->obj.name, to_rname);
1319                 rc = 0;
1320         }
1321         write_unlock(&global_rwlock);
1322         return rc;
1323 }
1324
1325 /*
1326  * Return TRUE if the given rule exists, FALSE otherwise
1327  *
1328  */
1329 int rule_exists(const char *rname)
1330 {
1331         struct rbce_rule *rule;
1332
1333         read_lock(&global_rwlock);
1334         rule = find_rule_name(rname);
1335         read_unlock(&global_rwlock);
1336         return rule != NULL;
1337 }
1338
1339 /*====================== Magic file handling =======================*/
1340 /*
1341  * Reclassify
1342  */
1343 static struct rbce_private_data *create_private_data(struct rbce_private_data *,
1344                                                      int);
1345
1346 static inline
1347 void reset_evaluation(struct rbce_private_data *pdata,int termflag)
1348 {
1349         /* reset TAG ruleterm evaluation results to pick up 
1350          * on next classification event
1351          */
1352         if (use_persistent_state && gl_mask_vecs[termflag]) {
1353                 bitvector_and_not( pdata->eval, pdata->eval, 
1354                                    gl_mask_vecs[termflag] );
1355                 bitvector_and_not( pdata->true, pdata->true, 
1356                                    gl_mask_vecs[termflag] );
1357         }
1358 }
1359   
1360 int set_tasktag(int pid, char *tag)
1361 {
1362         char *tp;
1363         int rc = 0;
1364         struct task_struct *tsk;
1365         struct rbce_private_data *pdata;
1366         int len;
1367
1368         if (!tag) {
1369                 return -EINVAL;
1370         }
1371         len = strlen(tag) + 1;
1372         tp = kmalloc(len, GFP_ATOMIC);
1373         if (!tp) {
1374                 return -ENOMEM;
1375         }
1376         strncpy(tp,tag,len);
1377
1378         read_lock(&tasklist_lock);
1379         if ((tsk = find_task_by_pid(pid)) == NULL) {
1380                 rc = -EINVAL;
1381                 goto out;
1382         }
1383
1384         if (unlikely(!RBCE_DATA(tsk))) {
1385                 RBCE_DATAP(tsk) = create_private_data(NULL, 0);
1386                 if (!RBCE_DATA(tsk)) {
1387                         rc = -ENOMEM;
1388                         goto out;
1389                 }
1390         }
1391         pdata = RBCE_DATA(tsk);
1392         if (pdata->app_tag) {
1393                 kfree(pdata->app_tag);
1394         }
1395         pdata->app_tag = tp;
1396         reset_evaluation(pdata,RBCE_TERMFLAG_TAG);
1397         
1398  out:
1399         read_unlock(&tasklist_lock);
1400         if (rc != 0) 
1401                 kfree(tp);
1402         return rc;
1403 }
1404
1405 /*====================== Classification Functions =======================*/
1406
1407 /*
1408  * Match the given full path name with the command expression.
1409  * This function treats the folowing 2 charaters as special if seen in
1410  * cmd_exp, all other chanracters are compared as is:
1411  *              ? - compares to any one single character
1412  *              * - compares to one or more single characters
1413  *
1414  * If fullpath is 1, tsk_comm is compared in full. otherwise only the command
1415  * name (basename(tsk_comm)) is compared.
1416  */
1417 static int match_cmd(const char *tsk_comm, const char *cmd_exp, int fullpath)
1418 {
1419         const char *c, *t, *last_ast, *cmd = tsk_comm;
1420         char next_c;
1421
1422         // get the command name if we don't have to match the fullpath
1423         if (!fullpath && ((c = strrchr(tsk_comm, '/')) != NULL)) {
1424                 cmd = c + 1;
1425         }
1426
1427         /* now faithfully assume the entire pathname is in cmd */
1428
1429         /* we now have to effectively implement a regular expression 
1430          * for now assume 
1431          *    '?'   any single character 
1432          *    '*'   one or more '?'
1433          *    rest  must match
1434          */
1435
1436         c = cmd_exp;
1437         t = cmd;
1438         if (t == NULL || c == NULL) {
1439                 return 0;
1440         }
1441
1442         last_ast = NULL;
1443         next_c = '\0';
1444
1445         while (*c && *t) {
1446                 switch (*c) {
1447                 case '?':
1448                         if (*t == '/') {
1449                                 return 0;
1450                         }
1451                         c++;
1452                         t++;
1453                         continue;
1454                 case '*':
1455                         if (*t == '/') {
1456                                 return 0;
1457                         }
1458                         // eat up all '*' in c
1459                         while (*(c + 1) == '*')
1460                                 c++;
1461                         next_c = '\0';
1462                         last_ast = c;
1463                         //t++;  // Add this for matching '*' with "one" 
1464                                 // or more chars.
1465                         while (*t && (*t != *(c + 1)) && *t != '/')
1466                                 t++;
1467                         if (*t == *(c + 1)) {
1468                                 c++;
1469                                 if (*c != '/') {
1470                                         if (*c == '?') {
1471                                                 if (*t == '/') {
1472                                                         return 0;
1473                                                 }
1474                                                 t++;
1475                                                 c++;
1476                                         }
1477                                         next_c = *c;
1478                                         if (*c) {
1479                                                 if (*t == '/') {
1480                                                         return 0;
1481                                                 }
1482                                                 t++;
1483                                                 c++;
1484                                                 if (!*c && *t)
1485                                                         c = last_ast;
1486                                         }
1487                                 } else {
1488                                         last_ast = NULL;
1489                                 }
1490                                 continue;
1491                         }
1492                         return 0;
1493                 case '/':
1494                         next_c = '\0';
1495                  /*FALLTHRU*/ default:
1496                         if (*t == *c && next_c != *t) {
1497                                 c++, t++;
1498                                 continue;
1499                         } else {
1500                                 /* reset to last asterix and 
1501                                    continue from there */
1502                                 if (last_ast) {
1503                                         c = last_ast;
1504                                 } else {
1505                                         return 0;
1506                                 }
1507                         }
1508                 }
1509         }
1510
1511         /* check for trailing "*" */
1512         while (*c == '*')
1513                 c++;
1514
1515         return (!*c && !*t);
1516 }
1517
1518 static void reverse(char *str, int n)
1519 {
1520         char s;
1521         int i, j = n - 1;
1522
1523         for (i = 0; i < j; i++, j--) {
1524                 s = str[i];
1525                 str[i] = str[j];
1526                 str[j] = s;
1527         }
1528 }
1529
1530 static int itoa(int n, char *str)
1531 {
1532         int i = 0, sz = 0;
1533
1534         do {
1535                 str[i++] = n % 10 + '0';
1536                 sz++;
1537                 n = n / 10;
1538         } while (n > 0);
1539
1540         (void)reverse(str, sz);
1541         return sz;
1542 }
1543
1544 static int v4toa(__u32 y, char *a)
1545 {
1546         int i;
1547         int size = 0;
1548
1549         for (i = 0; i < 4; i++) {
1550                 size += itoa(y & 0xff, &a[size]);
1551                 a[size++] = '.';
1552                 y >>= 8;
1553         }
1554         return --size;
1555 }
1556
1557 int match_ipv4(struct ckrm_net_struct *ns, char **string)
1558 {
1559         char *ptr = *string;
1560         int size;
1561         char a4[16];
1562
1563         size = v4toa(ns->ns_daddrv4, a4);
1564
1565         *string += size;
1566         return !strncmp(a4, ptr, size);
1567 }
1568
1569 int match_port(struct ckrm_net_struct *ns, char *ptr)
1570 {
1571         char a[5];
1572         int size = itoa(ns->ns_dport, a);
1573
1574         return !strncmp(a, ptr, size);
1575 }
1576
1577 static int __evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
1578                            struct rbce_rule *rule, bitvector_t * vec_eval,
1579                            bitvector_t * vec_true, char **filename);
1580 /*
1581  * evaluate the given task against the given rule with the vec_eval and
1582  * vec_true in context. Return 1 if the task satisfies the given rule, 0
1583  * otherwise.
1584  *
1585  * If the bit corresponding to the rule is set in the vec_eval, then the
1586  * corresponding bit in vec_true is the result. If it is not set, evaluate
1587  * the rule and set the bits in both the vectors accordingly.
1588  *
1589  * On return, filename will have the pointer to the pathname of the task's
1590  * executable, if the rule had any command related terms.
1591  *
1592  * Caller must hold the global_rwlock atleast in read mode.
1593  */
1594 static inline int
1595 evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
1596               struct rbce_rule *rule, bitvector_t * vec_eval,
1597               bitvector_t * vec_true, char **filename)
1598 {
1599         int tidx = rule->index;
1600
1601         if (!bitvector_test(tidx, vec_eval)) {
1602                 if (__evaluate_rule
1603                     (tsk, ns, rule, vec_eval, vec_true, filename)) {
1604                         bitvector_set(tidx, vec_true);
1605                 }
1606                 bitvector_set(tidx, vec_eval);
1607         }
1608         return bitvector_test(tidx, vec_true);
1609 }
1610
1611 /*
1612  * evaluate the given task against every term in the given rule with
1613  * vec_eval and vec_true in context.
1614  *
1615  * If the bit corresponding to a rule term is set in the vec_eval, then the
1616  * corresponding bit in vec_true is the result for taht particular. If it is
1617  * not set, evaluate the rule term and set the bits in both the vectors
1618  * accordingly.
1619  *
1620  * This fucntions returns true only if all terms in the rule evaluate true.
1621  *
1622  * On return, filename will have the pointer to the pathname of the task's
1623  * executable, if the rule had any command related terms.
1624  *
1625  * Caller must hold the global_rwlock atleast in read mode.
1626  */
1627 static int
1628 __evaluate_rule(struct task_struct *tsk, struct ckrm_net_struct *ns,
1629                 struct rbce_rule *rule, bitvector_t * vec_eval,
1630                 bitvector_t * vec_true, char **filename)
1631 {
1632         int i;
1633         int no_ip = 1;
1634
1635         for (i = rule->num_terms; --i >= 0;) {
1636                 int rc = 1, tidx = rule->terms[i];
1637
1638                 if (!bitvector_test(tidx, vec_eval)) {
1639                         struct rbce_rule_term *term = &gl_terms[tidx];
1640
1641                         switch (term->op) {
1642
1643                         case RBCE_RULE_CMD_PATH:
1644                         case RBCE_RULE_CMD:
1645 #if 0
1646                                 if (!*filename) {       /* get this once */
1647                                         if (((*filename =
1648                                               kmalloc(NAME_MAX,
1649                                                       GFP_ATOMIC)) == NULL)
1650                                             ||
1651                                             (get_exe_path_name
1652                                              (tsk, *filename, NAME_MAX) < 0)) {
1653                                                 rc = 0;
1654                                                 break;
1655                                         }
1656                                 }
1657                                 rc = match_cmd(*filename, term->u.string,
1658                                                (term->op ==
1659                                                 RBCE_RULE_CMD_PATH));
1660 #else
1661                                 rc = match_cmd(tsk->comm, term->u.string,
1662                                                (term->op ==
1663                                                 RBCE_RULE_CMD_PATH));
1664 #endif
1665                                 break;
1666                         case RBCE_RULE_REAL_UID:
1667                                 if (term->operator == RBCE_LESS_THAN) {
1668                                         rc = (tsk->uid < term->u.id);
1669                                 } else if (term->operator == RBCE_GREATER_THAN){
1670                                         rc = (tsk->uid > term->u.id);
1671                                 } else if (term->operator == RBCE_NOT) {
1672                                         rc = (tsk->uid != term->u.id);
1673                                 } else {
1674                                         rc = (tsk->uid == term->u.id);
1675                                 }
1676                                 break;
1677                         case RBCE_RULE_REAL_GID:
1678                                 if (term->operator == RBCE_LESS_THAN) {
1679                                         rc = (tsk->gid < term->u.id);
1680                                 } else if (term->operator == RBCE_GREATER_THAN){
1681                                         rc = (tsk->gid > term->u.id);
1682                                 } else if (term->operator == RBCE_NOT) {
1683                                         rc = (tsk->gid != term->u.id);
1684                                 } else {
1685                                         rc = (tsk->gid == term->u.id);
1686                                 }
1687                                 break;
1688                         case RBCE_RULE_EFFECTIVE_UID:
1689                                 if (term->operator == RBCE_LESS_THAN) {
1690                                         rc = (tsk->euid < term->u.id);
1691                                 } else if (term->operator == RBCE_GREATER_THAN){
1692                                         rc = (tsk->euid > term->u.id);
1693                                 } else if (term->operator == RBCE_NOT) {
1694                                         rc = (tsk->euid != term->u.id);
1695                                 } else {
1696                                         rc = (tsk->euid == term->u.id);
1697                                 }
1698                                 break;
1699                         case RBCE_RULE_EFFECTIVE_GID:
1700                                 if (term->operator == RBCE_LESS_THAN) {
1701                                         rc = (tsk->egid < term->u.id);
1702                                 } else if (term->operator == RBCE_GREATER_THAN){
1703                                         rc = (tsk->egid > term->u.id);
1704                                 } else if (term->operator == RBCE_NOT) {
1705                                         rc = (tsk->egid != term->u.id);
1706                                 } else {
1707                                         rc = (tsk->egid == term->u.id);
1708                                 }
1709                                 break;
1710                         case RBCE_RULE_APP_TAG:
1711                                 rc = (RBCE_DATA(tsk)
1712                                       && RBCE_DATA(tsk)->
1713                                       app_tag) ? !strcmp(RBCE_DATA(tsk)->
1714                                                          app_tag,
1715                                                          term->u.string) : 0;
1716                                 break;
1717                         case RBCE_RULE_DEP_RULE:
1718                                 rc = evaluate_rule(tsk, NULL, term->u.deprule,
1719                                                    vec_eval, vec_true,
1720                                                    filename);
1721                                 break;
1722
1723                         case RBCE_RULE_IPV4:
1724                                 // TBD: add NOT_EQUAL match. At present rbce
1725                                 // recognises EQUAL matches only.
1726                                 if (ns && term->operator == RBCE_EQUAL) {
1727                                         int ma = 0;
1728                                         int mp = 0;
1729                                         char *ptr = term->u.string;
1730
1731                                         if (term->u.string[0] == '*')
1732                                                 ma = 1;
1733                                         else
1734                                                 ma = match_ipv4(ns, &ptr);
1735
1736                                         if (*ptr != '\\') {     // error
1737                                                 rc = 0;
1738                                                 break;
1739                                         } else {
1740                                                 ++ptr;
1741                                                 if (*ptr == '*')
1742                                                         mp = 1;
1743                                                 else
1744                                                         mp = match_port(ns,
1745                                                                         ptr);
1746                                         }
1747                                         rc = mp && ma;
1748                                 } else
1749                                         rc = 0;
1750                                 no_ip = 0;
1751                                 break;
1752
1753                         case RBCE_RULE_IPV6:    // no support yet
1754                                 rc = 0;
1755                                 no_ip = 0;
1756                                 break;
1757
1758                         case RBCE_RULE_XID:
1759                         {
1760                                 xid_t xid = vx_task_xid(tsk);
1761
1762                                 if (term->operator == RBCE_LESS_THAN) {
1763                                         rc = (xid < term->u.id);
1764                                 } else if (term->operator == RBCE_GREATER_THAN) {
1765                                         rc = (xid > term->u.id);
1766                                 } else if (term->operator == RBCE_NOT) {
1767                                         rc = (xid != term->u.id);
1768                                 } else {
1769                                         rc = (xid == term->u.id);
1770                                 }
1771                                 break;
1772                         }
1773                                 
1774                         default:
1775                                 rc = 0;
1776                                 printk(KERN_ERR "Error evaluate term op=%d\n",
1777                                        term->op);
1778                                 break;
1779                         }
1780                         if (!rc && no_ip) {
1781                                 bitvector_clear(tidx, vec_true);
1782                         } else {
1783                                 bitvector_set(tidx, vec_true);
1784                         }
1785                         bitvector_set(tidx, vec_eval);
1786                 } else {
1787                         rc = bitvector_test(tidx, vec_true);
1788                 }
1789                 if (!rc) {
1790                         return 0;
1791                 }
1792         }
1793         return 1;
1794 }
1795
1796 //#define PDATA_DEBUG
1797 #ifdef PDATA_DEBUG
1798
1799 #define MAX_PDATA 10000
1800 void *pdata_arr[MAX_PDATA];
1801 int pdata_count, pdata_next;
1802 static spinlock_t pdata_lock = SPIN_LOCK_UNLOCKED;
1803
1804 static inline int valid_pdata(struct rbce_private_data *pdata)
1805 {
1806         int i;
1807
1808         if (!pdata) {
1809                 return 1;
1810         }
1811         spin_lock(&pdata_lock);
1812         for (i = 0; i < MAX_PDATA; i++) {
1813                 if (pdata_arr[i] == pdata) {
1814                         spin_unlock(&pdata_lock);
1815                         return 1;
1816                 }
1817         }
1818         spin_unlock(&pdata_lock);
1819         printk(KERN_WARNING "INVALID/CORRUPT PDATA %p\n", pdata);
1820         return 0;
1821 }
1822
1823 static inline void store_pdata(struct rbce_private_data *pdata)
1824 {
1825         int i = 0;
1826
1827         if (pdata) {
1828                 spin_lock(&pdata_lock);
1829
1830                 while (i < MAX_PDATA) {
1831                         if (pdata_arr[pdata_next] == NULL) {
1832                                 printk(KERN_DEBUG "storing %p at %d, count %d\n", pdata,
1833                                        pdata_next, pdata_count);
1834                                 pdata_arr[pdata_next++] = pdata;
1835                                 if (pdata_next == MAX_PDATA) {
1836                                         pdata_next = 0;
1837                                 }
1838                                 pdata_count++;
1839                                 break;
1840                         }
1841                         pdata_next++;
1842                         i++;
1843                 }
1844                 spin_unlock(&pdata_lock);
1845         }
1846         if (i == MAX_PDATA) {
1847                 printk(KERN_DEBUG "PDATA BUFFER FULL pdata_count %d pdata %p\n",
1848                        pdata_count, pdata);
1849         }
1850 }
1851
1852 static inline void unstore_pdata(struct rbce_private_data *pdata)
1853 {
1854         int i;
1855         if (pdata) {
1856                 spin_lock(&pdata_lock);
1857                 for (i = 0; i < MAX_PDATA; i++) {
1858                         if (pdata_arr[i] == pdata) {
1859                                 printk(KERN_DEBUG "unstoring %p at %d, count %d\n", pdata,
1860                                        i, pdata_count);
1861                                 pdata_arr[i] = NULL;
1862                                 pdata_count--;
1863                                 pdata_next = i;
1864                                 break;
1865                         }
1866                 }
1867                 spin_unlock(&pdata_lock);
1868                 if (i == MAX_PDATA) {
1869                         printk(KERN_DEBUG "pdata %p not found in the stored array\n",
1870                                pdata);
1871                 }
1872         }
1873         return;
1874 }
1875
1876 #else                           // PDATA_DEBUG
1877
1878 #define valid_pdata(pdata) (1)
1879 #define store_pdata(pdata)
1880 #define unstore_pdata(pdata)
1881
1882 #endif                          // PDATA_DEBUG
1883
1884 /*
1885  * Allocate and initialize a rbce_private_data data structure.
1886  *
1887  * Caller must hold global_rwlock atleast in read mode.
1888  */
1889
1890 static inline void
1891 copy_ext_private_data(struct rbce_private_data *src,
1892                       struct rbce_private_data *dst)
1893 {
1894         if (src)
1895                 dst->ext_data = src->ext_data;
1896         else
1897                 memset(&dst->ext_data, 0, sizeof(dst->ext_data));
1898 }
1899
1900 static struct rbce_private_data *create_private_data(struct rbce_private_data
1901                                                      *src, int copy_sample)
1902 {
1903         int vsize, psize, bsize;
1904         struct rbce_private_data *pdata;
1905
1906         if (use_persistent_state) {
1907                 vsize = gl_allocated;
1908                 bsize = vsize / 8 + sizeof(bitvector_t);
1909                 psize = sizeof(struct rbce_private_data) + 2 * bsize;
1910         } else {
1911                 psize = sizeof(struct rbce_private_data);
1912         }
1913
1914         pdata = kmalloc(psize, GFP_ATOMIC);
1915         if (pdata != NULL) {
1916                 if (use_persistent_state) {
1917                         pdata->bitmap_version = gl_bitmap_version;
1918                         pdata->eval = (bitvector_t *) & pdata->data[0];
1919                         pdata->true = (bitvector_t *) & pdata->data[bsize];
1920                         if (src && (src->bitmap_version == gl_bitmap_version)) {
1921                                 memcpy(pdata->data, src->data, 2 * bsize);
1922                         } else {
1923                                 bitvector_init(pdata->eval, vsize);
1924                                 bitvector_init(pdata->true, vsize);
1925                         }
1926                 }
1927                 copy_ext_private_data(src, pdata);
1928                 //if (src) { // inherit evaluate and app_tag
1929                 //      pdata->evaluate = src->evaluate;
1930                 //      if(src->app_tag) {
1931                 //              int len = strlen(src->app_tag)+1;
1932                 //              printk(KERN_DEBUG "CREATE_PRIVATE: apptag %s len %d\n",
1933                 //                          src->app_tag,len);
1934                 //              pdata->app_tag = kmalloc(len, GFP_ATOMIC);
1935                 //              if (pdata->app_tag) {
1936                 //                      strcpy(pdata->app_tag, src->app_tag);
1937                 //              }
1938                 //      }
1939                 //} else {
1940                 pdata->evaluate = 1;
1941                 pdata->rules_version = src ? src->rules_version : 0;
1942                 pdata->app_tag = NULL;
1943                 //}
1944         }
1945         store_pdata(pdata);
1946         return pdata;
1947 }
1948
1949 static inline void free_private_data(struct rbce_private_data *pdata)
1950 {
1951         if (valid_pdata(pdata)) {
1952                 unstore_pdata(pdata);
1953                 kfree(pdata);
1954         }
1955 }
1956
1957 static void free_all_private_data(void)
1958 {
1959         struct task_struct *proc, *thread;
1960
1961         read_lock(&tasklist_lock);
1962         do_each_thread(proc, thread) {
1963                 struct rbce_private_data *pdata;
1964
1965                 pdata = RBCE_DATA(thread);
1966                 RBCE_DATAP(thread) = NULL;
1967                 free_private_data(pdata);
1968         } while_each_thread(proc, thread);
1969         read_unlock(&tasklist_lock);
1970         return;
1971 }
1972
1973 /*
1974  * reclassify function, which is called by all the callback functions.
1975  *
1976  * Takes that task to be reclassified and ruleflags that indicates the
1977  * attributes that caused this reclassification request.
1978  *
1979  * On success, returns the core class pointer to which the given task should
1980  * belong to.
1981  */
1982 static struct ckrm_core_class *rbce_classify(struct task_struct *tsk,
1983                                              struct ckrm_net_struct *ns,
1984                                              unsigned long termflag,
1985                                              int classtype)
1986 {
1987         int i;
1988         struct rbce_rule *rule;
1989         bitvector_t *vec_true = NULL, *vec_eval = NULL;
1990         struct rbce_class *tgt = NULL;
1991         struct ckrm_core_class *cls = NULL;
1992         char *filename = NULL;
1993
1994         if (!valid_pdata(RBCE_DATA(tsk))) {
1995                 return NULL;
1996         }
1997         if (classtype >= CKRM_MAX_CLASSTYPES) {
1998                 // can't handle more than CKRM_MAX_CLASSTYPES
1999                 return NULL;
2000         }
2001         // fast path to avoid locking in case CE is not enabled or if no rules
2002         // are defined or if the tasks states that no evaluation is needed.
2003         if (!rbce_enabled || !gl_num_rules ||
2004             (RBCE_DATA(tsk) && !RBCE_DATA(tsk)->evaluate)) {
2005                 return NULL;
2006         }
2007         // FIXME: optimize_policy should be called from here if
2008         // gl_action is non-zero. Also, it has to be called with the
2009         // global_rwlock held in write mode.
2010
2011         read_lock(&global_rwlock);
2012
2013         vec_eval = vec_true = NULL;
2014         if (use_persistent_state) {
2015                 struct rbce_private_data *pdata = RBCE_DATA(tsk);
2016
2017                 if (!pdata
2018                     || (pdata
2019                         && (gl_bitmap_version != pdata->bitmap_version))) {
2020                         struct rbce_private_data *new_pdata =
2021                             create_private_data(pdata, 1);
2022
2023                         if (new_pdata) {
2024                                 if (pdata) {
2025                                         new_pdata->rules_version =
2026                                             pdata->rules_version;
2027                                         new_pdata->evaluate = pdata->evaluate;
2028                                         new_pdata->app_tag = pdata->app_tag;
2029                                         free_private_data(pdata);
2030                                 }
2031                                 pdata = RBCE_DATAP(tsk) = new_pdata;
2032                                 termflag = RBCE_TERMFLAG_ALL;   
2033                                 // need to evaluate them all
2034                         } else {
2035                                 // we shouldn't free the pdata as it has more 
2036                                 // details than the vectors. But, this 
2037                                 // reclassification should go thru
2038                                 pdata = NULL;
2039                         }
2040                 }
2041                 if (!pdata) {
2042                         goto cls_determined;
2043                 }
2044                 vec_eval = pdata->eval;
2045                 vec_true = pdata->true;
2046         } else {
2047                 int bsize = gl_allocated;
2048
2049                 vec_eval = bitvector_alloc(bsize);
2050                 vec_true = bitvector_alloc(bsize);
2051
2052                 if (vec_eval == NULL || vec_true == NULL) {
2053                         goto cls_determined;
2054                 }
2055                 termflag = RBCE_TERMFLAG_ALL; 
2056                 // need to evaluate all of them now
2057         }
2058
2059         /* 
2060          * using bit ops invalidate all terms related to this termflag
2061          * context (only in per task vec)
2062          */
2063         DPRINTK(DBG_CLASSIFY_DETAILS, "\nClassify: termflag=%lx\n", termflag);
2064         DPRINTK(DBG_CLASSIFY_DETAILS, "     eval before: ");
2065         bitvector_print(DBG_CLASSIFY_DETAILS, vec_eval);
2066         DPRINTK(DBG_CLASSIFY_DETAILS, "\n     true before: ");
2067         bitvector_print(DBG_CLASSIFY_DETAILS, vec_true);
2068         DPRINTK(DBG_CLASSIFY_DETAILS, "\n     redo => ");
2069
2070         if (termflag == RBCE_TERMFLAG_ALL) {
2071                 DPRINTK(DBG_CLASSIFY_DETAILS, "  redoall ");
2072                 bitvector_zero(vec_eval);
2073         } else {
2074                 for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
2075                         if (test_bit(i, &termflag)) {
2076                                 bitvector_t *maskvec = gl_mask_vecs[i];
2077
2078                                 DPRINTK(DBG_CLASSIFY_DETAILS, "  mask(%d) ", i);
2079                                 bitvector_print(DBG_CLASSIFY_DETAILS, maskvec);
2080                                 bitvector_and_not(vec_eval, vec_eval, maskvec);
2081                         }
2082                 }
2083         }
2084         bitvector_and(vec_true, vec_true, vec_eval);
2085
2086         DPRINTK(DBG_CLASSIFY_DETAILS, "\n     eval now:    ");
2087         bitvector_print(DBG_CLASSIFY_DETAILS, vec_eval);
2088         DPRINTK(DBG_CLASSIFY_DETAILS, "\n");
2089
2090         /* run through the rules in order and see what needs evaluation */
2091         list_for_each_entry(rule, &rules_list[classtype], obj.link) {
2092                 if (rule->state == RBCE_RULE_ENABLED &&
2093                     rule->target_class &&
2094                     rule->target_class->classobj &&
2095                     evaluate_rule(tsk, ns, rule, vec_eval, vec_true,
2096                                   &filename)) {
2097                         tgt = rule->target_class;
2098                         cls = rule->target_class->classobj;
2099                         break;
2100                 }
2101         }
2102
2103       cls_determined:
2104         DPRINTK(DBG_CLASSIFY_RES,
2105                 "==> |%s|; pid %d; euid %d; egid %d; ruid %d; rgid %d;"
2106                 "tag |%s| ===> class |%s|\n",
2107                 filename ? filename : tsk->comm,
2108                 tsk->pid,
2109                 tsk->euid,
2110                 tsk->egid,
2111                 tsk->uid,
2112                 tsk->gid,
2113                 RBCE_DATA(tsk) ? RBCE_DATA(tsk)->app_tag : "",
2114                 tgt ? tgt->obj.name : "");
2115         DPRINTK(DBG_CLASSIFY_DETAILS, "     eval after: ");
2116         bitvector_print(DBG_CLASSIFY_DETAILS, vec_eval);
2117         DPRINTK(DBG_CLASSIFY_DETAILS, "\n     true after: ");
2118         bitvector_print(DBG_CLASSIFY_DETAILS, vec_true);
2119         DPRINTK(DBG_CLASSIFY_DETAILS, "\n");
2120
2121         if (!use_persistent_state) {
2122                 if (vec_eval) {
2123                         bitvector_free(vec_eval);
2124                 }
2125                 if (vec_true) {
2126                         bitvector_free(vec_true);
2127                 }
2128         }
2129         ckrm_core_grab(cls);
2130         read_unlock(&global_rwlock);
2131         if (filename) {
2132                 kfree(filename);
2133         }
2134         if (RBCE_DATA(tsk)) {
2135                 RBCE_DATA(tsk)->rules_version = gl_rules_version;
2136         }
2137         return cls;
2138 }
2139
2140 /*****************************************************************************
2141  *
2142  * Module specific utilization of core RBCE functionality
2143  *
2144  * Includes support for the various classtypes 
2145  * New classtypes will require extensions here
2146  * 
2147  *****************************************************************************/
2148
2149 /* helper functions that are required in the extended version */
2150
2151 static inline void rbce_tc_manual(struct task_struct *tsk)
2152 {
2153         read_lock(&global_rwlock);
2154
2155         if (!RBCE_DATA(tsk)) {
2156                 RBCE_DATAP(tsk) =
2157                     (void *)create_private_data(RBCE_DATA(tsk->parent), 0);
2158         }
2159         if (RBCE_DATA(tsk)) {
2160                 RBCE_DATA(tsk)->evaluate = 0;
2161         }
2162         read_unlock(&global_rwlock);
2163         return;
2164 }
2165
2166 /*****************************************************************************
2167  *   load any extensions
2168  *****************************************************************************/
2169
2170 #ifdef RBCE_EXTENSION
2171 #include "rbcemod_ext.c"
2172 #endif
2173
2174 /*****************************************************************************
2175  *    VARIOUS CLASSTYPES
2176  *****************************************************************************/
2177
2178 // to enable type coercion of the function pointers
2179
2180 /*============================================================================
2181  *    TASKCLASS CLASSTYPE
2182  *============================================================================*/
2183
2184 int tc_classtype = -1;
2185
2186 /*
2187  * fork callback to be registered with core module.
2188  */
2189 inline static void *rbce_tc_forkcb(struct task_struct *tsk)
2190 {
2191         int rule_version_changed = 1;
2192         struct ckrm_core_class *cls;
2193         read_lock(&global_rwlock);
2194         // dup ce_data
2195         RBCE_DATAP(tsk) =
2196             (void *)create_private_data(RBCE_DATA(tsk->parent), 0);
2197         read_unlock(&global_rwlock);
2198
2199         if (RBCE_DATA(tsk->parent)) {
2200                 rule_version_changed =
2201                     (RBCE_DATA(tsk->parent)->rules_version != gl_rules_version);
2202         }
2203         cls = rule_version_changed ?
2204             rbce_classify(tsk, NULL, RBCE_TERMFLAG_ALL, tc_classtype) : NULL;
2205
2206         // note the fork notification to any user client will be sent through
2207         // the guaranteed fork-reclassification
2208         return cls;
2209 }
2210
2211 /*
2212  * exit callback to be registered with core module.
2213  */
2214 static void rbce_tc_exitcb(struct task_struct *tsk)
2215 {
2216         struct rbce_private_data *pdata;
2217
2218         send_exit_notification(tsk);
2219
2220         pdata = RBCE_DATA(tsk);
2221         RBCE_DATAP(tsk) = NULL;
2222         if (pdata) {
2223                 if (pdata->app_tag) {
2224                         kfree(pdata->app_tag);
2225                 }
2226                 free_private_data(pdata);
2227         }
2228         return;
2229 }
2230
2231 #define AENT(x) [ CKRM_EVENT_##x] = #x
2232 static const char *event_names[CKRM_NUM_EVENTS] = {
2233         AENT(NEWTASK),
2234         AENT(FORK),
2235         AENT(EXIT),
2236         AENT(EXEC),
2237         AENT(UID),
2238         AENT(GID),
2239         AENT(XID),
2240         AENT(LOGIN),
2241         AENT(USERADD),
2242         AENT(USERDEL),
2243         AENT(LISTEN_START),
2244         AENT(LISTEN_STOP),
2245         AENT(APPTAG),
2246         AENT(RECLASSIFY),
2247         AENT(MANUAL),
2248 };
2249
2250 void *rbce_tc_classify(enum ckrm_event event, ...)
2251 {
2252         va_list args;
2253         void *cls = NULL;
2254         struct task_struct *tsk;
2255         struct rbce_private_data *pdata;
2256
2257         va_start(args, event);
2258         tsk = va_arg(args, struct task_struct *);
2259         va_end(args);
2260
2261         /* we only have to deal with events between 
2262          * [ CKRM_LATCHABLE_EVENTS .. CKRM_NONLATCHABLE_EVENTS ) 
2263          */
2264
2265         // printk(KERN_DEBUG "tc_classify %p:%d:%s '%s'\n",tsk,tsk->pid,
2266         //                      tsk->comm,event_names[event]);
2267
2268         switch (event) {
2269
2270         case CKRM_EVENT_FORK:
2271                 cls = rbce_tc_forkcb(tsk);
2272                 break;
2273
2274         case CKRM_EVENT_EXIT:
2275                 rbce_tc_exitcb(tsk);
2276                 break;
2277
2278         case CKRM_EVENT_EXEC:
2279                 cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_CMD |
2280                                     RBCE_TERMFLAG_UID | RBCE_TERMFLAG_GID,
2281                                     tc_classtype);
2282                 break;
2283
2284         case CKRM_EVENT_UID:
2285                 cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_UID, tc_classtype);
2286                 break;
2287
2288         case CKRM_EVENT_GID:
2289                 cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_GID, tc_classtype);
2290                 break;
2291
2292         case CKRM_EVENT_XID:
2293                 cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_XID, tc_classtype);
2294                 break;
2295
2296         case CKRM_EVENT_LOGIN:
2297         case CKRM_EVENT_USERADD:
2298         case CKRM_EVENT_USERDEL:
2299         case CKRM_EVENT_LISTEN_START:
2300         case CKRM_EVENT_LISTEN_STOP:
2301         case CKRM_EVENT_APPTAG:
2302                 /* no interest in this events .. */
2303                 break;
2304
2305         default:
2306                 /* catch all */
2307                 break;
2308
2309         case CKRM_EVENT_RECLASSIFY:
2310                 if ((pdata = (RBCE_DATA(tsk)))) {
2311                         pdata->evaluate = 1;
2312                 }
2313                 cls = rbce_classify(tsk, NULL, RBCE_TERMFLAG_ALL, tc_classtype);
2314                 break;
2315
2316         }
2317         // printk(KERN_DEBUG "tc_classify %p:%d:%s '%s' ==> %p\n",tsk,tsk->pid,
2318         //                      tsk->comm,event_names[event],cls);
2319
2320         return cls;
2321 }
2322
2323 #ifndef RBCE_EXTENSION
2324 static void rbce_tc_notify(int event, void *core, struct task_struct *tsk)
2325 {
2326         printk(KERN_DEBUG "tc_manual %p:%d:%s '%s'\n", tsk, tsk->pid, tsk->comm,
2327                event_names[event]);
2328         if (event != CKRM_EVENT_MANUAL)
2329                 return;
2330         rbce_tc_manual(tsk);
2331 }
2332 #endif
2333
2334 static struct ckrm_eng_callback rbce_taskclass_ecbs = {
2335         .c_interest = (unsigned long)(-1),      // set whole bitmap
2336         .classify = (ce_classify_fct_t) rbce_tc_classify,
2337         .class_delete = rbce_class_deletecb,
2338 #ifndef RBCE_EXTENSION
2339         .n_interest = (1 << CKRM_EVENT_MANUAL),
2340         .notify = (ce_notify_fct_t) rbce_tc_notify,
2341         .always_callback = 0,
2342 #else
2343         .n_interest = (unsigned long)(-1),      // set whole bitmap
2344         .notify = (ce_notify_fct_t) rbce_tc_ext_notify,
2345         .class_add = rbce_class_addcb,
2346         .always_callback = 1,
2347 #endif
2348 };
2349
2350 /*============================================================================
2351  *    ACCEPTQ CLASSTYPE
2352  *============================================================================*/
2353
2354 int sc_classtype = -1;
2355
2356 void *rbce_sc_classify(enum ckrm_event event, ...)
2357 {
2358         // no special consideratation
2359         void *result;
2360         va_list args;
2361         struct task_struct *tsk;
2362         struct ckrm_net_struct *ns;
2363
2364         va_start(args, event);
2365         ns = va_arg(args, struct ckrm_net_struct *);
2366         tsk = va_arg(args, struct task_struct *);
2367         va_end(args);
2368
2369         result = rbce_classify(tsk, ns, RBCE_TERMFLAG_ALL, sc_classtype);
2370
2371         DPRINTK(DBG_CLASSIFY_RES,
2372                 "==>  %d.%d.%d.%d\\%d , %p:%d:%s '%s' => %p\n",
2373                 NIPQUAD(ns->ns_daddrv4), ns->ns_dport,
2374                 tsk, tsk ? tsk->pid : 0, tsk ? tsk->comm : "-",
2375                 event_names[event], result);
2376         return result;
2377 }
2378
2379 static struct ckrm_eng_callback rbce_acceptQclass_ecbs = {
2380         .c_interest = (unsigned long)(-1),
2381         .always_callback = 0,   // enable during debugging only
2382         .classify = (ce_classify_fct_t) & rbce_sc_classify,
2383         .class_delete = rbce_class_deletecb,
2384 };
2385
2386 /*============================================================================
2387  *    Module Initialization ...
2388  *============================================================================*/
2389
2390 #define TASKCLASS_NAME  "taskclass"
2391 #define SOCKCLASS_NAME  "socket_class"
2392
2393 struct ce_regtable_struct {
2394         const char *name;
2395         struct ckrm_eng_callback *cbs;
2396         int *clsvar;
2397 };
2398
2399 struct ce_regtable_struct ce_regtable[] = {
2400         {TASKCLASS_NAME, &rbce_taskclass_ecbs, &tc_classtype},
2401         {SOCKCLASS_NAME, &rbce_acceptQclass_ecbs, &sc_classtype},
2402         {NULL}
2403 };
2404
2405 static void unregister_classtype_engines(void)
2406   {
2407         int rc;
2408         struct ce_regtable_struct *ceptr = ce_regtable;
2409
2410         while (ceptr->name) {
2411                 if (*ceptr->clsvar >= 0) {
2412                         printk(KERN_DEBUG "ce unregister with <%s>\n",ceptr->name);
2413                         while ((rc = ckrm_unregister_engine(ceptr->name)) == -EAGAIN)
2414                                 ;
2415                         printk(KERN_DEBUG "ce unregister with <%s> rc=%d\n",ceptr->name,rc);
2416                         *ceptr->clsvar = -1;
2417                 }
2418                 ceptr++;
2419         }
2420   }
2421
2422 static int register_classtype_engines(void)
2423 {
2424         int rc;
2425         struct ce_regtable_struct *ceptr = ce_regtable;
2426
2427         while (ceptr->name) {
2428                 rc = ckrm_register_engine(ceptr->name, ceptr->cbs);
2429                 printk(KERN_DEBUG "ce register with <%s> typeId=%d\n",ceptr->name,rc);
2430                 if ((rc < 0) && (rc != -ENOENT)) {
2431                         unregister_classtype_engines();
2432                         return (rc);
2433                 }
2434                 if (rc != -ENOENT) 
2435                         *ceptr->clsvar = rc;
2436                 ceptr++;
2437         }
2438         return 0;
2439 }
2440
2441 // =========== /proc/sysctl/debug/rbce debug stuff =============
2442
2443 #ifdef DEBUG
2444 static struct ctl_table_header *rbce_sysctl_table_header;
2445
2446 #define CTL_RBCE_DEBUG (201)    // picked some number.. dont know algo to pick
2447 static struct ctl_table rbce_entry_table[] = {
2448         {
2449          .ctl_name = CTL_RBCE_DEBUG,
2450          .procname = "rbce",
2451          .data = &rbcedebug,
2452          .maxlen = sizeof(int),
2453          .mode = 0644,
2454          .proc_handler = &proc_dointvec,
2455          },
2456         {0}
2457 };
2458
2459 static struct ctl_table rbce_root_table[] = {
2460         {
2461          .ctl_name = CTL_DEBUG,
2462          .procname = "debug",
2463          .data = NULL,
2464          .maxlen = 0,
2465          .mode = 0555,
2466          .child = rbce_entry_table},
2467         {0}
2468 };
2469
2470 static inline void start_debug(void)
2471 {
2472         rbce_sysctl_table_header = register_sysctl_table(rbce_root_table, 1);
2473 }
2474 static inline void stop_debug(void)
2475 {
2476         if (rbce_sysctl_table_header)
2477                 unregister_sysctl_table(rbce_sysctl_table_header);
2478 }
2479
2480 #else
2481
2482 static inline void start_debug(void)
2483 {
2484 }
2485 static inline void stop_debug(void)
2486 {
2487 }
2488
2489 #endif                          // DEBUG
2490
2491 extern int rbce_mkdir(struct inode *, struct dentry *, int);
2492 extern int rbce_rmdir(struct inode *, struct dentry *);
2493 extern int rbce_create_magic(void);
2494 extern int rbce_clear_magic(void);
2495
2496 rbce_eng_callback_t rcfs_ecbs = {
2497         rbce_mkdir,
2498         rbce_rmdir,
2499         rbce_create_magic,
2500         rbce_clear_magic
2501 };
2502
2503 /* ======================= Module definition Functions ====================== */
2504
2505 int init_rbce(void)
2506 {
2507         int rc, i, line;
2508
2509         printk(KERN_DEBUG "<1>\nInstalling \'%s\' module\n", modname);
2510
2511         for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
2512                 INIT_LIST_HEAD(&rules_list[i]);
2513         }
2514
2515         rc = init_rbce_ext_pre();
2516         line = __LINE__;
2517         if (rc)
2518                 goto out;
2519
2520         rc = register_classtype_engines();
2521         line = __LINE__;
2522         if (rc)
2523                 goto out_unreg_ckrm;    // need to remove anyone opened
2524
2525         /* register any other class type engine here */
2526
2527         rc = rcfs_register_engine(&rcfs_ecbs);
2528         line = __LINE__;
2529         if (rc)
2530                 goto out_unreg_ckrm;
2531
2532         if (rcfs_mounted) {
2533                 rc = rbce_create_magic();
2534                 line = __LINE__;
2535                 if (rc)
2536                         goto out_unreg_rcfs;
2537         }
2538
2539         start_debug();
2540
2541         rc = init_rbce_ext_post();
2542         line = __LINE__;
2543         if (rc)
2544                 goto out_debug;
2545
2546         return 0;               // SUCCESS
2547
2548       out_debug:
2549         stop_debug();
2550
2551       out_unreg_rcfs:
2552         rcfs_unregister_engine(&rcfs_ecbs);
2553       out_unreg_ckrm:
2554         unregister_classtype_engines();
2555         exit_rbce_ext();
2556       out:
2557
2558         printk(KERN_DEBUG "<1>%s: error installing rc=%d line=%d\n", __FUNCTION__, rc,
2559                line);
2560         return rc;
2561 }
2562
2563 void exit_rbce(void)
2564 {
2565         int i;
2566
2567         printk(KERN_DEBUG "<1>Removing \'%s\' module\n", modname);
2568
2569         stop_debug();
2570         exit_rbce_ext();
2571
2572         // Print warnings if lists are not empty, which is a bug
2573         if (!list_empty(&class_list)) {
2574                 printk(KERN_DEBUG "exit_rbce: Class list is not empty\n");
2575         }
2576
2577         for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
2578                 if (!list_empty(&rules_list[i])) {
2579                         printk(KERN_DEBUG "exit_rbce: Rules list for classtype %d"
2580                              " is not empty\n", i);
2581                 }
2582         }
2583
2584         if (rcfs_mounted)
2585                 rbce_clear_magic();
2586
2587         rcfs_unregister_engine(&rcfs_ecbs);
2588         unregister_classtype_engines();
2589         free_all_private_data();
2590 }
2591
2592 EXPORT_SYMBOL(get_rule);
2593 EXPORT_SYMBOL(rule_exists);
2594 EXPORT_SYMBOL(change_rule);
2595 EXPORT_SYMBOL(delete_rule);
2596 EXPORT_SYMBOL(rename_rule);
2597 EXPORT_SYMBOL(set_tasktag);
2598
2599 module_init(init_rbce);
2600 module_exit(exit_rbce);
2601
2602