Commit 87de87d5e47f94b4ea647a5bd1bc8dc1f7930db4

Authored by David S. Miller
1 parent a67fa76d8b

wext: Dispatch and handle compat ioctls entirely in net/wireless/wext.c

Next we can kill the hacks in fs/compat_ioctl.c and also
dispatch compat ioctls down into the driver and 80211 protocol
helper layers in order to handle iw_point objects embedded in
stream replies which need to be translated.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files with 134 additions and 6 deletions Side-by-side Diff

... ... @@ -1757,12 +1757,6 @@
1757 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 1760 static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
1767 1761 {
1768 1762 struct iwreq __user *iwr;
include/linux/wireless.h
... ... @@ -677,6 +677,19 @@
677 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 694 * A frequency
682 695 * For numbers lower than 10^9, we encode the number in 'm' and
... ... @@ -12,6 +12,8 @@
12 12 extern void wext_proc_exit(struct net *net);
13 13 extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
14 14 void __user *arg);
  15 +extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
  16 + unsigned long arg);
15 17 #else
16 18 static inline int wext_proc_init(struct net *net)
17 19 {
... ... @@ -23,6 +25,11 @@
23 25 }
24 26 static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
25 27 void __user *arg)
  28 +{
  29 + return -EINVAL;
  30 +}
  31 +static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
  32 + unsigned long arg)
26 33 {
27 34 return -EINVAL;
28 35 }
... ... @@ -90,6 +90,7 @@
90 90 #include <asm/unistd.h>
91 91  
92 92 #include <net/compat.h>
  93 +#include <net/wext.h>
93 94  
94 95 #include <net/sock.h>
95 96 #include <linux/netfilter.h>
96 97  
97 98  
... ... @@ -2210,9 +2211,18 @@
2210 2211 {
2211 2212 struct socket *sock = file->private_data;
2212 2213 int ret = -ENOIOCTLCMD;
  2214 + struct sock *sk;
  2215 + struct net *net;
2213 2216  
  2217 + sk = sock->sk;
  2218 + net = sock_net(sk);
  2219 +
2214 2220 if (sock->ops->compat_ioctl)
2215 2221 ret = sock->ops->compat_ioctl(sock, cmd, arg);
  2222 +
  2223 + if (ret == -ENOIOCTLCMD &&
  2224 + (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
  2225 + ret = compat_wext_handle_ioctl(net, cmd, arg);
2216 2226  
2217 2227 return ret;
2218 2228 }
... ... @@ -1112,6 +1112,110 @@
1112 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 1219 /************************* EVENT PROCESSING *************************/
1116 1220 /*
1117 1221 * Process events generated by the wireless layer or the driver.