patch-2.1.6 linux/drivers/isdn/isdn_common.c
Next file: linux/drivers/isdn/isdn_net.c
Previous file: linux/drivers/char/wdt.c
Back to the patch index
Back to the overall index
- Lines: 617
- Date:
Mon Oct 28 20:57:44 1996
- Orig file:
v2.1.5/linux/drivers/isdn/isdn_common.c
- Orig date:
Wed Oct 16 10:48:16 1996
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
@@ -726,6 +726,8 @@
/*
* isdn_readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off.
+ *
+ * I hope I got the EFAULT error path right -AK.
*/
int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
{
@@ -736,6 +738,7 @@
int dflag;
struct sk_buff *skb;
u_char *cp;
+ int ret = 0;
if (!dev->drv[di])
return 0;
@@ -749,6 +752,7 @@
cp = buf;
count = 0;
while (left) {
+ ret = 0;
if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
break;
if (skb->lock)
@@ -765,15 +769,19 @@
count_pull = count_put = 0;
while ((count_pull < skb->len) && (left-- > 0)) {
if (dev->drv[di]->DLEflag & DLEmask) {
- if (user)
- put_fs_byte(DLE,cp++);
- else
+ if (user) {
+ ret = put_user(DLE,cp);
+ cp++;
+ if (ret) break;
+ } else
*cp++ = DLE;
dev->drv[di]->DLEflag &= ~DLEmask;
} else {
- if (user)
- put_fs_byte(*p,cp++);
- else
+ if (user) {
+ ret = put_user(*p,cp);
+ if (ret) break;
+ cp++;
+ } else
*cp++ = *p;
if (*p == DLE) {
dev->drv[di]->DLEflag |= DLEmask;
@@ -794,10 +802,12 @@
dflag = 0;
}
count_put = count_pull;
+ ret = 0;
if (user)
- copy_to_user(cp, skb->data, count_put);
+ ret = copy_to_user(cp, skb->data, count_put);
else
memcpy(cp, skb->data, count_put);
+ count_put -= ret;
cp += count_put;
left -= count_put;
}
@@ -821,11 +831,11 @@
* but we pull off the data we got until now.
*/
skb_pull(skb,count_pull);
- skb->lock = 0;
+ skb->lock = 0;
}
dev->drv[di]->rcvcount[channel] -= count_put;
}
- return count;
+ return ret ? -EFAULT : count;
}
static __inline int isdn_minor2drv(int minor)
@@ -923,9 +933,10 @@
p = isdn_statstr();
file->private_data = 0;
if ((len = strlen(p)) <= count) {
- copy_to_user(buf, p, len);
+ if (copy_to_user(buf, p, len))
+ return -EFAULT;
file->f_pos += len;
- return len;
+ return len;
}
return 0;
}
@@ -1072,35 +1083,25 @@
return ret;
save_flags(flags);
cli();
- if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(int)))) {
- restore_flags(flags);
- return ret;
- }
- copy_from_user((char *) &i, src, sizeof(int));
- src += sizeof(int);
+ ret = get_user(i, src);
+ if (ret)
+ goto out;
+ src += sizeof(int);
while (i) {
char *c;
char *c2;
- if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(cfg)))) {
- restore_flags(flags);
- return ret;
- }
- copy_from_user((char *) &cfg, src, sizeof(cfg));
+ if(copy_from_user((char *) &cfg, src, sizeof(cfg)))
+ goto fault;
src += sizeof(cfg);
if (!isdn_net_new(cfg.name, NULL)) {
restore_flags(flags);
return -EIO;
}
- if ((ret = isdn_net_setcfg(&cfg))) {
- restore_flags(flags);
- return ret;
- }
- if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
- restore_flags(flags);
- return ret;
- }
- copy_from_user(buf, src, sizeof(buf));
+ if ((ret = isdn_net_setcfg(&cfg)))
+ goto out;
+ if(copy_from_user(buf, src, sizeof(buf)))
+ goto fault;
src += sizeof(buf);
c = buf;
while (*c) {
@@ -1109,20 +1110,15 @@
strcpy(phone.phone, c);
strcpy(phone.name, cfg.name);
phone.outgoing = 0;
- if ((ret = isdn_net_addphone(&phone))) {
- restore_flags(flags);
- return ret;
- }
+ if ((ret = isdn_net_addphone(&phone)))
+ goto fault;
if (c2)
c = c2;
else
c += strlen(c);
}
- if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
- restore_flags(flags);
- return ret;
- }
- copy_from_user(buf, src, sizeof(buf));
+ if(copy_from_user(buf, src, sizeof(buf)))
+ goto fault;
src += sizeof(buf);
c = buf;
while (*c) {
@@ -1131,10 +1127,8 @@
strcpy(phone.phone, c);
strcpy(phone.name, cfg.name);
phone.outgoing = 1;
- if ((ret = isdn_net_addphone(&phone))) {
- restore_flags(flags);
- return ret;
- }
+ if ((ret = isdn_net_addphone(&phone)))
+ goto out;
if (c2)
c = c2;
else
@@ -1142,8 +1136,12 @@
}
i--;
}
+out:
restore_flags(flags);
- return 0;
+ return ret;
+fault:
+ restore_flags(flags);
+ return -EFAULT;
}
static int isdn_get_allcfg(char *dest)
@@ -1152,17 +1150,13 @@
isdn_net_ioctl_phone phone;
isdn_net_dev *p;
ulong flags;
- int ret;
+ int ret = 0;
/* Walk through netdev-chain */
save_flags(flags);
cli();
p = dev->netdev;
while (p) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 10))) {
- restore_flags(flags);
- return ret;
- }
strcpy(cfg.eaz, p->local.msn);
cfg.exclusive = p->local.exclusive;
if (p->local.pre_device >= 0) {
@@ -1179,28 +1173,29 @@
cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
- copy_to_user(dest, p->local.name, 10);
+ ret = 0;
+ ret += copy_to_user(dest, p->local.name, 10);
dest += 10;
- copy_to_user(dest, (char *) &cfg, sizeof(cfg));
+ ret += copy_to_user(dest, (char *) &cfg, sizeof(cfg));
dest += sizeof(cfg);
strcpy(phone.name, p->local.name);
phone.outgoing = 0;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
+ if (ret)
+ break;
+ if ((ret = isdn_net_getphones(&phone, dest)) < 0)
+ break;
+ else
dest += ret;
strcpy(phone.name, p->local.name);
phone.outgoing = 1;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
+ if ((ret = isdn_net_getphones(&phone, dest)) < 0)
+ break;
+ else
dest += ret;
p = p->next;
}
restore_flags(flags);
- return 0;
+ return ret;
}
static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1209,7 +1204,7 @@
isdn_ctrl c;
int drvidx;
int chidx;
- int ret;
+ int ret = 0;
char *s;
char name[10];
char bname[21];
@@ -1227,14 +1222,15 @@
if (arg) {
ulong *p = (ulong *)arg;
int i;
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(ulong)*ISDN_MAX_CHANNELS*2)))
- return ret;
for (i = 0;i<ISDN_MAX_CHANNELS;i++) {
- put_fs_long(dev->ibytes[i],p++);
- put_fs_long(dev->obytes[i],p++);
+ ret = put_user(dev->ibytes[i],p);
+ if (ret) break;
+ p++;
+ ret = put_user(dev->obytes[i],p);
+ p++;
+ if (ret) break;
}
- return 0;
+ return ret;
} else
return -EINVAL;
break;
@@ -1259,62 +1255,48 @@
case IIOCNETAIF:
/* Add a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
- return ret;
- copy_from_user(name, (char *) arg, sizeof(name));
+ if(copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
s = name;
} else
s = NULL;
if ((s = isdn_net_new(s, NULL))) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
- return ret;
- copy_to_user((char *) arg, s, strlen(s) + 1);
- return 0;
+ return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : ret;
} else
return -ENODEV;
case IIOCNETASL:
/* Add a slave to a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname))))
- return ret;
- copy_from_user(bname, (char *) arg, sizeof(bname));
+ if(copy_from_user(bname, (char *) arg, sizeof(bname)))
+ return -EFAULT;
} else
return -EINVAL;
if ((s = isdn_net_newslave(bname))) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
- return ret;
- copy_to_user((char *) arg, s, strlen(s) + 1);
- return 0;
+ return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : 0;
} else
return -ENODEV;
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
- return ret;
- copy_from_user(name, (char *) arg, sizeof(name));
- return isdn_net_rm(name);
+ ret = copy_from_user(name, (char *) arg, sizeof(name));
+ return ret ? -EFAULT : isdn_net_rm(name);
} else
return -EINVAL;
case IIOCNETSCF:
/* Set configurable parameters of a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
- return ret;
- copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
- return isdn_net_setcfg(&cfg);
+ ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+ return ret ? -EFAULT : isdn_net_setcfg(&cfg);
} else
return -EINVAL;
case IIOCNETGCF:
/* Get configurable parameters of a network-interface */
- if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
- return ret;
- copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+ if (arg) {
+ if(copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
if (!(ret = isdn_net_getcfg(&cfg))) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg))))
- return ret;
- copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg));
+ if(copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+ return -EFAULT;
}
return ret;
} else
@@ -1322,68 +1304,51 @@
case IIOCNETANM:
/* Add a phone-number to a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
- return ret;
- copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
- return isdn_net_addphone(&phone);
+ ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+ return ret ? -EFAULT : isdn_net_addphone(&phone);
} else
return -EINVAL;
case IIOCNETGNM:
/* Get list of phone-numbers of a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
- return ret;
- copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
- return isdn_net_getphones(&phone, (char *) arg);
+ ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+ return ret ? -EFAULT : isdn_net_getphones(&phone, (char *) arg);
} else
return -EINVAL;
case IIOCNETDNM:
/* Delete a phone-number of a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
- return ret;
- copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
- return isdn_net_delphone(&phone);
+ ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+ return ret ? -EFAULT : isdn_net_delphone(&phone);
} else
return -EINVAL;
case IIOCNETDIL:
/* Force dialing of a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
- return ret;
- copy_from_user(name, (char *) arg, sizeof(name));
- return isdn_net_force_dial(name);
+ ret = copy_from_user(name, (char *) arg, sizeof(name));
+ return ret ? -EFAULT : isdn_net_force_dial(name);
} else
return -EINVAL;
#ifdef CONFIG_ISDN_PPP
case IIOCNETALN:
- if(arg) {
- if ((ret = verify_area(VERIFY_READ,
- (void*)arg,
- sizeof(name))))
- return ret;
- } else
- return -EINVAL;
- copy_from_user(name,(char*)arg,sizeof(name));
- return isdn_ppp_dial_slave(name);
+ if (arg)
+ ret = copy_from_user(name,(char*)arg,sizeof(name));
+ else
+ return -EINVAL;
+ return ret ? -EFAULT : isdn_ppp_dial_slave(name);
case IIOCNETDLN:
+
if(arg) {
- if ((ret = verify_area(VERIFY_READ,
- (void*)arg,
- sizeof(name))))
- return ret;
+ ret = copy_from_user(name,(char*)arg,sizeof(name));
} else
return -EINVAL;
- copy_from_user(name,(char*)arg,sizeof(name));
- return isdn_ppp_hangup_slave(name);
+ return ret ? -EFAULT : isdn_ppp_hangup_slave(name);
#endif
case IIOCNETHUP:
/* Force hangup of a network-interface */
if (arg) {
- if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
- return ret;
- copy_from_user(name, (char *) arg, sizeof(name));
- return isdn_net_force_hangup(name);
+ ret = copy_from_user(name, (char *) arg, sizeof(name));
+ return ret ? -EFAULT : isdn_net_force_hangup(name);
} else
return -EINVAL;
break;
@@ -1405,12 +1370,10 @@
if (arg) {
int i;
char *p;
- if ((ret = verify_area(VERIFY_READ, (void *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
- copy_from_user((char *) &iocts, (char *) arg,
- sizeof(isdn_ioctl_struct));
- if (strlen(iocts.drvid)) {
+ if(copy_from_user((char *) &iocts, (char *) arg,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
+ if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
drvidx = -1;
@@ -1450,17 +1413,14 @@
if (arg) {
char *p = (char *) arg;
int i;
-
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
-
+
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- copy_to_user(p, dev->mdm.info[i].emu.profile,
- ISDN_MODEM_ANZREG);
+ if(copy_to_user(p, dev->mdm.info[i].emu.profile,
+ ISDN_MODEM_ANZREG))
+ return -EFAULT;
p += ISDN_MODEM_ANZREG;
- copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
+ if(copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
+ return -EFAULT;
p += ISDN_MSNLEN;
}
return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1473,17 +1433,14 @@
char *p = (char *) arg;
int i;
- if ((ret = verify_area(VERIFY_READ, (void *) arg,
- (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
-
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- copy_from_user(dev->mdm.info[i].emu.profile, p,
- ISDN_MODEM_ANZREG);
- p += ISDN_MODEM_ANZREG;
- copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
- p += ISDN_MSNLEN;
+ if(copy_from_user(dev->mdm.info[i].emu.profile, p,
+ ISDN_MODEM_ANZREG))
+ return -EFAULT;
+ p += ISDN_MODEM_ANZREG;
+ if(copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+ return -EFAULT;
+ p += ISDN_MSNLEN;
}
return 0;
} else
@@ -1497,11 +1454,10 @@
char *p;
char nstring[255];
- if ((ret = verify_area(VERIFY_READ, (void *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
- copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
- if (strlen(iocts.drvid)) {
+ ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+
+ if (ret) return -EFAULT;
+ if (strlen(iocts.drvid)) {
drvidx = -1;
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
if (!(strcmp(dev->drvid[i], iocts.drvid))) {
@@ -1513,9 +1469,8 @@
if (drvidx == -1)
return -ENODEV;
if (cmd == IIOCSETMAP) {
- if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255)))
- return ret;
- copy_from_user(nstring, (char *) iocts.arg, 255);
+ ret = copy_from_user(nstring, (char *) iocts.arg, 255);
+ if (ret) return -EFAULT;
memset(dev->drv[drvidx]->msn2eaz, 0,
sizeof(dev->drv[drvidx]->msn2eaz));
p = strtok(nstring, ",");
@@ -1531,21 +1486,16 @@
strlen(dev->drv[drvidx]->msn2eaz[i]) ?
dev->drv[drvidx]->msn2eaz[i] : "-",
(i < 9) ? "," : "\0");
- if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg,
- strlen(nstring) + 1)))
- return ret;
- copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1);
- }
+ if(copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1))
+ return -EFAULT;
+ }
return 0;
} else
return -EINVAL;
case IIOCDBGVAR:
if (arg) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong))))
- return ret;
- copy_to_user((char *) arg, (char *) &dev, sizeof(ulong));
- return 0;
- } else
+ return copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)) ? -EFAULT : 0;
+ } else
return -EINVAL;
break;
default:
@@ -1556,10 +1506,10 @@
if (arg) {
int i;
char *p;
- if ((ret = verify_area(VERIFY_READ, (void *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
- copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+
+ ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+ if (ret)
+ return -EFAULT;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1573,17 +1523,13 @@
drvidx = 0;
if (drvidx == -1)
return -ENODEV;
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
c.driver = drvidx;
c.command = ISDN_CMD_IOCTL;
c.arg = cmd;
memcpy(c.num, (char *) &iocts.arg, sizeof(ulong));
ret = dev->drv[drvidx]->interface->command(&c);
memcpy((char *) &iocts.arg, c.num, sizeof(ulong));
- copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
- return ret;
+ return copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)) ? -EFAULT : 0;
} else
return -EINVAL;
}
@@ -1890,9 +1836,12 @@
skb_reserve(skb, dev->drv[drvidx]->interface->hl_hdrlen);
skb->free = 1;
- if (user)
- copy_from_user(skb_put(skb, len), buf, len);
- else
+ if (user) {
+ if(copy_from_user(skb_put(skb, len), buf, len)) {
+ kfree_skb(skb,FREE_WRITE);
+ return -EFAULT;
+ }
+ } else
memcpy(skb_put(skb, len), buf, len);
ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov