aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit_watch.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 20:12:04 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:16 -0400
commitae7b8f4108bcffb42173f867ce845268c7202d48 (patch)
tree049d357dcbffe597c77c534ea211c3efd26680e3 /kernel/audit_watch.c
parentb7ba83715317007962ee318587de92f14e9c3aaa (diff)
Audit: clean up the audit_watch split
No real changes, just cleanup to the audit_watch split patch which we done with minimal code changes for easy review. Now fix interfaces to make things work better. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'kernel/audit_watch.c')
-rw-r--r--kernel/audit_watch.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 8df43696f4ba..c2ca7168bfd1 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -51,12 +51,12 @@ struct audit_watch {
51 unsigned long ino; /* associated inode number */ 51 unsigned long ino; /* associated inode number */
52 struct audit_parent *parent; /* associated parent */ 52 struct audit_parent *parent; /* associated parent */
53 struct list_head wlist; /* entry in parent->watches list */ 53 struct list_head wlist; /* entry in parent->watches list */
54 struct list_head rules; /* associated rules */ 54 struct list_head rules; /* anchor for krule->rlist */
55}; 55};
56 56
57struct audit_parent { 57struct audit_parent {
58 struct list_head ilist; /* entry in inotify registration list */ 58 struct list_head ilist; /* tmp list used to free parents */
59 struct list_head watches; /* associated watches */ 59 struct list_head watches; /* anchor for audit_watch->wlist */
60 struct inotify_watch wdata; /* inotify watch data */ 60 struct inotify_watch wdata; /* inotify watch data */
61 unsigned flags; /* status flags */ 61 unsigned flags; /* status flags */
62}; 62};
@@ -78,13 +78,18 @@ struct inotify_handle *audit_ih;
78/* Inotify events we care about. */ 78/* Inotify events we care about. */
79#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF 79#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
80 80
81static void audit_free_parent(struct inotify_watch *i_watch) 81static void audit_free_parent(struct audit_parent *parent)
82{
83 WARN_ON(!list_empty(&parent->watches));
84 kfree(parent);
85}
86
87static void audit_destroy_watch(struct inotify_watch *i_watch)
82{ 88{
83 struct audit_parent *parent; 89 struct audit_parent *parent;
84 90
85 parent = container_of(i_watch, struct audit_parent, wdata); 91 parent = container_of(i_watch, struct audit_parent, wdata);
86 WARN_ON(!list_empty(&parent->watches)); 92 audit_free_parent(parent);
87 kfree(parent);
88} 93}
89 94
90void audit_get_watch(struct audit_watch *watch) 95void audit_get_watch(struct audit_watch *watch)
@@ -115,19 +120,11 @@ char *audit_watch_path(struct audit_watch *watch)
115 return watch->path; 120 return watch->path;
116} 121}
117 122
118struct list_head *audit_watch_rules(struct audit_watch *watch) 123int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
119{ 124{
120 return &watch->rules; 125 return (watch->ino != (unsigned long)-1) &&
121} 126 (watch->ino == ino) &&
122 127 (watch->dev == dev);
123unsigned long audit_watch_inode(struct audit_watch *watch)
124{
125 return watch->ino;
126}
127
128dev_t audit_watch_dev(struct audit_watch *watch)
129{
130 return watch->dev;
131} 128}
132 129
133/* Initialize a parent watch entry. */ 130/* Initialize a parent watch entry. */
@@ -149,7 +146,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp)
149 wd = inotify_add_watch(audit_ih, &parent->wdata, 146 wd = inotify_add_watch(audit_ih, &parent->wdata,
150 ndp->path.dentry->d_inode, AUDIT_IN_WATCH); 147 ndp->path.dentry->d_inode, AUDIT_IN_WATCH);
151 if (wd < 0) { 148 if (wd < 0) {
152 audit_free_parent(&parent->wdata); 149 audit_free_parent(parent);
153 return ERR_PTR(wd); 150 return ERR_PTR(wd);
154 } 151 }
155 152
@@ -251,15 +248,19 @@ static void audit_update_watch(struct audit_parent *parent,
251 struct audit_entry *oentry, *nentry; 248 struct audit_entry *oentry, *nentry;
252 249
253 mutex_lock(&audit_filter_mutex); 250 mutex_lock(&audit_filter_mutex);
251 /* Run all of the watches on this parent looking for the one that
252 * matches the given dname */
254 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { 253 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
255 if (audit_compare_dname_path(dname, owatch->path, NULL)) 254 if (audit_compare_dname_path(dname, owatch->path, NULL))
256 continue; 255 continue;
257 256
258 /* If the update involves invalidating rules, do the inode-based 257 /* If the update involves invalidating rules, do the inode-based
259 * filtering now, so we don't omit records. */ 258 * filtering now, so we don't omit records. */
260 if (invalidating && current->audit_context) 259 if (invalidating && !audit_dummy_context())
261 audit_filter_inodes(current, current->audit_context); 260 audit_filter_inodes(current, current->audit_context);
262 261
262 /* updating ino will likely change which audit_hash_list we
263 * are on so we need a new watch for the new list */
263 nwatch = audit_dupe_watch(owatch); 264 nwatch = audit_dupe_watch(owatch);
264 if (IS_ERR(nwatch)) { 265 if (IS_ERR(nwatch)) {
265 mutex_unlock(&audit_filter_mutex); 266 mutex_unlock(&audit_filter_mutex);
@@ -275,12 +276,21 @@ static void audit_update_watch(struct audit_parent *parent,
275 list_del(&oentry->rule.rlist); 276 list_del(&oentry->rule.rlist);
276 list_del_rcu(&oentry->list); 277 list_del_rcu(&oentry->list);
277 278
278 nentry = audit_dupe_rule(&oentry->rule, nwatch); 279 nentry = audit_dupe_rule(&oentry->rule);
279 if (IS_ERR(nentry)) { 280 if (IS_ERR(nentry)) {
280 list_del(&oentry->rule.list); 281 list_del(&oentry->rule.list);
281 audit_panic("error updating watch, removing"); 282 audit_panic("error updating watch, removing");
282 } else { 283 } else {
283 int h = audit_hash_ino((u32)ino); 284 int h = audit_hash_ino((u32)ino);
285
286 /*
287 * nentry->rule.watch == oentry->rule.watch so
288 * we must drop that reference and set it to our
289 * new watch.
290 */
291 audit_put_watch(nentry->rule.watch);
292 audit_get_watch(nwatch);
293 nentry->rule.watch = nwatch;
284 list_add(&nentry->rule.rlist, &nwatch->rules); 294 list_add(&nentry->rule.rlist, &nwatch->rules);
285 list_add_rcu(&nentry->list, &audit_inode_hash[h]); 295 list_add_rcu(&nentry->list, &audit_inode_hash[h]);
286 list_replace(&oentry->rule.list, 296 list_replace(&oentry->rule.list,
@@ -329,14 +339,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
329 339
330/* Unregister inotify watches for parents on in_list. 340/* Unregister inotify watches for parents on in_list.
331 * Generates an IN_IGNORED event. */ 341 * Generates an IN_IGNORED event. */
332void audit_inotify_unregister(struct list_head *in_list) 342void audit_watch_inotify_unregister(struct list_head *in_list)
333{ 343{
334 struct audit_parent *p, *n; 344 struct audit_parent *p, *n;
335 345
336 list_for_each_entry_safe(p, n, in_list, ilist) { 346 list_for_each_entry_safe(p, n, in_list, ilist) {
337 list_del(&p->ilist); 347 list_del(&p->ilist);
338 inotify_rm_watch(audit_ih, &p->wdata); 348 inotify_rm_watch(audit_ih, &p->wdata);
339 /* the unpin matching the pin in audit_do_del_rule() */ 349 /* the unpin matching the pin in audit_remove_watch_rule() */
340 unpin_inotify_watch(&p->wdata); 350 unpin_inotify_watch(&p->wdata);
341 } 351 }
342} 352}
@@ -423,13 +433,13 @@ static void audit_add_to_parent(struct audit_krule *krule,
423 433
424/* Find a matching watch entry, or add this one. 434/* Find a matching watch entry, or add this one.
425 * Caller must hold audit_filter_mutex. */ 435 * Caller must hold audit_filter_mutex. */
426int audit_add_watch(struct audit_krule *krule) 436int audit_add_watch(struct audit_krule *krule, struct list_head **list)
427{ 437{
428 struct audit_watch *watch = krule->watch; 438 struct audit_watch *watch = krule->watch;
429 struct inotify_watch *i_watch; 439 struct inotify_watch *i_watch;
430 struct audit_parent *parent; 440 struct audit_parent *parent;
431 struct nameidata *ndp = NULL, *ndw = NULL; 441 struct nameidata *ndp = NULL, *ndw = NULL;
432 int ret = 0; 442 int h, ret = 0;
433 443
434 mutex_unlock(&audit_filter_mutex); 444 mutex_unlock(&audit_filter_mutex);
435 445
@@ -475,6 +485,8 @@ int audit_add_watch(struct audit_krule *krule)
475 /* match get in audit_init_parent or inotify_find_watch */ 485 /* match get in audit_init_parent or inotify_find_watch */
476 put_inotify_watch(&parent->wdata); 486 put_inotify_watch(&parent->wdata);
477 487
488 h = audit_hash_ino((u32)watch->ino);
489 *list = &audit_inode_hash[h];
478error: 490error:
479 audit_put_nd(ndp, ndw); /* NULL args OK */ 491 audit_put_nd(ndp, ndw); /* NULL args OK */
480 return ret; 492 return ret;
@@ -514,8 +526,7 @@ static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
514 parent = container_of(i_watch, struct audit_parent, wdata); 526 parent = container_of(i_watch, struct audit_parent, wdata);
515 527
516 if (mask & (IN_CREATE|IN_MOVED_TO) && inode) 528 if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
517 audit_update_watch(parent, dname, inode->i_sb->s_dev, 529 audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
518 inode->i_ino, 0);
519 else if (mask & (IN_DELETE|IN_MOVED_FROM)) 530 else if (mask & (IN_DELETE|IN_MOVED_FROM))
520 audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1); 531 audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
521 /* inotify automatically removes the watch and sends IN_IGNORED */ 532 /* inotify automatically removes the watch and sends IN_IGNORED */
@@ -531,7 +542,7 @@ static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
531 542
532static const struct inotify_operations audit_inotify_ops = { 543static const struct inotify_operations audit_inotify_ops = {
533 .handle_event = audit_handle_ievent, 544 .handle_event = audit_handle_ievent,
534 .destroy_watch = audit_free_parent, 545 .destroy_watch = audit_destroy_watch,
535}; 546};
536 547
537static int __init audit_watch_init(void) 548static int __init audit_watch_init(void)