diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 301 |
1 files changed, 71 insertions, 230 deletions
diff --git a/net/socket.c b/net/socket.c index 2f378449bc1b..a93c99b518ca 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -163,12 +163,6 @@ static DEFINE_SPINLOCK(net_family_lock); | |||
163 | static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; | 163 | static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * Statistics counters of the socket lists | ||
167 | */ | ||
168 | |||
169 | static DEFINE_PER_CPU(int, sockets_in_use); | ||
170 | |||
171 | /* | ||
172 | * Support routines. | 166 | * Support routines. |
173 | * Move socket addresses back and forth across the kernel/user | 167 | * Move socket addresses back and forth across the kernel/user |
174 | * divide and look after the messy bits. | 168 | * divide and look after the messy bits. |
@@ -580,7 +574,6 @@ struct socket *sock_alloc(void) | |||
580 | inode->i_gid = current_fsgid(); | 574 | inode->i_gid = current_fsgid(); |
581 | inode->i_op = &sockfs_inode_ops; | 575 | inode->i_op = &sockfs_inode_ops; |
582 | 576 | ||
583 | this_cpu_add(sockets_in_use, 1); | ||
584 | return sock; | 577 | return sock; |
585 | } | 578 | } |
586 | EXPORT_SYMBOL(sock_alloc); | 579 | EXPORT_SYMBOL(sock_alloc); |
@@ -607,7 +600,6 @@ void sock_release(struct socket *sock) | |||
607 | if (rcu_dereference_protected(sock->wq, 1)->fasync_list) | 600 | if (rcu_dereference_protected(sock->wq, 1)->fasync_list) |
608 | pr_err("%s: fasync list not empty!\n", __func__); | 601 | pr_err("%s: fasync list not empty!\n", __func__); |
609 | 602 | ||
610 | this_cpu_sub(sockets_in_use, 1); | ||
611 | if (!sock->file) { | 603 | if (!sock->file) { |
612 | iput(SOCK_INODE(sock)); | 604 | iput(SOCK_INODE(sock)); |
613 | return; | 605 | return; |
@@ -969,9 +961,28 @@ static long sock_do_ioctl(struct net *net, struct socket *sock, | |||
969 | * If this ioctl is unknown try to hand it down | 961 | * If this ioctl is unknown try to hand it down |
970 | * to the NIC driver. | 962 | * to the NIC driver. |
971 | */ | 963 | */ |
972 | if (err == -ENOIOCTLCMD) | 964 | if (err != -ENOIOCTLCMD) |
973 | err = dev_ioctl(net, cmd, argp); | 965 | return err; |
974 | 966 | ||
967 | if (cmd == SIOCGIFCONF) { | ||
968 | struct ifconf ifc; | ||
969 | if (copy_from_user(&ifc, argp, sizeof(struct ifconf))) | ||
970 | return -EFAULT; | ||
971 | rtnl_lock(); | ||
972 | err = dev_ifconf(net, &ifc, sizeof(struct ifreq)); | ||
973 | rtnl_unlock(); | ||
974 | if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) | ||
975 | err = -EFAULT; | ||
976 | } else { | ||
977 | struct ifreq ifr; | ||
978 | bool need_copyout; | ||
979 | if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) | ||
980 | return -EFAULT; | ||
981 | err = dev_ioctl(net, cmd, &ifr, &need_copyout); | ||
982 | if (!err && need_copyout) | ||
983 | if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) | ||
984 | return -EFAULT; | ||
985 | } | ||
975 | return err; | 986 | return err; |
976 | } | 987 | } |
977 | 988 | ||
@@ -996,12 +1007,19 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
996 | sock = file->private_data; | 1007 | sock = file->private_data; |
997 | sk = sock->sk; | 1008 | sk = sock->sk; |
998 | net = sock_net(sk); | 1009 | net = sock_net(sk); |
999 | if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { | 1010 | if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) { |
1000 | err = dev_ioctl(net, cmd, argp); | 1011 | struct ifreq ifr; |
1012 | bool need_copyout; | ||
1013 | if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) | ||
1014 | return -EFAULT; | ||
1015 | err = dev_ioctl(net, cmd, &ifr, &need_copyout); | ||
1016 | if (!err && need_copyout) | ||
1017 | if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) | ||
1018 | return -EFAULT; | ||
1001 | } else | 1019 | } else |
1002 | #ifdef CONFIG_WEXT_CORE | 1020 | #ifdef CONFIG_WEXT_CORE |
1003 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { | 1021 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { |
1004 | err = dev_ioctl(net, cmd, argp); | 1022 | err = wext_handle_ioctl(net, cmd, argp); |
1005 | } else | 1023 | } else |
1006 | #endif | 1024 | #endif |
1007 | switch (cmd) { | 1025 | switch (cmd) { |
@@ -2621,29 +2639,11 @@ out_fs: | |||
2621 | 2639 | ||
2622 | core_initcall(sock_init); /* early initcall */ | 2640 | core_initcall(sock_init); /* early initcall */ |
2623 | 2641 | ||
2624 | static int __init jit_init(void) | ||
2625 | { | ||
2626 | #ifdef CONFIG_BPF_JIT_ALWAYS_ON | ||
2627 | bpf_jit_enable = 1; | ||
2628 | #endif | ||
2629 | return 0; | ||
2630 | } | ||
2631 | pure_initcall(jit_init); | ||
2632 | |||
2633 | #ifdef CONFIG_PROC_FS | 2642 | #ifdef CONFIG_PROC_FS |
2634 | void socket_seq_show(struct seq_file *seq) | 2643 | void socket_seq_show(struct seq_file *seq) |
2635 | { | 2644 | { |
2636 | int cpu; | 2645 | seq_printf(seq, "sockets: used %d\n", |
2637 | int counter = 0; | 2646 | sock_inuse_get(seq->private)); |
2638 | |||
2639 | for_each_possible_cpu(cpu) | ||
2640 | counter += per_cpu(sockets_in_use, cpu); | ||
2641 | |||
2642 | /* It can be negative, by the way. 8) */ | ||
2643 | if (counter < 0) | ||
2644 | counter = 0; | ||
2645 | |||
2646 | seq_printf(seq, "sockets: used %d\n", counter); | ||
2647 | } | 2647 | } |
2648 | #endif /* CONFIG_PROC_FS */ | 2648 | #endif /* CONFIG_PROC_FS */ |
2649 | 2649 | ||
@@ -2680,89 +2680,25 @@ static int do_siocgstampns(struct net *net, struct socket *sock, | |||
2680 | return err; | 2680 | return err; |
2681 | } | 2681 | } |
2682 | 2682 | ||
2683 | static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) | 2683 | static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) |
2684 | { | ||
2685 | struct ifreq __user *uifr; | ||
2686 | int err; | ||
2687 | |||
2688 | uifr = compat_alloc_user_space(sizeof(struct ifreq)); | ||
2689 | if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) | ||
2690 | return -EFAULT; | ||
2691 | |||
2692 | err = dev_ioctl(net, SIOCGIFNAME, uifr); | ||
2693 | if (err) | ||
2694 | return err; | ||
2695 | |||
2696 | if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) | ||
2697 | return -EFAULT; | ||
2698 | |||
2699 | return 0; | ||
2700 | } | ||
2701 | |||
2702 | static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | ||
2703 | { | 2684 | { |
2704 | struct compat_ifconf ifc32; | 2685 | struct compat_ifconf ifc32; |
2705 | struct ifconf ifc; | 2686 | struct ifconf ifc; |
2706 | struct ifconf __user *uifc; | ||
2707 | struct compat_ifreq __user *ifr32; | ||
2708 | struct ifreq __user *ifr; | ||
2709 | unsigned int i, j; | ||
2710 | int err; | 2687 | int err; |
2711 | 2688 | ||
2712 | if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) | 2689 | if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) |
2713 | return -EFAULT; | 2690 | return -EFAULT; |
2714 | 2691 | ||
2715 | memset(&ifc, 0, sizeof(ifc)); | 2692 | ifc.ifc_len = ifc32.ifc_len; |
2716 | if (ifc32.ifcbuf == 0) { | 2693 | ifc.ifc_req = compat_ptr(ifc32.ifcbuf); |
2717 | ifc32.ifc_len = 0; | ||
2718 | ifc.ifc_len = 0; | ||
2719 | ifc.ifc_req = NULL; | ||
2720 | uifc = compat_alloc_user_space(sizeof(struct ifconf)); | ||
2721 | } else { | ||
2722 | size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) * | ||
2723 | sizeof(struct ifreq); | ||
2724 | uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); | ||
2725 | ifc.ifc_len = len; | ||
2726 | ifr = ifc.ifc_req = (void __user *)(uifc + 1); | ||
2727 | ifr32 = compat_ptr(ifc32.ifcbuf); | ||
2728 | for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) { | ||
2729 | if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) | ||
2730 | return -EFAULT; | ||
2731 | ifr++; | ||
2732 | ifr32++; | ||
2733 | } | ||
2734 | } | ||
2735 | if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) | ||
2736 | return -EFAULT; | ||
2737 | 2694 | ||
2738 | err = dev_ioctl(net, SIOCGIFCONF, uifc); | 2695 | rtnl_lock(); |
2696 | err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq)); | ||
2697 | rtnl_unlock(); | ||
2739 | if (err) | 2698 | if (err) |
2740 | return err; | 2699 | return err; |
2741 | 2700 | ||
2742 | if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) | 2701 | ifc32.ifc_len = ifc.ifc_len; |
2743 | return -EFAULT; | ||
2744 | |||
2745 | ifr = ifc.ifc_req; | ||
2746 | ifr32 = compat_ptr(ifc32.ifcbuf); | ||
2747 | for (i = 0, j = 0; | ||
2748 | i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; | ||
2749 | i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) { | ||
2750 | if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq))) | ||
2751 | return -EFAULT; | ||
2752 | ifr32++; | ||
2753 | ifr++; | ||
2754 | } | ||
2755 | |||
2756 | if (ifc32.ifcbuf == 0) { | ||
2757 | /* Translate from 64-bit structure multiple to | ||
2758 | * a 32-bit one. | ||
2759 | */ | ||
2760 | i = ifc.ifc_len; | ||
2761 | i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); | ||
2762 | ifc32.ifc_len = i; | ||
2763 | } else { | ||
2764 | ifc32.ifc_len = i; | ||
2765 | } | ||
2766 | if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) | 2702 | if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) |
2767 | return -EFAULT; | 2703 | return -EFAULT; |
2768 | 2704 | ||
@@ -2773,9 +2709,9 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2773 | { | 2709 | { |
2774 | struct compat_ethtool_rxnfc __user *compat_rxnfc; | 2710 | struct compat_ethtool_rxnfc __user *compat_rxnfc; |
2775 | bool convert_in = false, convert_out = false; | 2711 | bool convert_in = false, convert_out = false; |
2776 | size_t buf_size = ALIGN(sizeof(struct ifreq), 8); | 2712 | size_t buf_size = 0; |
2777 | struct ethtool_rxnfc __user *rxnfc; | 2713 | struct ethtool_rxnfc __user *rxnfc = NULL; |
2778 | struct ifreq __user *ifr; | 2714 | struct ifreq ifr; |
2779 | u32 rule_cnt = 0, actual_rule_cnt; | 2715 | u32 rule_cnt = 0, actual_rule_cnt; |
2780 | u32 ethcmd; | 2716 | u32 ethcmd; |
2781 | u32 data; | 2717 | u32 data; |
@@ -2812,18 +2748,14 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2812 | case ETHTOOL_SRXCLSRLDEL: | 2748 | case ETHTOOL_SRXCLSRLDEL: |
2813 | buf_size += sizeof(struct ethtool_rxnfc); | 2749 | buf_size += sizeof(struct ethtool_rxnfc); |
2814 | convert_in = true; | 2750 | convert_in = true; |
2751 | rxnfc = compat_alloc_user_space(buf_size); | ||
2815 | break; | 2752 | break; |
2816 | } | 2753 | } |
2817 | 2754 | ||
2818 | ifr = compat_alloc_user_space(buf_size); | 2755 | if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ)) |
2819 | rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8); | ||
2820 | |||
2821 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||
2822 | return -EFAULT; | 2756 | return -EFAULT; |
2823 | 2757 | ||
2824 | if (put_user(convert_in ? rxnfc : compat_ptr(data), | 2758 | ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc; |
2825 | &ifr->ifr_ifru.ifru_data)) | ||
2826 | return -EFAULT; | ||
2827 | 2759 | ||
2828 | if (convert_in) { | 2760 | if (convert_in) { |
2829 | /* We expect there to be holes between fs.m_ext and | 2761 | /* We expect there to be holes between fs.m_ext and |
@@ -2851,7 +2783,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2851 | return -EFAULT; | 2783 | return -EFAULT; |
2852 | } | 2784 | } |
2853 | 2785 | ||
2854 | ret = dev_ioctl(net, SIOCETHTOOL, ifr); | 2786 | ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL); |
2855 | if (ret) | 2787 | if (ret) |
2856 | return ret; | 2788 | return ret; |
2857 | 2789 | ||
@@ -2892,113 +2824,43 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2892 | 2824 | ||
2893 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) | 2825 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) |
2894 | { | 2826 | { |
2895 | void __user *uptr; | ||
2896 | compat_uptr_t uptr32; | 2827 | compat_uptr_t uptr32; |
2897 | struct ifreq __user *uifr; | 2828 | struct ifreq ifr; |
2829 | void __user *saved; | ||
2830 | int err; | ||
2898 | 2831 | ||
2899 | uifr = compat_alloc_user_space(sizeof(*uifr)); | 2832 | if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq))) |
2900 | if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) | ||
2901 | return -EFAULT; | 2833 | return -EFAULT; |
2902 | 2834 | ||
2903 | if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) | 2835 | if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) |
2904 | return -EFAULT; | 2836 | return -EFAULT; |
2905 | 2837 | ||
2906 | uptr = compat_ptr(uptr32); | 2838 | saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc; |
2907 | 2839 | ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32); | |
2908 | if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) | ||
2909 | return -EFAULT; | ||
2910 | |||
2911 | return dev_ioctl(net, SIOCWANDEV, uifr); | ||
2912 | } | ||
2913 | |||
2914 | static int bond_ioctl(struct net *net, unsigned int cmd, | ||
2915 | struct compat_ifreq __user *ifr32) | ||
2916 | { | ||
2917 | struct ifreq kifr; | ||
2918 | mm_segment_t old_fs; | ||
2919 | int err; | ||
2920 | 2840 | ||
2921 | switch (cmd) { | 2841 | err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL); |
2922 | case SIOCBONDENSLAVE: | 2842 | if (!err) { |
2923 | case SIOCBONDRELEASE: | 2843 | ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved; |
2924 | case SIOCBONDSETHWADDR: | 2844 | if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq))) |
2925 | case SIOCBONDCHANGEACTIVE: | 2845 | err = -EFAULT; |
2926 | if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) | ||
2927 | return -EFAULT; | ||
2928 | |||
2929 | old_fs = get_fs(); | ||
2930 | set_fs(KERNEL_DS); | ||
2931 | err = dev_ioctl(net, cmd, | ||
2932 | (struct ifreq __user __force *) &kifr); | ||
2933 | set_fs(old_fs); | ||
2934 | |||
2935 | return err; | ||
2936 | default: | ||
2937 | return -ENOIOCTLCMD; | ||
2938 | } | 2846 | } |
2847 | return err; | ||
2939 | } | 2848 | } |
2940 | 2849 | ||
2941 | /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ | 2850 | /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ |
2942 | static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, | 2851 | static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, |
2943 | struct compat_ifreq __user *u_ifreq32) | 2852 | struct compat_ifreq __user *u_ifreq32) |
2944 | { | 2853 | { |
2945 | struct ifreq __user *u_ifreq64; | 2854 | struct ifreq ifreq; |
2946 | char tmp_buf[IFNAMSIZ]; | ||
2947 | void __user *data64; | ||
2948 | u32 data32; | 2855 | u32 data32; |
2949 | 2856 | ||
2950 | if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), | 2857 | if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) |
2951 | IFNAMSIZ)) | ||
2952 | return -EFAULT; | 2858 | return -EFAULT; |
2953 | if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) | 2859 | if (get_user(data32, &u_ifreq32->ifr_data)) |
2954 | return -EFAULT; | 2860 | return -EFAULT; |
2955 | data64 = compat_ptr(data32); | 2861 | ifreq.ifr_data = compat_ptr(data32); |
2956 | 2862 | ||
2957 | u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); | 2863 | return dev_ioctl(net, cmd, &ifreq, NULL); |
2958 | |||
2959 | if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], | ||
2960 | IFNAMSIZ)) | ||
2961 | return -EFAULT; | ||
2962 | if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) | ||
2963 | return -EFAULT; | ||
2964 | |||
2965 | return dev_ioctl(net, cmd, u_ifreq64); | ||
2966 | } | ||
2967 | |||
2968 | static int dev_ifsioc(struct net *net, struct socket *sock, | ||
2969 | unsigned int cmd, struct compat_ifreq __user *uifr32) | ||
2970 | { | ||
2971 | struct ifreq __user *uifr; | ||
2972 | int err; | ||
2973 | |||
2974 | uifr = compat_alloc_user_space(sizeof(*uifr)); | ||
2975 | if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) | ||
2976 | return -EFAULT; | ||
2977 | |||
2978 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); | ||
2979 | |||
2980 | if (!err) { | ||
2981 | switch (cmd) { | ||
2982 | case SIOCGIFFLAGS: | ||
2983 | case SIOCGIFMETRIC: | ||
2984 | case SIOCGIFMTU: | ||
2985 | case SIOCGIFMEM: | ||
2986 | case SIOCGIFHWADDR: | ||
2987 | case SIOCGIFINDEX: | ||
2988 | case SIOCGIFADDR: | ||
2989 | case SIOCGIFBRDADDR: | ||
2990 | case SIOCGIFDSTADDR: | ||
2991 | case SIOCGIFNETMASK: | ||
2992 | case SIOCGIFPFLAGS: | ||
2993 | case SIOCGIFTXQLEN: | ||
2994 | case SIOCGMIIPHY: | ||
2995 | case SIOCGMIIREG: | ||
2996 | if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) | ||
2997 | err = -EFAULT; | ||
2998 | break; | ||
2999 | } | ||
3000 | } | ||
3001 | return err; | ||
3002 | } | 2864 | } |
3003 | 2865 | ||
3004 | static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | 2866 | static int compat_sioc_ifmap(struct net *net, unsigned int cmd, |
@@ -3006,7 +2868,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | |||
3006 | { | 2868 | { |
3007 | struct ifreq ifr; | 2869 | struct ifreq ifr; |
3008 | struct compat_ifmap __user *uifmap32; | 2870 | struct compat_ifmap __user *uifmap32; |
3009 | mm_segment_t old_fs; | ||
3010 | int err; | 2871 | int err; |
3011 | 2872 | ||
3012 | uifmap32 = &uifr32->ifr_ifru.ifru_map; | 2873 | uifmap32 = &uifr32->ifr_ifru.ifru_map; |
@@ -3020,10 +2881,7 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | |||
3020 | if (err) | 2881 | if (err) |
3021 | return -EFAULT; | 2882 | return -EFAULT; |
3022 | 2883 | ||
3023 | old_fs = get_fs(); | 2884 | err = dev_ioctl(net, cmd, &ifr, NULL); |
3024 | set_fs(KERNEL_DS); | ||
3025 | err = dev_ioctl(net, cmd, (void __user __force *)&ifr); | ||
3026 | set_fs(old_fs); | ||
3027 | 2885 | ||
3028 | if (cmd == SIOCGIFMAP && !err) { | 2886 | if (cmd == SIOCGIFMAP && !err) { |
3029 | err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); | 2887 | err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); |
@@ -3156,10 +3014,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
3156 | case SIOCSIFBR: | 3014 | case SIOCSIFBR: |
3157 | case SIOCGIFBR: | 3015 | case SIOCGIFBR: |
3158 | return old_bridge_ioctl(argp); | 3016 | return old_bridge_ioctl(argp); |
3159 | case SIOCGIFNAME: | ||
3160 | return dev_ifname32(net, argp); | ||
3161 | case SIOCGIFCONF: | 3017 | case SIOCGIFCONF: |
3162 | return dev_ifconf(net, argp); | 3018 | return compat_dev_ifconf(net, argp); |
3163 | case SIOCETHTOOL: | 3019 | case SIOCETHTOOL: |
3164 | return ethtool_ioctl(net, argp); | 3020 | return ethtool_ioctl(net, argp); |
3165 | case SIOCWANDEV: | 3021 | case SIOCWANDEV: |
@@ -3167,11 +3023,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
3167 | case SIOCGIFMAP: | 3023 | case SIOCGIFMAP: |
3168 | case SIOCSIFMAP: | 3024 | case SIOCSIFMAP: |
3169 | return compat_sioc_ifmap(net, cmd, argp); | 3025 | return compat_sioc_ifmap(net, cmd, argp); |
3170 | case SIOCBONDENSLAVE: | ||
3171 | case SIOCBONDRELEASE: | ||
3172 | case SIOCBONDSETHWADDR: | ||
3173 | case SIOCBONDCHANGEACTIVE: | ||
3174 | return bond_ioctl(net, cmd, argp); | ||
3175 | case SIOCADDRT: | 3026 | case SIOCADDRT: |
3176 | case SIOCDELRT: | 3027 | case SIOCDELRT: |
3177 | return routing_ioctl(net, sock, cmd, argp); | 3028 | return routing_ioctl(net, sock, cmd, argp); |
@@ -3231,12 +3082,15 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
3231 | case SIOCGMIIPHY: | 3082 | case SIOCGMIIPHY: |
3232 | case SIOCGMIIREG: | 3083 | case SIOCGMIIREG: |
3233 | case SIOCSMIIREG: | 3084 | case SIOCSMIIREG: |
3234 | return dev_ifsioc(net, sock, cmd, argp); | ||
3235 | |||
3236 | case SIOCSARP: | 3085 | case SIOCSARP: |
3237 | case SIOCGARP: | 3086 | case SIOCGARP: |
3238 | case SIOCDARP: | 3087 | case SIOCDARP: |
3239 | case SIOCATMARK: | 3088 | case SIOCATMARK: |
3089 | case SIOCBONDENSLAVE: | ||
3090 | case SIOCBONDRELEASE: | ||
3091 | case SIOCBONDSETHWADDR: | ||
3092 | case SIOCBONDCHANGEACTIVE: | ||
3093 | case SIOCGIFNAME: | ||
3240 | return sock_do_ioctl(net, sock, cmd, arg); | 3094 | return sock_do_ioctl(net, sock, cmd, arg); |
3241 | } | 3095 | } |
3242 | 3096 | ||
@@ -3391,19 +3245,6 @@ int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, | |||
3391 | } | 3245 | } |
3392 | EXPORT_SYMBOL(kernel_sendpage_locked); | 3246 | EXPORT_SYMBOL(kernel_sendpage_locked); |
3393 | 3247 | ||
3394 | int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) | ||
3395 | { | ||
3396 | mm_segment_t oldfs = get_fs(); | ||
3397 | int err; | ||
3398 | |||
3399 | set_fs(KERNEL_DS); | ||
3400 | err = sock->ops->ioctl(sock, cmd, arg); | ||
3401 | set_fs(oldfs); | ||
3402 | |||
3403 | return err; | ||
3404 | } | ||
3405 | EXPORT_SYMBOL(kernel_sock_ioctl); | ||
3406 | |||
3407 | int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) | 3248 | int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) |
3408 | { | 3249 | { |
3409 | return sock->ops->shutdown(sock, how); | 3250 | return sock->ops->shutdown(sock, how); |