--- linux-2.2.20/arch/sparc64/kernel/ioctl32.c Fri Nov 2 11:39:06 2001 +++ linux/arch/sparc64/kernel/ioctl32.c Sat Dec 22 05:20:53 2001 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -45,6 +47,7 @@ #include #include #include +#include #include /* Ugly hack. */ @@ -533,31 +536,46 @@ if (err) return -EFAULT; break; - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: + case SIOCDEVPRIVATE: + case (SIOCDEVPRIVATE+1): + case (SIOCDEVPRIVATE+2): + case (SIOCDEVPRIVATE+3): case SIOCETHTOOL: + { + int len; + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL); if (!ifr.ifr_data) return -EAGAIN; - if(cmd == SIOCETHTOOL) { - u32 data; + if(cmd == SIOCETHTOOL) + len = sizeof(struct ethtool_cmd); + else if((!strncmp(ifr.ifr_name, "tunl", 4)) || + (!strncmp(ifr.ifr_name, "gre", 3))) + len = sizeof(struct ip_tunnel_parm); + else + len = 0; + if(len) { + u32 data; + __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); if(copy_from_user(ifr.ifr_data, (char *)A(data), - sizeof(struct ethtool_cmd))) { + len)) { free_page((unsigned long)ifr.ifr_data); return -EFAULT; } } + break; + } default: if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; break; + } old_fs = get_fs(); set_fs (KERNEL_DS); @@ -579,9 +597,10 @@ if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) return -EFAULT; break; - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: + case SIOCDEVPRIVATE: + case (SIOCDEVPRIVATE+1): + case (SIOCDEVPRIVATE+2): + case (SIOCDEVPRIVATE+3): case SIOCETHTOOL: { u32 data; @@ -590,14 +609,20 @@ __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); if(cmd == SIOCETHTOOL) len = sizeof(struct ethtool_cmd); - if(cmd == SIOCGPPPVER) - len = strlen(PPP_VERSION) + 1; - else if(cmd == SIOCGPPPCSTATS) - len = sizeof(struct ppp_comp_stats); + if(!strncmp(ifr.ifr_name, "ppp", 3)) { + if(cmd == SIOCGPPPVER) + len = strlen(PPP_VERSION) + 1; + else if(cmd == SIOCGPPPCSTATS) + len = sizeof(struct ppp_comp_stats); + else + len = sizeof(struct ppp_stats); + } else if((!strncmp(ifr.ifr_name, "tunl", 4)) || + (!strncmp(ifr.ifr_name, "gre", 3))) + len = sizeof(struct ip_tunnel_parm); else - len = sizeof(struct ppp_stats); - - len = copy_to_user((char *)A(data), ifr.ifr_data, len); + len = 0; + if(len) + len = copy_to_user((char *)A(data), ifr.ifr_data, len); free_page((unsigned long)ifr.ifr_data); if(len) return -EFAULT; @@ -2373,9 +2398,10 @@ case SIOCSIFNETMASK: case SIOCSIFPFLAGS: case SIOCGIFPFLAGS: - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: + case SIOCDEVPRIVATE: + case (SIOCDEVPRIVATE+1): + case (SIOCDEVPRIVATE+2): + case (SIOCDEVPRIVATE+3): case SIOCGIFTXQLEN: case SIOCSIFTXQLEN: case SIOCETHTOOL: