diff options
author | David S. Miller <davem@davemloft.net> | 2019-02-08 18:00:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-08 18:00:17 -0500 |
commit | a655fe9f194842693258f43b5382855db1c2f654 (patch) | |
tree | a6e523c42378f43881c421530941dcbb529461ab /net/socket.c | |
parent | 7499a288bf1a4a49be9d72beb0a5c7b9aa6ffec9 (diff) | |
parent | 27b4ad621e887ce8e5eb508a0103f13d30f6b38a (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.c | 82 |
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 *)) | |||
963 | EXPORT_SYMBOL(dlci_ioctl_set); | 963 | EXPORT_SYMBOL(dlci_ioctl_set); |
964 | 964 | ||
965 | static long sock_do_ioctl(struct net *net, struct socket *sock, | 965 | static 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 | ||
3015 | static 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 | |||
3019 | static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | 3063 | static 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 | ||
3138 | out: | 3181 | out: |
@@ -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; |