Commit cfcad62c74abfef83762dc05a556d21bdf3980a2

Authored by Eric Paris
Committed by Al Viro
1 parent ea7ae60bfe

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>

Showing 6 changed files with 572 additions and 506 deletions Side-by-side Diff

... ... @@ -70,7 +70,7 @@
70 70 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
71 71 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
72 72 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
73   -obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
  73 +obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o
74 74 obj-$(CONFIG_GCOV_KERNEL) += gcov/
75 75 obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
76 76 obj-$(CONFIG_KPROBES) += kprobes.o
... ... @@ -115,9 +115,6 @@
115 115 /* The netlink socket. */
116 116 static struct sock *audit_sock;
117 117  
118   -/* Inotify handle. */
119   -struct inotify_handle *audit_ih;
120   -
121 118 /* Hash for inode-based rules */
122 119 struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
123 120  
... ... @@ -971,13 +968,6 @@
971 968 mutex_unlock(&audit_cmd_mutex);
972 969 }
973 970  
974   -#ifdef CONFIG_AUDITSYSCALL
975   -static const struct inotify_operations audit_inotify_ops = {
976   - .handle_event = audit_handle_ievent,
977   - .destroy_watch = audit_free_parent,
978   -};
979   -#endif
980   -
981 971 /* Initialize audit support at boot time. */
982 972 static int __init audit_init(void)
983 973 {
... ... @@ -1002,12 +992,6 @@
1002 992 audit_ever_enabled |= !!audit_default;
1003 993  
1004 994 audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
1005   -
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 995  
1012 996 for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
1013 997 INIT_LIST_HEAD(&audit_inode_hash[i]);
... ... @@ -53,18 +53,7 @@
53 53 };
54 54  
55 55 /* Rule lists */
56   -struct audit_parent;
57   -
58   -struct 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   -
  56 +struct audit_watch;
68 57 struct audit_tree;
69 58 struct audit_chunk;
70 59  
71 60  
... ... @@ -108,18 +97,30 @@
108 97  
109 98 int audit_send_list(void *);
110 99  
111   -struct inotify_watch;
112   -/* Inotify handle */
113   -extern struct inotify_handle *audit_ih;
114   -
115   -extern void audit_free_parent(struct inotify_watch *);
116   -extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
117   - const char *, struct inode *);
118 100 extern int selinux_audit_rule_update(void);
119 101  
120 102 extern struct mutex audit_filter_mutex;
121 103 extern void audit_free_rule_rcu(struct rcu_head *);
122 104 extern struct list_head audit_filter_list[];
  105 +
  106 +/* audit watch functions */
  107 +extern unsigned long audit_watch_inode(struct audit_watch *watch);
  108 +extern dev_t audit_watch_dev(struct audit_watch *watch);
  109 +extern void audit_put_watch(struct audit_watch *watch);
  110 +extern void audit_get_watch(struct audit_watch *watch);
  111 +extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op);
  112 +extern int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw);
  113 +extern void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw);
  114 +extern int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
  115 + struct nameidata *ndw);
  116 +extern void audit_remove_watch(struct audit_watch *watch);
  117 +extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list);
  118 +extern void audit_inotify_unregister(struct list_head *in_list);
  119 +extern char *audit_watch_path(struct audit_watch *watch);
  120 +extern struct list_head *audit_watch_rules(struct audit_watch *watch);
  121 +
  122 +extern struct audit_entry *audit_dupe_rule(struct audit_krule *old,
  123 + struct audit_watch *watch);
123 124  
124 125 #ifdef CONFIG_AUDIT_TREE
125 126 extern struct audit_chunk *audit_tree_lookup(const struct inode *);
kernel/audit_watch.c
  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 +
  46 +struct 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 +
  56 +struct 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. */
  64 +struct 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 +
  80 +static 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 +
  89 +void audit_get_watch(struct audit_watch *watch)
  90 +{
  91 + atomic_inc(&watch->count);
  92 +}
  93 +
  94 +void 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 +
  104 +void 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 +
  112 +char *audit_watch_path(struct audit_watch *watch)
  113 +{
  114 + return watch->path;
  115 +}
  116 +
  117 +struct list_head *audit_watch_rules(struct audit_watch *watch)
  118 +{
  119 + return &watch->rules;
  120 +}
  121 +
  122 +unsigned long audit_watch_inode(struct audit_watch *watch)
  123 +{
  124 + return watch->ino;
  125 +}
  126 +
  127 +dev_t audit_watch_dev(struct audit_watch *watch)
  128 +{
  129 + return watch->dev;
  130 +}
  131 +
  132 +/* Initialize a parent watch entry. */
  133 +static 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. */
  159 +static 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. */
  177 +int 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. */
  202 +static 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 +
  222 +out:
  223 + return new;
  224 +}
  225 +
  226 +static 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. */
  248 +static 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 +
  304 +add_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. */
  311 +static 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. */
  335 +void 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. */
  348 +int 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. */
  383 +void 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. */
  397 +static 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. */
  429 +int 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 +
  474 +void 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. */
  499 +static 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 +
  522 +static const struct inotify_operations audit_inotify_ops = {
  523 + .handle_event = audit_handle_ievent,
  524 + .destroy_watch = audit_free_parent,
  525 +};
  526 +
  527 +static 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 +}
  534 +subsys_initcall(audit_watch_init);
kernel/auditfilter.c
... ... @@ -27,7 +27,6 @@
27 27 #include <linux/namei.h>
28 28 #include <linux/netlink.h>
29 29 #include <linux/sched.h>
30   -#include <linux/inotify.h>
31 30 #include <linux/security.h>
32 31 #include "audit.h"
33 32  
... ... @@ -44,36 +43,6 @@
44 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   -
59   -struct 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 46 /* Audit filter lists, defined in <linux/audit.h> */
78 47 struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
79 48 LIST_HEAD_INIT(audit_filter_list[0]),
... ... @@ -97,41 +66,6 @@
97 66  
98 67 DEFINE_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   -
103   -void 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   -
112   -static inline void audit_get_watch(struct audit_watch *watch)
113   -{
114   - atomic_inc(&watch->count);
115   -}
116   -
117   -static 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   -
127   -static 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   -
135 69 static inline void audit_free_rule(struct audit_entry *e)
136 70 {
137 71 int i;
... ... @@ -156,50 +90,6 @@
156 90 audit_free_rule(e);
157 91 }
158 92  
159   -/* Initialize a parent watch entry. */
160   -static 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. */
186   -static 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 93 /* Initialize an audit filterlist entry. */
204 94 static inline struct audit_entry *audit_init_entry(u32 field_count)
205 95 {
... ... @@ -260,31 +150,6 @@
260 150 return 0;
261 151 }
262 152  
263   -/* Translate a watch string to kernel respresentation. */
264   -static 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   -
288 153 static __u32 *classes[AUDIT_SYSCALL_CLASSES];
289 154  
290 155 int __init audit_register_class(int class, unsigned *list)
... ... @@ -766,7 +631,8 @@
766 631 break;
767 632 case AUDIT_WATCH:
768 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 636 break;
771 637 case AUDIT_DIR:
772 638 data->buflen += data->values[i] =
... ... @@ -818,7 +684,8 @@
818 684 return 1;
819 685 break;
820 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 689 return 1;
823 690 break;
824 691 case AUDIT_DIR:
... ... @@ -844,32 +711,6 @@
844 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. */
849   -static 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   -
869   -out:
870   - return new;
871   -}
872   -
873 714 /* Duplicate LSM field information. The lsm_rule is opaque, so must be
874 715 * re-initialized. */
875 716 static inline int audit_dupe_lsm_field(struct audit_field *df,
... ... @@ -904,8 +745,8 @@
904 745 * rule with the new rule in the filterlist, then free the old rule.
905 746 * The rlist element is undefined; list manipulations are handled apart from
906 747 * the initial copy. */
907   -static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
908   - struct audit_watch *watch)
  748 +struct audit_entry *audit_dupe_rule(struct audit_krule *old,
  749 + struct audit_watch *watch)
