Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] Re: [PATCH] fix oops from removing running dvb_net



HI Again, 

this is my update of the patch (After some endurance
testing on my stability mainframe it again froze, I 
saw that the argument range check was missing, argh
what a careless coding)

Here's the patch version 03, it should do the job well
for kernels 2.4 for dvb-s and budgets. For budgets on
2.6 a more work is needed (can someone help me there
for the inspiration) to secure budgets on 2.6 because the 
budget-core is loaded separately and MOD_INC_USE_COUNT 
gets bound to budget-core and not to actual budget driver
...

Emard
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_net.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_net.c	2003-12-12 22:22:19.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c	2003-12-13 18:58:46.000000000 +0100
@@ -306,7 +306,7 @@ static int dvb_net_feed_start(struct net
 	return 0;
 }
 
-static void dvb_net_feed_stop(struct net_device *dev)
+static int dvb_net_feed_stop(struct net_device *dev)
 {
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
 	int i;
@@ -337,7 +337,11 @@ static void dvb_net_feed_stop(struct net
 		priv->demux->release_section_feed(priv->demux, priv->secfeed);
 		priv->secfeed=0;
 	} else
+	{
 		printk("%s: no feed to stop\n", dev->name);
+		return -1;
+	}
+	return 0;
 }
 
 
@@ -360,7 +364,8 @@ static void wq_set_multicast_list (void 
 	struct net_device *dev = data;
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
 
-	dvb_net_feed_stop(dev);
+	if(dvb_net_feed_stop(dev))
+		return; // no feed to stop
 
 	priv->rx_mode = RX_MODE_UNI;
 	
@@ -387,8 +392,8 @@ static void wq_set_multicast_list (void 
 		}
 	}
 
-		dvb_net_feed_start(dev);
-	}
+	dvb_net_feed_start(dev);
+}
 
 
 static void dvb_net_set_multicast_list (struct net_device *dev)
@@ -592,6 +597,11 @@ static int dvb_net_remove_if(struct dvb_
 	if (priv->in_use)
 		return -EBUSY;
 
+	if (netif_running(&dvbnet->device[num]))
+	{
+		printk("dvb_net.c: WARNING attempt to remove netif in use\n");
+		return -EBUSY;
+	}
 	dvb_net_stop(&dvbnet->device[num]);
 	flush_scheduled_work();
 	kfree(priv);
@@ -649,8 +659,11 @@ static int dvb_net_do_ioctl(struct inode
 		struct dvb_net_priv *priv_data;
 		struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
 
-		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-		    !dvbnet->state[dvbnetif->if_num])
+		if(dvbnetif->if_num < 0 ||
+		    dvbnetif->if_num >= DVB_NET_DEVICES_MAX)
+			return -EFAULT;
+
+		if(!dvbnet->state[dvbnetif->if_num])
 			return -EFAULT;
 
 		netdev=(struct net_device*)&dvbnet->device[dvbnetif->if_num];
@@ -659,9 +672,22 @@ static int dvb_net_do_ioctl(struct inode
 		break;
 	}
 	case NET_REMOVE_IF:
+	{
+		int deviceno = (int) (long) parg;
+
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		return dvb_net_remove_if(dvbnet, (int) (long) parg);
+
+		if(deviceno < 0 ||
+		   deviceno >= DVB_NET_DEVICES_MAX)
+			return -EFAULT;
+
+		if(!dvbnet->state[deviceno])
+			return -EFAULT;
+
+		return dvb_net_remove_if(dvbnet, deviceno);
+
+	}
 	default:
 		return -EINVAL;
 	}
Only in dvb-kernel/linux/drivers/media/dvb/dvb-core: dvb_net.c.orig
Only in dvb-kernel/linux/drivers/media/dvb/dvb-core: dvb_net.c~
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/av7110.c dvb-kernel/linux/drivers/media/dvb/ttpci/av7110.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/av7110.c	2003-12-12 22:22:18.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/av7110.c	2003-12-13 00:04:41.000000000 +0100
@@ -3124,7 +3124,7 @@ static void dvb_feed_start_pid(struct dv
         int i;
         
 	DEB_EE(("av7110: %p\n",av7110));
-
+	
         npids[0]=npids[1]=npids[2]=npids[3]=0xffff;
         npids[4]=0xffff;
         i=dvbdmxfeed->pes_type;
@@ -3162,7 +3162,7 @@ static void dvb_feed_stop_pid(struct dvb
         int i;
         
 	DEB_EE(("av7110: %p\n",av7110));
-
+	
         if (dvbdmxfeed->pes_type<=1) {
                 AV_Stop(av7110, dvbdmxfeed->pes_type ? 
                         RP_VIDEO : RP_AUDIO);
@@ -3231,7 +3231,7 @@ static int av7110_start_feed(struct dvb_
         
         if (feed->type == DMX_TYPE_SEC) {
                 int i;
-
+		MOD_INC_USE_COUNT;
 	        for (i=0; i<demux->filternum; i++) {
 		        if (demux->filter[i].state!=DMX_STATE_READY)
 			        continue;
@@ -3275,7 +3275,7 @@ static int av7110_stop_feed(struct dvb_d
         
         if (feed->type == DMX_TYPE_SEC) {
                 int i;
-
+		MOD_DEC_USE_COUNT;
 	        for (i=0; i<demux->filternum; i++)
 		        if (demux->filter[i].state==DMX_STATE_GO && 
 			    demux->filter[i].filter.parent==&feed->feed.sec) {
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-core.c dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c
--- dvb-kernel.orig/linux/drivers/media/dvb/ttpci/budget-core.c	2003-12-12 22:22:18.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c	2003-12-12 21:47:17.000000000 +0100
@@ -10,7 +10,7 @@ int budget_debug = 0;
 static int stop_ts_capture(struct budget *budget)
 {
 	DEB_EE(("budget: %p\n",budget));
-
+	MOD_DEC_USE_COUNT;
         if (--budget->feeding)
                 return budget->feeding;
 
@@ -25,7 +25,7 @@ static int start_ts_capture (struct budg
         struct saa7146_dev *dev=budget->dev;
 
 	DEB_EE(("budget: %p\n",budget));
-
+	MOD_INC_USE_COUNT;
         if (budget->feeding) 
                 return ++budget->feeding;
 

Home | Main Index | Thread Index