diff options
-rw-r--r-- | fs/compat_ioctl.c | 6 | ||||
-rw-r--r-- | include/linux/wireless.h | 13 | ||||
-rw-r--r-- | include/net/wext.h | 7 | ||||
-rw-r--r-- | net/socket.c | 10 | ||||
-rw-r--r-- | net/wireless/wext.c | 104 |
5 files changed, 134 insertions, 6 deletions
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 97dba0d92348..8ab850bf2eee 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -1757,12 +1757,6 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a | |||
1757 | return sys_ioctl(fd, cmd, (unsigned long)tdata); | 1757 | return sys_ioctl(fd, cmd, (unsigned long)tdata); |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | struct compat_iw_point { | ||
1761 | compat_caddr_t pointer; | ||
1762 | __u16 length; | ||
1763 | __u16 flags; | ||
1764 | }; | ||
1765 | |||
1766 | static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | 1760 | static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) |
1767 | { | 1761 | { |
1768 | struct iwreq __user *iwr; | 1762 | struct iwreq __user *iwr; |
diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 4a95a0e5eeca..79d846875825 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h | |||
@@ -677,6 +677,19 @@ struct iw_point | |||
677 | __u16 flags; /* Optional params */ | 677 | __u16 flags; /* Optional params */ |
678 | }; | 678 | }; |
679 | 679 | ||
680 | #ifdef __KERNEL__ | ||
681 | #ifdef CONFIG_COMPAT | ||
682 | |||
683 | #include <linux/compat.h> | ||
684 | |||
685 | struct compat_iw_point { | ||
686 | compat_caddr_t pointer; | ||
687 | __u16 length; | ||
688 | __u16 flags; | ||
689 | }; | ||
690 | #endif | ||
691 | #endif | ||
692 | |||
680 | /* | 693 | /* |
681 | * A frequency | 694 | * A frequency |
682 | * For numbers lower than 10^9, we encode the number in 'm' and | 695 | * For numbers lower than 10^9, we encode the number in 'm' and |
diff --git a/include/net/wext.h b/include/net/wext.h index 80b31d826b7a..6d76a39a9c5b 100644 --- a/include/net/wext.h +++ b/include/net/wext.h | |||
@@ -12,6 +12,8 @@ extern int wext_proc_init(struct net *net); | |||
12 | extern void wext_proc_exit(struct net *net); | 12 | extern void wext_proc_exit(struct net *net); |
13 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 13 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
14 | void __user *arg); | 14 | void __user *arg); |
15 | extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
16 | unsigned long arg); | ||
15 | #else | 17 | #else |
16 | static inline int wext_proc_init(struct net *net) | 18 | static inline int wext_proc_init(struct net *net) |
17 | { | 19 | { |
@@ -26,6 +28,11 @@ static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned | |||
26 | { | 28 | { |
27 | return -EINVAL; | 29 | return -EINVAL; |
28 | } | 30 | } |
31 | static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
32 | unsigned long arg) | ||
33 | { | ||
34 | return -EINVAL; | ||
35 | } | ||
29 | #endif | 36 | #endif |
30 | 37 | ||
31 | #endif /* __NET_WEXT_H */ | 38 | #endif /* __NET_WEXT_H */ |
diff --git a/net/socket.c b/net/socket.c index 66c4a8cf6db9..81fe82513046 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <asm/unistd.h> | 90 | #include <asm/unistd.h> |
91 | 91 | ||
92 | #include <net/compat.h> | 92 | #include <net/compat.h> |
93 | #include <net/wext.h> | ||
93 | 94 | ||
94 | #include <net/sock.h> | 95 | #include <net/sock.h> |
95 | #include <linux/netfilter.h> | 96 | #include <linux/netfilter.h> |
@@ -2210,10 +2211,19 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, | |||
2210 | { | 2211 | { |
2211 | struct socket *sock = file->private_data; | 2212 | struct socket *sock = file->private_data; |
2212 | int ret = -ENOIOCTLCMD; | 2213 | int ret = -ENOIOCTLCMD; |
2214 | struct sock *sk; | ||
2215 | struct net *net; | ||
2216 | |||
2217 | sk = sock->sk; | ||
2218 | net = sock_net(sk); | ||
2213 | 2219 | ||
2214 | if (sock->ops->compat_ioctl) | 2220 | if (sock->ops->compat_ioctl) |
2215 | ret = sock->ops->compat_ioctl(sock, cmd, arg); | 2221 | ret = sock->ops->compat_ioctl(sock, cmd, arg); |
2216 | 2222 | ||
2223 | if (ret == -ENOIOCTLCMD && | ||
2224 | (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) | ||
2225 | ret = compat_wext_handle_ioctl(net, cmd, arg); | ||
2226 | |||
2217 | return ret; | 2227 | return ret; |
2218 | } | 2228 | } |
2219 | #endif | 2229 | #endif |
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 09022cbb58ba..1a4636a9fcde 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -1112,6 +1112,110 @@ int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | |||
1112 | return ret; | 1112 | return ret; |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | #ifdef CONFIG_COMPAT | ||
1116 | static int compat_standard_call(struct net_device *dev, | ||
1117 | struct iwreq *iwr, | ||
1118 | unsigned int cmd, | ||
1119 | iw_handler handler) | ||
1120 | { | ||
1121 | const struct iw_ioctl_description *descr; | ||
1122 | struct compat_iw_point *iwp_compat; | ||
1123 | struct iw_request_info info; | ||
1124 | struct iw_point iwp; | ||
1125 | int err; | ||
1126 | |||
1127 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | ||
1128 | |||
1129 | if (descr->header_type != IW_HEADER_TYPE_POINT) | ||
1130 | return ioctl_standard_call(dev, iwr, cmd, handler); | ||
1131 | |||
1132 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1133 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1134 | iwp.length = iwp_compat->length; | ||
1135 | iwp.flags = iwp_compat->flags; | ||
1136 | |||
1137 | info.cmd = cmd; | ||
1138 | info.flags = 0; | ||
1139 | |||
1140 | err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, &info); | ||
1141 | |||
1142 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1143 | iwp_compat->length = iwp.length; | ||
1144 | iwp_compat->flags = iwp.flags; | ||
1145 | |||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
1150 | unsigned int cmd, iw_handler handler) | ||
1151 | { | ||
1152 | const struct iw_priv_args *descr; | ||
1153 | struct iw_request_info info; | ||
1154 | int ret, extra_size; | ||
1155 | |||
1156 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
1157 | |||
1158 | /* Prepare the call */ | ||
1159 | info.cmd = cmd; | ||
1160 | info.flags = 0; | ||
1161 | |||
1162 | /* Check if we have a pointer to user space data or not. */ | ||
1163 | if (extra_size == 0) { | ||
1164 | /* No extra arguments. Trivial to handle */ | ||
1165 | ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); | ||
1166 | } else { | ||
1167 | struct compat_iw_point *iwp_compat; | ||
1168 | struct iw_point iwp; | ||
1169 | |||
1170 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1171 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1172 | iwp.length = iwp_compat->length; | ||
1173 | iwp.flags = iwp_compat->flags; | ||
1174 | |||
1175 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | ||
1176 | handler, dev, &info, extra_size); | ||
1177 | |||
1178 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1179 | iwp_compat->length = iwp.length; | ||
1180 | iwp_compat->flags = iwp.flags; | ||
1181 | } | ||
1182 | |||
1183 | /* Call commit handler if needed and defined */ | ||
1184 | if (ret == -EIWCOMMIT) | ||
1185 | ret = call_commit_handler(dev); | ||
1186 | |||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
1191 | unsigned long arg) | ||
1192 | { | ||
1193 | void __user *argp = (void __user *)arg; | ||
1194 | struct iwreq iwr; | ||
1195 | char *colon; | ||
1196 | int ret; | ||
1197 | |||
1198 | if (copy_from_user(&iwr, argp, sizeof(struct iwreq))) | ||
1199 | return -EFAULT; | ||
1200 | |||
1201 | iwr.ifr_name[IFNAMSIZ-1] = 0; | ||
1202 | colon = strchr(iwr.ifr_name, ':'); | ||
1203 | if (colon) | ||
1204 | *colon = 0; | ||
1205 | |||
1206 | ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, | ||
1207 | compat_standard_call, | ||
1208 | compat_private_call); | ||
1209 | |||
1210 | if (ret >= 0 && | ||
1211 | IW_IS_GET(cmd) && | ||
1212 | copy_to_user(argp, &iwr, sizeof(struct iwreq))) | ||
1213 | return -EFAULT; | ||
1214 | |||
1215 | return ret; | ||
1216 | } | ||
1217 | #endif | ||
1218 | |||
1115 | /************************* EVENT PROCESSING *************************/ | 1219 | /************************* EVENT PROCESSING *************************/ |
1116 | /* | 1220 | /* |
1117 | * Process events generated by the wireless layer or the driver. | 1221 | * Process events generated by the wireless layer or the driver. |