From: Alan Cox <alan@lxorguk.ukuu.org.uk>
To: linux-kernel@vger.kernel.org, kkeil@suse.de
Subject: [PATCH] isdn: Switch to unlocked_ioctl
Date: Thu, 22 May 2008 21:52:16 +0100 [thread overview]
Message-ID: <20080522215216.36dd95e7@core> (raw)
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@redhat.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,
};
reply other threads:[~2008-05-22 21:05 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080522215216.36dd95e7@core \
--to=alan@lxorguk.ukuu.org.uk \
--cc=kkeil@suse.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.