lkml.org 
[lkml]   [1999]   [Jan]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateThu, 7 Jan 1999 04:21:52 +0100 (CET)
FromDaniel Kobras <>
Subject[PATCH] userspace access in net-ioctl()s.
Hi,

I hope I'm not missing something here... Recently when messing around with
my network card, I found the ioctl routine in rtl8139.c needed some
copy_(from|to)_user() calls to behave the way I'd expected it to. Digging
a little bit further, I found the same in various other ioctl()-code in
drivers/net/. Patch is attached. I'm pretty sure it does the Right
Thing[TM] for me in the rtl8139.c case, couldn't test the others though so
please check.
Thanks,

Daniel.

--- drivers/net/3c59x.c.orig Thu Jan 7 02:00:49 1999
+++ drivers/net/3c59x.c Thu Jan 7 02:57:37 1999
@@ -83,6 +83,7 @@
#include <asm/irq.h> /* For NR_IRQS only. */
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/uaccess.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -2003,9 +2004,12 @@
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
int ioaddr = dev->base_addr;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];
int phy = vp->phys[0] & 0x1f;

+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;
+
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
dev->name, rq->ifr_ifrn.ifrn_name, cmd,
@@ -2017,9 +2021,11 @@
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
EL3WINDOW(4);
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
--- drivers/net/eepro100.c.orig Thu Jan 7 02:28:47 1999
+++ drivers/net/eepro100.c Thu Jan 7 02:30:52 1999
@@ -62,6 +62,7 @@
#include <asm/spinlock.h>
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/uaccess.h>

/*
* Module documentation
@@ -1374,14 +1375,19 @@
{
struct speedo_private *sp = (struct speedo_private *)dev->priv;
long ioaddr = dev->base_addr;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];
int phy = sp->phy[0] & 0x1f;

+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = phy;
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
data[3] = mdio_read(ioaddr, data[0], data[1]);
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!capable(CAP_NET_ADMIN))
--- drivers/net/epic100.c.orig Thu Jan 7 02:31:03 1999
+++ drivers/net/epic100.c Thu Jan 7 02:35:08 1999
@@ -78,6 +78,7 @@
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
+#include <asm/uaccess.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -1275,7 +1276,10 @@
static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
long ioaddr = dev->base_addr;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];
+
+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;

switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
@@ -1293,9 +1297,11 @@
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
#endif
}
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (! dev->start) {
outl(0x0200, ioaddr + GENCTL);
--- drivers/net/plip.c.orig Thu Jan 7 02:44:48 1999
+++ drivers/net/plip.c Thu Jan 7 03:03:18 1999
@@ -108,6 +108,7 @@
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <asm/spinlock.h>
+#include <asm/uaccess.h>

#include <linux/parport.h>

@@ -1111,16 +1112,21 @@
plip_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
struct net_local *nl = (struct net_local *) dev->priv;
- struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
+ struct plipconf pc;

- switch(pc->pcmd) {
+ if (copy_from_user(&pc,rq->ifr_data,sizeof(struct plipconf)))
+ return -EFAULT;
+
+ switch(pc.pcmd) {
case PLIP_GET_TIMEOUT:
- pc->trigger = nl->trigger;
- pc->nibble = nl->nibble;
+ pc.trigger = nl->trigger;
+ pc.nibble = nl->nibble;
+ if (copy_to_user(rq->ifr_data,&pc,sizeof(struct plipconf)))
+ return -EFAULT;
break;
case PLIP_SET_TIMEOUT:
- nl->trigger = pc->trigger;
- nl->nibble = pc->nibble;
+ nl->trigger = pc.trigger;
+ nl->nibble = pc.nibble;
break;
default:
return -EOPNOTSUPP;
--- drivers/net/rtl8139.c.orig Fri Jan 1 02:25:59 1999
+++ drivers/net/rtl8139.c Thu Jan 7 03:00:05 1999
@@ -73,6 +73,7 @@
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/uaccess.h>

/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
This is only in the support-all-kernels source code. */
@@ -1277,7 +1278,10 @@
static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];
+
+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;

switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
@@ -1285,11 +1289,13 @@
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+ mdio_write(dev, data[0] & 0x3f, data[1] & 0x1f, data[2]);
return 0;
default:
return -EOPNOTSUPP;
--- drivers/net/shaper.c.orig Thu Jan 7 02:45:18 1999
+++ drivers/net/shaper.c Thu Jan 7 03:02:36 1999
@@ -72,6 +72,7 @@
#include <net/dst.h>
#include <net/arp.h>
#include <linux/if_shaper.h>
+#include <asm/uaccess.h>

int sh_debug; /* Debug flag */

@@ -553,13 +554,17 @@

static int shaper_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
- struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data;
+ struct shaperconf ss;
struct shaper *sh=dev->priv;
- switch(ss->ss_cmd)
+
+ if (copy_from_user(&ss,ifr->ifr_data,sizeof(struct shaperconf)))
+ return -EFAULT;
+
+ switch(ss.ss_cmd)
{
case SHAPER_SET_DEV:
{
- struct device *them=dev_get(ss->ss_name);
+ struct device *them=dev_get(ss.ss_name);
if(them==NULL)
return -ENODEV;
if(sh->dev)
@@ -569,13 +574,18 @@
case SHAPER_GET_DEV:
if(sh->dev==NULL)
return -ENODEV;
- strcpy(ss->ss_name, sh->dev->name);
+ strcpy(ss.ss_name, sh->dev->name);
+ if (copy_to_user(ifr->ifr_data,&ss,sizeof(struct shaperconf)))
+ return -EFAULT;
return 0;
case SHAPER_SET_SPEED:
- shaper_setspeed(sh,ss->ss_speed);
+ shaper_setspeed(sh,ss.ss_speed);
return 0;
case SHAPER_GET_SPEED:
- ss->ss_speed=sh->bitspersec;
+ ss.ss_speed=sh->bitspersec;
+ if (copy_to_user(ifr->ifr_data,&ss,sizeof(struct shaperconf)))
+ return -EFAULT;
+
return 0;
default:
return -EINVAL;
--- drivers/net/via-rhine.c.orig Thu Jan 7 02:50:01 1999
+++ drivers/net/via-rhine.c Thu Jan 7 02:52:48 1999
@@ -79,6 +79,7 @@
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/uaccess.h>

/* This driver was written to use PCI memory space, however some boards
only work with I/O space accesses. */
@@ -1187,17 +1188,22 @@

static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];

+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
--- drivers/net/yellowfin.c.orig Thu Jan 7 02:53:02 1999
+++ drivers/net/yellowfin.c Thu Jan 7 02:54:32 1999
@@ -77,6 +77,7 @@
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/uaccess.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -1353,17 +1354,22 @@
static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
long ioaddr = dev->base_addr;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 data[4];

+ if (copy_from_user(data,rq->ifr_data,8))
+ return -EFAULT;
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = ((struct yellowfin_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+ if (copy_to_user(rq->ifr_data,data,8))
+ return -EFAULT;
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
\
 
 \ /
  Last update: 2005-03-22 13:49    [from the cache]
©2003-2010