lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Thu, 22 May 2008 21:52:16 +0100
From:	Alan Cox <alan@...rguk.ukuu.org.uk>
To:	linux-kernel@...r.kernel.org, kkeil@...e.de
Subject: [PATCH] isdn: Switch to unlocked_ioctl

Push the BKL down into the ISDN drivers ready for eliminating the old
ioctl method calls. Would benefit from careful review as the needed changes
were quite hairy.

Signed-off-by: Alan Cox <alan@...hat.com>

diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 6ca0bb9..f2a2e8a 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -782,73 +783,86 @@ capi_poll(struct file *file, poll_table * wait)
 	return mask;
 }
 
-static int
-capi_ioctl(struct inode *inode, struct file *file,
-	   unsigned int cmd, unsigned long arg)
+static long capi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct capidev *cdev = file->private_data;
 	struct capi20_appl *ap = &cdev->ap;
 	capi_ioctl_struct data;
-	int retval = -EINVAL;
+	int retval = 0;
 	void __user *argp = (void __user *)arg;
 
+	lock_kernel();
 	switch (cmd) {
 	case CAPI_REGISTER:
 		{
-			if (ap->applid)
-				return -EEXIST;
+			if (ap->applid) {
+				retval = -EEXIST;
+				break;
+			}
 
 			if (copy_from_user(&cdev->ap.rparam, argp,
-					   sizeof(struct capi_register_params)))
-				return -EFAULT;
+					   sizeof(struct capi_register_params))) {
+				retval = -EFAULT;
+				break;
+			}
 			
 			cdev->ap.private = cdev;
 			cdev->ap.recv_message = capi_recv_message;
 			cdev->errcode = capi20_register(ap);
 			if (cdev->errcode) {
 				ap->applid = 0;
-				return -EIO;
+				retval = -EIO;
+				break;
 			}
 		}
-		return (int)ap->applid;
+		retval = (int)ap->applid;
+		break;
 
 	case CAPI_GET_VERSION:
 		{
 			if (copy_from_user(&data.contr, argp,
-						sizeof(data.contr)))
-				return -EFAULT;
+						sizeof(data.contr))) {
+				retval = -EFAULT;
+				break;
+			}
 		        cdev->errcode = capi20_get_version(data.contr, &data.version);
 			if (cdev->errcode)
-				return -EIO;
-			if (copy_to_user(argp, &data.version,
+				retval = -EIO;
+			else if (copy_to_user(argp, &data.version,
 					 sizeof(data.version)))
-				return -EFAULT;
+				retval = -EFAULT;
 		}
-		return 0;
+		break;
 
 	case CAPI_GET_SERIAL:
 		{
 			if (copy_from_user(&data.contr, argp,
-					   sizeof(data.contr)))
-				return -EFAULT;
+					   sizeof(data.contr))) {
+				retval = -EFAULT;
+				break;
+			}
 			cdev->errcode = capi20_get_serial (data.contr, data.serial);
 			if (cdev->errcode)
-				return -EIO;
-			if (copy_to_user(argp, data.serial,
+				retval = -EIO;
+			else if (copy_to_user(argp, data.serial,
 					 sizeof(data.serial)))
-				return -EFAULT;
+				retval = -EFAULT;
 		}
-		return 0;
+		break;
 	case CAPI_GET_PROFILE:
 		{
 			if (copy_from_user(&data.contr, argp,
-					   sizeof(data.contr)))
-				return -EFAULT;
+					   sizeof(data.contr))) {
+				retval = -EFAULT;
+				break;
+			}
 
 			if (data.contr == 0) {
 				cdev->errcode = capi20_get_profile(data.contr, &data.profile);
-				if (cdev->errcode)
-					return -EIO;
+				if (cdev->errcode) {
+					retval = -EIO;
+					break;
+				}
 
 				retval = copy_to_user(argp,
 				      &data.profile.ncontroller,
@@ -863,70 +877,77 @@ capi_ioctl(struct inode *inode, struct file *file,
 						   sizeof(data.profile));
 			}
 			if (retval)
-				return -EFAULT;
+				retval = -EFAULT;
 		}
