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