aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/net/socket.c b/net/socket.c
index e89884e2197b..d80d87a395ea 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -941,8 +941,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
941EXPORT_SYMBOL(dlci_ioctl_set); 941EXPORT_SYMBOL(dlci_ioctl_set);
942 942
943static long sock_do_ioctl(struct net *net, struct socket *sock, 943static long sock_do_ioctl(struct net *net, struct socket *sock,
944 unsigned int cmd, unsigned long arg, 944 unsigned int cmd, unsigned long arg)
945 unsigned int ifreq_size)
946{ 945{
947 int err; 946 int err;
948 void __user *argp = (void __user *)arg; 947 void __user *argp = (void __user *)arg;
@@ -968,11 +967,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
968 } else { 967 } else {
969 struct ifreq ifr; 968 struct ifreq ifr;
970 bool need_copyout; 969 bool need_copyout;
971 if (copy_from_user(&ifr, argp, ifreq_size)) 970 if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
972 return -EFAULT; 971 return -EFAULT;
973 err = dev_ioctl(net, cmd, &ifr, &need_copyout); 972 err = dev_ioctl(net, cmd, &ifr, &need_copyout);
974 if (!err && need_copyout) 973 if (!err && need_copyout)
975 if (copy_to_user(argp, &ifr, ifreq_size)) 974 if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
976 return -EFAULT; 975 return -EFAULT;
977 } 976 }
978 return err; 977 return err;
@@ -1071,8 +1070,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1071 err = open_related_ns(&net->ns, get_net_ns); 1070 err = open_related_ns(&net->ns, get_net_ns);
1072 break; 1071 break;
1073 default: 1072 default:
1074 err = sock_do_ioctl(net, sock, cmd, arg, 1073 err = sock_do_ioctl(net, sock, cmd, arg);
1075 sizeof(struct ifreq));
1076 break; 1074 break;
1077 } 1075 }
1078 return err; 1076 return err;
@@ -2780,8 +2778,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
2780 int err; 2778 int err;
2781 2779
2782 set_fs(KERNEL_DS); 2780 set_fs(KERNEL_DS);
2783 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv, 2781 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
2784 sizeof(struct compat_ifreq));
2785 set_fs(old_fs); 2782 set_fs(old_fs);
2786 if (!err) 2783 if (!err)
2787 err = compat_put_timeval(&ktv, up); 2784 err = compat_put_timeval(&ktv, up);
@@ -2797,8 +2794,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
2797 int err; 2794 int err;
2798 2795
2799 set_fs(KERNEL_DS); 2796 set_fs(KERNEL_DS);
2800 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts, 2797 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
2801 sizeof(struct compat_ifreq));
2802 set_fs(old_fs); 2798 set_fs(old_fs);
2803 if (!err) 2799 if (!err)
2804 err = compat_put_timespec(&kts, up); 2800 err = compat_put_timespec(&kts, up);
@@ -2994,6 +2990,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
2994 return dev_ioctl(net, cmd, &ifreq, NULL); 2990 return dev_ioctl(net, cmd, &ifreq, NULL);
2995} 2991}
2996 2992
2993static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
2994 unsigned int cmd,
2995 struct compat_ifreq __user *uifr32)
2996{
2997 struct ifreq __user *uifr;
2998 int err;
2999
3000 /* Handle the fact that while struct ifreq has the same *layout* on
3001 * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
3002 * which are handled elsewhere, it still has different *size* due to
3003 * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
3004 * resulting in struct ifreq being 32 and 40 bytes respectively).
3005 * As a result, if the struct happens to be at the end of a page and
3006 * the next page isn't readable/writable, we get a fault. To prevent
3007 * that, copy back and forth to the full size.
3008 */
3009
3010 uifr = compat_alloc_user_space(sizeof(*uifr));
3011 if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
3012 return -EFAULT;
3013
3014 err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3015
3016 if (!err) {
3017 switch (cmd) {
3018 case SIOCGIFFLAGS:
3019 case SIOCGIFMETRIC:
3020 case SIOCGIFMTU:
3021 case SIOCGIFMEM:
3022 case SIOCGIFHWADDR:
3023 case SIOCGIFINDEX:
3024 case SIOCGIFADDR:
3025 case SIOCGIFBRDADDR:
3026 case SIOCGIFDSTADDR:
3027 case SIOCGIFNETMASK:
3028 case SIOCGIFPFLAGS:
3029 case SIOCGIFTXQLEN:
3030 case SIOCGMIIPHY:
3031 case SIOCGMIIREG:
3032 case SIOCGIFNAME:
3033 if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3034 err = -EFAULT;
3035 break;
3036 }
3037 }
3038 return err;
3039}
3040
2997static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 3041static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2998 struct compat_ifreq __user *uifr32) 3042 struct compat_ifreq __user *uifr32)
2999{ 3043{
@@ -3109,8 +3153,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
3109 } 3153 }
3110 3154
3111 set_fs(KERNEL_DS); 3155 set_fs(KERNEL_DS);
3112 ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r, 3156 ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
3113 sizeof(struct compat_ifreq));
3114 set_fs(old_fs); 3157 set_fs(old_fs);
3115 3158
3116out: 3159out:
@@ -3210,21 +3253,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3210 case SIOCSIFTXQLEN: 3253 case SIOCSIFTXQLEN:
3211 case SIOCBRADDIF: 3254 case SIOCBRADDIF:
3212 case SIOCBRDELIF: 3255 case SIOCBRDELIF:
3256 case SIOCGIFNAME:
3213 case SIOCSIFNAME: 3257 case SIOCSIFNAME:
3214 case SIOCGMIIPHY: 3258 case SIOCGMIIPHY:
3215 case SIOCGMIIREG: 3259 case SIOCGMIIREG:
3216 case SIOCSMIIREG: 3260 case SIOCSMIIREG:
3217 case SIOCSARP:
3218 case SIOCGARP:
3219 case SIOCDARP:
3220 case SIOCATMARK:
3221 case SIOCBONDENSLAVE: 3261 case SIOCBONDENSLAVE:
3222 case SIOCBONDRELEASE: 3262 case SIOCBONDRELEASE:
3223 case SIOCBONDSETHWADDR: 3263 case SIOCBONDSETHWADDR:
3224 case SIOCBONDCHANGEACTIVE: 3264 case SIOCBONDCHANGEACTIVE:
3225 case SIOCGIFNAME: 3265 return compat_ifreq_ioctl(net, sock, cmd, argp);
3226 return sock_do_ioctl(net, sock, cmd, arg, 3266
3227 sizeof(struct compat_ifreq)); 3267 case SIOCSARP:
3268 case SIOCGARP:
3269 case SIOCDARP:
3270 case SIOCATMARK:
3271 return sock_do_ioctl(net, sock, cmd, arg);
3228 } 3272 }
3229 3273
3230 return -ENOIOCTLCMD; 3274 return -ENOIOCTLCMD;