-		return 0;
+		break;
 
 	case CAPI_GET_MANUFACTURER:
 		{
 			if (copy_from_user(&data.contr, argp,
-					   sizeof(data.contr)))
-				return -EFAULT;
+					   sizeof(data.contr))) {
+				retval = -EFAULT;
+				break;
+			}
 			cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);
 			if (cdev->errcode)
-				return -EIO;
-
-			if (copy_to_user(argp, data.manufacturer,
+				retval = -EIO;
+			else if (copy_to_user(argp, data.manufacturer,
 					 sizeof(data.manufacturer)))
-				return -EFAULT;
+				retval = -EFAULT;
 
 		}
-		return 0;
+		break;
 	case CAPI_GET_ERRCODE:
 		data.errcode = cdev->errcode;
 		cdev->errcode = CAPI_NOERROR;
 		if (arg) {
 			if (copy_to_user(argp, &data.errcode,
-					 sizeof(data.errcode)))
-				return -EFAULT;
+					 sizeof(data.errcode))) {
+				retval = -EFAULT;
+				break;
+			}
 		}
-		return data.errcode;
+		retval = data.errcode;
+		break;
 
 	case CAPI_INSTALLED:
-		if (capi20_isinstalled() == CAPI_NOERROR)
-			return 0;
-		return -ENXIO;
+		if (capi20_isinstalled() != CAPI_NOERROR)
+			retval = -ENXIO;
+		break;
 
 	case CAPI_MANUFACTURER_CMD:
 		{
 			struct capi_manufacturer_cmd mcmd;
 			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
-				return -EFAULT;
-			return capi20_manufacturer(mcmd.cmd, mcmd.data);
+				retval = -EPERM;
+			else if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
+				retval = -EFAULT;
+			else
+				retval = capi20_manufacturer(mcmd.cmd, mcmd.data);
 		}
-		return 0;
+		break;
 
 	case CAPI_SET_FLAGS:
 	case CAPI_CLR_FLAGS:
 		{
 			unsigned userflags;
 			if (copy_from_user(&userflags, argp,
-					   sizeof(userflags)))
-				return -EFAULT;
+					   sizeof(userflags))) {
+				retval = -EFAULT;
+				break;
+			}
 			if (cmd == CAPI_SET_FLAGS)
 				cdev->userflags |= userflags;
 			else
 				cdev->userflags &= ~userflags;
 		}
-		return 0;
+		break;
 
 	case CAPI_GET_FLAGS:
 		if (copy_to_user(argp, &cdev->userflags,
 				 sizeof(cdev->userflags)))
-			return -EFAULT;
-		return 0;
+			retval = -EFAULT;
+		break;
 
 	case CAPI_NCCI_OPENCOUNT:
 		{
@@ -936,13 +957,16 @@ capi_ioctl(struct inode *inode, struct file *file,
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 			unsigned ncci;
 			int count = 0;
-			if (copy_from_user(&ncci, argp, sizeof(ncci)))
-				return -EFAULT;
+			if (copy_from_user(&ncci, argp, sizeof(ncci))) {
+				retval = -EFAULT;
+				break;
+			}
 
 			mutex_lock(&cdev->ncci_list_mtx);
 			if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) {
 				mutex_unlock(&cdev->ncci_list_mtx);
-				return 0;
+				retval = 0;
+				break;
 			}
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 			if ((mp = nccip->minorp) != NULL) {
@@ -950,9 +974,9 @@ capi_ioctl(struct inode *inode, struct file *file,
 			}
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 			mutex_unlock(&cdev->ncci_list_mtx);
-			return count;
+			retval = count;
 		}
-		return 0;
+		break;
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	case CAPI_NCCI_GETUNIT:
@@ -960,24 +984,28 @@ capi_ioctl(struct inode *inode, struct file *file,
 			struct capincci *nccip;
 			struct capiminor *mp;
 			unsigned ncci;
-			int unit = 0;
 			if (copy_from_user(&ncci, argp,
-					   sizeof(ncci)))
-				return -EFAULT;
+					   sizeof(ncci))) {
+				retval = -EFAULT;
+				break;
+			}
 			mutex_lock(&cdev->ncci_list_mtx);
 			nccip = capincci_find(cdev, (u32) ncci);
 			if (!nccip || (mp = nccip->minorp) == NULL) {
 				mutex_unlock(&cdev->ncci_list_mtx);
-				return -ESRCH;
+				retval = -ESRCH;
+				break;
 			}
