Commit 0e76422c authored by Bodo Stroesser's avatar Bodo Stroesser Committed by Linus Torvalds

[PATCH] uml: fix UML network driver endianness bugs

ifa->ifa_address and ifa->ifa_mask are defined as __u32, but used as if they
were char[4].

Network code uses htons() to convert it.  So UML's method to access these
fields is wrong for bigendians (e.g.  s390)

I replaced bytewise copying by memcpy(), maybe even that might be removed, if
ifa->ifa_address/mask may be used immediately.
Signed-off-by: default avatarBodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Cc: <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4f027241
...@@ -96,7 +96,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -96,7 +96,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static int uml_net_open(struct net_device *dev) static int uml_net_open(struct net_device *dev)
{ {
struct uml_net_private *lp = dev->priv; struct uml_net_private *lp = dev->priv;
char addr[sizeof("255.255.255.255\0")];
int err; int err;
spin_lock(&lp->lock); spin_lock(&lp->lock);
...@@ -107,7 +106,7 @@ static int uml_net_open(struct net_device *dev) ...@@ -107,7 +106,7 @@ static int uml_net_open(struct net_device *dev)
} }
if(!lp->have_mac){ if(!lp->have_mac){
dev_ip_addr(dev, addr, &lp->mac[2]); dev_ip_addr(dev, &lp->mac[2]);
set_ether_mac(dev, lp->mac); set_ether_mac(dev, lp->mac);
} }
...@@ -664,8 +663,6 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, ...@@ -664,8 +663,6 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
void *ptr) void *ptr)
{ {
struct in_ifaddr *ifa = ptr; struct in_ifaddr *ifa = ptr;
u32 addr = ifa->ifa_address;
u32 netmask = ifa->ifa_mask;
struct net_device *dev = ifa->ifa_dev->dev; struct net_device *dev = ifa->ifa_dev->dev;
struct uml_net_private *lp; struct uml_net_private *lp;
void (*proc)(unsigned char *, unsigned char *, void *); void (*proc)(unsigned char *, unsigned char *, void *);
...@@ -685,14 +682,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, ...@@ -685,14 +682,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
break; break;
} }
if(proc != NULL){ if(proc != NULL){
addr_buf[0] = addr & 0xff; memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));
addr_buf[1] = (addr >> 8) & 0xff; memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
addr_buf[2] = (addr >> 16) & 0xff;
addr_buf[3] = addr >> 24;
netmask_buf[0] = netmask & 0xff;
netmask_buf[1] = (netmask >> 8) & 0xff;
netmask_buf[2] = (netmask >> 16) & 0xff;
netmask_buf[3] = netmask >> 24;
(*proc)(addr_buf, netmask_buf, &lp->user); (*proc)(addr_buf, netmask_buf, &lp->user);
} }
return(NOTIFY_DONE); return(NOTIFY_DONE);
...@@ -774,27 +765,18 @@ int setup_etheraddr(char *str, unsigned char *addr) ...@@ -774,27 +765,18 @@ int setup_etheraddr(char *str, unsigned char *addr)
return(1); return(1);
} }
void dev_ip_addr(void *d, char *buf, char *bin_buf) void dev_ip_addr(void *d, unsigned char *bin_buf)
{ {
struct net_device *dev = d; struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr; struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in; struct in_ifaddr *in;
u32 addr;
if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
printk(KERN_WARNING "dev_ip_addr - device not assigned an " printk(KERN_WARNING "dev_ip_addr - device not assigned an "
"IP address\n"); "IP address\n");
return; return;
} }
addr = in->ifa_address; memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
(addr >> 16) & 0xff, addr >> 24);
if(bin_buf){
bin_buf[0] = addr & 0xff;
bin_buf[1] = (addr >> 8) & 0xff;
bin_buf[2] = (addr >> 16) & 0xff;
bin_buf[3] = addr >> 24;
}
} }
void set_ether_mac(void *d, unsigned char *addr) void set_ether_mac(void *d, unsigned char *addr)
...@@ -829,14 +811,8 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, ...@@ -829,14 +811,8 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
if(ip == NULL) return; if(ip == NULL) return;
in = ip->ifa_list; in = ip->ifa_list;
while(in != NULL){ while(in != NULL){
address[0] = in->ifa_address & 0xff; memcpy(address, &in->ifa_address, sizeof(address));
address[1] = (in->ifa_address >> 8) & 0xff; memcpy(netmask, &in->ifa_mask, sizeof(netmask));
address[2] = (in->ifa_address >> 16) & 0xff;
address[3] = in->ifa_address >> 24;
netmask[0] = in->ifa_mask & 0xff;
netmask[1] = (in->ifa_mask >> 8) & 0xff;
netmask[2] = (in->ifa_mask >> 16) & 0xff;
netmask[3] = in->ifa_mask >> 24;
(*cb)(address, netmask, arg); (*cb)(address, netmask, arg);
in = in->ifa_next; in = in->ifa_next;
} }
......
...@@ -25,7 +25,7 @@ struct net_user_info { ...@@ -25,7 +25,7 @@ struct net_user_info {
}; };
extern void ether_user_init(void *data, void *dev); extern void ether_user_init(void *data, void *dev);
extern void dev_ip_addr(void *d, char *buf, char *bin_buf); extern void dev_ip_addr(void *d, unsigned char *bin_buf);
extern void set_ether_mac(void *d, unsigned char *addr); extern void set_ether_mac(void *d, unsigned char *addr);
extern void iter_addresses(void *d, void (*cb)(unsigned char *, extern void iter_addresses(void *d, void (*cb)(unsigned char *,
unsigned char *, void *), unsigned char *, void *),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment