[PATCH] redirect speedstep-centrino maintainer mail to cpufreq list
[linux-2.6] / kernel / auditfilter.c
1 /* auditfilter.c -- filtering of audit events
2  *
3  * Copyright 2003-2004 Red Hat, Inc.
4  * Copyright 2005 Hewlett-Packard Development Company, L.P.
5  * Copyright 2005 IBM Corporation
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/audit.h>
24 #include <linux/kthread.h>
25 #include <linux/netlink.h>
26 #include <linux/selinux.h>
27 #include "audit.h"
28
29 /* There are three lists of rules -- one to search at task creation
30  * time, one to search at syscall entry time, and another to search at
31  * syscall exit time. */
32 struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
33         LIST_HEAD_INIT(audit_filter_list[0]),
34         LIST_HEAD_INIT(audit_filter_list[1]),
35         LIST_HEAD_INIT(audit_filter_list[2]),
36         LIST_HEAD_INIT(audit_filter_list[3]),
37         LIST_HEAD_INIT(audit_filter_list[4]),
38         LIST_HEAD_INIT(audit_filter_list[5]),
39 #if AUDIT_NR_FILTERS != 6
40 #error Fix audit_filter_list initialiser
41 #endif
42 };
43
44 static inline void audit_free_rule(struct audit_entry *e)
45 {
46         int i;
47         if (e->rule.fields)
48                 for (i = 0; i < e->rule.field_count; i++) {
49                         struct audit_field *f = &e->rule.fields[i];
50                         kfree(f->se_str);
51                         selinux_audit_rule_free(f->se_rule);
52                 }
53         kfree(e->rule.fields);
54         kfree(e);
55 }
56
57 static inline void audit_free_rule_rcu(struct rcu_head *head)
58 {
59         struct audit_entry *e = container_of(head, struct audit_entry, rcu);
60         audit_free_rule(e);
61 }
62
63 /* Initialize an audit filterlist entry. */
64 static inline struct audit_entry *audit_init_entry(u32 field_count)
65 {
66         struct audit_entry *entry;
67         struct audit_field *fields;
68
69         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
70         if (unlikely(!entry))
71                 return NULL;
72
73         fields = kzalloc(sizeof(*fields) * field_count, GFP_KERNEL);
74         if (unlikely(!fields)) {
75                 kfree(entry);
76                 return NULL;
77         }
78         entry->rule.fields = fields;
79
80         return entry;
81 }
82
83 /* Unpack a filter field's string representation from user-space
84  * buffer. */
85 static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
86 {
87         char *str;
88
89         if (!*bufp || (len == 0) || (len > *remain))
90                 return ERR_PTR(-EINVAL);
91
92         /* Of the currently implemented string fields, PATH_MAX
93          * defines the longest valid length.
94          */
95         if (len > PATH_MAX)
96                 return ERR_PTR(-ENAMETOOLONG);
97
98         str = kmalloc(len + 1, GFP_KERNEL);
99         if (unlikely(!str))
100                 return ERR_PTR(-ENOMEM);
101
102         memcpy(str, *bufp, len);
103         str[len] = 0;
104         *bufp += len;
105         *remain -= len;
106
107         return str;
108 }
109
110 /* Common user-space to kernel rule translation. */
111 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
112 {
113         unsigned listnr;
114         struct audit_entry *entry;
115         int i, err;
116
117         err = -EINVAL;
118         listnr = rule->flags & ~AUDIT_FILTER_PREPEND;
119         switch(listnr) {
120         default:
121                 goto exit_err;
122         case AUDIT_FILTER_USER:
123         case AUDIT_FILTER_TYPE:
124 #ifdef CONFIG_AUDITSYSCALL
125         case AUDIT_FILTER_ENTRY:
126         case AUDIT_FILTER_EXIT:
127         case AUDIT_FILTER_TASK:
128 #endif
129                 ;
130         }
131         if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
132             rule->action != AUDIT_ALWAYS)
133                 goto exit_err;
134         if (rule->field_count > AUDIT_MAX_FIELDS)
135                 goto exit_err;
136
137         err = -ENOMEM;
138         entry = audit_init_entry(rule->field_count);
139         if (!entry)
140                 goto exit_err;
141
142         entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
143         entry->rule.listnr = listnr;
144         entry->rule.action = rule->action;
145         entry->rule.field_count = rule->field_count;
146
147         for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
148                 entry->rule.mask[i] = rule->mask[i];
149
150         return entry;
151
152 exit_err:
153         return ERR_PTR(err);
154 }
155
156 /* Translate struct audit_rule to kernel's rule respresentation.
157  * Exists for backward compatibility with userspace. */
158 static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
159 {
160         struct audit_entry *entry;
161         int err = 0;
162         int i;
163
164         entry = audit_to_entry_common(rule);
165         if (IS_ERR(entry))
166                 goto exit_nofree;
167
168         for (i = 0; i < rule->field_count; i++) {
169                 struct audit_field *f = &entry->rule.fields[i];
170
171                 f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
172                 f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
173                 f->val = rule->values[i];
174
175                 if (f->type & AUDIT_UNUSED_BITS ||
176                     f->type == AUDIT_SE_USER ||
177                     f->type == AUDIT_SE_ROLE ||
178                     f->type == AUDIT_SE_TYPE ||
179                     f->type == AUDIT_SE_SEN ||
180                     f->type == AUDIT_SE_CLR) {
181                         err = -EINVAL;
182                         goto exit_free;
183                 }
184
185                 entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
186
187                 /* Support for legacy operators where
188                  * AUDIT_NEGATE bit signifies != and otherwise assumes == */
189                 if (f->op & AUDIT_NEGATE)
190                         f->op = AUDIT_NOT_EQUAL;
191                 else if (!f->op)
192                         f->op = AUDIT_EQUAL;
193                 else if (f->op == AUDIT_OPERATORS) {
194                         err = -EINVAL;
195                         goto exit_free;
196                 }
197         }
198
199 exit_nofree:
200         return entry;
201
202 exit_free:
203         audit_free_rule(entry);
204         return ERR_PTR(err);
205 }
206
207 /* Translate struct audit_rule_data to kernel's rule respresentation. */
208 static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
209                                                size_t datasz)
210 {
211         int err = 0;
212         struct audit_entry *entry;
213         void *bufp;
214         size_t remain = datasz - sizeof(struct audit_rule_data);
215         int i;
216         char *str;
217
218         entry = audit_to_entry_common((struct audit_rule *)data);
219         if (IS_ERR(entry))
220                 goto exit_nofree;
221
222         bufp = data->buf;
223         entry->rule.vers_ops = 2;
224         for (i = 0; i < data->field_count; i++) {
225                 struct audit_field *f = &entry->rule.fields[i];
226
227                 err = -EINVAL;
228                 if (!(data->fieldflags[i] & AUDIT_OPERATORS) ||
229                     data->fieldflags[i] & ~AUDIT_OPERATORS)
230                         goto exit_free;
231
232                 f->op = data->fieldflags[i] & AUDIT_OPERATORS;
233                 f->type = data->fields[i];
234                 f->val = data->values[i];
235                 f->se_str = NULL;
236                 f->se_rule = NULL;
237                 switch(f->type) {
238                 case AUDIT_SE_USER:
239                 case AUDIT_SE_ROLE:
240                 case AUDIT_SE_TYPE:
241                 case AUDIT_SE_SEN:
242                 case AUDIT_SE_CLR:
243                         str = audit_unpack_string(&bufp, &remain, f->val);
244                         if (IS_ERR(str))
245                                 goto exit_free;
246                         entry->rule.buflen += f->val;
247
248                         err = selinux_audit_rule_init(f->type, f->op, str,
249                                                       &f->se_rule);
250                         /* Keep currently invalid fields around in case they
251                          * become valid after a policy reload. */
252                         if (err == -EINVAL) {
253                                 printk(KERN_WARNING "audit rule for selinux "
254                                        "\'%s\' is invalid\n",  str);
255                                 err = 0;
256                         }
257                         if (err) {
258                                 kfree(str);
259                                 goto exit_free;
260                         } else
261                                 f->se_str = str;
262                         break;
263                 }
264         }
265
266 exit_nofree:
267         return entry;
268
269 exit_free:
270         audit_free_rule(entry);
271         return ERR_PTR(err);
272 }
273
274 /* Pack a filter field's string representation into data block. */
275 static inline size_t audit_pack_string(void **bufp, char *str)
276 {
277         size_t len = strlen(str);
278
279         memcpy(*bufp, str, len);
280         *bufp += len;
281
282         return len;
283 }
284
285 /* Translate kernel rule respresentation to struct audit_rule.
286  * Exists for backward compatibility with userspace. */
287 static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
288 {
289         struct audit_rule *rule;
290         int i;
291
292         rule = kmalloc(sizeof(*rule), GFP_KERNEL);
293         if (unlikely(!rule))
294                 return ERR_PTR(-ENOMEM);
295         memset(rule, 0, sizeof(*rule));
296
297         rule->flags = krule->flags | krule->listnr;
298         rule->action = krule->action;
299         rule->field_count = krule->field_count;
300         for (i = 0; i < rule->field_count; i++) {
301                 rule->values[i] = krule->fields[i].val;
302                 rule->fields[i] = krule->fields[i].type;
303
304                 if (krule->vers_ops == 1) {
305                         if (krule->fields[i].op & AUDIT_NOT_EQUAL)
306                                 rule->fields[i] |= AUDIT_NEGATE;
307                 } else {
308                         rule->fields[i] |= krule->fields[i].op;
309                 }
310         }
311         for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
312
313         return rule;
314 }
315
316 /* Translate kernel rule respresentation to struct audit_rule_data. */
317 static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
318 {
319         struct audit_rule_data *data;
320         void *bufp;
321         int i;
322
323         data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
324         if (unlikely(!data))
325                 return ERR_PTR(-ENOMEM);
326         memset(data, 0, sizeof(*data));
327
328         data->flags = krule->flags | krule->listnr;
329         data->action = krule->action;
330         data->field_count = krule->field_count;
331         bufp = data->buf;
332         for (i = 0; i < data->field_count; i++) {
333                 struct audit_field *f = &krule->fields[i];
334
335                 data->fields[i] = f->type;
336                 data->fieldflags[i] = f->op;
337                 switch(f->type) {
338                 case AUDIT_SE_USER:
339                 case AUDIT_SE_ROLE:
340                 case AUDIT_SE_TYPE:
341                 case AUDIT_SE_SEN:
342                 case AUDIT_SE_CLR:
343                         data->buflen += data->values[i] =
344                                 audit_pack_string(&bufp, f->se_str);
345                         break;
346                 default:
347                         data->values[i] = f->val;
348                 }
349         }
350         for (i = 0; i < AUDIT_BITMASK_SIZE; i++) data->mask[i] = krule->mask[i];
351
352         return data;
353 }
354
355 /* Compare two rules in kernel format.  Considered success if rules
356  * don't match. */
357 static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
358 {
359         int i;
360
361         if (a->flags != b->flags ||
362             a->listnr != b->listnr ||
363             a->action != b->action ||
364             a->field_count != b->field_count)
365                 return 1;
366
367         for (i = 0; i < a->field_count; i++) {
368                 if (a->fields[i].type != b->fields[i].type ||
369                     a->fields[i].op != b->fields[i].op)
370                         return 1;
371
372                 switch(a->fields[i].type) {
373                 case AUDIT_SE_USER:
374                 case AUDIT_SE_ROLE:
375                 case AUDIT_SE_TYPE:
376                 case AUDIT_SE_SEN:
377                 case AUDIT_SE_CLR:
378                         if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
379                                 return 1;
380                         break;
381                 default:
382                         if (a->fields[i].val != b->fields[i].val)
383                                 return 1;
384                 }
385         }
386
387         for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
388                 if (a->mask[i] != b->mask[i])
389                         return 1;
390
391         return 0;
392 }
393
394 /* Duplicate selinux field information.  The se_rule is opaque, so must be
395  * re-initialized. */
396 static inline int audit_dupe_selinux_field(struct audit_field *df,
397                                            struct audit_field *sf)
398 {
399         int ret = 0;
400         char *se_str;
401
402         /* our own copy of se_str */
403         se_str = kstrdup(sf->se_str, GFP_KERNEL);
404         if (unlikely(IS_ERR(se_str)))
405             return -ENOMEM;
406         df->se_str = se_str;
407
408         /* our own (refreshed) copy of se_rule */
409         ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
410                                       &df->se_rule);
411         /* Keep currently invalid fields around in case they
412          * become valid after a policy reload. */
413         if (ret == -EINVAL) {
414                 printk(KERN_WARNING "audit rule for selinux \'%s\' is "
415                        "invalid\n", df->se_str);
416                 ret = 0;
417         }
418
419         return ret;
420 }
421
422 /* Duplicate an audit rule.  This will be a deep copy with the exception
423  * of the watch - that pointer is carried over.  The selinux specific fields
424  * will be updated in the copy.  The point is to be able to replace the old
425  * rule with the new rule in the filterlist, then free the old rule. */
426 static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
427 {
428         u32 fcount = old->field_count;
429         struct audit_entry *entry;
430         struct audit_krule *new;
431         int i, err = 0;
432
433         entry = audit_init_entry(fcount);
434         if (unlikely(!entry))
435                 return ERR_PTR(-ENOMEM);
436
437         new = &entry->rule;
438         new->vers_ops = old->vers_ops;
439         new->flags = old->flags;
440         new->listnr = old->listnr;
441         new->action = old->action;
442         for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
443                 new->mask[i] = old->mask[i];
444         new->buflen = old->buflen;
445         new->field_count = old->field_count;
446         memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
447
448         /* deep copy this information, updating the se_rule fields, because
449          * the originals will all be freed when the old rule is freed. */
450         for (i = 0; i < fcount; i++) {
451                 switch (new->fields[i].type) {
452                 case AUDIT_SE_USER:
453                 case AUDIT_SE_ROLE:
454                 case AUDIT_SE_TYPE:
455                 case AUDIT_SE_SEN:
456                 case AUDIT_SE_CLR:
457                         err = audit_dupe_selinux_field(&new->fields[i],
458                                                        &old->fields[i]);
459                 }
460                 if (err) {
461                         audit_free_rule(entry);
462                         return ERR_PTR(err);
463                 }
464         }
465
466         return entry;
467 }
468
469 /* Add rule to given filterlist if not a duplicate.  Protected by
470  * audit_netlink_mutex. */
471 static inline int audit_add_rule(struct audit_entry *entry,
472                                   struct list_head *list)
473 {
474         struct audit_entry *e;
475
476         /* Do not use the _rcu iterator here, since this is the only
477          * addition routine. */
478         list_for_each_entry(e, list, list) {
479                 if (!audit_compare_rule(&entry->rule, &e->rule))
480                         return -EEXIST;
481         }
482
483         if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
484                 list_add_rcu(&entry->list, list);
485         } else {
486                 list_add_tail_rcu(&entry->list, list);
487         }
488
489         return 0;
490 }
491
492 /* Remove an existing rule from filterlist.  Protected by
493  * audit_netlink_mutex. */
494 static inline int audit_del_rule(struct audit_entry *entry,
495                                  struct list_head *list)
496 {
497         struct audit_entry  *e;
498
499         /* Do not use the _rcu iterator here, since this is the only
500          * deletion routine. */
501         list_for_each_entry(e, list, list) {
502                 if (!audit_compare_rule(&entry->rule, &e->rule)) {
503                         list_del_rcu(&e->list);
504                         call_rcu(&e->rcu, audit_free_rule_rcu);
505                         return 0;
506                 }
507         }
508         return -ENOENT;         /* No matching rule */
509 }
510
511 /* List rules using struct audit_rule.  Exists for backward
512  * compatibility with userspace. */
513 static int audit_list(void *_dest)
514 {
515         int pid, seq;
516         int *dest = _dest;
517         struct audit_entry *entry;
518         int i;
519
520         pid = dest[0];
521         seq = dest[1];
522         kfree(dest);
523
524         mutex_lock(&audit_netlink_mutex);
525
526         /* The *_rcu iterators not needed here because we are
527            always called with audit_netlink_mutex held. */
528         for (i=0; i<AUDIT_NR_FILTERS; i++) {
529                 list_for_each_entry(entry, &audit_filter_list[i], list) {
530                         struct audit_rule *rule;
531
532                         rule = audit_krule_to_rule(&entry->rule);
533                         if (unlikely(!rule))
534                                 break;
535                         audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
536                                          rule, sizeof(*rule));
537                         kfree(rule);
538                 }
539         }
540         audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
541         
542         mutex_unlock(&audit_netlink_mutex);
543         return 0;
544 }
545
546 /* List rules using struct audit_rule_data. */
547 static int audit_list_rules(void *_dest)
548 {
549         int pid, seq;
550         int *dest = _dest;
551         struct audit_entry *e;
552         int i;
553
554         pid = dest[0];
555         seq = dest[1];
556         kfree(dest);
557
558         mutex_lock(&audit_netlink_mutex);
559
560         /* The *_rcu iterators not needed here because we are
561            always called with audit_netlink_mutex held. */
562         for (i=0; i<AUDIT_NR_FILTERS; i++) {
563                 list_for_each_entry(e, &audit_filter_list[i], list) {
564                         struct audit_rule_data *data;
565
566                         data = audit_krule_to_data(&e->rule);
567                         if (unlikely(!data))
568                                 break;
569                         audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
570                                          data, sizeof(*data));
571                         kfree(data);
572                 }
573         }
574         audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
575
576         mutex_unlock(&audit_netlink_mutex);
577         return 0;
578 }
579
580 /**
581  * audit_receive_filter - apply all rules to the specified message type
582  * @type: audit message type
583  * @pid: target pid for netlink audit messages
584  * @uid: target uid for netlink audit messages
585  * @seq: netlink audit message sequence (serial) number
586  * @data: payload data
587  * @datasz: size of payload data
588  * @loginuid: loginuid of sender
589  * @sid: SE Linux Security ID of sender
590  */
591 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
592                          size_t datasz, uid_t loginuid, u32 sid)
593 {
594         struct task_struct *tsk;
595         int *dest;
596         int err = 0;
597         struct audit_entry *entry;
598
599         switch (type) {
600         case AUDIT_LIST:
601         case AUDIT_LIST_RULES:
602                 /* We can't just spew out the rules here because we might fill
603                  * the available socket buffer space and deadlock waiting for
604                  * auditctl to read from it... which isn't ever going to
605                  * happen if we're actually running in the context of auditctl
606                  * trying to _send_ the stuff */
607                  
608                 dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
609                 if (!dest)
610                         return -ENOMEM;
611                 dest[0] = pid;
612                 dest[1] = seq;
613
614                 if (type == AUDIT_LIST)
615                         tsk = kthread_run(audit_list, dest, "audit_list");
616                 else
617                         tsk = kthread_run(audit_list_rules, dest,
618                                           "audit_list_rules");
619                 if (IS_ERR(tsk)) {
620                         kfree(dest);
621                         err = PTR_ERR(tsk);
622                 }
623                 break;
624         case AUDIT_ADD:
625         case AUDIT_ADD_RULE:
626                 if (type == AUDIT_ADD)
627                         entry = audit_rule_to_entry(data);
628                 else
629                         entry = audit_data_to_entry(data, datasz);
630                 if (IS_ERR(entry))
631                         return PTR_ERR(entry);
632
633                 err = audit_add_rule(entry,
634                                      &audit_filter_list[entry->rule.listnr]);
635                 if (sid) {
636                         char *ctx = NULL;
637                         u32 len;
638                         if (selinux_ctxid_to_string(sid, &ctx, &len)) {
639                                 /* Maybe call audit_panic? */
640                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
641                                  "auid=%u ssid=%u add rule to list=%d res=%d",
642                                  loginuid, sid, entry->rule.listnr, !err);
643                         } else
644                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
645                                  "auid=%u subj=%s add rule to list=%d res=%d",
646                                  loginuid, ctx, entry->rule.listnr, !err);
647                         kfree(ctx);
648                 } else
649                         audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
650                                 "auid=%u add rule to list=%d res=%d",
651                                 loginuid, entry->rule.listnr, !err);
652
653                 if (err)
654                         audit_free_rule(entry);
655                 break;
656         case AUDIT_DEL:
657         case AUDIT_DEL_RULE:
658                 if (type == AUDIT_DEL)
659                         entry = audit_rule_to_entry(data);
660                 else
661                         entry = audit_data_to_entry(data, datasz);
662                 if (IS_ERR(entry))
663                         return PTR_ERR(entry);
664
665                 err = audit_del_rule(entry,
666                                      &audit_filter_list[entry->rule.listnr]);
667
668                 if (sid) {
669                         char *ctx = NULL;
670                         u32 len;
671                         if (selinux_ctxid_to_string(sid, &ctx, &len)) {
672                                 /* Maybe call audit_panic? */
673                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
674                                         "auid=%u ssid=%u remove rule from list=%d res=%d",
675                                          loginuid, sid, entry->rule.listnr, !err);
676                         } else
677                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
678                                         "auid=%u subj=%s remove rule from list=%d res=%d",
679                                          loginuid, ctx, entry->rule.listnr, !err);
680                         kfree(ctx);
681                 } else
682                         audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
683                                 "auid=%u remove rule from list=%d res=%d",
684                                 loginuid, entry->rule.listnr, !err);
685
686                 audit_free_rule(entry);
687                 break;
688         default:
689                 return -EINVAL;
690         }
691
692         return err;
693 }
694
695 int audit_comparator(const u32 left, const u32 op, const u32 right)
696 {
697         switch (op) {
698         case AUDIT_EQUAL:
699                 return (left == right);
700         case AUDIT_NOT_EQUAL:
701                 return (left != right);
702         case AUDIT_LESS_THAN:
703                 return (left < right);
704         case AUDIT_LESS_THAN_OR_EQUAL:
705                 return (left <= right);
706         case AUDIT_GREATER_THAN:
707                 return (left > right);
708         case AUDIT_GREATER_THAN_OR_EQUAL:
709                 return (left >= right);
710         }
711         BUG();
712         return 0;
713 }
714
715
716
717 static int audit_filter_user_rules(struct netlink_skb_parms *cb,
718                                    struct audit_krule *rule,
719                                    enum audit_state *state)
720 {
721         int i;
722
723         for (i = 0; i < rule->field_count; i++) {
724                 struct audit_field *f = &rule->fields[i];
725                 int result = 0;
726
727                 switch (f->type) {
728                 case AUDIT_PID:
729                         result = audit_comparator(cb->creds.pid, f->op, f->val);
730                         break;
731                 case AUDIT_UID:
732                         result = audit_comparator(cb->creds.uid, f->op, f->val);
733                         break;
734                 case AUDIT_GID:
735                         result = audit_comparator(cb->creds.gid, f->op, f->val);
736                         break;
737                 case AUDIT_LOGINUID:
738                         result = audit_comparator(cb->loginuid, f->op, f->val);
739                         break;
740                 }
741
742                 if (!result)
743                         return 0;
744         }
745         switch (rule->action) {
746         case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
747         case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
748         case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
749         }
750         return 1;
751 }
752
753 int audit_filter_user(struct netlink_skb_parms *cb, int type)
754 {
755         struct audit_entry *e;
756         enum audit_state   state;
757         int ret = 1;
758
759         rcu_read_lock();
760         list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
761                 if (audit_filter_user_rules(cb, &e->rule, &state)) {
762                         if (state == AUDIT_DISABLED)
763                                 ret = 0;
764                         break;
765                 }
766         }
767         rcu_read_unlock();
768
769         return ret; /* Audit by default */
770 }
771
772 int audit_filter_type(int type)
773 {
774         struct audit_entry *e;
775         int result = 0;
776         
777         rcu_read_lock();
778         if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
779                 goto unlock_and_return;
780
781         list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
782                                 list) {
783                 int i;
784                 for (i = 0; i < e->rule.field_count; i++) {
785                         struct audit_field *f = &e->rule.fields[i];
786                         if (f->type == AUDIT_MSGTYPE) {
787                                 result = audit_comparator(type, f->op, f->val);
788                                 if (!result)
789                                         break;
790                         }
791                 }
792                 if (result)
793                         goto unlock_and_return;
794         }
795 unlock_and_return:
796         rcu_read_unlock();
797         return result;
798 }
799
800 /* Check to see if the rule contains any selinux fields.  Returns 1 if there
801    are selinux fields specified in the rule, 0 otherwise. */
802 static inline int audit_rule_has_selinux(struct audit_krule *rule)
803 {
804         int i;
805
806         for (i = 0; i < rule->field_count; i++) {
807                 struct audit_field *f = &rule->fields[i];
808                 switch (f->type) {
809                 case AUDIT_SE_USER:
810                 case AUDIT_SE_ROLE:
811                 case AUDIT_SE_TYPE:
812                 case AUDIT_SE_SEN:
813                 case AUDIT_SE_CLR:
814                         return 1;
815                 }
816         }
817
818         return 0;
819 }
820
821 /* This function will re-initialize the se_rule field of all applicable rules.
822  * It will traverse the filter lists serarching for rules that contain selinux
823  * specific filter fields.  When such a rule is found, it is copied, the
824  * selinux field is re-initialized, and the old rule is replaced with the
825  * updated rule. */
826 int selinux_audit_rule_update(void)
827 {
828         struct audit_entry *entry, *n, *nentry;
829         int i, err = 0;
830
831         /* audit_netlink_mutex synchronizes the writers */
832         mutex_lock(&audit_netlink_mutex);
833
834         for (i = 0; i < AUDIT_NR_FILTERS; i++) {
835                 list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
836                         if (!audit_rule_has_selinux(&entry->rule))
837                                 continue;
838
839                         nentry = audit_dupe_rule(&entry->rule);
840                         if (unlikely(IS_ERR(nentry))) {
841                                 /* save the first error encountered for the
842                                  * return value */
843                                 if (!err)
844                                         err = PTR_ERR(nentry);
845                                 audit_panic("error updating selinux filters");
846                                 list_del_rcu(&entry->list);
847                         } else {
848                                 list_replace_rcu(&entry->list, &nentry->list);
849                         }
850                         call_rcu(&entry->rcu, audit_free_rule_rcu);
851                 }
852         }
853
854         mutex_unlock(&audit_netlink_mutex);
855
856         return err;
857 }