-			unit = mp->minor;
+			retval = mp->minor;
 			mutex_unlock(&cdev->ncci_list_mtx);
-			return unit;
 		}
-		return 0;
+		break;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+	default:
+		retval = -ENOTTY;
 	}
-	return -EINVAL;
+	unlock_kernel();
+	return retval;
 }
 
 static int
@@ -1010,7 +1038,7 @@ static const struct file_operations capi_fops =
 	.read		= capi_read,
 	.write		= capi_write,
 	.poll		= capi_poll,
-	.ioctl		= capi_ioctl,
+	.unlocked_ioctl	= capi_ioctl,
 	.open		= capi_open,
 	.release	= capi_release,
 };
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 8b256a6..5537fec 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #endif
 #include <linux/isdnif.h>
+#include <linux/smp_lock.h>
 #include <net/net_namespace.h>
 #include "isdn_divert.h"
 
@@ -175,15 +176,15 @@ isdn_divert_close(struct inode *ino, struct file *filep)
 /*********/
 /* IOCTL */
 /*********/
-static int
-isdn_divert_ioctl(struct inode *inode, struct file *file,
-		  uint cmd, ulong arg)
+static long
+isdn_divert_ioctl(struct file *file, uint cmd, ulong arg)
 {
 	divert_ioctl dioctl;
 	int i;
 	unsigned long flags;
 	divert_rule *rulep;
 	char *cp;
+	long ret = 0;
 
 	if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl)))
 		return -EFAULT;
@@ -194,59 +195,85 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
 			break;
 
 		case IIOCGETDRV:
-			if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
-				return (-EINVAL);
+			lock_kernel();
+			dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam);
+			unlock_kernel();
+			if (dioctl.getid.drvid < 0)
+				return -EINVAL;
 			break;
 
 		case IIOCGETNAM:
+			lock_kernel();
 			cp = divert_if.drv_to_name(dioctl.getid.drvid);
 			if (!cp)
-				return (-EINVAL);
-			if (!*cp)
-				return (-EINVAL);
-			strcpy(dioctl.getid.drvnam, cp);
-			break;
+				ret = -EINVAL;
+			else if (!*cp)
+				ret = -EINVAL;
+			else
+				strcpy(dioctl.getid.drvnam, cp);
+			unlock_kernel();
+			return ret;
 
 		case IIOCGETRULE:
-			if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-				return (-EINVAL);
-			dioctl.getsetrule.rule = *rulep;	/* copy data */
-			break;
+			lock_kernel();
+			rulep = getruleptr(dioctl.getsetrule.ruleidx);
+			if (rulep == NULL)
+				ret = -EINVAL;
+			else
+				dioctl.getsetrule.rule = *rulep;	/* copy data */
+			unlock_kernel();
+			return ret;
 
 		case IIOCMODRULE:
-			if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-				return (-EINVAL);
-            spin_lock_irqsave(&divert_lock, flags);
+			lock_kernel();
+			rulep = getruleptr(dioctl.getsetrule.ruleidx);
+			if (rulep == NULL) {
+				unlock_kernel();
+				return -EINVAL;
+			}
+			spin_lock_irqsave(&divert_lock, flags);
 			*rulep = dioctl.getsetrule.rule;	/* copy data */
 			spin_unlock_irqrestore(&divert_lock, flags);
-			return (0);	/* no copy required */
-			break;
+			unlock_kernel();
+			return 0;
 
 		case IIOCINSRULE:
-			return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
-			break;
+			lock_kernel();
+			ret = insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule);
+			unlock_kernel();
+			return ret;
 
 		case IIOCDELRULE:
-			return (deleterule(dioctl.getsetrule.ruleidx));
-			break;
+			lock_kernel();
+			ret = deleterule(dioctl.getsetrule.ruleidx);
+			unlock_kernel();
+			return ret;
 
 		case IIOCDODFACT:
-			return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+			lock_kernel();
+			ret = deflect_extern_action(dioctl.fwd_ctrl.subcmd,
 						  dioctl.fwd_ctrl.callid,
-						 dioctl.fwd_ctrl.to_nr));
+						 dioctl.fwd_ctrl.to_nr);
+			unlock_kernel();
+			return ret;
 
 		case IIOCDOCFACT:
 		case IIOCDOCFDIS:
 		case IIOCDOCFINT:
-			if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
-				return (-EINVAL);	/* invalid driver */
-			if ((i = cf_command(dioctl.cf_ctrl.drvid,
+			lock_kernel();
+			if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) {
+				unlock_kernel();
+				return -EINVAL;	/* invalid driver */
+			}
+			i = cf_command(dioctl.cf_ctrl.drvid,
 					    (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
 					    dioctl.cf_ctrl.cfproc,
 					    dioctl.cf_ctrl.msn,
 					    dioctl.cf_ctrl.service,
 					    dioctl.cf_ctrl.fwd_nr,
-					    &dioctl.cf_ctrl.procid)))
+					    &dioctl.cf_ctrl.procid);
+			unlock_kernel();
+			if (i)
 				return (i);
 			break;
 
@@ -263,7 +290,7 @@ static const struct file_operations isdn_fops =
 	.read           = isdn_divert_read,
 	.write          = isdn_divert_write,
 	.poll           = isdn_divert_poll,
-	.ioctl          = isdn_divert_ioctl,
+	.unlocked_ioctl = isdn_divert_ioctl,
 	.open           = isdn_divert_open,
 	.release        = isdn_divert_close,                                      
 };
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 0f3c66d..264581e 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1270,14 +1270,14 @@ isdn_poll(struct file *file, poll_table * wait)
 }
 
 
-static int
-isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+static long isdn_ioctl(struct file *file, uint cmd, ulong arg)
 {
+	struct inode *inode = file->f_path.dentry->d_inode;
 	uint minor = iminor(inode);
 	isdn_ctrl c;
 	int drvidx;
 	int chidx;
-	int ret;
+	long ret = 0;
 	int i;
 	char __user *p;
 	char *s;
@@ -1309,10 +1309,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					if (!access_ok(VERIFY_WRITE, p,
 							sizeof(ulong) * ISDN_MAX_CHANNELS * 2))
 						return -EFAULT;
+					lock_kernel();
 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 						put_user(dev->ibytes[i], p++);
 						put_user(dev->obytes[i], p++);
 					}
+					unlock_kernel();
 					return 0;
 				} else
 					return -EINVAL;
@@ -1324,7 +1326,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&phone, argp, sizeof(phone)))
 						return -EFAULT;
-					return isdn_net_getpeer(&phone, argp);
+					lock_kernel();
+					ret = isdn_net_getpeer(&phone, argp);
+					unlock_kernel();
+					return ret;
 				} else
 					return -EINVAL;
 #endif
@@ -1335,13 +1340,17 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 	if (!dev->drivers)
 		return -ENODEV;
 	if (minor <= ISDN_MINOR_BMAX) {
+		lock_kernel();
 		drvidx = isdn_minor2drv(minor);
 		if (drvidx < 0)
-			return -ENODEV;
-		chidx = isdn_minor2chan(minor);
-		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-			return -ENODEV;
-		return 0;
+			ret = -ENODEV;
+		else {
+			chidx = isdn_minor2chan(minor);
+			if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
+				ret = -ENODEV;
+		}
+		unlock_kernel();
+		return ret;
 	}
 	if (minor <= ISDN_MINOR_CTRLMAX) {
 /*
@@ -1368,8 +1377,13 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				} else {
 					s = NULL;
 				}
+
+				lock_kernel();
 				ret = mutex_lock_interruptible(&dev->mtx);
-				if( ret ) return ret;
+				if( ret ) {
+					unlock_kernel();
+					return ret;
+				}
 				if ((s = isdn_net_new(s, NULL))) {
 					if (copy_to_user(argp, s, strlen(s) + 1)){
 						ret = -EFAULT;
@@ -1379,6 +1393,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				} else
 					ret = -ENODEV;
 				mutex_unlock(&dev->mtx);
+				unlock_kernel();
 				return ret;
 			case IIOCNETASL:
 				/* Add a slave to a network-interface */
@@ -1387,8 +1402,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 						return -EFAULT;
 				} else
 					return -EINVAL;
