Commit ea481f6f authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse: SIOCGIFCONF handling - the rest of it

Fixed the type of SIOCGIFCONF callback; inet instance was already
correctly annotated, decnet one was _not_.  Moreover, decnet callback
needed fixing - dereferencing userland address.
parent eaeaf871
...@@ -558,7 +558,7 @@ extern int dev_restart(struct net_device *dev); ...@@ -558,7 +558,7 @@ extern int dev_restart(struct net_device *dev);
extern int netpoll_trap(void); extern int netpoll_trap(void);
#endif #endif
typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len); typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf);
static inline int unregister_gifconf(unsigned int family) static inline int unregister_gifconf(unsigned int family)
{ {
......
...@@ -1958,7 +1958,7 @@ static int dev_ifconf(char __user *arg) ...@@ -1958,7 +1958,7 @@ static int dev_ifconf(char __user *arg)
{ {
struct ifconf ifc; struct ifconf ifc;
struct net_device *dev; struct net_device *dev;
char *pos; char __user *pos;
int len; int len;
int total; int total;
int i; int i;
......
...@@ -1294,35 +1294,43 @@ int unregister_dnaddr_notifier(struct notifier_block *nb) ...@@ -1294,35 +1294,43 @@ int unregister_dnaddr_notifier(struct notifier_block *nb)
* it as a compile time option. Probably you should use the * it as a compile time option. Probably you should use the
* rtnetlink interface instead. * rtnetlink interface instead.
*/ */
int dnet_gifconf(struct net_device *dev, char *buf, int len) int dnet_gifconf(struct net_device *dev, char __user *buf, int len)
{ {
struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
struct dn_ifaddr *ifa; struct dn_ifaddr *ifa;
struct ifreq *ifr = (struct ifreq *)buf; char buffer[DN_IFREQ_SIZE];
struct ifreq *ifr = (struct ifreq *)buffer;
struct sockaddr_dn *addr = (struct sockaddr_dn *)&ifr->ifr_addr;
int done = 0; int done = 0;
if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL)) if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL))
return 0; return 0;
for(; ifa; ifa = ifa->ifa_next) { for(; ifa; ifa = ifa->ifa_next) {
if (!ifr) { if (!buf) {
done += sizeof(DN_IFREQ_SIZE); done += sizeof(DN_IFREQ_SIZE);
continue; continue;
} }
if (len < DN_IFREQ_SIZE) if (len < DN_IFREQ_SIZE)
return done; return done;
memset(ifr, 0, DN_IFREQ_SIZE); memset(buffer, 0, DN_IFREQ_SIZE);
if (ifa->ifa_label) if (ifa->ifa_label)
strcpy(ifr->ifr_name, ifa->ifa_label); strcpy(ifr->ifr_name, ifa->ifa_label);
else else
strcpy(ifr->ifr_name, dev->name); strcpy(ifr->ifr_name, dev->name);
(*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_family = AF_DECnet; addr->sdn_family = AF_DECnet;
(*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_len = 2; addr->sdn_add.a_len = 2;
(*(dn_address *)(*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_addr) = ifa->ifa_local; memcpy(addr->sdn_add.a_addr, &ifa->ifa_local,
sizeof(dn_address));
if (copy_to_user(buf, buffer, DN_IFREQ_SIZE)) {
done = -EFAULT;
break;
}
ifr = (struct ifreq *)((char *)ifr + DN_IFREQ_SIZE); buf += DN_IFREQ_SIZE;
len -= DN_IFREQ_SIZE; len -= DN_IFREQ_SIZE;
done += DN_IFREQ_SIZE; done += DN_IFREQ_SIZE;
} }
......
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