@@ -51,12 +51,12 @@ struct audit_watch {
51
51
unsigned long ino ; /* associated inode number */
52
52
struct audit_parent * parent ; /* associated parent */
53
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
57
57
struct audit_parent {
58
- struct list_head ilist ; /* entry in inotify registration list */
59
- struct list_head watches ; /* associated watches */
58
+ struct list_head ilist ; /* tmp list used to free parents */
59
+ struct list_head watches ; /* anchor for audit_watch->wlist */
60
60
struct inotify_watch wdata ; /* inotify watch data */
61
61
unsigned flags ; /* status flags */
62
62
};
@@ -78,13 +78,18 @@ struct inotify_handle *audit_ih;
78
78
/* Inotify events we care about. */
79
79
#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
80
80
81
- static void audit_free_parent (struct inotify_watch * i_watch )
81
+ static void audit_free_parent (struct audit_parent * parent )
82
+ {
83
+ WARN_ON (!list_empty (& parent -> watches ));
84
+ kfree (parent );
85
+ }
86
+
87
+ static void audit_destroy_watch (struct inotify_watch * i_watch )
82
88
{
83
89
struct audit_parent * parent ;
84
90
85
91
parent = container_of (i_watch , struct audit_parent , wdata );
86
- WARN_ON (!list_empty (& parent -> watches ));
87
- kfree (parent );
92
+ audit_free_parent (parent );
88
93
}
89
94
90
95
void audit_get_watch (struct audit_watch * watch )
@@ -115,19 +120,11 @@ char *audit_watch_path(struct audit_watch *watch)
115
120
return watch -> path ;
116
121
}
117
122
118
- struct list_head * audit_watch_rules (struct audit_watch * watch )
123
+ int audit_watch_compare (struct audit_watch * watch , unsigned long ino , dev_t dev )
119
124
{
120
- return & watch -> rules ;
121
- }
122
-
123
- unsigned long audit_watch_inode (struct audit_watch * watch )
124
- {
125
- return watch -> ino ;
126
- }
127
-
128
- dev_t audit_watch_dev (struct audit_watch * watch )
129
- {
130
- return watch -> dev ;
125
+ return (watch -> ino != (unsigned long )-1 ) &&
126
+ (watch -> ino == ino ) &&
127
+ (watch -> dev == dev );
131
128
}
132
129
133
130
/* Initialize a parent watch entry. */
@@ -149,7 +146,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp)
149
146
wd = inotify_add_watch (audit_ih , & parent -> wdata ,
150
147
ndp -> path .dentry -> d_inode , AUDIT_IN_WATCH );
151
148
if (wd < 0 ) {
152
- audit_free_parent (& parent -> wdata );
149
+ audit_free_parent (parent );
153
150
return ERR_PTR (wd );
154
151
}
155
152
@@ -251,15 +248,19 @@ static void audit_update_watch(struct audit_parent *parent,
251
248
struct audit_entry * oentry , * nentry ;
252
249
253
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
253
list_for_each_entry_safe (owatch , nextw , & parent -> watches , wlist ) {
255
254
if (audit_compare_dname_path (dname , owatch -> path , NULL ))
256
255
continue ;
257
256
258
257
/* If the update involves invalidating rules, do the inode-based
259
258
* filtering now, so we don't omit records. */
260
- if (invalidating && current -> audit_context )
259
+ if (invalidating && ! audit_dummy_context () )
261
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
264
nwatch = audit_dupe_watch (owatch );
264
265
if (IS_ERR (nwatch )) {
265
266
mutex_unlock (& audit_filter_mutex );
@@ -275,12 +276,21 @@ static void audit_update_watch(struct audit_parent *parent,
275
276
list_del (& oentry -> rule .rlist );
276
277
list_del_rcu (& oentry -> list );
277
278
278
- nentry = audit_dupe_rule (& oentry -> rule , nwatch );
279
+ nentry = audit_dupe_rule (& oentry -> rule );
279
280
if (IS_ERR (nentry )) {
280
281
list_del (& oentry -> rule .list );
281
282
audit_panic ("error updating watch, removing" );
282
283
} else {
283
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
294
list_add (& nentry -> rule .rlist , & nwatch -> rules );
285
295
list_add_rcu (& nentry -> list , & audit_inode_hash [h ]);
286
296
list_replace (& oentry -> rule .list ,
@@ -329,14 +339,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
329
339
330
340
/* Unregister inotify watches for parents on in_list.
331
341
* Generates an IN_IGNORED event. */
332
- void audit_inotify_unregister (struct list_head * in_list )
342
+ void audit_watch_inotify_unregister (struct list_head * in_list )
333
343
{
334
344
struct audit_parent * p , * n ;
335
345
336
346
list_for_each_entry_safe (p , n , in_list , ilist ) {
337
347
list_del (& p -> ilist );
338
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
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
434
/* Find a matching watch entry, or add this one.
425
435
* Caller must hold audit_filter_mutex. */
426
- int audit_add_watch (struct audit_krule * krule )
436
+ int audit_add_watch (struct audit_krule * krule , struct list_head * * list )
427
437
{
428
438
struct audit_watch * watch = krule -> watch ;
429
439
struct inotify_watch * i_watch ;
430
440
struct audit_parent * parent ;
431
441
struct nameidata * ndp = NULL , * ndw = NULL ;
432
- int ret = 0 ;
442
+ int h , ret = 0 ;
433
443
434
444
mutex_unlock (& audit_filter_mutex );
435
445
@@ -475,6 +485,8 @@ int audit_add_watch(struct audit_krule *krule)
475
485
/* match get in audit_init_parent or inotify_find_watch */
476
486
put_inotify_watch (& parent -> wdata );
477
487
488
+ h = audit_hash_ino ((u32 )watch -> ino );
489
+ * list = & audit_inode_hash [h ];
478
490
error :
479
491
audit_put_nd (ndp , ndw ); /* NULL args OK */
480
492
return ret ;
@@ -514,8 +526,7 @@ static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
514
526
parent = container_of (i_watch , struct audit_parent , wdata );
515
527
516
528
if (mask & (IN_CREATE |IN_MOVED_TO ) && inode )
517
- audit_update_watch (parent , dname , inode -> i_sb -> s_dev ,
518
- inode -> i_ino , 0 );
529
+ audit_update_watch (parent , dname , inode -> i_sb -> s_dev , inode -> i_ino , 0 );
519
530
else if (mask & (IN_DELETE |IN_MOVED_FROM ))
520
531
audit_update_watch (parent , dname , (dev_t )- 1 , (unsigned long )-1 , 1 );
521
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
532
543
static const struct inotify_operations audit_inotify_ops = {
533
544
.handle_event = audit_handle_ievent ,
534
- .destroy_watch = audit_free_parent ,
545
+ .destroy_watch = audit_destroy_watch ,
535
546
};
536
547
537
548
static int __init audit_watch_init (void )
0 commit comments