+				lock_kernel();
 				ret = mutex_lock_interruptible(&dev->mtx);
-				if( ret ) return ret;
+				if( ret ) {
+					unlock_kernel();
+					return ret;
+				}
 				if ((s = isdn_net_newslave(bname))) {
 					if (copy_to_user(argp, s, strlen(s) + 1)){
 						ret = -EFAULT;
@@ -1398,16 +1417,22 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				} else
 					ret = -ENODEV;
 				mutex_unlock(&dev->mtx);
+				unlock_kernel();
 				return ret;
 			case IIOCNETDIF:
 				/* Delete a network-interface */
 				if (arg) {
 					if (copy_from_user(name, argp, sizeof(name)))
 						return -EFAULT;
+					lock_kernel();
 					ret = mutex_lock_interruptible(&dev->mtx);
-					if( ret ) return ret;
+					if( ret ) {
+						unlock_kernel();
+						return ret;
+					}
 					ret = isdn_net_rm(name);
 					mutex_unlock(&dev->mtx);
+					unlock_kernel();
 					return ret;
 				} else
 					return -EINVAL;
@@ -1416,7 +1441,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&cfg, argp, sizeof(cfg)))
 						return -EFAULT;
-					return isdn_net_setcfg(&cfg);
+					lock_kernel();
+					ret = isdn_net_setcfg(&cfg);
+					unlock_kernel();
 				} else
 					return -EINVAL;
 			case IIOCNETGCF:
@@ -1424,10 +1451,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&cfg, argp, sizeof(cfg)))
 						return -EFAULT;
+					lock_kernel();
 					if (!(ret = isdn_net_getcfg(&cfg))) {
 						if (copy_to_user(argp, &cfg, sizeof(cfg)))
-							return -EFAULT;
+							ret = -EFAULT;
 					}
+					unlock_kernel();
 					return ret;
 				} else
 					return -EINVAL;
@@ -1436,10 +1465,15 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&phone, argp, sizeof(phone)))
 						return -EFAULT;
+					lock_kernel();
 					ret = mutex_lock_interruptible(&dev->mtx);
-					if( ret ) return ret;
+					if( ret ) {
+						unlock_kernel();
+						return ret;
+					}
 					ret = isdn_net_addphone(&phone);
 					mutex_unlock(&dev->mtx);
+					unlock_kernel();
 					return ret;
 				} else
 					return -EINVAL;
@@ -1448,10 +1482,15 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&phone, argp, sizeof(phone)))
 						return -EFAULT;
+					lock_kernel();
 					ret = mutex_lock_interruptible(&dev->mtx);
-					if( ret ) return ret;
+					if( ret ) {
+						unlock_kernel();
+						return ret;
+					}
 					ret = isdn_net_getphones(&phone, argp);
 					mutex_unlock(&dev->mtx);
+					unlock_kernel();
 					return ret;
 				} else
 					return -EINVAL;
@@ -1460,10 +1499,15 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(&phone, argp, sizeof(phone)))
 						return -EFAULT;
+					lock_kernel();
 					ret = mutex_lock_interruptible(&dev->mtx);
-					if( ret ) return ret;
+					if( ret ) {
+						unlock_kernel();
+						return ret;
+					}
 					ret = isdn_net_delphone(&phone);
 					mutex_unlock(&dev->mtx);
+					unlock_kernel();
 					return ret;
 				} else
 					return -EINVAL;
