Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1849

kernel-2.6.18-238.el5.src.rpm

From: Alexander Viro <aviro@redhat.com>
Date: Tue, 22 Dec 2009 16:40:11 -0500
Subject: [misc] audit: fix breakage and leaks in audit_tree.c
Message-id: <20091222164011.GB14493@shell.devel.redhat.com>
Patchwork-id: 22253
O-Subject: [rhel5][bz549750] fix braindamage in audit_tree.c
Bugzilla: 549750
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
RH-Acked-by: Eric Paris <eparis@redhat.com>

Mainline commits 6f5d51148921c242680a7a1d9913384a30ab3cbe
and b4c30aad39805902cf5b855aa8a8b22d728ad057; fix breakage in
untag_chunk() and leaks in tag_chunk()

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index d4ab307..e53fc98 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -278,7 +278,7 @@ static void untag_chunk(struct node *p)
 		owner->root = NULL;
 	}
 
-	for (i = j = 0; i < size; i++, j++) {
+	for (i = j = 0; j <= size; i++, j++) {
 		struct audit_tree *s;
 		if (&chunk->owners[j] == p) {
 			list_del_init(&p->list);
@@ -291,7 +291,7 @@ static void untag_chunk(struct node *p)
 		if (!s) /* result of earlier fallback */
 			continue;
 		get_tree(s);
-		list_replace_init(&chunk->owners[i].list, &new->owners[j].list);
+		list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
 	}
 
 	list_replace_rcu(&chunk->hash, &new->hash);
@@ -374,15 +374,17 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 	for (n = 0; n < old->count; n++) {
 		if (old->owners[n].owner == tree) {
 			spin_unlock(&hash_lock);
-			put_inotify_watch(watch);
+			put_inotify_watch(&old->watch);
 			return 0;
 		}
 	}
 	spin_unlock(&hash_lock);
 
 	chunk = alloc_chunk(old->count + 1);
-	if (!chunk)
+	if (!chunk) {
+		put_inotify_watch(&old->watch);
 		return -ENOMEM;
+	}
 
 	mutex_lock(&inode->inotify_mutex);
 	if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
@@ -424,7 +426,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 	spin_unlock(&hash_lock);
 	inotify_evict_watch(&old->watch);
 	mutex_unlock(&inode->inotify_mutex);
-	put_inotify_watch(&old->watch);
+	put_inotify_watch(&old->watch); /* pair to inotify_find_watch */
+	put_inotify_watch(&old->watch); /* and kill it */
 	return 0;
 }