[PATCH] fix deadlocks in AUDIT_LIST/AUDIT_LIST_RULES
[pandora-kernel.git] / 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 void audit_list(int pid, int seq, struct sk_buff_head *q)
514 {
515         struct sk_buff *skb;
516         struct audit_entry *entry;
517         int i;
518
519         /* The *_rcu iterators not needed here because we are
520            always called with audit_netlink_mutex held. */
521         for (i=0; i<AUDIT_NR_FILTERS; i++) {
522                 list_for_each_entry(entry, &audit_filter_list[i], list) {
523                         struct audit_rule *rule;
524
525                         rule = audit_krule_to_rule(&entry->rule);
526                         if (unlikely(!rule))
527                                 break;
528                         skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
529                                          rule, sizeof(*rule));
530                         if (skb)
531                                 skb_queue_tail(q, skb);
532                         kfree(rule);
533                 }
534         }
535         skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
536         if (skb)
537                 skb_queue_tail(q, skb);
538 }
539
540 /* List rules using struct audit_rule_data. */
541 static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
542 {
543         struct sk_buff *skb;
544         struct audit_entry *e;
545         int i;
546
547         /* The *_rcu iterators not needed here because we are
548            always called with audit_netlink_mutex held. */
549         for (i=0; i<AUDIT_NR_FILTERS; i++) {
550                 list_for_each_entry(e, &audit_filter_list[i], list) {
551                         struct audit_rule_data *data;
552
553                         data = audit_krule_to_data(&e->rule);
554                         if (unlikely(!data))
555                                 break;
556                         skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
557                                          data, sizeof(*data));
558                         if (skb)
559                                 skb_queue_tail(q, skb);
560                         kfree(data);
561                 }
562         }
563         skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
564         if (skb)
565                 skb_queue_tail(q, skb);
566 }
567
568 /**
569  * audit_receive_filter - apply all rules to the specified message type
570  * @type: audit message type
571  * @pid: target pid for netlink audit messages
572  * @uid: target uid for netlink audit messages
573  * @seq: netlink audit message sequence (serial) number
574  * @data: payload data
575  * @datasz: size of payload data
576  * @loginuid: loginuid of sender
577  * @sid: SE Linux Security ID of sender
578  */
579 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
580                          size_t datasz, uid_t loginuid, u32 sid)
581 {
582         struct task_struct *tsk;
583         struct audit_netlink_list *dest;
584         int err = 0;
585         struct audit_entry *entry;
586
587         switch (type) {
588         case AUDIT_LIST:
589         case AUDIT_LIST_RULES:
590                 /* We can't just spew out the rules here because we might fill
591                  * the available socket buffer space and deadlock waiting for
592                  * auditctl to read from it... which isn't ever going to
593                  * happen if we're actually running in the context of auditctl
594                  * trying to _send_ the stuff */
595                  
596                 dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
597                 if (!dest)
598                         return -ENOMEM;
599                 dest->pid = pid;
600                 skb_queue_head_init(&dest->q);
601
602                 if (type == AUDIT_LIST)
603                         audit_list(pid, seq, &dest->q);
604                 else
605                         audit_list_rules(pid, seq, &dest->q);
606
607                 tsk = kthread_run(audit_send_list, dest, "audit_send_list");
608                 if (IS_ERR(tsk)) {
609                         skb_queue_purge(&dest->q);
610                         kfree(dest);
611                         err = PTR_ERR(tsk);
612                 }
613                 break;
614         case AUDIT_ADD:
615         case AUDIT_ADD_RULE:
616                 if (type == AUDIT_ADD)
617                         entry = audit_rule_to_entry(data);
618                 else
619                         entry = audit_data_to_entry(data, datasz);
620                 if (IS_ERR(entry))
621                         return PTR_ERR(entry);
622
623                 err = audit_add_rule(entry,
624                                      &audit_filter_list[entry->rule.listnr]);
625                 if (sid) {
626                         char *ctx = NULL;
627                         u32 len;
628                         if (selinux_ctxid_to_string(sid, &ctx, &len)) {
629                                 /* Maybe call audit_panic? */
630                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
631                                  "auid=%u ssid=%u add rule to list=%d res=%d",
632                                  loginuid, sid, entry->rule.listnr, !err);
633                         } else
634                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
635                                  "auid=%u subj=%s add rule to list=%d res=%d",
636                                  loginuid, ctx, entry->rule.listnr, !err);
637                         kfree(ctx);
638                 } else
639                         audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
640                                 "auid=%u add rule to list=%d res=%d",
641                                 loginuid, entry->rule.listnr, !err);
642
643                 if (err)
644                         audit_free_rule(entry);
645                 break;
646         case AUDIT_DEL:
647         case AUDIT_DEL_RULE:
648                 if (type == AUDIT_DEL)
649                         entry = audit_rule_to_entry(data);
650                 else
651                         entry = audit_data_to_entry(data, datasz);
652                 if (IS_ERR(entry))
653                         return PTR_ERR(entry);
654
655                 err = audit_del_rule(entry,
656                                      &audit_filter_list[entry->rule.listnr]);
657
658                 if (sid) {
659                         char *ctx = NULL;
660                         u32 len;
661                         if (selinux_ctxid_to_string(sid, &ctx, &len)) {
662                                 /* Maybe call audit_panic? */
663                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
664                                         "auid=%u ssid=%u remove rule from list=%d res=%d",
665                                          loginuid, sid, entry->rule.listnr, !err);
666                         } else
667                                 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
668                                         "auid=%u subj=%s remove rule from list=%d res=%d",
669                                          loginuid, ctx, entry->rule.listnr, !err);
670                         kfree(ctx);
671                 } else
672                         audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
673                                 "auid=%u remove rule from list=%d res=%d",
674                                 loginuid, entry->rule.listnr, !err);
675
676                 audit_free_rule(entry);
677                 break;
678         default:
679                 return -EINVAL;
680         }
681
682         return err;
683 }
684
685 int audit_comparator(const u32 left, const u32 op, const u32 right)
686 {
687         switch (op) {
688         case AUDIT_EQUAL:
689                 return (left == right);
690         case AUDIT_NOT_EQUAL:
691                 return (left != right);
692         case AUDIT_LESS_THAN:
693                 return (left < right);
694         case AUDIT_LESS_THAN_OR_EQUAL:
695                 return (left <= right);
696         case AUDIT_GREATER_THAN:
697                 return (left > right);
698         case AUDIT_GREATER_THAN_OR_EQUAL:
699                 return (left >= right);
700         }
701         BUG();
702         return 0;
703 }
704
705
706
707 static int audit_filter_user_rules(struct netlink_skb_parms *cb,
708                                    struct audit_krule *rule,
709                                    enum audit_state *state)
710 {
711         int i;
712
713         for (i = 0; i < rule->field_count; i++) {
714                 struct audit_field *f = &rule->fields[i];
715                 int result = 0;
716
717                 switch (f->type) {
718                 case AUDIT_PID:
719                         result = audit_comparator(cb->creds.pid, f->op, f->val);
720                         break;
721                 case AUDIT_UID:
722                         result = audit_comparator(cb->creds.uid, f->op, f->val);
723                         break;
724                 case AUDIT_GID:
725                         result = audit_comparator(cb->creds.gid, f->op, f->val);
726                         break;
727                 case AUDIT_LOGINUID:
728                         result = audit_comparator(cb->loginuid, f->op, f->val);
729                         break;
730                 }
731
732                 if (!result)
733                         return 0;
734         }
735         switch (rule->action) {
736         case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
737         case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
738         case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
739         }
740         return 1;
741 }
742
743 int audit_filter_user(struct netlink_skb_parms *cb, int type)
744 {
745         struct audit_entry *e;
746         enum audit_state   state;
747         int ret = 1;
748
749         rcu_read_lock();
750         list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
751                 if (audit_filter_user_rules(cb, &e->rule, &state)) {
752                         if (state == AUDIT_DISABLED)
753                                 ret = 0;
754                         break;
755                 }
756         }
757         rcu_read_unlock();
758
759         return ret; /* Audit by default */
760 }
761
762 int audit_filter_type(int type)
763 {
764         struct audit_entry *e;
765         int result = 0;
766         
767         rcu_read_lock();
768         if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
769                 goto unlock_and_return;
770
771         list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
772                                 list) {
773                 int i;
774                 for (i = 0; i < e->rule.field_count; i++) {
775                         struct audit_field *f = &e->rule.fields[i];
776                         if (f->type == AUDIT_MSGTYPE) {
777                                 result = audit_comparator(type, f->op, f->val);
778                                 if (!result)
779                                         break;
780                         }
781                 }
782                 if (result)
783                         goto unlock_and_return;
784         }
785 unlock_and_return:
786         rcu_read_unlock();
787         return result;
788 }
789
790 /* Check to see if the rule contains any selinux fields.  Returns 1 if there
791    are selinux fields specified in the rule, 0 otherwise. */
792 static inline int audit_rule_has_selinux(struct audit_krule *rule)
793 {
794         int i;
795
796         for (i = 0; i < rule->field_count; i++) {
797                 struct audit_field *f = &rule->fields[i];
798                 switch (f->type) {
799                 case AUDIT_SE_USER:
800                 case AUDIT_SE_ROLE:
801                 case AUDIT_SE_TYPE:
802                 case AUDIT_SE_SEN:
803                 case AUDIT_SE_CLR:
804                         return 1;
805                 }
806         }
807
808         return 0;
809 }
810
811 /* This function will re-initialize the se_rule field of all applicable rules.
812  * It will traverse the filter lists serarching for rules that contain selinux
813  * specific filter fields.  When such a rule is found, it is copied, the
814  * selinux field is re-initialized, and the old rule is replaced with the
815  * updated rule. */
816 int selinux_audit_rule_update(void)
817 {
818         struct audit_entry *entry, *n, *nentry;
819         int i, err = 0;
820
821         /* audit_netlink_mutex synchronizes the writers */
822         mutex_lock(&audit_netlink_mutex);
823
824         for (i = 0; i < AUDIT_NR_FILTERS; i++) {
825                 list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
826                         if (!audit_rule_has_selinux(&entry->rule))
827                                 continue;
828
829                         nentry = audit_dupe_rule(&entry->rule);
830                         if (unlikely(IS_ERR(nentry))) {
831                                 /* save the first error encountered for the
832                                  * return value */
833                                 if (!err)
834                                         err = PTR_ERR(nentry);
835                                 audit_panic("error updating selinux filters");
836                                 list_del_rcu(&entry->list);
837                         } else {
838                                 list_replace_rcu(&entry->list, &nentry->list);
839                         }
840                         call_rcu(&entry->rcu, audit_free_rule_rcu);
841                 }
842         }
843
844         mutex_unlock(&audit_netlink_mutex);
845
846         return err;
847 }