@@ -1472,7 +1516,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 				if (arg) {
 					if (copy_from_user(name, argp, sizeof(name)))
 						return -EFAULT;
-					return isdn_net_force_dial(name);
+					lock_kernel();
+					ret = isdn_net_force_dial(name);
+					unlock_kernel();
+					return ret;
 				} else
 					return -EINVAL;
 #ifdef CONFIG_ISDN_PPP
@@ -1481,13 +1528,19 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					return -EINVAL;
 				if (copy_from_user(name, argp, sizeof(name)))
 					return -EFAULT;
-				return isdn_ppp_dial_slave(name);
+				lock_kernel();
+				ret = isdn_ppp_dial_slave(name);
+				unlock_kernel();
+				return ret;
 			case IIOCNETDLN:
 				if (!arg)
 					return -EINVAL;
 				if (copy_from_user(name, argp, sizeof(name)))
 					return -EFAULT;
-				return isdn_ppp_hangup_slave(name);
+				lock_kernel();
+				ret = isdn_ppp_hangup_slave(name);
+				unlock_kernel();
+				return ret;
 #endif
 			case IIOCNETHUP:
 				/* Force hangup of a network-interface */
@@ -1495,20 +1548,26 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					return -EINVAL;
 				if (copy_from_user(name, argp, sizeof(name)))
 					return -EFAULT;
-				return isdn_net_force_hangup(name);
-				break;
+				lock_kernel();
+				ret = isdn_net_force_hangup(name);
+				unlock_kernel();
+				return ret;
 #endif                          /* CONFIG_NETDEVICES */
 			case IIOCSETVER:
+				lock_kernel();
 				dev->net_verbose = arg;
+				unlock_kernel();
 				printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
 				return 0;
 			case IIOCSETGST:
+				lock_kernel();
 				if (arg)
 					dev->global_flags |= ISDN_GLOBAL_STOPPED;
 				else
 					dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
 				printk(KERN_INFO "isdn: Global Mode %s\n",
 				       (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
+				unlock_kernel();
 				return 0;
 			case IIOCSETBRJ:
 				drvidx = -1;
@@ -1520,6 +1579,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 						return -EFAULT;
 					iocts.drvid[sizeof(iocts.drvid)-1] = 0;
 					if (strlen(iocts.drvid)) {
+						lock_kernel();
 						if ((p = strchr(iocts.drvid, ',')))
 							*p = 0;
 						drvidx = -1;
@@ -1528,19 +1588,23 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 								drvidx = i;
 								break;
 							}
+						unlock_kernel();
 					}
 				}
 				if (drvidx == -1)
 					return -ENODEV;
+				lock_kernel();
 				if (iocts.arg)
 					dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
 				else
 					dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+				unlock_kernel();
 				return 0;
 			case IIOCSIGPRF:
+				lock_kernel();
 				dev->profd = current;
+				unlock_kernel();
 				return 0;
-				break;
 			case IIOCGETPRF:
 				/* Get all Modem-Profiles */
 				if (arg) {
@@ -1552,19 +1616,23 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 						   * ISDN_MAX_CHANNELS))
 						return -EFAULT;
 
+					lock_kernel();
 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+						ret = -EFAULT;
 						if (copy_to_user(p, dev->mdm.info[i].emu.profile,
 						      ISDN_MODEM_NUMREG))
-							return -EFAULT;
+						      	break;
 						p += ISDN_MODEM_NUMREG;
 						if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
-							return -EFAULT;
+							break;
 						p += ISDN_MSNLEN;
 						if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
-							return -EFAULT;
+							break;
 						p += ISDN_LMSNLEN;
+						ret = ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN * ISDN_MAX_CHANNELS;
 					}
-					return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
+					unlock_kernel();
+					return ret;
 				} else
 					return -EINVAL;
 				break;
@@ -1578,20 +1646,23 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
 						   * ISDN_MAX_CHANNELS))
 						return -EFAULT;
-
+					lock_kernel();
 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+						ret = -EFAULT;
 						if (copy_from_user(dev->mdm.info[i].emu.profile, p,
 						     ISDN_MODEM_NUMREG))
