Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2678

kernel-2.6.18-194.11.1.el5.src.rpm

Date: Fri, 13 Oct 2006 09:20:09 -0400
From: Steve Dickson <SteveD@redhat.com>
Subject: [RHEL5/FC6][NFS4] - BUG in __list_add at lib/list_debug.c:31!

The attached upstream patch fixes NFSv4 problem of using
memory after its been freed which was causing a BUG()
to pop in the lists code.

This patch was found and tested by IBM. I also was able to reproduce
this problem verified this patch indeed fixed the problem.

The bz is: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=206996

steved.

Committer: Trond Myklebust <Trond.Myklebust@netapp.com>  2006-09-22 23:24:54
Parent: 275a082fe9308e710324e26ccb5363c53d8fd45f
Child:  158998b6fe36f6acef087f574c96d44713499cc9

    NFSv4: Fix a use-after-free issue with the nfs server.
	    
		    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

--- linux-2.6.18.i686/fs/nfs/client.c.orig	2006-10-12 07:30:35.875265000 -0400
+++ linux-2.6.18.i686/fs/nfs/client.c	2006-10-12 09:19:15.135509000 -0400
@@ -165,6 +165,26 @@ error_0:
 	return NULL;
 }
 
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4
+	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+		nfs4_kill_renewd(clp);
+	while (!list_empty(&clp->cl_unused)) {
+		struct nfs4_state_owner *sp;
+
+		sp = list_entry(clp->cl_unused.next,
+				struct nfs4_state_owner,
+				so_list);
+		list_del(&sp->so_list);
+		kfree(sp);
+	}
+	BUG_ON(!list_empty(&clp->cl_state_owners));
+	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+		nfs_idmap_delete(clp);
+#endif
+}
+
 /*
  * Destroy a shared client record
  */
@@ -172,21 +192,7 @@ static void nfs_free_client(struct nfs_c
 {
 	dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
 
-#ifdef CONFIG_NFS_V4
-	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) {
-		while (!list_empty(&clp->cl_unused)) {
-			struct nfs4_state_owner *sp;
-
-			sp = list_entry(clp->cl_unused.next,
-					struct nfs4_state_owner,
-					so_list);
-			list_del(&sp->so_list);
-			kfree(sp);
-		}
-		BUG_ON(!list_empty(&clp->cl_state_owners));
-		nfs_idmap_delete(clp);
-	}
-#endif
+	nfs4_shutdown_client(clp);
 
 	nfs_fscache_release_client_cookie(clp);
 
@@ -320,25 +326,11 @@ found_client:
 	if (new)
 		nfs_free_client(new);
 
-	if (clp->cl_cons_state == NFS_CS_INITING) {
-		DECLARE_WAITQUEUE(myself, current);
-
-		add_wait_queue(&nfs_client_active_wq, &myself);
-
-		for (;;) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			if (signal_pending(current) ||
-			    clp->cl_cons_state > NFS_CS_READY)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&nfs_client_active_wq, &myself);
-
-		if (signal_pending(current)) {
-			nfs_put_client(clp);
-			return ERR_PTR(-ERESTARTSYS);
-		}
+	error = wait_event_interruptible(nfs_client_active_wq,
+		clp->cl_cons_state != NFS_CS_INITING);
+	if (error < 0) {
+		nfs_put_client(clp);
+		return ERR_PTR(-ERESTARTSYS);
 	}
 
 	if (clp->cl_cons_state < NFS_CS_READY) {
--- linux-2.6.18.i686/fs/nfs/nfs4renewd.c.orig	2006-10-12 07:30:33.897855000 -0400
+++ linux-2.6.18.i686/fs/nfs/nfs4renewd.c	2006-10-12 09:02:34.847340000 -0400
@@ -121,6 +121,7 @@ nfs4_schedule_state_renewal(struct nfs_c
 			__FUNCTION__, (timeout + HZ - 1) / HZ);
 	cancel_delayed_work(&clp->cl_renewd);
 	schedule_delayed_work(&clp->cl_renewd, timeout);
+	set_bit(NFS_CS_RENEWD, &clp->cl_res_state);
 	spin_unlock(&clp->cl_lock);
 }
 
--- linux-2.6.18.i686/fs/nfs/super.c.orig	2006-10-12 07:30:35.956265000 -0400
+++ linux-2.6.18.i686/fs/nfs/super.c	2006-10-12 09:02:35.474171000 -0400
@@ -881,13 +881,15 @@ static int nfs4_get_sb(struct file_syste
 		goto out_free;
 	}
 
+	if (s->s_fs_info != server) {
+		nfs_free_server(server);
+		server = NULL;
+	}
+
 	if (!s->s_root) {
 		/* initial superblock/root creation */
 		s->s_flags = flags;
-
 		nfs4_fill_super(s);
-	} else {
-		nfs_free_server(server);
 	}
 
 	mntroot = nfs4_get_root(s, &mntfh);
--- linux-2.6.18.i686/include/linux/nfs_fs_sb.h.orig	2006-10-12 07:30:35.319560000 -0400
+++ linux-2.6.18.i686/include/linux/nfs_fs_sb.h	2006-10-12 09:02:35.494151000 -0400
@@ -20,6 +20,7 @@ struct nfs_client {
 #define NFS_CS_RPCIOD		0		/* - rpciod started */
 #define NFS_CS_CALLBACK		1		/* - callback started */
 #define NFS_CS_IDMAP		2		/* - idmap started */
+#define NFS_CS_RENEWD		3		/* - renewd started */
 	struct sockaddr_in	cl_addr;	/* server identifier */
 	char *			cl_hostname;	/* hostname of server */
 	struct list_head	cl_share_link;	/* link in global client list */