Blame view

kernel/auditfilter.c 33.2 KB
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /* auditfilter.c -- filtering of audit events
   *
   * Copyright 2003-2004 Red Hat, Inc.
   * Copyright 2005 Hewlett-Packard Development Company, L.P.
   * Copyright 2005 IBM Corporation
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include <linux/kernel.h>
  #include <linux/audit.h>
  #include <linux/kthread.h>
f368c07d7   Amy Griffis   [PATCH] audit: pa...
25
26
27
  #include <linux/mutex.h>
  #include <linux/fs.h>
  #include <linux/namei.h>
fe7752bab   David Woodhouse   [PATCH] Fix audit...
28
  #include <linux/netlink.h>
f368c07d7   Amy Griffis   [PATCH] audit: pa...
29
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
30
  #include <linux/slab.h>
2a862b32f   Ahmed S. Darwish   Audit: use new LS...
31
  #include <linux/security.h>
fe7752bab   David Woodhouse   [PATCH] Fix audit...
32
  #include "audit.h"
f368c07d7   Amy Griffis   [PATCH] audit: pa...
33
34
35
36
37
38
39
  /*
   * Locking model:
   *
   * audit_filter_mutex:
   * 		Synchronizes writes and blocking reads of audit's filterlist
   * 		data.  Rcu is used to traverse the filterlist and access
   * 		contents of structs audit_entry, audit_watch and opaque
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
40
   * 		LSM rules during filtering.  If modified, these structures
f368c07d7   Amy Griffis   [PATCH] audit: pa...
41
42
43
44
   * 		must be copied and replace their counterparts in the filterlist.
   * 		An audit_parent struct is not accessed during filtering, so may
   * 		be written directly provided audit_filter_mutex is held.
   */
f368c07d7   Amy Griffis   [PATCH] audit: pa...
45
  /* Audit filter lists, defined in <linux/audit.h> */
fe7752bab   David Woodhouse   [PATCH] Fix audit...
46
47
48
49
50
51
52
53
54
55
56
  struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
  	LIST_HEAD_INIT(audit_filter_list[0]),
  	LIST_HEAD_INIT(audit_filter_list[1]),
  	LIST_HEAD_INIT(audit_filter_list[2]),
  	LIST_HEAD_INIT(audit_filter_list[3]),
  	LIST_HEAD_INIT(audit_filter_list[4]),
  	LIST_HEAD_INIT(audit_filter_list[5]),
  #if AUDIT_NR_FILTERS != 6
  #error Fix audit_filter_list initialiser
  #endif
  };
e45aa212e   Al Viro   audit rules order...
57
58
59
60
61
62
63
64
  static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
  	LIST_HEAD_INIT(audit_rules_list[0]),
  	LIST_HEAD_INIT(audit_rules_list[1]),
  	LIST_HEAD_INIT(audit_rules_list[2]),
  	LIST_HEAD_INIT(audit_rules_list[3]),
  	LIST_HEAD_INIT(audit_rules_list[4]),
  	LIST_HEAD_INIT(audit_rules_list[5]),
  };
fe7752bab   David Woodhouse   [PATCH] Fix audit...
65

74c3cbe33   Al Viro   [PATCH] audit: wa...
66
  DEFINE_MUTEX(audit_filter_mutex);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
67

93315ed6d   Amy Griffis   [PATCH] audit str...
68
  static inline void audit_free_rule(struct audit_entry *e)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
69
  {
3dc7e3153   Darrel Goeddel   [PATCH] support f...
70
  	int i;
c28bb7da7   Zhenwen Xu   make the e->rule....
71
  	struct audit_krule *erule = &e->rule;
ae7b8f410   Eric Paris   Audit: clean up t...
72

f368c07d7   Amy Griffis   [PATCH] audit: pa...
73
  	/* some rules don't have associated watches */
c28bb7da7   Zhenwen Xu   make the e->rule....
74
75
76
77
78
  	if (erule->watch)
  		audit_put_watch(erule->watch);
  	if (erule->fields)
  		for (i = 0; i < erule->field_count; i++) {
  			struct audit_field *f = &erule->fields[i];
04305e4af   Ahmed S. Darwish   Audit: Final rena...
79
80
  			kfree(f->lsm_str);
  			security_audit_rule_free(f->lsm_rule);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
81
  		}
c28bb7da7   Zhenwen Xu   make the e->rule....
82
83
  	kfree(erule->fields);
  	kfree(erule->filterkey);
93315ed6d   Amy Griffis   [PATCH] audit str...
84
85
  	kfree(e);
  }
74c3cbe33   Al Viro   [PATCH] audit: wa...
86
  void audit_free_rule_rcu(struct rcu_head *head)
93315ed6d   Amy Griffis   [PATCH] audit str...
87
88
89
90
  {
  	struct audit_entry *e = container_of(head, struct audit_entry, rcu);
  	audit_free_rule(e);
  }
3dc7e3153   Darrel Goeddel   [PATCH] support f...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  /* Initialize an audit filterlist entry. */
  static inline struct audit_entry *audit_init_entry(u32 field_count)
  {
  	struct audit_entry *entry;
  	struct audit_field *fields;
  
  	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  	if (unlikely(!entry))
  		return NULL;
  
  	fields = kzalloc(sizeof(*fields) * field_count, GFP_KERNEL);
  	if (unlikely(!fields)) {
  		kfree(entry);
  		return NULL;
  	}
  	entry->rule.fields = fields;
  
  	return entry;
  }
93315ed6d   Amy Griffis   [PATCH] audit str...
110
111
  /* Unpack a filter field's string representation from user-space
   * buffer. */
74c3cbe33   Al Viro   [PATCH] audit: wa...
112
  char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
93315ed6d   Amy Griffis   [PATCH] audit str...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  {
  	char *str;
  
  	if (!*bufp || (len == 0) || (len > *remain))
  		return ERR_PTR(-EINVAL);
  
  	/* Of the currently implemented string fields, PATH_MAX
  	 * defines the longest valid length.
  	 */
  	if (len > PATH_MAX)
  		return ERR_PTR(-ENAMETOOLONG);
  
  	str = kmalloc(len + 1, GFP_KERNEL);
  	if (unlikely(!str))
  		return ERR_PTR(-ENOMEM);
  
  	memcpy(str, *bufp, len);
  	str[len] = 0;
  	*bufp += len;
  	*remain -= len;
  
  	return str;
  }
f368c07d7   Amy Griffis   [PATCH] audit: pa...
136
137
138
139
140
  /* Translate an inode field to kernel respresentation. */
  static inline int audit_to_inode(struct audit_krule *krule,
  				 struct audit_field *f)
  {
  	if (krule->listnr != AUDIT_FILTER_EXIT ||
5af75d8d5   Al Viro   audit: validate c...
141
142
  	    krule->watch || krule->inode_f || krule->tree ||
  	    (f->op != Audit_equal && f->op != Audit_not_equal))
f368c07d7   Amy Griffis   [PATCH] audit: pa...
143
144
145
146
147
  		return -EINVAL;
  
  	krule->inode_f = f;
  	return 0;
  }
b915543b4   Al Viro   [PATCH] audit sys...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  static __u32 *classes[AUDIT_SYSCALL_CLASSES];
  
  int __init audit_register_class(int class, unsigned *list)
  {
  	__u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL);
  	if (!p)
  		return -ENOMEM;
  	while (*list != ~0U) {
  		unsigned n = *list++;
  		if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) {
  			kfree(p);
  			return -EINVAL;
  		}
  		p[AUDIT_WORD(n)] |= AUDIT_BIT(n);
  	}
  	if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) {
  		kfree(p);
  		return -EINVAL;
  	}
  	classes[class] = p;
  	return 0;
  }
55669bfa1   Al Viro   [PATCH] audit: AU...
170
171
  int audit_match_class(int class, unsigned syscall)
  {
c926e4f43   Klaus Weidner   [PATCH] audit: fi...
172
  	if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32))
55669bfa1   Al Viro   [PATCH] audit: AU...
173
174
175
176
177
  		return 0;
  	if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class]))
  		return 0;
  	return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
  }
327b9eebb   Al Viro   audit_match_signa...
178
  #ifdef CONFIG_AUDITSYSCALL
