From: Greg Kroah-Hartman Date: Tue, 28 Aug 2012 16:44:46 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.5.4~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=261f10efed8555a3dda9dc13066c7fd437b69153;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: audit-don-t-free_chunk-after-fsnotify_add_mark.patch audit-fix-refcounting-in-audit-tree.patch --- diff --git a/queue-3.0/audit-don-t-free_chunk-after-fsnotify_add_mark.patch b/queue-3.0/audit-don-t-free_chunk-after-fsnotify_add_mark.patch new file mode 100644 index 00000000000..3b978f8549e --- /dev/null +++ b/queue-3.0/audit-don-t-free_chunk-after-fsnotify_add_mark.patch @@ -0,0 +1,49 @@ +From 0fe33aae0e94b4097dd433c9399e16e17d638cd8 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 15 Aug 2012 12:55:22 +0200 +Subject: audit: don't free_chunk() after fsnotify_add_mark() + +From: Miklos Szeredi + +commit 0fe33aae0e94b4097dd433c9399e16e17d638cd8 upstream. + +Don't do free_chunk() after fsnotify_add_mark(). That one does a delayed unref +via the destroy list and this results in use-after-free. + +Signed-off-by: Miklos Szeredi +Acked-by: Eric Paris +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/audit_tree.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/kernel/audit_tree.c ++++ b/kernel/audit_tree.c +@@ -265,7 +265,7 @@ static void untag_chunk(struct node *p) + + fsnotify_duplicate_mark(&new->mark, entry); + if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { +- free_chunk(new); ++ fsnotify_put_mark(&new->mark); + goto Fallback; + } + +@@ -328,7 +328,7 @@ static int create_chunk(struct inode *in + + entry = &chunk->mark; + if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { +- free_chunk(chunk); ++ fsnotify_put_mark(entry); + return -ENOSPC; + } + +@@ -402,7 +402,7 @@ static int tag_chunk(struct inode *inode + fsnotify_duplicate_mark(chunk_entry, old_entry); + if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { + spin_unlock(&old_entry->lock); +- free_chunk(chunk); ++ fsnotify_put_mark(chunk_entry); + fsnotify_put_mark(old_entry); + return -ENOSPC; + } diff --git a/queue-3.0/audit-fix-refcounting-in-audit-tree.patch b/queue-3.0/audit-fix-refcounting-in-audit-tree.patch new file mode 100644 index 00000000000..00ea5c61ba4 --- /dev/null +++ b/queue-3.0/audit-fix-refcounting-in-audit-tree.patch @@ -0,0 +1,87 @@ +From a2140fc0cb0325bb6384e788edd27b9a568714e2 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 15 Aug 2012 12:55:22 +0200 +Subject: audit: fix refcounting in audit-tree + +From: Miklos Szeredi + +commit a2140fc0cb0325bb6384e788edd27b9a568714e2 upstream. + +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 +Reported-by: Valentin Avram +Reported-by: Peter Moody +Acked-by: Eric Paris +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/audit_tree.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/kernel/audit_tree.c ++++ b/kernel/audit_tree.c +@@ -256,7 +256,6 @@ static void untag_chunk(struct node *p) + spin_unlock(&hash_lock); + spin_unlock(&entry->lock); + fsnotify_destroy_mark(entry); +- fsnotify_put_mark(entry); + goto out; + } + +@@ -299,7 +298,6 @@ static void untag_chunk(struct node *p) + spin_unlock(&hash_lock); + spin_unlock(&entry->lock); + fsnotify_destroy_mark(entry); +- fsnotify_put_mark(entry); + goto out; + + Fallback: +@@ -338,6 +336,7 @@ static int create_chunk(struct inode *in + spin_unlock(&hash_lock); + chunk->dead = 1; + spin_unlock(&entry->lock); ++ fsnotify_get_mark(entry); + fsnotify_destroy_mark(entry); + fsnotify_put_mark(entry); + return 0; +@@ -418,6 +417,7 @@ static int tag_chunk(struct inode *inode + spin_unlock(&chunk_entry->lock); + spin_unlock(&old_entry->lock); + ++ fsnotify_get_mark(chunk_entry); + fsnotify_destroy_mark(chunk_entry); + + fsnotify_put_mark(chunk_entry); +@@ -451,7 +451,6 @@ static int tag_chunk(struct inode *inode + spin_unlock(&old_entry->lock); + fsnotify_destroy_mark(old_entry); + fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ +- fsnotify_put_mark(old_entry); /* and kill it */ + return 0; + } + diff --git a/queue-3.0/series b/queue-3.0/series index 4f731184955..d9c23ebd8a7 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -15,3 +15,5 @@ mm-hugetlbfs-correctly-populate-shared-pmd.patch nfsv3-ensure-that-do_proc_get_root-reports-errors-correctly.patch nfsv4.1-remove-a-bogus-bug_on-in-nfs4_layoutreturn_done.patch nfs-alias-the-nfs-module-to-nfs4.patch +audit-don-t-free_chunk-after-fsnotify_add_mark.patch +audit-fix-refcounting-in-audit-tree.patch