[PATCH 5/8] UML - Balance list_add and list_del in the network driver

From: Jeff Dike
Date: Mon Feb 06 2006 - 21:22:48 EST


The network driver added an interface to the "opened" list when it was
configured, not when it was brought up, and removed it when it was taken
down. A sequence of ifconfig up, ifconfig down, ... caused it to be removed
multiple times from the list without being added in between, resulting in
a crash. This patch moves the add to when the interface is brought up.

Signed-off-by: Jeff Dike <jdike@xxxxxxxxxxx>

Index: linux-2.6.15/arch/um/drivers/net_kern.c
===================================================================
--- linux-2.6.15.orig/arch/um/drivers/net_kern.c 2006-02-06 17:33:55.000000000 -0500
+++ linux-2.6.15/arch/um/drivers/net_kern.c 2006-02-06 17:35:58.000000000 -0500
@@ -131,9 +131,8 @@ static int uml_net_open(struct net_devic
SA_INTERRUPT | SA_SHIRQ, dev->name, dev);
if(err != 0){
printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
- if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
- lp->fd = -1;
err = -ENETUNREACH;
+ goto out_close;
}

lp->tl.data = (unsigned long) &lp->user;
@@ -145,9 +144,19 @@ static int uml_net_open(struct net_devic
*/
while((err = uml_net_rx(dev)) > 0) ;

- out:
spin_unlock(&lp->lock);
- return(err);
+
+ spin_lock(&opened_lock);
+ list_add(&lp->list, &opened);
+ spin_unlock(&opened_lock);
+
+ return 0;
+out_close:
+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+ lp->fd = -1;
+out:
+ spin_unlock(&lp->lock);
+ return err;
}

static int uml_net_close(struct net_device *dev)
@@ -161,9 +170,13 @@ static int uml_net_close(struct net_devi
if(lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
- list_del(&lp->list);

spin_unlock(&lp->lock);
+
+ spin_lock(&opened_lock);
+ list_del(&lp->list);
+ spin_unlock(&opened_lock);
+
return 0;
}

@@ -410,11 +423,7 @@ static int eth_configure(int n, void *in
if (device->have_mac)
set_ether_mac(dev, device->mac);

- spin_lock(&opened_lock);
- list_add(&lp->list, &opened);
- spin_unlock(&opened_lock);
-
- return(0);
+ return 0;
}

static struct uml_net *find_device(int n)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/