e54dc2431   Amy Griffis   [PATCH] audit sig...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  static inline int audit_match_class_bits(int class, u32 *mask)
  {
  	int i;
  
  	if (classes[class]) {
  		for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
  			if (mask[i] & classes[class][i])
  				return 0;
  	}
  	return 1;
  }
  
  static int audit_match_signal(struct audit_entry *entry)
  {
  	struct audit_field *arch = entry->rule.arch_f;
  
  	if (!arch) {
  		/* When arch is unspecified, we must check both masks on biarch
  		 * as syscall number alone is ambiguous. */
  		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
  					       entry->rule.mask) &&
  			audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
  					       entry->rule.mask));
  	}
  
  	switch(audit_classify_arch(arch->val)) {
  	case 0: /* native */
  		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
  					       entry->rule.mask));
  	case 1: /* 32bit on biarch */
  		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
  					       entry->rule.mask));
  	default:
  		return 1;
  	}
  }
327b9eebb   Al Viro   audit_match_signa...
215
  #endif
e54dc2431   Amy Griffis   [PATCH] audit sig...
216

93315ed6d   Amy Griffis   [PATCH] audit str...
217
218
219
220
221
  /* Common user-space to kernel rule translation. */
  static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
  {
  	unsigned listnr;
  	struct audit_entry *entry;
93315ed6d   Amy Griffis   [PATCH] audit str...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  	int i, err;
  
  	err = -EINVAL;
  	listnr = rule->flags & ~AUDIT_FILTER_PREPEND;
  	switch(listnr) {
  	default:
  		goto exit_err;
  	case AUDIT_FILTER_USER:
  	case AUDIT_FILTER_TYPE:
  #ifdef CONFIG_AUDITSYSCALL
  	case AUDIT_FILTER_ENTRY:
  	case AUDIT_FILTER_EXIT:
  	case AUDIT_FILTER_TASK:
  #endif
  		;
  	}
014149cce   Al Viro   [PATCH] deprecate...
238
239
240
241
242
243
  	if (unlikely(rule->action == AUDIT_POSSIBLE)) {
  		printk(KERN_ERR "AUDIT_POSSIBLE is deprecated
  ");
  		goto exit_err;
  	}
  	if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS)
93315ed6d   Amy Griffis   [PATCH] audit str...
244
245
246
247
248
  		goto exit_err;
  	if (rule->field_count > AUDIT_MAX_FIELDS)
  		goto exit_err;
  
  	err = -ENOMEM;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
249
250
  	entry = audit_init_entry(rule->field_count);
  	if (!entry)
93315ed6d   Amy Griffis   [PATCH] audit str...
251
  		goto exit_err;
93315ed6d   Amy Griffis   [PATCH] audit str...
252
253
254
255
256
  
  	entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
  	entry->rule.listnr = listnr;
  	entry->rule.action = rule->action;
  	entry->rule.field_count = rule->field_count;
93315ed6d   Amy Griffis   [PATCH] audit str...
257
258
259
  
  	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
  		entry->rule.mask[i] = rule->mask[i];
b915543b4   Al Viro   [PATCH] audit sys...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  	for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) {
  		int bit = AUDIT_BITMASK_SIZE * 32 - i - 1;
  		__u32 *p = &entry->rule.mask[AUDIT_WORD(bit)];
  		__u32 *class;
  
  		if (!(*p & AUDIT_BIT(bit)))
  			continue;
  		*p &= ~AUDIT_BIT(bit);
  		class = classes[i];
  		if (class) {
  			int j;
  			for (j = 0; j < AUDIT_BITMASK_SIZE; j++)
  				entry->rule.mask[j] |= class[j];
  		}
  	}
93315ed6d   Amy Griffis   [PATCH] audit str...
275
276
277
278
279
  	return entry;
  
  exit_err:
  	return ERR_PTR(err);
  }
5af75d8d5   Al Viro   audit: validate c...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  static u32 audit_ops[] =
  {
  	[Audit_equal] = AUDIT_EQUAL,
  	[Audit_not_equal] = AUDIT_NOT_EQUAL,
  	[Audit_bitmask] = AUDIT_BIT_MASK,
  	[Audit_bittest] = AUDIT_BIT_TEST,
  	[Audit_lt] = AUDIT_LESS_THAN,
  	[Audit_gt] = AUDIT_GREATER_THAN,
  	[Audit_le] = AUDIT_LESS_THAN_OR_EQUAL,
  	[Audit_ge] = AUDIT_GREATER_THAN_OR_EQUAL,
  };
  
  static u32 audit_to_op(u32 op)
  {
  	u32 n;
  	for (n = Audit_equal; n < Audit_bad && audit_ops[n] != op; n++)
  		;
  	return n;
  }
93315ed6d   Amy Griffis   [PATCH] audit str...
299
300
301
302
303
304
  /* Translate struct audit_rule to kernel's rule respresentation.
   * Exists for backward compatibility with userspace. */
  static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
  {
  	struct audit_entry *entry;
  	int err = 0;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
305
  	int i;
93315ed6d   Amy Griffis   [PATCH] audit str...
306
307
308
309
310
311
  	entry = audit_to_entry_common(rule);
  	if (IS_ERR(entry))
  		goto exit_nofree;
  
  	for (i = 0; i < rule->field_count; i++) {
  		struct audit_field *f = &entry->rule.fields[i];
5af75d8d5   Al Viro   audit: validate c...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  		u32 n;
  
  		n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
  
  		/* Support for legacy operators where
  		 * AUDIT_NEGATE bit signifies != and otherwise assumes == */
  		if (n & AUDIT_NEGATE)
  			f->op = Audit_not_equal;
  		else if (!n)
  			f->op = Audit_equal;
  		else
  			f->op = audit_to_op(n);
  
  		entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1;
93315ed6d   Amy Griffis   [PATCH] audit str...
326

93315ed6d   Amy Griffis   [PATCH] audit str...
327
328
  		f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
  		f->val = rule->values[i];
f368c07d7   Amy Griffis   [PATCH] audit: pa...
329
  		err = -EINVAL;
5af75d8d5   Al Viro   audit: validate c...
330
331
  		if (f->op == Audit_bad)
  			goto exit_free;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
332
  		switch(f->type) {
0a73dccc4   Al Viro   [PATCH] validate ...
333
  		default:
3dc7e3153   Darrel Goeddel   [PATCH] support f...
334
  			goto exit_free;
0a73dccc4   Al Viro   [PATCH] validate ...
335
336
337
338
339
340
341
342
343
344
345
  		case AUDIT_PID:
  		case AUDIT_UID:
  		case AUDIT_EUID:
  		case AUDIT_SUID:
  		case AUDIT_FSUID:
  		case AUDIT_GID:
  		case AUDIT_EGID:
  		case AUDIT_SGID:
  		case AUDIT_FSGID:
  		case AUDIT_LOGINUID:
  		case AUDIT_PERS:
0a73dccc4   Al Viro   [PATCH] validate ...
346
  		case AUDIT_MSGTYPE:
3b33ac318   Steve Grubb   [PATCH] fix ppid ...
347
  		case AUDIT_PPID:
0a73dccc4   Al Viro   [PATCH] validate ...
348
349
350
351
  		case AUDIT_DEVMAJOR:
  		case AUDIT_DEVMINOR:
  		case AUDIT_EXIT:
  		case AUDIT_SUCCESS:
74f2345b6   Eric Paris   [PATCH] allow aud...
352
  			/* bit ops are only useful on syscall args */
5af75d8d5   Al Viro   audit: validate c...
353
  			if (f->op == Audit_bitmask || f->op == Audit_bittest)
74f2345b6   Eric Paris   [PATCH] allow aud...
354
  				goto exit_free;
74f2345b6   Eric Paris   [PATCH] allow aud...
355
  			break;
0a73dccc4   Al Viro   [PATCH] validate ...
356
357
358
359
360
  		case AUDIT_ARG0:
  		case AUDIT_ARG1:
  		case AUDIT_ARG2:
  		case AUDIT_ARG3:
  			break;
4b8a311bb   Eric Paris   [PATCH] arch filt...
361
362
  		/* arch is only allowed to be = or != */
  		case AUDIT_ARCH:
5af75d8d5   Al Viro   audit: validate c...
363
  			if (f->op != Audit_not_equal && f->op != Audit_equal)
4b8a311bb   Eric Paris   [PATCH] arch filt...
364
  				goto exit_free;
e54dc2431   Amy Griffis   [PATCH] audit sig...
365
  			entry->rule.arch_f = f;
4b8a311bb   Eric Paris   [PATCH] arch filt...
366
  			break;
55669bfa1   Al Viro   [PATCH] audit: AU...
367
368
369
370
  		case AUDIT_PERM:
  			if (f->val & ~15)
  				goto exit_free;
  			break;
8b67dca94   Al Viro   [PATCH] new predi...
371
372
373
374
  		case AUDIT_FILETYPE:
  			if ((f->val & ~S_IFMT) > S_IFMT)
  				goto exit_free;
  			break;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
375
376
377
378
379
  		case AUDIT_INODE:
  			err = audit_to_inode(&entry->rule, f);
  			if (err)
  				goto exit_free;
  			break;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
380
  		}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
381
  	}
93315ed6d   Amy Griffis   [PATCH] audit str...
382

5af75d8d5   Al Viro   audit: validate c...
383
384
  	if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
  		entry->rule.inode_f = NULL;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
385

93315ed6d   Amy Griffis   [PATCH] audit str...
386
387
388
389
390
391
  exit_nofree:
  	return entry;
  
  exit_free:
  	audit_free_rule(entry);
  	return ERR_PTR(err);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
392
  }
93315ed6d   Amy Griffis   [PATCH] audit str...
393
394
395
  /* Translate struct audit_rule_data to kernel's rule respresentation. */
  static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
  					       size_t datasz)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
396
  {
93315ed6d   Amy Griffis   [PATCH] audit str...
397
398
399
  	int err = 0;
  	struct audit_entry *entry;
  	void *bufp;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
400
  	size_t remain = datasz - sizeof(struct audit_rule_data);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
401
  	int i;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
402
  	char *str;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
403

93315ed6d   Amy Griffis   [PATCH] audit str...
404
405
406
  	entry = audit_to_entry_common((struct audit_rule *)data);
  	if (IS_ERR(entry))
  		goto exit_nofree;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
407

93315ed6d   Amy Griffis   [PATCH] audit str...
408
409
410
411
412
413
  	bufp = data->buf;
  	entry->rule.vers_ops = 2;
  	for (i = 0; i < data->field_count; i++) {
  		struct audit_field *f = &entry->rule.fields[i];
  
  		err = -EINVAL;
5af75d8d5   Al Viro   audit: validate c...
414
415
416
  
  		f->op = audit_to_op(data->fieldflags[i]);
  		if (f->op == Audit_bad)
93315ed6d   Amy Griffis   [PATCH] audit str...
417
  			goto exit_free;
93315ed6d   Amy Griffis   [PATCH] audit str...
418
  		f->type = data->fields[i];
3dc7e3153   Darrel Goeddel   [PATCH] support f...
419
  		f->val = data->values[i];
04305e4af   Ahmed S. Darwish   Audit: Final rena...
420
421
  		f->lsm_str = NULL;
  		f->lsm_rule = NULL;
93315ed6d   Amy Griffis   [PATCH] audit str...
422
  		switch(f->type) {
0a73dccc4   Al Viro   [PATCH] validate ...
423
424
425
426
427
428
429
430
431
432
433
  		case AUDIT_PID:
  		case AUDIT_UID:
  		case AUDIT_EUID:
  		case AUDIT_SUID:
  		case AUDIT_FSUID:
  		case AUDIT_GID:
  		case AUDIT_EGID:
  		case AUDIT_SGID:
  		case AUDIT_FSGID:
  		case AUDIT_LOGINUID:
  		case AUDIT_PERS:
0a73dccc4   Al Viro   [PATCH] validate ...
434
435
436
437
438
439
440
441
442
443
444
  		case AUDIT_MSGTYPE:
  		case AUDIT_PPID:
  		case AUDIT_DEVMAJOR:
  		case AUDIT_DEVMINOR:
  		case AUDIT_EXIT:
  		case AUDIT_SUCCESS:
  		case AUDIT_ARG0:
  		case AUDIT_ARG1:
  		case AUDIT_ARG2:
  		case AUDIT_ARG3:
  			break;
e54dc2431   Amy Griffis   [PATCH] audit sig...
445
446
447
  		case AUDIT_ARCH:
  			entry->rule.arch_f = f;
  			break;
3a6b9f85c   Darrel Goeddel   [PATCH] audit: re...
448
449
450
451
452
  		case AUDIT_SUBJ_USER:
  		case AUDIT_SUBJ_ROLE:
  		case AUDIT_SUBJ_TYPE:
  		case AUDIT_SUBJ_SEN:
  		case AUDIT_SUBJ_CLR:
6e5a2d1d3   Darrel Goeddel   [PATCH] audit: su...
453
454
455
456
457
  		case AUDIT_OBJ_USER:
  		case AUDIT_OBJ_ROLE:
  		case AUDIT_OBJ_TYPE:
  		case AUDIT_OBJ_LEV_LOW:
  		case AUDIT_OBJ_LEV_HIGH:
3dc7e3153   Darrel Goeddel   [PATCH] support f...
458
459
460
461
  			str = audit_unpack_string(&bufp, &remain, f->val);
  			if (IS_ERR(str))
  				goto exit_free;
  			entry->rule.buflen += f->val;
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
462
  			err = security_audit_rule_init(f->type, f->op, str,
04305e4af   Ahmed S. Darwish   Audit: Final rena...
463
  						       (void **)&f->lsm_rule);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
464
465
466
  			/* Keep currently invalid fields around in case they
  			 * become valid after a policy reload. */
  			if (err == -EINVAL) {
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
467
  				printk(KERN_WARNING "audit rule for LSM "
3dc7e3153   Darrel Goeddel   [PATCH] support f...
468
469
470
471
472
473
474
475
  				       "\'%s\' is invalid
  ",  str);
  				err = 0;
  			}
  			if (err) {
  				kfree(str);
  				goto exit_free;
  			} else
04305e4af   Ahmed S. Darwish   Audit: Final rena...
476
  				f->lsm_str = str;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
477
  			break;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
478
479
480
481
482
483
484
485
486
487
488
489
  		case AUDIT_WATCH:
  			str = audit_unpack_string(&bufp, &remain, f->val);
  			if (IS_ERR(str))
  				goto exit_free;
  			entry->rule.buflen += f->val;
  
  			err = audit_to_watch(&entry->rule, str, f->val, f->op);
  			if (err) {
  				kfree(str);
  				goto exit_free;
  			}
  			break;
74c3cbe33   Al Viro   [PATCH] audit: wa...
490
491
492
493
494
495
496
497
498
499
500
  		case AUDIT_DIR:
  			str = audit_unpack_string(&bufp, &remain, f->val);
  			if (IS_ERR(str))
  				goto exit_free;
  			entry->rule.buflen += f->val;
  
  			err = audit_make_tree(&entry->rule, str, f->op);
  			kfree(str);
  			if (err)
  				goto exit_free;
  			break;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
501
502
503
504
505
  		case AUDIT_INODE:
  			err = audit_to_inode(&entry->rule, f);
  			if (err)
  				goto exit_free;
  			break;
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
506
507
508
509
510
511
512
513
514
515
  		case AUDIT_FILTERKEY:
  			err = -EINVAL;
  			if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
  				goto exit_free;
  			str = audit_unpack_string(&bufp, &remain, f->val);
  			if (IS_ERR(str))
  				goto exit_free;
  			entry->rule.buflen += f->val;
  			entry->rule.filterkey = str;
  			break;
55669bfa1   Al Viro   [PATCH] audit: AU...
516
517
518
519
  		case AUDIT_PERM:
  			if (f->val & ~15)
  				goto exit_free;
  			break;
8b67dca94   Al Viro   [PATCH] new predi...
520
521
522
523
  		case AUDIT_FILETYPE:
  			if ((f->val & ~S_IFMT) > S_IFMT)
  				goto exit_free;
  			break;
0a73dccc4   Al Viro   [PATCH] validate ...
524
525
  		default:
  			goto exit_free;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
526
527
  		}
  	}
5af75d8d5   Al Viro   audit: validate c...
528
529
  	if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
  		entry->rule.inode_f = NULL;
93315ed6d   Amy Griffis   [PATCH] audit str...
530
531
532
533
534
535
536
537
538
539
  
  exit_nofree:
  	return entry;
  
  exit_free:
  	audit_free_rule(entry);
  	return ERR_PTR(err);
  }
  
  /* Pack a filter field's string representation into data block. */
74c3cbe33   Al Viro   [PATCH] audit: wa...
540
  static inline size_t audit_pack_string(void **bufp, const char *str)
93315ed6d   Amy Griffis   [PATCH] audit str...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  {
  	size_t len = strlen(str);
  
  	memcpy(*bufp, str, len);
  	*bufp += len;
  
  	return len;
  }
  
  /* Translate kernel rule respresentation to struct audit_rule.
   * Exists for backward compatibility with userspace. */
  static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
  {
  	struct audit_rule *rule;
  	int i;
4668edc33   Burman Yan   [PATCH] kernel co...
556
  	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
93315ed6d   Amy Griffis   [PATCH] audit str...
557
  	if (unlikely(!rule))
0a3b483e8   Amy Griffis   [PATCH] fix audit...
558
  		return NULL;
93315ed6d   Amy Griffis   [PATCH] audit str...
559
560
561
562
563
564
565
566
567
  
  	rule->flags = krule->flags | krule->listnr;
  	rule->action = krule->action;
  	rule->field_count = krule->field_count;
  	for (i = 0; i < rule->field_count; i++) {
  		rule->values[i] = krule->fields[i].val;
  		rule->fields[i] = krule->fields[i].type;
  
  		if (krule->vers_ops == 1) {
5af75d8d5   Al Viro   audit: validate c...
568
  			if (krule->fields[i].op == Audit_not_equal)
93315ed6d   Amy Griffis   [PATCH] audit str...
569
570
  				rule->fields[i] |= AUDIT_NEGATE;
  		} else {
5af75d8d5   Al Viro   audit: validate c...
571
  			rule->fields[i] |= audit_ops[krule->fields[i].op];
93315ed6d   Amy Griffis   [PATCH] audit str...
572
573
574
575
576
577
  		}
  	}
  	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
  
  	return rule;
  }
fe7752bab   David Woodhouse   [PATCH] Fix audit...
578

93315ed6d   Amy Griffis   [PATCH] audit str...
579
580
581
582
583
584
585
586
587
  /* Translate kernel rule respresentation to struct audit_rule_data. */
  static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
  {
  	struct audit_rule_data *data;
  	void *bufp;
  	int i;
  
  	data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
  	if (unlikely(!data))
0a3b483e8   Amy Griffis   [PATCH] fix audit...
588
  		return NULL;
93315ed6d   Amy Griffis   [PATCH] audit str...
589
590
591
592
593
594
595
596
597
598
  	memset(data, 0, sizeof(*data));
  
  	data->flags = krule->flags | krule->listnr;
  	data->action = krule->action;
  	data->field_count = krule->field_count;
  	bufp = data->buf;
  	for (i = 0; i < data->field_count; i++) {
  		struct audit_field *f = &krule->fields[i];
  
  		data->fields[i] = f->type;
5af75d8d5   Al Viro   audit: validate c...
599
  		data->fieldflags[i] = audit_ops[f->op];
93315ed6d   Amy Griffis   [PATCH] audit str...
600
  		switch(f->type) {
3a6b9f85c   Darrel Goeddel   [PATCH] audit: re...
601
602
603
604
605
  		case AUDIT_SUBJ_USER:
  		case AUDIT_SUBJ_ROLE:
  		case AUDIT_SUBJ_TYPE:
  		case AUDIT_SUBJ_SEN:
  		case AUDIT_SUBJ_CLR:
6e5a2d1d3   Darrel Goeddel   [PATCH] audit: su...
606
607
608
609
610
  		case AUDIT_OBJ_USER:
  		case AUDIT_OBJ_ROLE:
  		case AUDIT_OBJ_TYPE:
  		case AUDIT_OBJ_LEV_LOW:
  		case AUDIT_OBJ_LEV_HIGH:
3dc7e3153   Darrel Goeddel   [PATCH] support f...
611
  			data->buflen += data->values[i] =
04305e4af   Ahmed S. Darwish   Audit: Final rena...
612
  				audit_pack_string(&bufp, f->lsm_str);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
613
  			break;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
614
615
  		case AUDIT_WATCH:
  			data->buflen += data->values[i] =
cfcad62c7   Eric Paris   audit: seperate a...
616
617
  				audit_pack_string(&bufp,
  						  audit_watch_path(krule->watch));
f368c07d7   Amy Griffis   [PATCH] audit: pa...
618
  			break;
74c3cbe33   Al Viro   [PATCH] audit: wa...
619
620
621
622
623
  		case AUDIT_DIR:
  			data->buflen += data->values[i] =
  				audit_pack_string(&bufp,
  						  audit_tree_path(krule->tree));
  			break;
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
624
625
626
627
  		case AUDIT_FILTERKEY:
  			data->buflen += data->values[i] =
  				audit_pack_string(&bufp, krule->filterkey);
  			break;
93315ed6d   Amy Griffis   [PATCH] audit str...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  		default:
  			data->values[i] = f->val;
  		}
  	}
  	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) data->mask[i] = krule->mask[i];
  
  	return data;
  }
  
  /* Compare two rules in kernel format.  Considered success if rules
   * don't match. */
  static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
  {
  	int i;
  
  	if (a->flags != b->flags ||
  	    a->listnr != b->listnr ||
  	    a->action != b->action ||
  	    a->field_count != b->field_count)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
647
648
649
  		return 1;
  
  	for (i = 0; i < a->field_count; i++) {
93315ed6d   Amy Griffis   [PATCH] audit str...
650
651
  		if (a->fields[i].type != b->fields[i].type ||
  		    a->fields[i].op != b->fields[i].op)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
652
  			return 1;
93315ed6d   Amy Griffis   [PATCH] audit str...
653
654
  
  		switch(a->fields[i].type) {
3a6b9f85c   Darrel Goeddel   [PATCH] audit: re...
655
656
657
658
659
  		case AUDIT_SUBJ_USER:
  		case AUDIT_SUBJ_ROLE:
  		case AUDIT_SUBJ_TYPE:
  		case AUDIT_SUBJ_SEN:
  		case AUDIT_SUBJ_CLR:
6e5a2d1d3   Darrel Goeddel   [PATCH] audit: su...
660
661
662
663
664
  		case AUDIT_OBJ_USER:
  		case AUDIT_OBJ_ROLE:
  		case AUDIT_OBJ_TYPE:
  		case AUDIT_OBJ_LEV_LOW:
  		case AUDIT_OBJ_LEV_HIGH:
04305e4af   Ahmed S. Darwish   Audit: Final rena...
665
  			if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str))
3dc7e3153   Darrel Goeddel   [PATCH] support f...
666
667
  				return 1;
  			break;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
668
  		case AUDIT_WATCH:
cfcad62c7   Eric Paris   audit: seperate a...
669
670
  			if (strcmp(audit_watch_path(a->watch),
  				   audit_watch_path(b->watch)))
f368c07d7   Amy Griffis   [PATCH] audit: pa...
671
672
  				return 1;
  			break;
74c3cbe33   Al Viro   [PATCH] audit: wa...
673
674
675
676
677
  		case AUDIT_DIR:
  			if (strcmp(audit_tree_path(a->tree),
  				   audit_tree_path(b->tree)))
  				return 1;
  			break;
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
678
679
680
681
682
  		case AUDIT_FILTERKEY:
  			/* both filterkeys exist based on above type compare */
  			if (strcmp(a->filterkey, b->filterkey))
  				return 1;
  			break;
93315ed6d   Amy Griffis   [PATCH] audit str...
683
684
685
686
  		default:
  			if (a->fields[i].val != b->fields[i].val)
  				return 1;
  		}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
