Commit a2140fc0cb0325bb6384e788edd27b9a568714e2

Authored by Miklos Szeredi
1 parent 0fe33aae0e

audit: fix refcounting in audit-tree

Refcounting of fsnotify_mark in audit tree is broken.  E.g:

                              refcount
create_chunk
  alloc_chunk                 1
  fsnotify_add_mark           2

untag_chunk
  fsnotify_get_mark           3
  fsnotify_destroy_mark
    audit_tree_freeing_mark   2
  fsnotify_put_mark           1
  fsnotify_put_mark           0
  via destroy_list
    fsnotify_mark_destroy    -1

This was reported by various people as triggering Oops when stopping auditd.

We could just remove the put_mark from audit_tree_freeing_mark() but that would
break freeing via inode destruction.  So this patch simply omits a put_mark
after calling destroy_mark or adds a get_mark before.

The additional get_mark is necessary where there's no other put_mark after
fsnotify_destroy_mark() since it assumes that the caller is holding a reference
(or the inode is keeping the mark pinned, not the case here AFAICS).

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reported-by: Valentin Avram <aval13@gmail.com>
Reported-by: Peter Moody <pmoody@google.com>
Acked-by: Eric Paris <eparis@redhat.com>
CC: stable@vger.kernel.org

Showing 1 changed file with 2 additions and 3 deletions Side-by-side Diff

... ... @@ -250,7 +250,6 @@
250 250 spin_unlock(&hash_lock);
251 251 spin_unlock(&entry->lock);
252 252 fsnotify_destroy_mark(entry);
253   - fsnotify_put_mark(entry);
254 253 goto out;
255 254 }
256 255  
... ... @@ -293,7 +292,6 @@
293 292 spin_unlock(&hash_lock);
294 293 spin_unlock(&entry->lock);
295 294 fsnotify_destroy_mark(entry);
296   - fsnotify_put_mark(entry);
297 295 goto out;
298 296  
299 297 Fallback:
... ... @@ -332,6 +330,7 @@
332 330 spin_unlock(&hash_lock);
333 331 chunk->dead = 1;
334 332 spin_unlock(&entry->lock);
  333 + fsnotify_get_mark(entry);
335 334 fsnotify_destroy_mark(entry);
336 335 fsnotify_put_mark(entry);
337 336 return 0;
... ... @@ -412,6 +411,7 @@
412 411 spin_unlock(&chunk_entry->lock);
413 412 spin_unlock(&old_entry->lock);
414 413  
  414 + fsnotify_get_mark(chunk_entry);
415 415 fsnotify_destroy_mark(chunk_entry);
416 416  
417 417 fsnotify_put_mark(chunk_entry);
... ... @@ -445,7 +445,6 @@
445 445 spin_unlock(&old_entry->lock);
446 446 fsnotify_destroy_mark(old_entry);
447 447 fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
448   - fsnotify_put_mark(old_entry); /* and kill it */
449 448 return 0;
450 449 }
451 450