909 750 {
910 751 u32 fcount = old->field_count;
911 752 struct audit_entry *entry;
... ... @@ -977,127 +818,6 @@
977 818 return entry;
978 819 }
979 820  
980   -static 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. */
1002   -static 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   -
1058   -add_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. */
1065   -static 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. */
1089   -static 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 821 /* Find an existing audit rule.
1102 822 * Caller must hold audit_filter_mutex to prevent stale rule data. */
1103 823 static struct audit_entry *audit_find_rule(struct audit_entry *entry,
... ... @@ -1135,134 +855,6 @@
1135 855 return found;
1136 856 }
1137 857  
1138   -/* Get path information necessary for adding watches. */
1139   -static 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. */
1175   -static 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. */
1189   -static 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. */
1221   -static 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   -
1266 858 static u64 prio_low = ~0ULL/2;
1267 859 static u64 prio_high = ~0ULL/2 - 1;
1268 860  
... ... @@ -1297,7 +889,7 @@
1297 889  
1298 890 /* Avoid calling path_lookup under audit_filter_mutex. */
1299 891 if (watch) {
1300   - err = audit_get_nd(watch->path, &ndp, &ndw);
  892 + err = audit_get_nd(audit_watch_path(watch), &ndp, &ndw);
1301 893 if (err)
1302 894 goto error;
1303 895 }
... ... @@ -1312,7 +904,7 @@
1312 904 }
1313 905 /* entry->rule.watch may have changed during audit_add_watch() */
1314 906 watch = entry->rule.watch;
1315   - h = audit_hash_ino((u32)watch->ino);
  907 + h = audit_hash_ino((u32)audit_watch_inode(watch));
1316 908 list = &audit_inode_hash[h];
1317 909 }
1318 910 if (tree) {
... ... @@ -1364,7 +956,7 @@
1364 956 static inline int audit_del_rule(struct audit_entry *entry)
1365 957 {
1366 958 struct audit_entry *e;
1367   - struct audit_watch *watch, *tmp_watch = entry->rule.watch;
  959 + struct audit_watch *watch = entry->rule.watch;
1368 960 struct audit_tree *tree = entry->rule.tree;
1369 961 struct list_head *list;
1370 962 LIST_HEAD(inotify_list);
1371 963  
... ... @@ -1386,30 +978,9 @@
1386 978 goto out;
1387 979 }
1388 980  
1389   - watch = e->rule.watch;
1390   - if (watch) {
1391   - struct audit_parent *parent = watch->parent;
  981 + if (e->rule.watch)
  982 + audit_remove_watch_rule(&e->rule, &inotify_list);
1392 983  
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   -
1413 984 if (e->rule.tree)
1414 985 audit_remove_tree_rule(&e->rule);
1415 986  
... ... @@ -1430,8 +1001,8 @@
1430 1001 audit_inotify_unregister(&inotify_list);
1431 1002  
1432 1003 out:
1433   - if (tmp_watch)
1434   - audit_put_watch(tmp_watch); /* match initial get */
  1004 + if (watch)
  1005 + audit_put_watch(watch); /* match initial get */
1435 1006 if (tree)
1436 1007 audit_put_tree(tree); /* that's the temporary one */
1437 1008  
... ... @@ -1785,7 +1356,7 @@
1785 1356 list_del(&r->list);
1786 1357 } else {
1787 1358 if (watch) {
1788   - list_add(&nentry->rule.rlist, &watch->rules);
  1359 + list_add(&nentry->rule.rlist, audit_watch_rules(watch));
1789 1360 list_del(&r->rlist);
1790 1361 } else if (tree)
1791 1362 list_replace_init(&r->rlist, &nentry->rule.rlist);
... ... @@ -1820,29 +1391,5 @@
1820 1391 mutex_unlock(&audit_filter_mutex);
1821 1392  
1822 1393 return err;
1823   -}
1824   -
1825   -/* Update watch data in audit rules based on inotify events. */
1826   -void 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 1394 }
... ... @@ -548,9 +548,9 @@
548 548 }
549 549 break;
550 550 case AUDIT_WATCH:
551   - if (name && rule->watch->ino != (unsigned long)-1)
552   - result = (name->dev == rule->watch->dev &&
553   - name->ino == rule->watch->ino);
  551 + if (name && audit_watch_inode(rule->watch) != (unsigned long)-1)
  552 + result = (name->dev == audit_watch_dev(rule->watch) &&
  553 + name->ino == audit_watch_inode(rule->watch));
554 554 break;
555 555 case AUDIT_DIR:
556 556 if (ctx)