687
688
689
690
691
692
693
694
  	}
  
  	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
  		if (a->mask[i] != b->mask[i])
  			return 1;
  
  	return 0;
  }
04305e4af   Ahmed S. Darwish   Audit: Final rena...
695
  /* Duplicate LSM field information.  The lsm_rule is opaque, so must be
3dc7e3153   Darrel Goeddel   [PATCH] support f...
696
   * re-initialized. */
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
697
  static inline int audit_dupe_lsm_field(struct audit_field *df,
3dc7e3153   Darrel Goeddel   [PATCH] support f...
698
699
700
  					   struct audit_field *sf)
  {
  	int ret = 0;
04305e4af   Ahmed S. Darwish   Audit: Final rena...
701
  	char *lsm_str;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
702

04305e4af   Ahmed S. Darwish   Audit: Final rena...
703
704
705
  	/* our own copy of lsm_str */
  	lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL);
  	if (unlikely(!lsm_str))
3e1fbd12c   Akinobu Mita   [PATCH] audit: fi...
706
  		return -ENOMEM;
04305e4af   Ahmed S. Darwish   Audit: Final rena...
707
  	df->lsm_str = lsm_str;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
708

04305e4af   Ahmed S. Darwish   Audit: Final rena...
709
710
711
  	/* our own (refreshed) copy of lsm_rule */
  	ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
  				       (void **)&df->lsm_rule);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