-							return -EFAULT;
+							break;
 						p += ISDN_MODEM_NUMREG;
 						if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
-							return -EFAULT;
+							break;
 						p += ISDN_LMSNLEN;
 						if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
-							return -EFAULT;
+							break;
 						p += ISDN_MSNLEN;
+						ret = 0;
 					}
-					return 0;
+					unlock_kernel();
+					return ret;
 				} else
 					return -EINVAL;
 				break;
@@ -1603,6 +1674,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					if (copy_from_user(&iocts, argp,
 					     sizeof(isdn_ioctl_struct)))
 						return -EFAULT;
+					lock_kernel();
 					iocts.drvid[sizeof(iocts.drvid)-1] = 0;
 					if (strlen(iocts.drvid)) {
 						drvidx = -1;
@@ -1613,8 +1685,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 							}
 					} else
 						drvidx = 0;
-					if (drvidx == -1)
+					if (drvidx == -1) {
+						unlock_kernel();
 						return -ENODEV;
+					}
 					if (cmd == IIOCSETMAP) {
 						int loop = 1;
 
@@ -1624,9 +1698,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 							int j = 0;
 
 							while (1) {
-								if (!access_ok(VERIFY_READ, p, 1))
+								if (get_user(bname[j], p++)) {
+									unlock_kernel();
 									return -EFAULT;
-								get_user(bname[j], p++);
+								}
 								switch (bname[j]) {
 									case '\0':
 										loop = 0;
@@ -1652,11 +1727,14 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 								strlen(dev->drv[drvidx]->msn2eaz[i]) ?
 								dev->drv[drvidx]->msn2eaz[i] : "_",
 								(i < 9) ? "," : "\0");
-							if (copy_to_user(p, bname, strlen(bname) + 1))
+							if (copy_to_user(p, bname, strlen(bname) + 1)) {
+								unlock_kernel();
 								return -EFAULT;
+							}
 							p += strlen(bname);
 						}
 					}
+					unlock_kernel();
 					return 0;
 				} else
 					return -EINVAL;
@@ -1679,6 +1757,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 					if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
 						return -EFAULT;
 					iocts.drvid[sizeof(iocts.drvid)-1] = 0;
+					lock_kernel();
 					if (strlen(iocts.drvid)) {
 						if ((p = strchr(iocts.drvid, ',')))
 							*p = 0;
@@ -1690,16 +1769,21 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 							}
 					} else
 						drvidx = 0;
-					if (drvidx == -1)
+					if (drvidx == -1) {
+						unlock_kernel();
 						return -ENODEV;
+					}
 					if (!access_ok(VERIFY_WRITE, argp,
-					     sizeof(isdn_ioctl_struct)))
+					     sizeof(isdn_ioctl_struct))) {
+						unlock_kernel();
 						return -EFAULT;
+					}
 					c.driver = drvidx;
 					c.command = ISDN_CMD_IOCTL;
 					c.arg = cmd;
 					memcpy(c.parm.num, &iocts.arg, sizeof(ulong));
 					ret = isdn_command(&c);
+					unlock_kernel();
 					memcpy(&iocts.arg, c.parm.num, sizeof(ulong));
 					if (copy_to_user(argp, &iocts, sizeof(isdn_ioctl_struct)))
 						return -EFAULT;
@@ -1709,8 +1793,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 		}
 	}
 #ifdef CONFIG_ISDN_PPP
-	if (minor <= ISDN_MINOR_PPPMAX)
-		return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
+	if (minor <= ISDN_MINOR_PPPMAX) {
+		lock_kernel();
+		ret = isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg);
+		unlock_kernel();
+		return ret;
+	}
 #endif
 	return -ENODEV;
 
@@ -1836,7 +1924,7 @@ static const struct file_operations isdn_fops =
 	.read		= isdn_read,
 	.write		= isdn_write,
 	.poll		= isdn_poll,
-	.ioctl		= isdn_ioctl,
+	.unlocked_ioctl	= isdn_ioctl,
 	.open		= isdn_open,
 	.release	= isdn_close,
 };
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