patch-2.4.25 linux-2.4.25/arch/ppc64/kernel/ioctl32.c
Next file: linux-2.4.25/arch/ppc64/kernel/irq.c
Previous file: linux-2.4.25/arch/ppc64/kernel/idle.c
Back to the patch index
Back to the overall index
- Lines: 509
- Date:
2004-02-18 05:36:30.000000000 -0800
- Orig file:
linux-2.4.24/arch/ppc64/kernel/ioctl32.c
- Orig date:
2003-08-25 04:44:40.000000000 -0700
diff -urN linux-2.4.24/arch/ppc64/kernel/ioctl32.c linux-2.4.25/arch/ppc64/kernel/ioctl32.c
@@ -566,11 +566,52 @@
goto out;
}
switch (ethcmd) {
- case ETHTOOL_GDRVINFO: len = sizeof(struct ethtool_drvinfo); break;
+ case ETHTOOL_GSTRINGS: {
+ struct ethtool_gstrings *stringsaddr = (struct ethtool_gstrings *)A(data);
+ if (get_user(len, (u32 *)&stringsaddr->len)) {
+ err = -EFAULT;
+ goto out;
+ }
+ if (len > (PAGE_SIZE - sizeof(struct ethtool_gstrings))/ETH_GSTRING_LEN ) {
+ err = -EINVAL;
+ goto out;
+ }
+ len = (len*ETH_GSTRING_LEN) + sizeof(struct ethtool_gstrings);
+ break;
+ }
+ case ETHTOOL_GSTATS: {
+ struct ethtool_stats *statsaddr = (struct ethtool_stats *)A(data);
+ if (get_user(len, (u32 *)&statsaddr->n_stats)) {
+ err = -EFAULT;
+ goto out;
+ }
+ if (len > (PAGE_SIZE - sizeof(struct ethtool_stats))/sizeof(u64) ) {
+ err = -EINVAL;
+ goto out;
+ }
+ len = (len*sizeof(u64)) + sizeof(struct ethtool_stats);
+ break;
+ }
+ case ETHTOOL_SWOL:
+ case ETHTOOL_GWOL:
+ len = sizeof(struct ethtool_wolinfo);
+ break;
+ case ETHTOOL_GDRVINFO:
+ len = sizeof(struct ethtool_drvinfo);
+ break;
case ETHTOOL_GMSGLVL:
case ETHTOOL_SMSGLVL:
case ETHTOOL_GLINK:
- case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break;
+ case ETHTOOL_NWAY_RST:
+ case ETHTOOL_SSG:
+ case ETHTOOL_GSG:
+ case ETHTOOL_GTXCSUM:
+ case ETHTOOL_STXCSUM:
+ case ETHTOOL_GRXCSUM:
+ case ETHTOOL_SRXCSUM:
+ case ETHTOOL_PHYS_ID:
+ len = sizeof(struct ethtool_value);
+ break;
case ETHTOOL_GREGS: {
struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data);
/* darned variable size arguments */
@@ -578,22 +619,44 @@
err = -EFAULT;
goto out;
}
+ if (len > PAGE_SIZE - sizeof(struct ethtool_regs)) {
+ err = -EINVAL;
+ goto out;
+ }
len += sizeof(struct ethtool_regs);
break;
}
- case ETHTOOL_GEEPROM:
- case ETHTOOL_SEEPROM: {
- struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data);
- /* darned variable size arguments */
- if (get_user(len, (u32 *)&promaddr->len)) {
- err = -EFAULT;
- goto out;
- }
- len += sizeof(struct ethtool_eeprom);
- break;
- }
+ case ETHTOOL_GEEPROM:
+ case ETHTOOL_SEEPROM: {
+ struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data);
+ /* darned variable size arguments */
+ if (get_user(len, (u32 *)&promaddr->len)) {
+ err = -EFAULT;
+ goto out;
+ }
+ if (len > PAGE_SIZE - sizeof(struct ethtool_eeprom)) {
+ err = -EINVAL;
+ goto out;
+ }
+ len += sizeof(struct ethtool_eeprom);
+ break;
+ }
+ case ETHTOOL_GRINGPARAM:
+ case ETHTOOL_SRINGPARAM:
+ len = sizeof(struct ethtool_ringparam);
+ break;
+ case ETHTOOL_GPAUSEPARAM:
+ case ETHTOOL_SPAUSEPARAM:
+ len = sizeof(struct ethtool_pauseparam);
+ break;
+ case ETHTOOL_GCOALESCE:
+ case ETHTOOL_SCOALESCE:
+ len = sizeof(struct ethtool_coalesce);
+ break;
case ETHTOOL_GSET:
- case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break;
+ case ETHTOOL_SSET:
+ len = sizeof(struct ethtool_cmd);
+ break;
default:
err = -EOPNOTSUPP;
goto out;
@@ -1238,12 +1301,16 @@
u32 iov_len;
} sg_iovec32_t;
+#define EMU_SG_MAX 128
+
static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
{
sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
sg_iovec_t *kiov;
int i;
+ if (sgp->iovec_count > EMU_SG_MAX)
+ return -EINVAL;
sgp->dxferp = kmalloc(sgp->iovec_count *
sizeof(sg_iovec_t), GFP_KERNEL);
if (!sgp->dxferp)
@@ -1257,39 +1324,9 @@
if (__get_user(iov_base32, &uiov->iov_base) ||
__get_user(kiov->iov_len, &uiov->iov_len))
return -EFAULT;
-
- kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
- if (!kiov->iov_base)
- return -ENOMEM;
- if (copy_from_user(kiov->iov_base,
- (void *) A(iov_base32),
- kiov->iov_len))
+ if (verify_area(VERIFY_WRITE, (void *)A(iov_base32), kiov->iov_len))
return -EFAULT;
-
- uiov++;
- kiov++;
- }
-
- return 0;
-}
-
-static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
-{
- sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
- sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
- int i;
-
- for (i = 0; i < sgp->iovec_count; i++) {
- u32 iov_base32;
-
- if (__get_user(iov_base32, &uiov->iov_base))
- return -EFAULT;
-
- if (copy_to_user((void *) A(iov_base32),
- kiov->iov_base,
- kiov->iov_len))
- return -EFAULT;
-
+ kiov->iov_base = (void *)A(iov_base32);
uiov++;
kiov++;
}
@@ -1299,16 +1336,6 @@
static void free_sg_iovec(sg_io_hdr_t *sgp)
{
- sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
- int i;
-
- for (i = 0; i < sgp->iovec_count; i++) {
- if (kiov->iov_base) {
- kfree(kiov->iov_base);
- kiov->iov_base = NULL;
- }
- kiov++;
- }
kfree(sgp->dxferp);
sgp->dxferp = NULL;
}
@@ -1337,6 +1364,10 @@
sg_io64.sbp = NULL;
err |= __get_user(cmdp32, &sg_io32->cmdp);
+ if (sg_io64.cmd_len > 4*PAGE_SIZE || sg_io64.mx_sb_len > 4*PAGE_SIZE) {
+ err = -EINVAL;
+ goto out;
+ }
sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
if (!sg_io64.cmdp) {
err = -ENOMEM;
@@ -1371,6 +1402,10 @@
goto out;
}
} else {
+ if (sg_io64.dxfer_len > 4*PAGE_SIZE) {
+ err = -EINVAL;
+ goto out;
+ }
sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
if (!sg_io64.dxferp) {
err = -ENOMEM;
@@ -1411,7 +1446,7 @@
err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
if (sg_io64.dxferp) {
if (sg_io64.iovec_count)
- err |= copy_back_sg_iovec(&sg_io64, dxferp32);
+ ;
else
err |= copy_to_user((void *)A(dxferp32),
sg_io64.dxferp,
@@ -1467,6 +1502,8 @@
case PPPIOCSCOMPRESS32:
if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
return -EFAULT;
+ if (data32.length > PAGE_SIZE)
+ return -EINVAL;
data.ptr = kmalloc (data32.length, GFP_KERNEL);
if (!data.ptr)
return -ENOMEM;
@@ -1669,10 +1706,9 @@
err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
if (err)
return -EFAULT;
- data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- cdreadaudio.buf = data;
+ if (verify_area(VERIFY_WRITE, (void *)A(addr), cdreadaudio.nframes*2352))
+ return -EFAULT;
+ cdreadaudio.buf = (void *)A(addr);
break;
case CDROM_SEND_PACKET:
karg = &cgc;
@@ -1681,9 +1717,9 @@
err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
if (err)
return -EFAULT;
- if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
- return -ENOMEM;
- cgc.buffer = data;
+ if (verify_area(VERIFY_WRITE, (void *)A(addr), cgc.buflen))
+ return -EFAULT;
+ cgc.buffer = (void *)A(addr);
break;
default:
do {
@@ -1698,18 +1734,6 @@
set_fs (KERNEL_DS);
err = sys_ioctl (fd, cmd, (unsigned long)karg);
set_fs (old_fs);
- if (err)
- goto out;
- switch (cmd) {
- case CDROMREADAUDIO:
- err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
- break;
- case CDROM_SEND_PACKET:
- err = copy_to_user((char *)A(addr), data, cgc.buflen);
- break;
- default:
- break;
- }
out: if (data)
kfree(data);
return err ? -EFAULT : 0;
@@ -2126,37 +2150,16 @@
if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
} else {
- iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
- if (iobuf.buffer == NULL) {
- err = -ENOMEM;
- goto out;
- }
-
- err = copy_from_user(iobuf.buffer, (void *)A(iobuf32.buffer), iobuf.length);
- if (err) {
- err = -EFAULT;
- goto out;
- }
+ iobuf.buffer = A(iobuf32.buffer);
+ if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length))
+ return -EINVAL;
}
old_fs = get_fs(); set_fs (KERNEL_DS);
- err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);
+ err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);
set_fs (old_fs);
- if (err)
- goto out;
-
- if (iobuf.buffer && iobuf.length > 0) {
- err = copy_to_user((void *)A(iobuf32.buffer), iobuf.buffer, iobuf.length);
- if (err) {
- err = -EFAULT;
- goto out;
- }
- }
- err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
-
- out:
- if (iobuf32.buffer && iobuf32.length > 0)
- kfree(iobuf.buffer);
+ if (!err)
+ err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
return err;
}
@@ -2179,40 +2182,19 @@
if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
sioc.arg = (void*)(unsigned long)sioc32.arg;
- } else {
- sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
- if (sioc.arg == NULL) {
- err = -ENOMEM;
- goto out;
- }
-
- err = copy_from_user(sioc.arg, (void *)A(sioc32.arg), sioc32.length);
- if (err) {
- err = -EFAULT;
- goto out;
- }
- }
-
- old_fs = get_fs(); set_fs (KERNEL_DS);
- err = sys_ioctl (fd, cmd, (unsigned long)&sioc);
- set_fs (old_fs);
- if (err) {
- goto out;
+ } else {
+ sioc.arg = A(sioc32.arg);
+ if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length))
+ return -EFAULT;
}
-
- if (sioc.arg && sioc.length > 0) {
- err = copy_to_user((void *)A(sioc32.arg), sioc.arg, sioc.length);
- if (err) {
- err = -EFAULT;
- goto out;
- }
- }
- err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
-
- out:
- if (sioc32.arg && sioc32.length > 0)
- kfree(sioc.arg);
-
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)&sioc);
+ set_fs (old_fs);
+
+ if (!err)
+ err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
+
return err;
}
@@ -2428,12 +2410,24 @@
return NULL;
}
if (ptr1) {
+ if (l->lv_allocated_le > 2*PAGE_SIZE/sizeof(pe_t)) {
+ kfree(l);
+ *errp = -EINVAL;
+ return NULL;
+ }
size = l->lv_allocated_le * sizeof(pe_t);
l->lv_current_pe = vmalloc(size);
if (l->lv_current_pe)
err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size);
}
if (!err && ptr2) {
+ /* small limit */
+ /* just verify area it? */
+ if (l->lv_remap_end > 256*PAGE_SIZE/sizeof(lv_block_exception_t)) {
+ put_lv_t(l);
+ *errp = -EINVAL;
+ return NULL;
+ }
size = l->lv_remap_end * sizeof(lv_block_exception_t);
l->lv_block_exception = lbe = vmalloc(size);
if (l->lv_block_exception) {
@@ -3597,17 +3591,11 @@
goto out;
uptr = (void *) A(udata);
- err = -ENOMEM;
buflen = kurb->buffer_length;
- kptr = kmalloc(buflen, GFP_KERNEL);
- if (!kptr)
- goto out;
-
- kurb->buffer = kptr;
- err = -EFAULT;
- if (copy_from_user(kptr, uptr, buflen))
- goto out_kptr;
+ err = verify_area(VERIFY_WRITE, uptr, buflen);
+ if (err)
+ goto out;
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -3618,15 +3606,9 @@
/* XXX Shit, this doesn't work for async URBs :-( XXX */
if (put_urb32(kurb, uurb)) {
err = -EFAULT;
- } else if ((kurb->endpoint & USB_DIR_IN) != 0) {
- if (copy_to_user(uptr, kptr, buflen))
- err = -EFAULT;
}
}
-out_kptr:
- kfree(kptr);
-
out:
kfree(kurb);
return err;
@@ -3698,14 +3680,13 @@
#define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32)
#define MEMREADOOB32 _IOWR('M',4,struct mtd_oob_buf32)
-static inline int
+static inline int
mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg;
struct mtd_oob_buf karg;
u32 tmp;
- char *ptr;
int ret;
if (get_user(karg.start, &uarg->start) ||
@@ -3713,21 +3694,12 @@
get_user(tmp, &uarg->ptr))
return -EFAULT;
- ptr = (char *)A(tmp);
- if (0 >= karg.length)
- return -EINVAL;
-
- karg.ptr = kmalloc(karg.length, GFP_KERNEL);
- if (NULL == karg.ptr)
- return -ENOMEM;
-
- if (copy_from_user(karg.ptr, ptr, karg.length)) {
- kfree(karg.ptr);
+ karg.ptr = A(tmp);
+ if (verify_area(VERIFY_WRITE, karg.ptr, karg.length))
return -EFAULT;
- }
set_fs(KERNEL_DS);
- if (MEMREADOOB32 == cmd)
+ if (MEMREADOOB32 == cmd)
ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
else if (MEMWRITEOOB32 == cmd)
ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
@@ -3736,14 +3708,12 @@
set_fs(old_fs);
if (0 == ret && cmd == MEMREADOOB32) {
- ret = copy_to_user(ptr, karg.ptr, karg.length);
- ret |= put_user(karg.start, &uarg->start);
+ ret = put_user(karg.start, &uarg->start);
ret |= put_user(karg.length, &uarg->length);
}
- kfree(karg.ptr);
- return ((0 == ret) ? 0 : -EFAULT);
-}
+ return ret;
+}
/* Fix sizeof(sizeof()) breakage */
#define BLKELVGET_32 _IOR(0x12,106,int)
@@ -3801,6 +3771,7 @@
COMPATIBLE_IOCTL(TCSETAW),
COMPATIBLE_IOCTL(TCSETAF),
COMPATIBLE_IOCTL(TCSBRK),
+COMPATIBLE_IOCTL(TCSBRKP),
COMPATIBLE_IOCTL(TCXONC),
COMPATIBLE_IOCTL(TCFLSH),
COMPATIBLE_IOCTL(TCGETS),
@@ -3836,6 +3807,8 @@
COMPATIBLE_IOCTL(TIOCSSERIAL),
COMPATIBLE_IOCTL(TIOCSERGETLSR),
COMPATIBLE_IOCTL(TIOCSLTC),
+COMPATIBLE_IOCTL(TIOCMIWAIT),
+COMPATIBLE_IOCTL(TIOCGICOUNT),
/* Big F */
COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO),
COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO),
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)