712
713
714
  	/* Keep currently invalid fields around in case they
  	 * become valid after a policy reload. */
  	if (ret == -EINVAL) {
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
715
  		printk(KERN_WARNING "audit rule for LSM \'%s\' is "
04305e4af   Ahmed S. Darwish   Audit: Final rena...
716
717
  		       "invalid
  ", df->lsm_str);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
718
719
720
721
722
723
724
  		ret = 0;
  	}
  
  	return ret;
  }
  
  /* Duplicate an audit rule.  This will be a deep copy with the exception
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
725
   * of the watch - that pointer is carried over.  The LSM specific fields
3dc7e3153   Darrel Goeddel   [PATCH] support f...
726
   * will be updated in the copy.  The point is to be able to replace the old
f368c07d7   Amy Griffis   [PATCH] audit: pa...
727
728
729
   * rule with the new rule in the filterlist, then free the old rule.
   * The rlist element is undefined; list manipulations are handled apart from
   * the initial copy. */
ae7b8f410   Eric Paris   Audit: clean up t...
730
  struct audit_entry *audit_dupe_rule(struct audit_krule *old)
3dc7e3153   Darrel Goeddel   [PATCH] support f...
731
732
733
734
  {
  	u32 fcount = old->field_count;
  	struct audit_entry *entry;
  	struct audit_krule *new;
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
735
  	char *fk;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
736
737
738
739
740
741
742
743
744
745
746
747
748
  	int i, err = 0;
  
  	entry = audit_init_entry(fcount);
  	if (unlikely(!entry))
  		return ERR_PTR(-ENOMEM);
  
  	new = &entry->rule;
  	new->vers_ops = old->vers_ops;
  	new->flags = old->flags;
  	new->listnr = old->listnr;
  	new->action = old->action;
  	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
  		new->mask[i] = old->mask[i];
0590b9335   Al Viro   fixing audit rule...
749
  	new->prio = old->prio;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
750
  	new->buflen = old->buflen;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
751
  	new->inode_f = old->inode_f;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
752
  	new->field_count = old->field_count;
ae7b8f410   Eric Paris   Audit: clean up t...
753

74c3cbe33   Al Viro   [PATCH] audit: wa...
754
755
756
757
758
759
760
761
  	/*
  	 * note that we are OK with not refcounting here; audit_match_tree()
  	 * never dereferences tree and we can't get false positives there
  	 * since we'd have to have rule gone from the list *and* removed
  	 * before the chunks found by lookup had been allocated, i.e. before
  	 * the beginning of list scan.
  	 */
  	new->tree = old->tree;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
762
  	memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
04305e4af   Ahmed S. Darwish   Audit: Final rena...
763
  	/* deep copy this information, updating the lsm_rule fields, because
3dc7e3153   Darrel Goeddel   [PATCH] support f...
764
765
766
  	 * the originals will all be freed when the old rule is freed. */
  	for (i = 0; i < fcount; i++) {
  		switch (new->fields[i].type) {
3a6b9f85c   Darrel Goeddel   [PATCH] audit: re...
767
768
769
770
771
  		case AUDIT_SUBJ_USER:
  		case AUDIT_SUBJ_ROLE:
  		case AUDIT_SUBJ_TYPE:
  		case AUDIT_SUBJ_SEN:
  		case AUDIT_SUBJ_CLR:
6e5a2d1d3   Darrel Goeddel   [PATCH] audit: su...
772
773
774
775
776
  		case AUDIT_OBJ_USER:
  		case AUDIT_OBJ_ROLE:
  		case AUDIT_OBJ_TYPE:
  		case AUDIT_OBJ_LEV_LOW:
  		case AUDIT_OBJ_LEV_HIGH:
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
777
  			err = audit_dupe_lsm_field(&new->fields[i],
3dc7e3153   Darrel Goeddel   [PATCH] support f...
778
  						       &old->fields[i]);
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
779
780
781
782
783
784
785
  			break;
  		case AUDIT_FILTERKEY:
  			fk = kstrdup(old->filterkey, GFP_KERNEL);
  			if (unlikely(!fk))
  				err = -ENOMEM;
  			else
  				new->filterkey = fk;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
786
787
788
789
790
791
  		}
  		if (err) {
  			audit_free_rule(entry);
  			return ERR_PTR(err);
  		}
  	}
ae7b8f410   Eric Paris   Audit: clean up t...
792
793
794
  	if (old->watch) {
  		audit_get_watch(old->watch);
  		new->watch = old->watch;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
795
  	}
3dc7e3153   Darrel Goeddel   [PATCH] support f...
796
797
  	return entry;
  }
f368c07d7   Amy Griffis   [PATCH] audit: pa...
798
799
800
  /* Find an existing audit rule.
   * Caller must hold audit_filter_mutex to prevent stale rule data. */
  static struct audit_entry *audit_find_rule(struct audit_entry *entry,
36c4f1b18   Al Viro   clean up audit_ru...
801
  					   struct list_head **p)
f368c07d7   Amy Griffis   [PATCH] audit: pa...
802
803
  {
  	struct audit_entry *e, *found = NULL;
36c4f1b18   Al Viro   clean up audit_ru...
804
  	struct list_head *list;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
805
  	int h;
36c4f1b18   Al Viro   clean up audit_ru...
806
807
808
809
  	if (entry->rule.inode_f) {
  		h = audit_hash_ino(entry->rule.inode_f->val);
  		*p = list = &audit_inode_hash[h];
  	} else if (entry->rule.watch) {
f368c07d7   Amy Griffis   [PATCH] audit: pa...
810
811
812
813
814
815
816
817
818
819
  		/* we don't know the inode number, so must walk entire hash */
  		for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
  			list = &audit_inode_hash[h];
  			list_for_each_entry(e, list, list)
  				if (!audit_compare_rule(&entry->rule, &e->rule)) {
  					found = e;
  					goto out;
  				}
  		}
  		goto out;
36c4f1b18   Al Viro   clean up audit_ru...
820
821
  	} else {
  		*p = list = &audit_filter_list[entry->rule.listnr];
f368c07d7   Amy Griffis   [PATCH] audit: pa...
822
823
824
825
826
827
828
829
830
831
832
  	}
  
  	list_for_each_entry(e, list, list)
  		if (!audit_compare_rule(&entry->rule, &e->rule)) {
  			found = e;
  			goto out;
  		}
  
  out:
  	return found;
  }
0590b9335   Al Viro   fixing audit rule...
833
834
  static u64 prio_low = ~0ULL/2;
  static u64 prio_high = ~0ULL/2 - 1;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
835
  /* Add rule to given filterlist if not a duplicate. */
36c4f1b18   Al Viro   clean up audit_ru...
836
  static inline int audit_add_rule(struct audit_entry *entry)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
837
  {
93315ed6d   Amy Griffis   [PATCH] audit str...
838
  	struct audit_entry *e;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
839
  	struct audit_watch *watch = entry->rule.watch;
74c3cbe33   Al Viro   [PATCH] audit: wa...
840
  	struct audit_tree *tree = entry->rule.tree;
36c4f1b18   Al Viro   clean up audit_ru...
841
  	struct list_head *list;
ae7b8f410   Eric Paris   Audit: clean up t...
842
  	int err;
471a5c7c8   Al Viro   [PATCH] introduce...
843
844
845
846
847
848
849
850
  #ifdef CONFIG_AUDITSYSCALL
  	int dont_count = 0;
  
  	/* If either of these, don't count towards total */
  	if (entry->rule.listnr == AUDIT_FILTER_USER ||
  		entry->rule.listnr == AUDIT_FILTER_TYPE)
  		dont_count = 1;
  #endif
f368c07d7   Amy Griffis   [PATCH] audit: pa...
851

f368c07d7   Amy Griffis   [PATCH] audit: pa...
852
  	mutex_lock(&audit_filter_mutex);
36c4f1b18   Al Viro   clean up audit_ru...
853
  	e = audit_find_rule(entry, &list);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
854
  	if (e) {
35fe4d0b1   Eric Paris   Audit: move audit...
855
  		mutex_unlock(&audit_filter_mutex);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
856
  		err = -EEXIST;
74c3cbe33   Al Viro   [PATCH] audit: wa...
857
858
859
  		/* normally audit_add_tree_rule() will free it on failure */
  		if (tree)
  			audit_put_tree(tree);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
860
861
  		goto error;
  	}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
862

f368c07d7   Amy Griffis   [PATCH] audit: pa...
863
864
  	if (watch) {
  		/* audit_filter_mutex is dropped and re-taken during this call */
ae7b8f410   Eric Paris   Audit: clean up t...
865
  		err = audit_add_watch(&entry->rule, &list);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
866
867
868
869
  		if (err) {
  			mutex_unlock(&audit_filter_mutex);
  			goto error;
  		}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
870
  	}
74c3cbe33   Al Viro   [PATCH] audit: wa...
871
872
873
874
875
876
877
  	if (tree) {
  		err = audit_add_tree_rule(&entry->rule);
  		if (err) {
  			mutex_unlock(&audit_filter_mutex);
  			goto error;
  		}
  	}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
878

0590b9335   Al Viro   fixing audit rule...
879
880
881
882
883
884
885
  	entry->rule.prio = ~0ULL;
  	if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
  		if (entry->rule.flags & AUDIT_FILTER_PREPEND)
  			entry->rule.prio = ++prio_high;
  		else
  			entry->rule.prio = --prio_low;
  	}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
