aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-06-11 14:31:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-23 23:50:59 -0400
commitcfcad62c74abfef83762dc05a556d21bdf3980a2 (patch)
treed253dbf8dfa4d31379dcd886cc1b41c69921acdd
parentea7ae60bfe39aeedfb29571c47280bf0067ee5f3 (diff)
audit: seperate audit inode watches into a subfile
In preparation for converting audit to use fsnotify instead of inotify we seperate the inode watching code into it's own file. This is similar to how the audit tree watching code is already seperated into audit_tree.c Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/audit.c16
-rw-r--r--kernel/audit.h39
-rw-r--r--kernel/audit_watch.c534
-rw-r--r--kernel/auditfilter.c481
-rw-r--r--kernel/auditsc.c6
6 files changed, 572 insertions, 506 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 0a32cb21ec97..da750010a6fc 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
70obj-$(CONFIG_STOP_MACHINE) += stop_machine.o 70obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
71obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o 71obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
72obj-$(CONFIG_AUDIT) += audit.o auditfilter.o 72obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
73obj-$(CONFIG_AUDITSYSCALL) += auditsc.o 73obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o
74obj-$(CONFIG_GCOV_KERNEL) += gcov/ 74obj-$(CONFIG_GCOV_KERNEL) += gcov/
75obj-$(CONFIG_AUDIT_TREE) += audit_tree.o 75obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
76obj-$(CONFIG_KPROBES) += kprobes.o 76obj-$(CONFIG_KPROBES) += kprobes.o
diff --git a/kernel/audit.c b/kernel/audit.c
index ce77e81a0e71..e07ad2340dbe 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -115,9 +115,6 @@ static atomic_t audit_lost = ATOMIC_INIT(0);
115/* The netlink socket. */ 115/* The netlink socket. */
116static struct sock *audit_sock; 116static struct sock *audit_sock;
117 117
118/* Inotify handle. */
119struct inotify_handle *audit_ih;
120
121/* Hash for inode-based rules */ 118/* Hash for inode-based rules */
122struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; 119struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
123 120
@@ -971,13 +968,6 @@ static void audit_receive(struct sk_buff *skb)
971 mutex_unlock(&audit_cmd_mutex); 968 mutex_unlock(&audit_cmd_mutex);
972} 969}
973 970
974#ifdef CONFIG_AUDITSYSCALL
975static const struct inotify_operations audit_inotify_ops = {
976 .handle_event = audit_handle_ievent,
977 .destroy_watch = audit_free_parent,
978};
979#endif
980
981/* Initialize audit support at boot time. */ 971/* Initialize audit support at boot time. */
982static int __init audit_init(void) 972static int __init audit_init(void)
983{ 973{
@@ -1003,12 +993,6 @@ static int __init audit_init(void)
1003 993
1004 audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); 994 audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
1005 995
1006#ifdef CONFIG_AUDITSYSCALL
1007 audit_ih = inotify_init(&audit_inotify_ops);
1008 if (IS_ERR(audit_ih))
1009 audit_panic("cannot initialize inotify handle");
1010#endif
1011
1012 for (i = 0; i < AUDIT_INODE_BUCKETS; i++) 996 for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
1013 INIT_LIST_HEAD(&audit_inode_hash[i]); 997 INIT_LIST_HEAD(&audit_inode_hash[i]);
1014 998
diff --git a/kernel/audit.h b/kernel/audit.h
index 16f18cac661b..704d5b01d9fd 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -53,18 +53,7 @@ enum audit_state {
53}; 53};
54 54
55/* Rule lists */ 55/* Rule lists */
56struct audit_parent; 56struct audit_watch;
57
58struct audit_watch {
59 atomic_t count; /* reference count */
60 char *path; /* insertion path */
61 dev_t dev; /* associated superblock device */
62 unsigned long ino; /* associated inode number */
63 struct audit_parent *parent; /* associated parent */
64 struct list_head wlist; /* entry in parent->watches list */
65 struct list_head rules; /* associated rules */
66};
67
68struct audit_tree; 57struct audit_tree;
69struct audit_chunk; 58struct audit_chunk;
70 59
@@ -108,19 +97,31 @@ struct audit_netlink_list {
108 97
109int audit_send_list(void *); 98int audit_send_list(void *);
110 99
111struct inotify_watch;
112/* Inotify handle */
113extern struct inotify_handle *audit_ih;
114
115extern void audit_free_parent(struct inotify_watch *);
116extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
117 const char *, struct inode *);
118extern int selinux_audit_rule_update(void); 100extern int selinux_audit_rule_update(void);
119 101
120extern struct mutex audit_filter_mutex; 102extern struct mutex audit_filter_mutex;
121extern void audit_free_rule_rcu(struct rcu_head *); 103extern void audit_free_rule_rcu(struct rcu_head *);
122extern struct list_head audit_filter_list[]; 104extern struct list_head audit_filter_list[];
123 105
106/* audit watch functions */
107extern unsigned long audit_watch_inode(struct audit_watch *watch);
108extern dev_t audit_watch_dev(struct audit_watch *watch);
109extern void audit_put_watch(struct audit_watch *watch);
110extern void audit_get_watch(struct audit_watch *watch);
111extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op);
112extern int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw);
113extern void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw);
114extern int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
115 struct nameidata *ndw);
116extern void audit_remove_watch(struct audit_watch *watch);
117extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list);
118extern void audit_inotify_unregister(struct list_head *in_list);
119extern char *audit_watch_path(struct audit_watch *watch);
120extern struct list_head *audit_watch_rules(struct audit_watch *watch);
121
122extern struct audit_entry *audit_dupe_rule(struct audit_krule *old,
123 struct audit_watch *watch);
124
124#ifdef CONFIG_AUDIT_TREE 125#ifdef CONFIG_AUDIT_TREE
125extern struct audit_chunk *audit_tree_lookup(const struct inode *); 126extern struct audit_chunk *audit_tree_lookup(const struct inode *);
126extern void audit_put_chunk(struct audit_chunk *); 127extern void audit_put_chunk(struct audit_chunk *);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
new file mode 100644
index 000000000000..da8be6d39c1a
--- /dev/null
+++ b/kernel/audit_watch.c
@@ -0,0 +1,534 @@
1/* audit_watch.c -- watching inodes
2 *
3 * Copyright 2003-2009 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/mutex.h>
26#include <linux/fs.h>
27#include <linux/namei.h>
28#include <linux/netlink.h>
29#include <linux/sched.h>
30#include <linux/inotify.h>
31#include <linux/security.h>
32#include "audit.h"
33
34/*
35 * Reference counting:
36 *
37 * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED
38 * event. Each audit_watch holds a reference to its associated parent.
39 *
40 * audit_watch: if added to lists, lifetime is from audit_init_watch() to
41 * audit_remove_watch(). Additionally, an audit_watch may exist
42 * temporarily to assist in searching existing filter data. Each
43 * audit_krule holds a reference to its associated watch.
44 */
45
46struct audit_watch {
47 atomic_t count; /* reference count */
48 char *path; /* insertion path */
49 dev_t dev; /* associated superblock device */
50 unsigned long ino; /* associated inode number */
51 struct audit_parent *parent; /* associated parent */
52 struct list_head wlist; /* entry in parent->watches list */
53 struct list_head rules; /* associated rules */
54};
55
56struct audit_parent {
57 struct list_head ilist; /* entry in inotify registration list */
58 struct list_head watches; /* associated watches */
59 struct inotify_watch wdata; /* inotify watch data */
60 unsigned flags; /* status flags */
61};
62
63/* Inotify handle. */
64struct inotify_handle *audit_ih;
65
66/*
67 * audit_parent status flags:
68 *
69 * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
70 * a filesystem event to ensure we're adding audit watches to a valid parent.
71 * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot
72 * receive them while we have nameidata, but must be used for IN_MOVE_SELF which
73 * we can receive while holding nameidata.
74 */
75#define AUDIT_PARENT_INVALID 0x001
76
77/* Inotify events we care about. */
78#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
79
80static void audit_free_parent(struct inotify_watch *i_watch)
81{
82 struct audit_parent *parent;
83
84 parent = container_of(i_watch, struct audit_parent, wdata);
85 WARN_ON(!list_empty(&parent->watches));
86 kfree(parent);
87}
88
89void audit_get_watch(struct audit_watch *watch)
90{
91 atomic_inc(&watch->count);
92}
93
94void audit_put_watch(struct audit_watch *watch)
95{
96 if (atomic_dec_and_test(&watch->count)) {
97 WARN_ON(watch->parent);
98 WARN_ON(!list_empty(&watch->rules));
99 kfree(watch->path);
100 kfree(watch);
101 }
102}
103
104void audit_remove_watch(struct audit_watch *watch)
105{
106 list_del(&watch->wlist);
107 put_inotify_watch(&watch->parent->wdata);
108 watch->parent = NULL;
109 audit_put_watch(watch); /* match initial get */
110}
111
112char *audit_watch_path(struct audit_watch *watch)
113{
114 return watch->path;
115}
116
117struct list_head *audit_watch_rules(struct audit_watch *watch)
118{
119 return &watch->rules;
120}
121
122unsigned long audit_watch_inode(struct audit_watch *watch)
123{
124 return watch->ino;
125}
126
127dev_t audit_watch_dev(struct audit_watch *watch)
128{
129 return watch->dev;
130}
131
132/* Initialize a parent watch entry. */
133static struct audit_parent *audit_init_parent(struct nameidata *ndp)
134{
135 struct audit_parent *parent;
136 s32 wd;
137
138 parent = kzalloc(sizeof(*parent), GFP_KERNEL);
139 if (unlikely(!parent))
140 return ERR_PTR(-ENOMEM);
141
142 INIT_LIST_HEAD(&parent->watches);
143 parent->flags = 0;
144
145 inotify_init_watch(&parent->wdata);
146 /* grab a ref so inotify watch hangs around until we take audit_filter_mutex */
147 get_inotify_watch(&parent->wdata);
148 wd = inotify_add_watch(audit_ih, &parent->wdata,
149 ndp->path.dentry->d_inode, AUDIT_IN_WATCH);
150 if (wd < 0) {
151 audit_free_parent(&parent->wdata);
152 return ERR_PTR(wd);
153 }
154
155 return parent;
156}
157
158/* Initialize a watch entry. */
159static struct audit_watch *audit_init_watch(char *path)
160{
161 struct audit_watch *watch;
162
163 watch = kzalloc(sizeof(*watch), GFP_KERNEL);
164 if (unlikely(!watch))
165 return ERR_PTR(-ENOMEM);
166
167 INIT_LIST_HEAD(&watch->rules);
168 atomic_set(&watch->count, 1);
169 watch->path = path;
170 watch->dev = (dev_t)-1;
171 watch->ino = (unsigned long)-1;
172
173 return watch;
174}
175
176/* Translate a watch string to kernel respresentation. */
177int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
178{
179 struct audit_watch *watch;
180
181 if (!audit_ih)
182 return -EOPNOTSUPP;
183
184 if (path[0] != '/' || path[len-1] == '/' ||
185 krule->listnr != AUDIT_FILTER_EXIT ||
186 op != Audit_equal ||
187 krule->inode_f || krule->watch || krule->tree)
188 return -EINVAL;
189
190 watch = audit_init_watch(path);
191 if (IS_ERR(watch))
192 return PTR_ERR(watch);
193
194 audit_get_watch(watch);
195 krule->watch = watch;
196
197 return 0;
198}
199
200/* Duplicate the given audit watch. The new watch's rules list is initialized
201 * to an empty list and wlist is undefined. */
202static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
203{
204 char *path;
205 struct audit_watch *new;
206
207 path = kstrdup(old->path, GFP_KERNEL);
208 if (unlikely(!path))
209 return ERR_PTR(-ENOMEM);
210
211 new = audit_init_watch(path);
212 if (IS_ERR(new)) {
213 kfree(path);
214 goto out;
215 }
216
217 new->dev = old->dev;
218 new->ino = old->ino;
219 get_inotify_watch(&old->parent->wdata);
220 new->parent = old->parent;
221
222out:
223 return new;
224}
225
226static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
227{
228 if (audit_enabled) {
229 struct audit_buffer *ab;
230 ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
231 audit_log_format(ab, "auid=%u ses=%u op=",
232 audit_get_loginuid(current),
233 audit_get_sessionid(current));
234 audit_log_string(ab, op);
235 audit_log_format(ab, " path=");
236 audit_log_untrustedstring(ab, w->path);
237 if (r->filterkey) {
238 audit_log_format(ab, " key=");
239 audit_log_untrustedstring(ab, r->filterkey);
240 } else
241 audit_log_format(ab, " key=(null)");
242 audit_log_format(ab, " list=%d res=1", r->listnr);
243 audit_log_end(ab);
244 }
245}
246
247/* Update inode info in audit rules based on filesystem event. */
248static void audit_update_watch(struct audit_parent *parent,
249 const char *dname, dev_t dev,
250 unsigned long ino, unsigned invalidating)
251{
252 struct audit_watch *owatch, *nwatch, *nextw;
253 struct audit_krule *r, *nextr;
254 struct audit_entry *oentry, *nentry;
255
256 mutex_lock(&audit_filter_mutex);
257 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
258 if (audit_compare_dname_path(dname, owatch->path, NULL))
259 continue;
260
261 /* If the update involves invalidating rules, do the inode-based
262 * filtering now, so we don't omit records. */
263 if (invalidating && current->audit_context)
264 audit_filter_inodes(current, current->audit_context);
265
266 nwatch = audit_dupe_watch(owatch);
267 if (IS_ERR(nwatch)) {
268 mutex_unlock(&audit_filter_mutex);
269 audit_panic("error updating watch, skipping");
270 return;
271 }
272 nwatch->dev = dev;
273 nwatch->ino = ino;
274
275 list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {
276
277 oentry = container_of(r, struct audit_entry, rule);
278 list_del(&oentry->rule.rlist);
279 list_del_rcu(&oentry->list);
280
281 nentry = audit_dupe_rule(&oentry->rule, nwatch);
282 if (IS_ERR(nentry)) {
283 list_del(&oentry->rule.list);
284 audit_panic("error updating watch, removing");
285 } else {
286 int h = audit_hash_ino((u32)ino);
287 list_add(&nentry->rule.rlist, &nwatch->rules);
288 list_add_rcu(&nentry->list, &audit_inode_hash[h]);
289 list_replace(&oentry->rule.list,
290 &nentry->rule.list);
291 }
292
293 audit_watch_log_rule_change(r, owatch, "updated rules");
294
295 call_rcu(&oentry->rcu, audit_free_rule_rcu);
296 }
297
298 audit_remove_watch(owatch);
299 goto add_watch_to_parent; /* event applies to a single watch */
300 }
301 mutex_unlock(&audit_filter_mutex);
302 return;
303
304add_watch_to_parent:
305 list_add(&nwatch->wlist, &parent->watches);
306 mutex_unlock(&audit_filter_mutex);
307 return;
308}
309
310/* Remove all watches & rules associated with a parent that is going away. */
311static void audit_remove_parent_watches(struct audit_parent *parent)
312{
313 struct audit_watch *w, *nextw;
314 struct audit_krule *r, *nextr;
315 struct audit_entry *e;
316
317 mutex_lock(&audit_filter_mutex);
318 parent->flags |= AUDIT_PARENT_INVALID;
319 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
320 list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
321 e = container_of(r, struct audit_entry, rule);
322 audit_watch_log_rule_change(r, w, "remove rule");
323 list_del(&r->rlist);
324 list_del(&r->list);
325 list_del_rcu(&e->list);
326 call_rcu(&e->rcu, audit_free_rule_rcu);
327 }
328 audit_remove_watch(w);
329 }
330 mutex_unlock(&audit_filter_mutex);
331}
332
333/* Unregister inotify watches for parents on in_list.
334 * Generates an IN_IGNORED event. */
335void audit_inotify_unregister(struct list_head *in_list)
336{
337 struct audit_parent *p, *n;
338
339 list_for_each_entry_safe(p, n, in_list, ilist) {
340 list_del(&p->ilist);
341 inotify_rm_watch(audit_ih, &p->wdata);
342 /* the unpin matching the pin in audit_do_del_rule() */
343 unpin_inotify_watch(&p->wdata);
344 }
345}
346
347/* Get path information necessary for adding watches. */
348int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
349{
350 struct nameidata *ndparent, *ndwatch;
351 int err;
352
353 ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
354 if (unlikely(!ndparent))
355 return -ENOMEM;
356
357 ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
358 if (unlikely(!ndwatch)) {
359 kfree(ndparent);
360 return -ENOMEM;
361 }
362
363 err = path_lookup(path, LOOKUP_PARENT, ndparent);
364 if (err) {
365 kfree(ndparent);
366 kfree(ndwatch);
367 return err;
368 }
369
370 err = path_lookup(path, 0, ndwatch);
371 if (err) {
372 kfree(ndwatch);
373 ndwatch = NULL;
374 }
375
376 *ndp = ndparent;
377 *ndw = ndwatch;
378
379 return 0;
380}
381
382/* Release resources used for watch path information. */
383void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
384{
385 if (ndp) {
386 path_put(&ndp->path);
387 kfree(ndp);
388 }
389 if (ndw) {
390 path_put(&ndw->path);
391 kfree(ndw);
392 }
393}
394
395/* Associate the given rule with an existing parent inotify_watch.
396 * Caller must hold audit_filter_mutex. */
397static void audit_add_to_parent(struct audit_krule *krule,
398 struct audit_parent *parent)
399{
400 struct audit_watch *w, *watch = krule->watch;
401 int watch_found = 0;
402
403 list_for_each_entry(w, &parent->watches, wlist) {
404 if (strcmp(watch->path, w->path))
405 continue;
406
407 watch_found = 1;
408
409 /* put krule's and initial refs to temporary watch */
410 audit_put_watch(watch);
411 audit_put_watch(watch);
412
413 audit_get_watch(w);
414 krule->watch = watch = w;
415 break;
416 }
417
418 if (!watch_found) {
419 get_inotify_watch(&parent->wdata);
420 watch->parent = parent;
421
422 list_add(&watch->wlist, &parent->watches);
423 }
424 list_add(&krule->rlist, &watch->rules);
425}
426
427/* Find a matching watch entry, or add this one.
428 * Caller must hold audit_filter_mutex. */
429int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
430 struct nameidata *ndw)
431{
432 struct audit_watch *watch = krule->watch;
433 struct inotify_watch *i_watch;
434 struct audit_parent *parent;
435 int ret = 0;
436
437 /* update watch filter fields */
438 if (ndw) {
439 watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev;
440 watch->ino = ndw->path.dentry->d_inode->i_ino;
441 }
442
443 /* The audit_filter_mutex must not be held during inotify calls because
444 * we hold it during inotify event callback processing. If an existing
445 * inotify watch is found, inotify_find_watch() grabs a reference before
446 * returning.
447 */
448 mutex_unlock(&audit_filter_mutex);
449
450 if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode,
451 &i_watch) < 0) {
452 parent = audit_init_parent(ndp);
453 if (IS_ERR(parent)) {
454 /* caller expects mutex locked */
455 mutex_lock(&audit_filter_mutex);
456 return PTR_ERR(parent);
457 }
458 } else
459 parent = container_of(i_watch, struct audit_parent, wdata);
460
461 mutex_lock(&audit_filter_mutex);
462
463 /* parent was moved before we took audit_filter_mutex */
464 if (parent->flags & AUDIT_PARENT_INVALID)
465 ret = -ENOENT;
466 else
467 audit_add_to_parent(krule, parent);
468
469 /* match get in audit_init_parent or inotify_find_watch */
470 put_inotify_watch(&parent->wdata);
471 return ret;
472}
473
474void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)
475{
476 struct audit_watch *watch = krule->watch;
477 struct audit_parent *parent = watch->parent;
478
479 list_del(&krule->rlist);
480
481 if (list_empty(&watch->rules)) {
482 audit_remove_watch(watch);
483
484 if (list_empty(&parent->watches)) {
485 /* Put parent on the inotify un-registration
486 * list. Grab a reference before releasing
487 * audit_filter_mutex, to be released in
488 * audit_inotify_unregister().
489 * If filesystem is going away, just leave
490 * the sucker alone, eviction will take
491 * care of it. */
492 if (pin_inotify_watch(&parent->wdata))
493 list_add(&parent->ilist, list);
494 }
495 }
496}
497
498/* Update watch data in audit rules based on inotify events. */
499static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
500 u32 cookie, const char *dname, struct inode *inode)
501{
502 struct audit_parent *parent;
503
504 parent = container_of(i_watch, struct audit_parent, wdata);
505
506 if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
507 audit_update_watch(parent, dname, inode->i_sb->s_dev,
508 inode->i_ino, 0);
509 else if (mask & (IN_DELETE|IN_MOVED_FROM))
510 audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
511 /* inotify automatically removes the watch and sends IN_IGNORED */
512 else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
513 audit_remove_parent_watches(parent);
514 /* inotify does not remove the watch, so remove it manually */
515 else if(mask & IN_MOVE_SELF) {
516 audit_remove_parent_watches(parent);
517 inotify_remove_watch_locked(audit_ih, i_watch);
518 } else if (mask & IN_IGNORED)
519 put_inotify_watch(i_watch);
520}
521
522static const struct inotify_operations audit_inotify_ops = {
523 .handle_event = audit_handle_ievent,
524 .destroy_watch = audit_free_parent,
525};
526
527static int __init audit_watch_init(void)
528{
529 audit_ih = inotify_init(&audit_inotify_ops);
530 if (IS_ERR(audit_ih))
531 audit_panic("cannot initialize inotify handle");
532 return 0;
533}
534subsys_initcall(audit_watch_init);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index e7466dd145c9..9d4c93437de6 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -27,7 +27,6 @@
27#include <linux/namei.h> 27#include <linux/namei.h>
28#include <linux/netlink.h> 28#include <linux/netlink.h>
29#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/inotify.h>
31#include <linux/security.h> 30#include <linux/security.h>
32#include "audit.h" 31#include "audit.h"
33 32
@@ -44,36 +43,6 @@
44 * be written directly provided audit_filter_mutex is held. 43 * be written directly provided audit_filter_mutex is held.
45 */ 44 */
46 45
47/*
48 * Reference counting:
49 *
50 * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED
51 * event. Each audit_watch holds a reference to its associated parent.
52 *
53 * audit_watch: if added to lists, lifetime is from audit_init_watch() to
54 * audit_remove_watch(). Additionally, an audit_watch may exist
55 * temporarily to assist in searching existing filter data. Each
56 * audit_krule holds a reference to its associated watch.
57 */
58
59struct audit_parent {
60 struct list_head ilist; /* entry in inotify registration list */
61 struct list_head watches; /* associated watches */
62 struct inotify_watch wdata; /* inotify watch data */
63 unsigned flags; /* status flags */
64};
65
66/*
67 * audit_parent status flags:
68 *
69 * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
70 * a filesystem event to ensure we're adding audit watches to a valid parent.
71 * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot
72 * receive them while we have nameidata, but must be used for IN_MOVE_SELF which
73 * we can receive while holding nameidata.
74 */
75#define AUDIT_PARENT_INVALID 0x001
76
77/* Audit filter lists, defined in <linux/audit.h> */ 46/* Audit filter lists, defined in <linux/audit.h> */
78struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { 47struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
79 LIST_HEAD_INIT(audit_filter_list[0]), 48 LIST_HEAD_INIT(audit_filter_list[0]),
@@ -97,41 +66,6 @@ static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
97 66
98DEFINE_MUTEX(audit_filter_mutex); 67DEFINE_MUTEX(audit_filter_mutex);
99 68
100/* Inotify events we care about. */
101#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
102
103void audit_free_parent(struct inotify_watch *i_watch)
104{
105 struct audit_parent *parent;
106
107 parent = container_of(i_watch, struct audit_parent, wdata);
108 WARN_ON(!list_empty(&parent->watches));
109 kfree(parent);
110}
111
112static inline void audit_get_watch(struct audit_watch *watch)
113{
114 atomic_inc(&watch->count);
115}
116
117static void audit_put_watch(struct audit_watch *watch)
118{
119 if (atomic_dec_and_test(&watch->count)) {
120 WARN_ON(watch->parent);
121 WARN_ON(!list_empty(&watch->rules));
122 kfree(watch->path);
123 kfree(watch);
124 }
125}
126
127static void audit_remove_watch(struct audit_watch *watch)
128{
129 list_del(&watch->wlist);
130 put_inotify_watch(&watch->parent->wdata);
131 watch->parent = NULL;
132 audit_put_watch(watch); /* match initial get */
133}
134
135static inline void audit_free_rule(struct audit_entry *e) 69static inline void audit_free_rule(struct audit_entry *e)
136{ 70{
137 int i; 71 int i;
@@ -156,50 +90,6 @@ void audit_free_rule_rcu(struct rcu_head *head)
156 audit_free_rule(e); 90 audit_free_rule(e);
157} 91}
158 92
159/* Initialize a parent watch entry. */
160static struct audit_parent *audit_init_parent(struct nameidata *ndp)
161{
162 struct audit_parent *parent;
163 s32 wd;
164
165 parent = kzalloc(sizeof(*parent), GFP_KERNEL);
166 if (unlikely(!parent))
167 return ERR_PTR(-ENOMEM);
168
169 INIT_LIST_HEAD(&parent->watches);
170 parent->flags = 0;
171
172 inotify_init_watch(&parent->wdata);
173 /* grab a ref so inotify watch hangs around until we take audit_filter_mutex */
174 get_inotify_watch(&parent->wdata);
175 wd = inotify_add_watch(audit_ih, &parent->wdata,
176 ndp->path.dentry->d_inode, AUDIT_IN_WATCH);
177 if (wd < 0) {
178 audit_free_parent(&parent->wdata);
179 return ERR_PTR(wd);
180 }
181
182 return parent;
183}
184
185/* Initialize a watch entry. */
186static struct audit_watch *audit_init_watch(char *path)
187{
188 struct audit_watch *watch;
189
190 watch = kzalloc(sizeof(*watch), GFP_KERNEL);
191 if (unlikely(!watch))
192 return ERR_PTR(-ENOMEM);
193
194 INIT_LIST_HEAD(&watch->rules);
195 atomic_set(&watch->count, 1);
196 watch->path = path;
197 watch->dev = (dev_t)-1;
198 watch->ino = (unsigned long)-1;
199
200 return watch;
201}
202
203/* Initialize an audit filterlist entry. */ 93/* Initialize an audit filterlist entry. */
204static inline struct audit_entry *audit_init_entry(u32 field_count) 94static inline struct audit_entry *audit_init_entry(u32 field_count)
205{ 95{
@@ -260,31 +150,6 @@ static inline int audit_to_inode(struct audit_krule *krule,
260 return 0; 150 return 0;
261} 151}
262 152
263/* Translate a watch string to kernel respresentation. */
264static int audit_to_watch(struct audit_krule *krule, char *path, int len,
265 u32 op)
266{
267 struct audit_watch *watch;
268
269 if (!audit_ih)
270 return -EOPNOTSUPP;
271
272 if (path[0] != '/' || path[len-1] == '/' ||
273 krule->listnr != AUDIT_FILTER_EXIT ||
274 op != Audit_equal ||
275 krule->inode_f || krule->watch || krule->tree)
276 return -EINVAL;
277
278 watch = audit_init_watch(path);
279 if (IS_ERR(watch))
280 return PTR_ERR(watch);
281
282 audit_get_watch(watch);
283 krule->watch = watch;
284
285 return 0;
286}
287
288static __u32 *classes[AUDIT_SYSCALL_CLASSES]; 153static __u32 *classes[AUDIT_SYSCALL_CLASSES];
289 154
290int __init audit_register_class(int class, unsigned *list) 155int __init audit_register_class(int class, unsigned *list)
@@ -766,7 +631,8 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
766 break; 631 break;
767 case AUDIT_WATCH: 632 case AUDIT_WATCH:
768 data->buflen += data->values[i] = 633 data->buflen += data->values[i] =
769 audit_pack_string(&bufp, krule->watch->path); 634 audit_pack_string(&bufp,
635 audit_watch_path(krule->watch));
770 break; 636 break;
771 case AUDIT_DIR: 637 case AUDIT_DIR:
772 data->buflen += data->values[i] = 638 data->buflen += data->values[i] =
@@ -818,7 +684,8 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
818 return 1; 684 return 1;
819 break; 685 break;
820 case AUDIT_WATCH: 686 case AUDIT_WATCH:
821 if (strcmp(a->watch->path, b->watch->path)) 687 if (strcmp(audit_watch_path(a->watch),
688 audit_watch_path(b->watch)))
822 return 1; 689 return 1;
823 break; 690 break;
824 case AUDIT_DIR: 691 case AUDIT_DIR:
@@ -844,32 +711,6 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
844 return 0; 711 return 0;
845} 712}
846 713
847/* Duplicate the given audit watch. The new watch's rules list is initialized
848 * to an empty list and wlist is undefined. */
849static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
850{
851 char *path;
852 struct audit_watch *new;
853
854 path = kstrdup(old->path, GFP_KERNEL);
855 if (unlikely(!path))
856 return ERR_PTR(-ENOMEM);
857
858 new = audit_init_watch(path);
859 if (IS_ERR(new)) {
860 kfree(path);
861 goto out;
862 }
863
864 new->dev = old->dev;
865 new->ino = old->ino;
866 get_inotify_watch(&old->parent->wdata);
867 new->parent = old->parent;
868
869out:
870 return new;
871}
872
873/* Duplicate LSM field information. The lsm_rule is opaque, so must be 714/* Duplicate LSM field information. The lsm_rule is opaque, so must be
874 * re-initialized. */ 715 * re-initialized. */
875static inline int audit_dupe_lsm_field(struct audit_field *df, 716static inline int audit_dupe_lsm_field(struct audit_field *df,
@@ -904,8 +745,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,
904 * rule with the new rule in the filterlist, then free the old rule. 745 * rule with the new rule in the filterlist, then free the old rule.
905 * The rlist element is undefined; list manipulations are handled apart from 746 * The rlist element is undefined; list manipulations are handled apart from
906 * the initial copy. */ 747 * the initial copy. */
907static struct audit_entry *audit_dupe_rule(struct audit_krule *old, 748struct audit_entry *audit_dupe_rule(struct audit_krule *old,
908 struct audit_watch *watch) 749 struct audit_watch *watch)
909{ 750{
910 u32 fcount = old->field_count; 751 u32 fcount = old->field_count;
911 struct audit_entry *entry; 752 struct audit_entry *entry;
@@ -977,127 +818,6 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
977 return entry; 818 return entry;
978} 819}
979 820
980static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
981{
982 if (audit_enabled) {
983 struct audit_buffer *ab;
984 ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
985 audit_log_format(ab, "auid=%u ses=%u op=",
986 audit_get_loginuid(current),
987 audit_get_sessionid(current));
988 audit_log_string(ab, op);
989 audit_log_format(ab, " path=");
990 audit_log_untrustedstring(ab, w->path);
991 if (r->filterkey) {
992 audit_log_format(ab, " key=");
993 audit_log_untrustedstring(ab, r->filterkey);
994 } else
995 audit_log_format(ab, " key=(null)");
996 audit_log_format(ab, " list=%d res=1", r->listnr);
997 audit_log_end(ab);
998 }
999}
1000
1001/* Update inode info in audit rules based on filesystem event. */
1002static void audit_update_watch(struct audit_parent *parent,
1003 const char *dname, dev_t dev,
1004 unsigned long ino, unsigned invalidating)
1005{
1006 struct audit_watch *owatch, *nwatch, *nextw;
1007 struct audit_krule *r, *nextr;
1008 struct audit_entry *oentry, *nentry;
1009
1010 mutex_lock(&audit_filter_mutex);
1011 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
1012 if (audit_compare_dname_path(dname, owatch->path, NULL))
1013 continue;
1014
1015 /* If the update involves invalidating rules, do the inode-based
1016 * filtering now, so we don't omit records. */
1017 if (invalidating && current->audit_context)
1018 audit_filter_inodes(current, current->audit_context);
1019
1020 nwatch = audit_dupe_watch(owatch);
1021 if (IS_ERR(nwatch)) {
1022 mutex_unlock(&audit_filter_mutex);
1023 audit_panic("error updating watch, skipping");
1024 return;
1025 }
1026 nwatch->dev = dev;
1027 nwatch->ino = ino;
1028
1029 list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {
1030
1031 oentry = container_of(r, struct audit_entry, rule);
1032 list_del(&oentry->rule.rlist);
1033 list_del_rcu(&oentry->list);
1034
1035 nentry = audit_dupe_rule(&oentry->rule, nwatch);
1036 if (IS_ERR(nentry)) {
1037 list_del(&oentry->rule.list);
1038 audit_panic("error updating watch, removing");
1039 } else {
1040 int h = audit_hash_ino((u32)ino);
1041 list_add(&nentry->rule.rlist, &nwatch->rules);
1042 list_add_rcu(&nentry->list, &audit_inode_hash[h]);
1043 list_replace(&oentry->rule.list,
1044 &nentry->rule.list);
1045 }
1046
1047 audit_watch_log_rule_change(r, owatch, "updated rules");
1048
1049 call_rcu(&oentry->rcu, audit_free_rule_rcu);
1050 }
1051
1052 audit_remove_watch(owatch);
1053 goto add_watch_to_parent; /* event applies to a single watch */
1054 }
1055 mutex_unlock(&audit_filter_mutex);
1056 return;
1057
1058add_watch_to_parent:
1059 list_add(&nwatch->wlist, &parent->watches);
1060 mutex_unlock(&audit_filter_mutex);
1061 return;
1062}
1063
1064/* Remove all watches & rules associated with a parent that is going away. */
1065static void audit_remove_parent_watches(struct audit_parent *parent)
1066{
1067 struct audit_watch *w, *nextw;
1068 struct audit_krule *r, *nextr;
1069 struct audit_entry *e;
1070
1071 mutex_lock(&audit_filter_mutex);
1072 parent->flags |= AUDIT_PARENT_INVALID;
1073 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
1074 list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
1075 e = container_of(r, struct audit_entry, rule);
1076 audit_watch_log_rule_change(r, w, "remove rule");
1077 list_del(&r->rlist);
1078 list_del(&r->list);
1079 list_del_rcu(&e->list);
1080 call_rcu(&e->rcu, audit_free_rule_rcu);
1081 }
1082 audit_remove_watch(w);
1083 }
1084 mutex_unlock(&audit_filter_mutex);
1085}
1086
1087/* Unregister inotify watches for parents on in_list.
1088 * Generates an IN_IGNORED event. */
1089static void audit_inotify_unregister(struct list_head *in_list)
1090{
1091 struct audit_parent *p, *n;
1092
1093 list_for_each_entry_safe(p, n, in_list, ilist) {
1094 list_del(&p->ilist);
1095 inotify_rm_watch(audit_ih, &p->wdata);
1096 /* the unpin matching the pin in audit_do_del_rule() */
1097 unpin_inotify_watch(&p->wdata);
1098 }
1099}
1100
1101/* Find an existing audit rule. 821/* Find an existing audit rule.
1102 * Caller must hold audit_filter_mutex to prevent stale rule data. */ 822 * Caller must hold audit_filter_mutex to prevent stale rule data. */
1103static struct audit_entry *audit_find_rule(struct audit_entry *entry, 823static struct audit_entry *audit_find_rule(struct audit_entry *entry,
@@ -1135,134 +855,6 @@ out:
1135 return found; 855 return found;
1136} 856}
1137 857
1138/* Get path information necessary for adding watches. */
1139static int audit_get_nd(char *path, struct nameidata **ndp,
1140 struct nameidata **ndw)
1141{
1142 struct nameidata *ndparent, *ndwatch;
1143 int err;
1144
1145 ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
1146 if (unlikely(!ndparent))
1147 return -ENOMEM;
1148
1149 ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
1150 if (unlikely(!ndwatch)) {
1151 kfree(ndparent);
1152 return -ENOMEM;
1153 }
1154
1155 err = path_lookup(path, LOOKUP_PARENT, ndparent);
1156 if (err) {
1157 kfree(ndparent);
1158 kfree(ndwatch);
1159 return err;
1160 }
1161
1162 err = path_lookup(path, 0, ndwatch);
1163 if (err) {
1164 kfree(ndwatch);
1165 ndwatch = NULL;
1166 }
1167
1168 *ndp = ndparent;
1169 *ndw = ndwatch;
1170
1171 return 0;
1172}
1173
1174/* Release resources used for watch path information. */
1175static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
1176{
1177 if (ndp) {
1178 path_put(&ndp->path);
1179 kfree(ndp);
1180 }
1181 if (ndw) {
1182 path_put(&ndw->path);
1183 kfree(ndw);
1184 }
1185}
1186
1187/* Associate the given rule with an existing parent inotify_watch.
1188 * Caller must hold audit_filter_mutex. */
1189static void audit_add_to_parent(struct audit_krule *krule,
1190 struct audit_parent *parent)
1191{
1192 struct audit_watch *w, *watch = krule->watch;
1193 int watch_found = 0;
1194
1195 list_for_each_entry(w, &parent->watches, wlist) {
1196 if (strcmp(watch->path, w->path))
1197 continue;
1198
1199 watch_found = 1;
1200
1201 /* put krule's and initial refs to temporary watch */
1202 audit_put_watch(watch);
1203 audit_put_watch(watch);
1204
1205 audit_get_watch(w);
1206 krule->watch = watch = w;
1207 break;
1208 }
1209
1210 if (!watch_found) {
1211 get_inotify_watch(&parent->wdata);
1212 watch->parent = parent;
1213
1214 list_add(&watch->wlist, &parent->watches);
1215 }
1216 list_add(&krule->rlist, &watch->rules);
1217}
1218
1219/* Find a matching watch entry, or add this one.
1220 * Caller must hold audit_filter_mutex. */
1221static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
1222 struct nameidata *ndw)
1223{
1224 struct audit_watch *watch = krule->watch;
1225 struct inotify_watch *i_watch;
1226 struct audit_parent *parent;
1227 int ret = 0;
1228
1229 /* update watch filter fields */
1230 if (ndw) {
1231 watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev;
1232 watch->ino = ndw->path.dentry->d_inode->i_ino;
1233 }
1234
1235 /* The audit_filter_mutex must not be held during inotify calls because
1236 * we hold it during inotify event callback processing. If an existing
1237 * inotify watch is found, inotify_find_watch() grabs a reference before
1238 * returning.
1239 */
1240 mutex_unlock(&audit_filter_mutex);
1241
1242 if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode,
1243 &i_watch) < 0) {
1244 parent = audit_init_parent(ndp);
1245 if (IS_ERR(parent)) {
1246 /* caller expects mutex locked */
1247 mutex_lock(&audit_filter_mutex);
1248 return PTR_ERR(parent);
1249 }
1250 } else
1251 parent = container_of(i_watch, struct audit_parent, wdata);
1252
1253 mutex_lock(&audit_filter_mutex);
1254
1255 /* parent was moved before we took audit_filter_mutex */
1256 if (parent->flags & AUDIT_PARENT_INVALID)
1257 ret = -ENOENT;
1258 else
1259 audit_add_to_parent(krule, parent);
1260
1261 /* match get in audit_init_parent or inotify_find_watch */
1262 put_inotify_watch(&parent->wdata);
1263 return ret;
1264}
1265
1266static u64 prio_low = ~0ULL/2; 858static u64 prio_low = ~0ULL/2;
1267static u64 prio_high = ~0ULL/2 - 1; 859static u64 prio_high = ~0ULL/2 - 1;
1268 860
@@ -1297,7 +889,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
1297 889
1298 /* Avoid calling path_lookup under audit_filter_mutex. */ 890 /* Avoid calling path_lookup under audit_filter_mutex. */
1299 if (watch) { 891 if (watch) {
1300 err = audit_get_nd(watch->path, &ndp, &ndw); 892 err = audit_get_nd(audit_watch_path(watch), &ndp, &ndw);
1301 if (err) 893 if (err)
1302 goto error; 894 goto error;
1303 } 895 }
@@ -1312,7 +904,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
1312 } 904 }
1313 /* entry->rule.watch may have changed during audit_add_watch() */ 905 /* entry->rule.watch may have changed during audit_add_watch() */
1314 watch = entry->rule.watch; 906 watch = entry->rule.watch;
1315 h = audit_hash_ino((u32)watch->ino); 907 h = audit_hash_ino((u32)audit_watch_inode(watch));
1316 list = &audit_inode_hash[h]; 908 list = &audit_inode_hash[h];
1317 } 909 }
1318 if (tree) { 910 if (tree) {
@@ -1364,7 +956,7 @@ error:
1364static inline int audit_del_rule(struct audit_entry *entry) 956static inline int audit_del_rule(struct audit_entry *entry)
1365{ 957{
1366 struct audit_entry *e; 958 struct audit_entry *e;
1367 struct audit_watch *watch, *tmp_watch = entry->rule.watch; 959 struct audit_watch *watch = entry->rule.watch;
1368 struct audit_tree *tree = entry->rule.tree; 960 struct audit_tree *tree = entry->rule.tree;
1369 struct list_head *list; 961 struct list_head *list;
1370 LIST_HEAD(inotify_list); 962 LIST_HEAD(inotify_list);
@@ -1386,29 +978,8 @@ static inline int audit_del_rule(struct audit_entry *entry)
1386 goto out; 978 goto out;
1387 } 979 }
1388 980
1389 watch = e->rule.watch; 981 if (e->rule.watch)
1390 if (watch) { 982 audit_remove_watch_rule(&e->rule, &inotify_list);
1391 struct audit_parent *parent = watch->parent;
1392
1393 list_del(&e->rule.rlist);
1394
1395 if (list_empty(&watch->rules)) {
1396 audit_remove_watch(watch);
1397
1398 if (list_empty(&parent->watches)) {
1399 /* Put parent on the inotify un-registration
1400 * list. Grab a reference before releasing
1401 * audit_filter_mutex, to be released in
1402 * audit_inotify_unregister().
1403 * If filesystem is going away, just leave
1404 * the sucker alone, eviction will take
1405 * care of it.
1406 */
1407 if (pin_inotify_watch(&parent->wdata))
1408 list_add(&parent->ilist, &inotify_list);
1409 }
1410 }
1411 }
1412 983
1413 if (e->rule.tree) 984 if (e->rule.tree)
1414 audit_remove_tree_rule(&e->rule); 985 audit_remove_tree_rule(&e->rule);
@@ -1430,8 +1001,8 @@ static inline int audit_del_rule(struct audit_entry *entry)
1430 audit_inotify_unregister(&inotify_list); 1001 audit_inotify_unregister(&inotify_list);
1431 1002
1432out: 1003out:
1433 if (tmp_watch) 1004 if (watch)
1434 audit_put_watch(tmp_watch); /* match initial get */ 1005 audit_put_watch(watch); /* match initial get */
1435 if (tree) 1006 if (tree)
1436 audit_put_tree(tree); /* that's the temporary one */ 1007 audit_put_tree(tree); /* that's the temporary one */
1437 1008
@@ -1785,7 +1356,7 @@ static int update_lsm_rule(struct audit_krule *r)
1785 list_del(&r->list); 1356 list_del(&r->list);
1786 } else { 1357 } else {
1787 if (watch) { 1358 if (watch) {
1788 list_add(&nentry->rule.rlist, &watch->rules); 1359 list_add(&nentry->rule.rlist, audit_watch_rules(watch));
1789 list_del(&r->rlist); 1360 list_del(&r->rlist);
1790 } else if (tree) 1361 } else if (tree)
1791 list_replace_init(&r->rlist, &nentry->rule.rlist); 1362 list_replace_init(&r->rlist, &nentry->rule.rlist);
@@ -1821,27 +1392,3 @@ int audit_update_lsm_rules(void)
1821 1392
1822 return err; 1393 return err;
1823} 1394}
1824
1825/* Update watch data in audit rules based on inotify events. */
1826void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
1827 u32 cookie, const char *dname, struct inode *inode)
1828{
1829 struct audit_parent *parent;
1830
1831 parent = container_of(i_watch, struct audit_parent, wdata);
1832
1833 if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
1834 audit_update_watch(parent, dname, inode->i_sb->s_dev,
1835 inode->i_ino, 0);
1836 else if (mask & (IN_DELETE|IN_MOVED_FROM))
1837 audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
1838 /* inotify automatically removes the watch and sends IN_IGNORED */
1839 else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
1840 audit_remove_parent_watches(parent);
1841 /* inotify does not remove the watch, so remove it manually */
1842 else if(mask & IN_MOVE_SELF) {
1843 audit_remove_parent_watches(parent);
1844 inotify_remove_watch_locked(audit_ih, i_watch);
1845 } else if (mask & IN_IGNORED)
1846 put_inotify_watch(i_watch);
1847}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b14d234b85f3..0b862cac6ca2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -548,9 +548,9 @@ static int audit_filter_rules(struct task_struct *tsk,
548 } 548 }
549 break; 549 break;
550 case AUDIT_WATCH: 550 case AUDIT_WATCH:
551 if (name && rule->watch->ino != (unsigned long)-1) 551 if (name && audit_watch_inode(rule->watch) != (unsigned long)-1)
552 result = (name->dev == rule->watch->dev && 552 result = (name->dev == audit_watch_dev(rule->watch) &&
553 name->ino == rule->watch->ino); 553 name->ino == audit_watch_inode(rule->watch));
554 break; 554 break;
555 case AUDIT_DIR: 555 case AUDIT_DIR:
556 if (ctx) 556 if (ctx)