aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-02-08 18:00:17 -0500
committerDavid S. Miller <davem@davemloft.net>2019-02-08 18:00:17 -0500
commita655fe9f194842693258f43b5382855db1c2f654 (patch)
treea6e523c42378f43881c421530941dcbb529461ab /net/socket.c
parent7499a288bf1a4a49be9d72beb0a5c7b9aa6ffec9 (diff)
parent27b4ad621e887ce8e5eb508a0103f13d30f6b38a (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
An ipvlan bug fix in 'net' conflicted with the abstraction away of the IPV6 specific support in 'net-next'. Similarly, a bug fix for mlx5 in 'net' conflicted with the flow action conversion in 'net-next'. Signed-off-by: David S. Miller <davem@davemloft.net>
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 d51930689b98..643a1648fcc2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -963,8 +963,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
963EXPORT_SYMBOL(dlci_ioctl_set); 963EXPORT_SYMBOL(dlci_ioctl_set);
964 964
965static long sock_do_ioctl(struct net *net, struct socket *sock, 965static long sock_do_ioctl(struct net *net, struct socket *sock,
966 unsigned int cmd, unsigned long arg, 966 unsigned int cmd, unsigned long arg)
967 unsigned int ifreq_size)
968{ 967{
969 int err; 968 int err;
970 void __user *argp = (void __user *)arg; 969 void __user *argp = (void __user *)arg;
@@ -990,11 +989,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
990 } else { 989 } else {
991 struct ifreq ifr; 990 struct ifreq ifr;
992 bool need_copyout; 991 bool need_copyout;
993 if (copy_from_user(&ifr, argp, ifreq_size)) 992 if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
994 return -EFAULT; 993 return -EFAULT;
995 err = dev_ioctl(net, cmd, &ifr, &need_copyout); 994 err = dev_ioctl(net, cmd, &ifr, &need_copyout);
996 if (!err && need_copyout) 995 if (!err && need_copyout)
997 if (copy_to_user(argp, &ifr, ifreq_size)) 996 if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
998 return -EFAULT; 997 return -EFAULT;
999 } 998 }
1000 return err; 999 return err;
@@ -1093,8 +1092,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1093 err = open_related_ns(&net->ns, get_net_ns); 1092 err = open_related_ns(&net->ns, get_net_ns);
1094 break; 1093 break;
1095 default: 1094 default:
1096 err = sock_do_ioctl(net, sock, cmd, arg, 1095 err = sock_do_ioctl(net, sock, cmd, arg);
1097 sizeof(struct ifreq));
1098 break; 1096 break;
1099 } 1097 }
1100 return err; 1098 return err;
@@ -2802,8 +2800,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
2802 int err; 2800 int err;
2803 2801
2804 set_fs(KERNEL_DS); 2802 set_fs(KERNEL_DS);
2805 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv, 2803 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
2806 sizeof(struct compat_ifreq));
2807 set_fs(old_fs); 2804 set_fs(old_fs);
2808 if (!err) 2805 if (!err)
2809 err = compat_put_timeval(&ktv, up); 2806 err = compat_put_timeval(&ktv, up);
@@ -2819,8 +2816,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
2819 int err; 2816 int err;
2820 2817
2821 set_fs(KERNEL_DS); 2818 set_fs(KERNEL_DS);
2822 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts, 2819 err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
2823 sizeof(struct compat_ifreq));
2824 set_fs(old_fs); 2820 set_fs(old_fs);
2825 if (!err) 2821 if (!err)
2826 err = compat_put_timespec(&kts, up); 2822 err = compat_put_timespec(&kts, up);
@@ -3016,6 +3012,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
3016 return dev_ioctl(net, cmd, &ifreq, NULL); 3012 return dev_ioctl(net, cmd, &ifreq, NULL);
3017} 3013}
3018 3014
3015static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
3016 unsigned int cmd,
3017 struct compat_ifreq __user *uifr32)
3018{
3019 struct ifreq __user *uifr;
3020 int err;
3021
3022 /* Handle the fact that while struct ifreq has the same *layout* on
3023 * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
3024 * which are handled elsewhere, it still has different *size* due to
3025 * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
3026 * resulting in struct ifreq being 32 and 40 bytes respectively).
3027 * As a result, if the struct happens to be at the end of a page and
3028 * the next page isn't readable/writable, we get a fault. To prevent
3029 * that, copy back and forth to the full size.
3030 */
3031
3032 uifr = compat_alloc_user_space(sizeof(*uifr));
3033 if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
3034 return -EFAULT;
3035
3036 err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3037
3038 if (!err) {
3039 switch (cmd) {
3040 case SIOCGIFFLAGS:
3041 case SIOCGIFMETRIC:
3042 case SIOCGIFMTU:
3043 case SIOCGIFMEM:
3044 case SIOCGIFHWADDR:
3045 case SIOCGIFINDEX:
3046 case SIOCGIFADDR:
3047 case SIOCGIFBRDADDR:
3048 case SIOCGIFDSTADDR:
3049 case SIOCGIFNETMASK:
3050 case SIOCGIFPFLAGS:
3051 case SIOCGIFTXQLEN:
3052 case SIOCGMIIPHY:
3053 case SIOCGMIIREG:
3054 case SIOCGIFNAME:
3055 if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3056 err = -EFAULT;
3057 break;
3058 }
3059 }
3060 return err;
3061}
3062
3019static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 3063static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3020 struct compat_ifreq __user *uifr32) 3064 struct compat_ifreq __user *uifr32)
3021{ 3065{
@@ -3131,8 +3175,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
3131 } 3175 }
3132 3176
3133 set_fs(KERNEL_DS); 3177 set_fs(KERNEL_DS);
3134 ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r, 3178 ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
3135 sizeof(struct compat_ifreq));
3136 set_fs(old_fs); 3179 set_fs(old_fs);
3137 3180
3138out: 3181out:
@@ -3232,21 +3275,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3232 case SIOCSIFTXQLEN: 3275 case SIOCSIFTXQLEN:
3233 case SIOCBRADDIF: 3276 case SIOCBRADDIF:
3234 case SIOCBRDELIF: 3277 case SIOCBRDELIF:
3278 case SIOCGIFNAME:
3235 case SIOCSIFNAME: 3279 case SIOCSIFNAME:
3236 case SIOCGMIIPHY: 3280 case SIOCGMIIPHY:
3237 case SIOCGMIIREG: 3281 case SIOCGMIIREG:
3238 case SIOCSMIIREG: 3282 case SIOCSMIIREG:
3239 case SIOCSARP:
3240 case SIOCGARP:
3241 case SIOCDARP:
3242 case SIOCATMARK:
3243 case SIOCBONDENSLAVE: 3283 case SIOCBONDENSLAVE:
3244 case SIOCBONDRELEASE: 3284 case SIOCBONDRELEASE:
3245 case SIOCBONDSETHWADDR: 3285 case SIOCBONDSETHWADDR:
3246 case SIOCBONDCHANGEACTIVE: 3286 case SIOCBONDCHANGEACTIVE:
3247 case SIOCGIFNAME: 3287 return compat_ifreq_ioctl(net, sock, cmd, argp);
3248 return sock_do_ioctl(net, sock, cmd, arg, 3288
3249 sizeof(struct compat_ifreq)); 3289 case SIOCSARP:
3290 case SIOCGARP:
3291 case SIOCDARP:
3292 case SIOCATMARK:
3293 return sock_do_ioctl(net, sock, cmd, arg);
3250 } 3294 }
3251 3295
3252 return -ENOIOCTLCMD; 3296 return -ENOIOCTLCMD;