886
  	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
e45aa212e   Al Viro   audit rules order...
887
888
  		list_add(&entry->rule.list,
  			 &audit_rules_list[entry->rule.listnr]);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
889
  		list_add_rcu(&entry->list, list);
6a2bceec0   Amy Griffis   [PATCH] fix AUDIT...
890
  		entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
891
  	} else {
e45aa212e   Al Viro   audit rules order...
892
893
  		list_add_tail(&entry->rule.list,
  			      &audit_rules_list[entry->rule.listnr]);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
894
895
  		list_add_tail_rcu(&entry->list, list);
  	}
471a5c7c8   Al Viro   [PATCH] introduce...
896
897
898
  #ifdef CONFIG_AUDITSYSCALL
  	if (!dont_count)
  		audit_n_rules++;
e54dc2431   Amy Griffis   [PATCH] audit sig...
899
900
901
  
  	if (!audit_match_signal(entry))
  		audit_signals++;
471a5c7c8   Al Viro   [PATCH] introduce...
902
  #endif
f368c07d7   Amy Griffis   [PATCH] audit: pa...
903
  	mutex_unlock(&audit_filter_mutex);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
904

f368c07d7   Amy Griffis   [PATCH] audit: pa...
905
906
907
   	return 0;
  
  error:
f368c07d7   Amy Griffis   [PATCH] audit: pa...
908
909
910
  	if (watch)
  		audit_put_watch(watch); /* tmp watch, matches initial get */
  	return err;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
911
  }
f368c07d7   Amy Griffis   [PATCH] audit: pa...
912
  /* Remove an existing rule from filterlist. */
36c4f1b18   Al Viro   clean up audit_ru...
913
  static inline int audit_del_rule(struct audit_entry *entry)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
914
915
  {
  	struct audit_entry  *e;
cfcad62c7   Eric Paris   audit: seperate a...
916
  	struct audit_watch *watch = entry->rule.watch;
74c3cbe33   Al Viro   [PATCH] audit: wa...
917
  	struct audit_tree *tree = entry->rule.tree;
36c4f1b18   Al Viro   clean up audit_ru...
918
  	struct list_head *list;
36c4f1b18   Al Viro   clean up audit_ru...
919
  	int ret = 0;
471a5c7c8   Al Viro   [PATCH] introduce...
920
921
922
923
924
925
926
927
  #ifdef CONFIG_AUDITSYSCALL
  	int dont_count = 0;
  
  	/* If either of these, don't count towards total */
  	if (entry->rule.listnr == AUDIT_FILTER_USER ||
  		entry->rule.listnr == AUDIT_FILTER_TYPE)
  		dont_count = 1;
  #endif
f368c07d7   Amy Griffis   [PATCH] audit: pa...
928

f368c07d7   Amy Griffis   [PATCH] audit: pa...
929
  	mutex_lock(&audit_filter_mutex);
36c4f1b18   Al Viro   clean up audit_ru...
930
  	e = audit_find_rule(entry, &list);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
931
932
933
934
935
  	if (!e) {
  		mutex_unlock(&audit_filter_mutex);
  		ret = -ENOENT;
  		goto out;
  	}
cfcad62c7   Eric Paris   audit: seperate a...
936
  	if (e->rule.watch)
a05fb6cc5   Eric Paris   audit: do not get...
937
  		audit_remove_watch_rule(&e->rule);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
938

74c3cbe33   Al Viro   [PATCH] audit: wa...
939
940
  	if (e->rule.tree)
  		audit_remove_tree_rule(&e->rule);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
941
  	list_del_rcu(&e->list);
e45aa212e   Al Viro   audit rules order...
942
  	list_del(&e->rule.list);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
943
  	call_rcu(&e->rcu, audit_free_rule_rcu);
471a5c7c8   Al Viro   [PATCH] introduce...
944
945
946
  #ifdef CONFIG_AUDITSYSCALL
  	if (!dont_count)
  		audit_n_rules--;
e54dc2431   Amy Griffis   [PATCH] audit sig...
947
948
949
  
  	if (!audit_match_signal(entry))
  		audit_signals--;
471a5c7c8   Al Viro   [PATCH] introduce...
950
  #endif
f368c07d7   Amy Griffis   [PATCH] audit: pa...
951
  	mutex_unlock(&audit_filter_mutex);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
952
  out:
cfcad62c7   Eric Paris   audit: seperate a...
953
954
  	if (watch)
  		audit_put_watch(watch); /* match initial get */
74c3cbe33   Al Viro   [PATCH] audit: wa...
955
956
  	if (tree)
  		audit_put_tree(tree);	/* that's the temporary one */
f368c07d7   Amy Griffis   [PATCH] audit: pa...
957
958
  
  	return ret;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
959
  }
93315ed6d   Amy Griffis   [PATCH] audit str...
960
961
  /* List rules using struct audit_rule.  Exists for backward
   * compatibility with userspace. */
9044e6bca   Al Viro   [PATCH] fix deadl...
962
  static void audit_list(int pid, int seq, struct sk_buff_head *q)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
963
  {
9044e6bca   Al Viro   [PATCH] fix deadl...
964
  	struct sk_buff *skb;
e45aa212e   Al Viro   audit rules order...
965
  	struct audit_krule *r;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
966
  	int i;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
967
968
  	/* This is a blocking read, so use audit_filter_mutex instead of rcu
  	 * iterator to sync with list writers. */
fe7752bab   David Woodhouse   [PATCH] Fix audit...
969
  	for (i=0; i<AUDIT_NR_FILTERS; i++) {
e45aa212e   Al Viro   audit rules order...
970
  		list_for_each_entry(r, &audit_rules_list[i], list) {
f368c07d7   Amy Griffis   [PATCH] audit: pa...
971
  			struct audit_rule *rule;
e45aa212e   Al Viro   audit rules order...
972
  			rule = audit_krule_to_rule(r);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
973
974
975
976
977
978
979
980
981
  			if (unlikely(!rule))
  				break;
  			skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
  					 rule, sizeof(*rule));
  			if (skb)
  				skb_queue_tail(q, skb);
  			kfree(rule);
  		}
  	}
9044e6bca   Al Viro   [PATCH] fix deadl...
982
983
984
  	skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
  	if (skb)
  		skb_queue_tail(q, skb);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
985
  }
93315ed6d   Amy Griffis   [PATCH] audit str...
986
  /* List rules using struct audit_rule_data. */
9044e6bca   Al Viro   [PATCH] fix deadl...
987
  static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
93315ed6d   Amy Griffis   [PATCH] audit str...
988
  {
9044e6bca   Al Viro   [PATCH] fix deadl...
989
  	struct sk_buff *skb;
e45aa212e   Al Viro   audit rules order...
990
  	struct audit_krule *r;
93315ed6d   Amy Griffis   [PATCH] audit str...
991
  	int i;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
992
993
  	/* This is a blocking read, so use audit_filter_mutex instead of rcu
  	 * iterator to sync with list writers. */
93315ed6d   Amy Griffis   [PATCH] audit str...
994
  	for (i=0; i<AUDIT_NR_FILTERS; i++) {
e45aa212e   Al Viro   audit rules order...
995
  		list_for_each_entry(r, &audit_rules_list[i], list) {
f368c07d7   Amy Griffis   [PATCH] audit: pa...
996
  			struct audit_rule_data *data;
e45aa212e   Al Viro   audit rules order...
997
  			data = audit_krule_to_data(r);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
998
999
1000
1001
  			if (unlikely(!data))
  				break;
  			skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
  					 data, sizeof(*data) + data->buflen);
9044e6bca   Al Viro   [PATCH] fix deadl...
1002
1003
  			if (skb)
  				skb_queue_tail(q, skb);
93315ed6d   Amy Griffis   [PATCH] audit str...
1004
1005
1006
  			kfree(data);
  		}
  	}
9044e6bca   Al Viro   [PATCH] fix deadl...
1007
1008
1009
  	skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
  	if (skb)
  		skb_queue_tail(q, skb);
93315ed6d   Amy Griffis   [PATCH] audit str...
1010
  }
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1011
  /* Log rule additions and removals */
