aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hidp
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/hidp')
-rw-r--r--net/bluetooth/hidp/sock.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 099646e4e2ef..6242446aa270 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -35,6 +35,7 @@
35#include <linux/ioctl.h> 35#include <linux/ioctl.h>
36#include <linux/file.h> 36#include <linux/file.h>
37#include <linux/init.h> 37#include <linux/init.h>
38#include <linux/compat.h>
38#include <net/sock.h> 39#include <net/sock.h>
39 40
40#include "hidp.h" 41#include "hidp.h"
@@ -143,11 +144,88 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
143 return -EINVAL; 144 return -EINVAL;
144} 145}
145 146
147#ifdef CONFIG_COMPAT
148struct compat_hidp_connadd_req {
149 int ctrl_sock; // Connected control socket
150 int intr_sock; // Connteted interrupt socket
151 __u16 parser;
152 __u16 rd_size;
153 compat_uptr_t rd_data;
154 __u8 country;
155 __u8 subclass;
156 __u16 vendor;
157 __u16 product;
158 __u16 version;
159 __u32 flags;
160 __u32 idle_to;
161 char name[128];
162};
163
164static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
165{
166 if (cmd == HIDPGETCONNLIST) {
167 struct hidp_connlist_req cl;
168 uint32_t uci;
169 int err;
170
171 if (get_user(cl.cnum, (uint32_t __user *) arg) ||
172 get_user(uci, (u32 __user *) (arg + 4)))
173 return -EFAULT;
174
175 cl.ci = compat_ptr(uci);
176
177 if (cl.cnum <= 0)
178 return -EINVAL;
179
180 err = hidp_get_connlist(&cl);
181
182 if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
183 err = -EFAULT;
184
185 return err;
186 } else if (cmd == HIDPCONNADD) {
187 struct compat_hidp_connadd_req ca;
188 struct hidp_connadd_req __user *uca;
189
190 uca = compat_alloc_user_space(sizeof(*uca));
191
192 if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
193 return -EFAULT;
194
195 if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
196 put_user(ca.intr_sock, &uca->intr_sock) ||
197 put_user(ca.parser, &uca->parser) ||
198 put_user(ca.rd_size, &uca->parser) ||
199 put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
200 put_user(ca.country, &uca->country) ||
201 put_user(ca.subclass, &uca->subclass) ||
202 put_user(ca.vendor, &uca->vendor) ||
203 put_user(ca.product, &uca->product) ||
204 put_user(ca.version, &uca->version) ||
205 put_user(ca.flags, &uca->flags) ||
206 put_user(ca.idle_to, &uca->idle_to) ||
207 copy_to_user(&uca->name[0], &ca.name[0], 128))
208 return -EFAULT;
209
210 arg = (unsigned long) uca;
211
212 /* Fall through. We don't actually write back any _changes_
213 to the structure anyway, so there's no need to copy back
214 into the original compat version */
215 }
216
217 return hidp_sock_ioctl(sock, cmd, arg);
218}
219#endif
220
146static const struct proto_ops hidp_sock_ops = { 221static const struct proto_ops hidp_sock_ops = {
147 .family = PF_BLUETOOTH, 222 .family = PF_BLUETOOTH,
148 .owner = THIS_MODULE, 223 .owner = THIS_MODULE,
149 .release = hidp_sock_release, 224 .release = hidp_sock_release,
150 .ioctl = hidp_sock_ioctl, 225 .ioctl = hidp_sock_ioctl,
226#ifdef CONFIG_COMPAT
227 .compat_ioctl = hidp_sock_compat_ioctl,
228#endif
151 .bind = sock_no_bind, 229 .bind = sock_no_bind,
152 .getname = sock_no_getname, 230 .getname = sock_no_getname,
153 .sendmsg = sock_no_sendmsg, 231 .sendmsg = sock_no_sendmsg,