2532386f4   Eric Paris   Audit: collect se...
1012
1013
1014
  static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid,
  				  char *action, struct audit_krule *rule,
  				  int res)
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1015
1016
  {
  	struct audit_buffer *ab;
1a6b9f231   Eric Paris   [AUDIT] make audi...
1017
1018
  	if (!audit_enabled)
  		return;
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1019
1020
1021
  	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
  	if (!ab)
  		return;
2532386f4   Eric Paris   Audit: collect se...
1022
  	audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid);
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1023
1024
1025
  	if (sid) {
  		char *ctx = NULL;
  		u32 len;
2a862b32f   Ahmed S. Darwish   Audit: use new LS...
1026
  		if (security_secid_to_secctx(sid, &ctx, &len))
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1027
  			audit_log_format(ab, " ssid=%u", sid);
2a862b32f   Ahmed S. Darwish   Audit: use new LS...
1028
  		else {
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1029
  			audit_log_format(ab, " subj=%s", ctx);
2a862b32f   Ahmed S. Darwish   Audit: use new LS...
1030
1031
  			security_release_secctx(ctx, len);
  		}
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1032
  	}
9d9609851   Eric Paris   Audit: clean up a...
1033
1034
1035
  	audit_log_format(ab, " op=");
  	audit_log_string(ab, action);
  	audit_log_key(ab, rule->filterkey);
5adc8a6ad   Amy Griffis   [PATCH] add rule ...
1036
1037
1038
  	audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
  	audit_log_end(ab);
  }
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1039
1040
1041
1042
1043
1044
1045
  /**
   * audit_receive_filter - apply all rules to the specified message type
   * @type: audit message type
   * @pid: target pid for netlink audit messages
   * @uid: target uid for netlink audit messages
   * @seq: netlink audit message sequence (serial) number
   * @data: payload data
93315ed6d   Amy Griffis   [PATCH] audit str...
1046
   * @datasz: size of payload data
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1047
   * @loginuid: loginuid of sender
9f0aecdd1   Randy Dunlap   [PATCH] audit: fi...
1048
   * @sessionid: sessionid for netlink audit message
ce29b682e   Steve Grubb   [PATCH] More user...
1049
   * @sid: SE Linux Security ID of sender
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1050
1051
   */
  int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
2532386f4   Eric Paris   Audit: collect se...
1052
  			 size_t datasz, uid_t loginuid, u32 sessionid, u32 sid)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1053
1054
  {
  	struct task_struct *tsk;
9044e6bca   Al Viro   [PATCH] fix deadl...
1055
  	struct audit_netlink_list *dest;
93315ed6d   Amy Griffis   [PATCH] audit str...
1056
1057
  	int err = 0;
  	struct audit_entry *entry;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1058
1059
1060
  
  	switch (type) {
  	case AUDIT_LIST:
93315ed6d   Amy Griffis   [PATCH] audit str...
1061
  	case AUDIT_LIST_RULES:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1062
1063
1064
1065
1066
  		/* We can't just spew out the rules here because we might fill
  		 * the available socket buffer space and deadlock waiting for
  		 * auditctl to read from it... which isn't ever going to
  		 * happen if we're actually running in the context of auditctl
  		 * trying to _send_ the stuff */
9ce34218a   Daniel Walker   whitespace fixes:...
1067

9044e6bca   Al Viro   [PATCH] fix deadl...
1068
  		dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1069
1070
  		if (!dest)
  			return -ENOMEM;
9044e6bca   Al Viro   [PATCH] fix deadl...
1071
1072
  		dest->pid = pid;
  		skb_queue_head_init(&dest->q);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1073

f368c07d7   Amy Griffis   [PATCH] audit: pa...
1074
  		mutex_lock(&audit_filter_mutex);
93315ed6d   Amy Griffis   [PATCH] audit str...
1075
  		if (type == AUDIT_LIST)
9044e6bca   Al Viro   [PATCH] fix deadl...
1076
  			audit_list(pid, seq, &dest->q);
93315ed6d   Amy Griffis   [PATCH] audit str...
1077
  		else
9044e6bca   Al Viro   [PATCH] fix deadl...
1078
  			audit_list_rules(pid, seq, &dest->q);
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1079
  		mutex_unlock(&audit_filter_mutex);
9044e6bca   Al Viro   [PATCH] fix deadl...
1080
1081
  
  		tsk = kthread_run(audit_send_list, dest, "audit_send_list");
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1082
  		if (IS_ERR(tsk)) {
9044e6bca   Al Viro   [PATCH] fix deadl...
1083
  			skb_queue_purge(&dest->q);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1084
1085
1086
1087
1088
  			kfree(dest);
  			err = PTR_ERR(tsk);
  		}
  		break;
  	case AUDIT_ADD:
93315ed6d   Amy Griffis   [PATCH] audit str...
1089
1090
1091
1092
1093
1094
1095
  	case AUDIT_ADD_RULE:
  		if (type == AUDIT_ADD)
  			entry = audit_rule_to_entry(data);
  		else
  			entry = audit_data_to_entry(data, datasz);
  		if (IS_ERR(entry))
  			return PTR_ERR(entry);
36c4f1b18   Al Viro   clean up audit_ru...
1096
  		err = audit_add_rule(entry);
9d9609851   Eric Paris   Audit: clean up a...
1097
  		audit_log_rule_change(loginuid, sessionid, sid, "add rule",
2532386f4   Eric Paris   Audit: collect se...
1098
  				      &entry->rule, !err);
5d3301088   Al Viro   [PATCH] add/remov...
1099
1100
  
  		if (err)
93315ed6d   Amy Griffis   [PATCH] audit str...
1101
  			audit_free_rule(entry);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1102
1103
  		break;
  	case AUDIT_DEL:
93315ed6d   Amy Griffis   [PATCH] audit str...
1104
1105
1106
1107
1108
1109
1110
  	case AUDIT_DEL_RULE:
  		if (type == AUDIT_DEL)
  			entry = audit_rule_to_entry(data);
  		else
  			entry = audit_data_to_entry(data, datasz);
  		if (IS_ERR(entry))
  			return PTR_ERR(entry);
36c4f1b18   Al Viro   clean up audit_ru...
1111
  		err = audit_del_rule(entry);
9d9609851   Eric Paris   Audit: clean up a...
1112
  		audit_log_rule_change(loginuid, sessionid, sid, "remove rule",
2532386f4   Eric Paris   Audit: collect se...
1113
  				      &entry->rule, !err);
5d3301088   Al Viro   [PATCH] add/remov...
1114

93315ed6d   Amy Griffis   [PATCH] audit str...
1115
  		audit_free_rule(entry);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1116
1117
1118
1119
1120
1121
1122
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return err;
  }
5af75d8d5   Al Viro   audit: validate c...
1123
  int audit_comparator(u32 left, u32 op, u32 right)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1124
1125
  {
  	switch (op) {
5af75d8d5   Al Viro   audit: validate c...
1126
  	case Audit_equal:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1127
  		return (left == right);
5af75d8d5   Al Viro   audit: validate c...
1128
  	case Audit_not_equal:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1129
  		return (left != right);
5af75d8d5   Al Viro   audit: validate c...
1130
  	case Audit_lt:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1131
  		return (left < right);
5af75d8d5   Al Viro   audit: validate c...
1132
  	case Audit_le:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1133
  		return (left <= right);
5af75d8d5   Al Viro   audit: validate c...
1134
  	case Audit_gt:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1135
  		return (left > right);
5af75d8d5   Al Viro   audit: validate c...
1136
  	case Audit_ge:
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1137
  		return (left >= right);
5af75d8d5   Al Viro   audit: validate c...
1138
  	case Audit_bitmask:
74f2345b6   Eric Paris   [PATCH] allow aud...
1139
  		return (left & right);
5af75d8d5   Al Viro   audit: validate c...
1140
  	case Audit_bittest:
74f2345b6   Eric Paris   [PATCH] allow aud...
1141
  		return ((left & right) == right);
5af75d8d5   Al Viro   audit: validate c...
1142
1143
1144
  	default:
  		BUG();
  		return 0;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1145
1146
  	}
  }
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1147
1148
  /* Compare given dentry name with last component in given path,
   * return of 0 indicates a match. */
9c937dcc7   Amy Griffis   [PATCH] log more ...
1149
1150
  int audit_compare_dname_path(const char *dname, const char *path,
  			     int *dirlen)
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
  {
  	int dlen, plen;
  	const char *p;
  
  	if (!dname || !path)
  		return 1;
  
  	dlen = strlen(dname);
  	plen = strlen(path);
  	if (plen < dlen)
  		return 1;
  
  	/* disregard trailing slashes */
  	p = path + plen - 1;
  	while ((*p == '/') && (p > path))
  		p--;
  
  	/* find last path component */
  	p = p - dlen + 1;
  	if (p < path)
  		return 1;
  	else if (p > path) {
  		if (*--p != '/')
  			return 1;
  		else
  			p++;
  	}
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1178

9c937dcc7   Amy Griffis   [PATCH] log more ...
1179
1180
1181
  	/* return length of path's directory component */
  	if (dirlen)
  		*dirlen = p - path;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1182
1183
  	return strncmp(p, dname, dlen);
  }
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1184
1185
  
  static int audit_filter_user_rules(struct netlink_skb_parms *cb,
93315ed6d   Amy Griffis   [PATCH] audit str...
1186
  				   struct audit_krule *rule,
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1187
1188
1189
1190
1191
  				   enum audit_state *state)
  {
  	int i;
  
  	for (i = 0; i < rule->field_count; i++) {
93315ed6d   Amy Griffis   [PATCH] audit str...
1192
  		struct audit_field *f = &rule->fields[i];
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1193
  		int result = 0;
c53fa1ed9   Patrick McHardy   netlink: kill log...
1194
  		u32 sid;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1195

93315ed6d   Amy Griffis   [PATCH] audit str...
1196
  		switch (f->type) {
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1197
  		case AUDIT_PID:
93315ed6d   Amy Griffis   [PATCH] audit str...
1198
  			result = audit_comparator(cb->creds.pid, f->op, f->val);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1199
1200
  			break;
  		case AUDIT_UID:
93315ed6d   Amy Griffis   [PATCH] audit str...
1201
  			result = audit_comparator(cb->creds.uid, f->op, f->val);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1202
1203
  			break;
  		case AUDIT_GID:
93315ed6d   Amy Griffis   [PATCH] audit str...
1204
  			result = audit_comparator(cb->creds.gid, f->op, f->val);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1205
1206
  			break;
  		case AUDIT_LOGINUID:
c53fa1ed9   Patrick McHardy   netlink: kill log...
1207
1208
  			result = audit_comparator(audit_get_loginuid(current),
  						  f->op, f->val);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1209
  			break;
d29be158a   Miloslav Trmac   Audit: add suppor...
1210
1211
1212
1213
1214
  		case AUDIT_SUBJ_USER:
  		case AUDIT_SUBJ_ROLE:
  		case AUDIT_SUBJ_TYPE:
  		case AUDIT_SUBJ_SEN:
  		case AUDIT_SUBJ_CLR:
c53fa1ed9   Patrick McHardy   netlink: kill log...
1215
1216
1217
  			if (f->lsm_rule) {
  				security_task_getsecid(current, &sid);
  				result = security_audit_rule_match(sid,
d29be158a   Miloslav Trmac   Audit: add suppor...
1218
1219
1220
1221
  								   f->type,
  								   f->op,
  								   f->lsm_rule,
  								   NULL);
c53fa1ed9   Patrick McHardy   netlink: kill log...
1222
  			}
d29be158a   Miloslav Trmac   Audit: add suppor...
1223
  			break;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1224
1225
1226
1227
1228
1229
1230
  		}
  
  		if (!result)
  			return 0;
  	}
  	switch (rule->action) {
  	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1231
1232
1233
1234
  	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
  	}
  	return 1;
  }
d8de72473   Peng Haitao   [PATCH] remove us...
1235
  int audit_filter_user(struct netlink_skb_parms *cb)
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1236
  {
11f57cedc   Ingo Molnar   [PATCH] audit: fi...
1237
  	enum audit_state state = AUDIT_DISABLED;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1238
  	struct audit_entry *e;
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  	int ret = 1;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
  		if (audit_filter_user_rules(cb, &e->rule, &state)) {
  			if (state == AUDIT_DISABLED)
  				ret = 0;
  			break;
  		}
  	}
  	rcu_read_unlock();
  
  	return ret; /* Audit by default */
  }
  
  int audit_filter_type(int type)
  {
  	struct audit_entry *e;
  	int result = 0;
9ce34218a   Daniel Walker   whitespace fixes:...
1258

fe7752bab   David Woodhouse   [PATCH] Fix audit...
1259
1260
1261
1262
1263
1264
  	rcu_read_lock();
  	if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
  		goto unlock_and_return;
  
  	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
  				list) {
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1265
  		int i;
93315ed6d   Amy Griffis   [PATCH] audit str...
1266
1267
1268
1269
  		for (i = 0; i < e->rule.field_count; i++) {
  			struct audit_field *f = &e->rule.fields[i];
  			if (f->type == AUDIT_MSGTYPE) {
  				result = audit_comparator(type, f->op, f->val);
fe7752bab   David Woodhouse   [PATCH] Fix audit...
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
  				if (!result)
  					break;
  			}
  		}
  		if (result)
  			goto unlock_and_return;
  	}
  unlock_and_return:
  	rcu_read_unlock();
  	return result;
  }
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1281

e45aa212e   Al Viro   audit rules order...
1282
  static int update_lsm_rule(struct audit_krule *r)
1a9d0797b   Al Viro   audit_update_lsm_...
1283
  {
e45aa212e   Al Viro   audit rules order...
1284
  	struct audit_entry *entry = container_of(r, struct audit_entry, rule);
1a9d0797b   Al Viro   audit_update_lsm_...
1285
  	struct audit_entry *nentry;
1a9d0797b   Al Viro   audit_update_lsm_...
1286
  	int err = 0;
e45aa212e   Al Viro   audit rules order...
1287
  	if (!security_audit_rule_known(r))
1a9d0797b   Al Viro   audit_update_lsm_...
1288
  		return 0;
ae7b8f410   Eric Paris   Audit: clean up t...
1289
  	nentry = audit_dupe_rule(r);
1a9d0797b   Al Viro   audit_update_lsm_...
1290
1291
1292
1293
1294
  	if (IS_ERR(nentry)) {
  		/* save the first error encountered for the
  		 * return value */
  		err = PTR_ERR(nentry);
  		audit_panic("error updating LSM filters");
ae7b8f410   Eric Paris   Audit: clean up t...
1295
  		if (r->watch)
e45aa212e   Al Viro   audit rules order...
1296
  			list_del(&r->rlist);
1a9d0797b   Al Viro   audit_update_lsm_...
1297
  		list_del_rcu(&entry->list);
e45aa212e   Al Viro   audit rules order...
1298
  		list_del(&r->list);
1a9d0797b   Al Viro   audit_update_lsm_...
1299
  	} else {
ae7b8f410   Eric Paris   Audit: clean up t...
1300
  		if (r->watch || r->tree)
e45aa212e   Al Viro   audit rules order...
1301
  			list_replace_init(&r->rlist, &nentry->rule.rlist);
1a9d0797b   Al Viro   audit_update_lsm_...
1302
  		list_replace_rcu(&entry->list, &nentry->list);
e45aa212e   Al Viro   audit rules order...
1303
  		list_replace(&r->list, &nentry->rule.list);
1a9d0797b   Al Viro   audit_update_lsm_...
1304
1305
1306
1307
1308
  	}
  	call_rcu(&entry->rcu, audit_free_rule_rcu);
  
  	return err;
  }
04305e4af   Ahmed S. Darwish   Audit: Final rena...
1309
  /* This function will re-initialize the lsm_rule field of all applicable rules.
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
1310
   * It will traverse the filter lists serarching for rules that contain LSM
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1311
   * specific filter fields.  When such a rule is found, it is copied, the
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
1312
   * LSM field is re-initialized, and the old rule is replaced with the
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1313
   * updated rule. */
d7a96f3a1   Ahmed S. Darwish   Audit: internally...
1314
  int audit_update_lsm_rules(void)
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1315
  {
e45aa212e   Al Viro   audit rules order...
1316
  	struct audit_krule *r, *n;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1317
  	int i, err = 0;
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1318
1319
  	/* audit_filter_mutex synchronizes the writers */
  	mutex_lock(&audit_filter_mutex);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1320
1321
  
  	for (i = 0; i < AUDIT_NR_FILTERS; i++) {
e45aa212e   Al Viro   audit rules order...
1322
1323
  		list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
  			int res = update_lsm_rule(r);
1a9d0797b   Al Viro   audit_update_lsm_...
1324
1325
  			if (!err)
  				err = res;
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1326
1327
  		}
  	}
f368c07d7   Amy Griffis   [PATCH] audit: pa...
1328
  	mutex_unlock(&audit_filter_mutex);
3dc7e3153   Darrel Goeddel   [PATCH] support f...
1329
1330
1331
  
  	return err;
  }