hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/net/bluetooth/hidp/sock.c
....@@ -46,9 +46,8 @@
4646 return 0;
4747 }
4848
49
-static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
49
+static int do_hidp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
5050 {
51
- void __user *argp = (void __user *) arg;
5251 struct hidp_connadd_req ca;
5352 struct hidp_conndel_req cd;
5453 struct hidp_connlist_req cl;
....@@ -57,7 +56,7 @@
5756 struct socket *isock;
5857 int err;
5958
60
- BT_DBG("cmd %x arg %lx", cmd, arg);
59
+ BT_DBG("cmd %x arg %p", cmd, argp);
6160
6261 switch (cmd) {
6362 case HIDPCONNADD:
....@@ -123,6 +122,11 @@
123122 return -EINVAL;
124123 }
125124
125
+static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
126
+{
127
+ return do_hidp_sock_ioctl(sock, cmd, (void __user *)arg);
128
+}
129
+
126130 #ifdef CONFIG_COMPAT
127131 struct compat_hidp_connadd_req {
128132 int ctrl_sock; /* Connected control socket */
....@@ -142,13 +146,15 @@
142146
143147 static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
144148 {
149
+ void __user *argp = compat_ptr(arg);
150
+ int err;
151
+
145152 if (cmd == HIDPGETCONNLIST) {
146153 struct hidp_connlist_req cl;
154
+ u32 __user *p = argp;
147155 u32 uci;
148
- int err;
149156
150
- if (get_user(cl.cnum, (u32 __user *) arg) ||
151
- get_user(uci, (u32 __user *) (arg + 4)))
157
+ if (get_user(cl.cnum, p) || get_user(uci, p + 1))
152158 return -EFAULT;
153159
154160 cl.ci = compat_ptr(uci);
....@@ -158,39 +164,55 @@
158164
159165 err = hidp_get_connlist(&cl);
160166
161
- if (!err && put_user(cl.cnum, (u32 __user *) arg))
167
+ if (!err && put_user(cl.cnum, p))
162168 err = -EFAULT;
163169
164170 return err;
165171 } else if (cmd == HIDPCONNADD) {
166
- struct compat_hidp_connadd_req ca;
167
- struct hidp_connadd_req __user *uca;
172
+ struct compat_hidp_connadd_req ca32;
173
+ struct hidp_connadd_req ca;
174
+ struct socket *csock;
175
+ struct socket *isock;
168176
169
- uca = compat_alloc_user_space(sizeof(*uca));
177
+ if (!capable(CAP_NET_ADMIN))
178
+ return -EPERM;
170179
171
- if (copy_from_user(&ca, (void __user *) arg, sizeof(ca)))
180
+ if (copy_from_user(&ca32, (void __user *) arg, sizeof(ca32)))
172181 return -EFAULT;
173182
174
- if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
175
- put_user(ca.intr_sock, &uca->intr_sock) ||
176
- put_user(ca.parser, &uca->parser) ||
177
- put_user(ca.rd_size, &uca->rd_size) ||
178
- put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
179
- put_user(ca.country, &uca->country) ||
180
- put_user(ca.subclass, &uca->subclass) ||
181
- put_user(ca.vendor, &uca->vendor) ||
182
- put_user(ca.product, &uca->product) ||
183
- put_user(ca.version, &uca->version) ||
184
- put_user(ca.flags, &uca->flags) ||
185
- put_user(ca.idle_to, &uca->idle_to) ||
186
- copy_to_user(&uca->name[0], &ca.name[0], 128))
187
- return -EFAULT;
183
+ ca.ctrl_sock = ca32.ctrl_sock;
184
+ ca.intr_sock = ca32.intr_sock;
185
+ ca.parser = ca32.parser;
186
+ ca.rd_size = ca32.rd_size;
187
+ ca.rd_data = compat_ptr(ca32.rd_data);
188
+ ca.country = ca32.country;
189
+ ca.subclass = ca32.subclass;
190
+ ca.vendor = ca32.vendor;
191
+ ca.product = ca32.product;
192
+ ca.version = ca32.version;
193
+ ca.flags = ca32.flags;
194
+ ca.idle_to = ca32.idle_to;
195
+ ca32.name[sizeof(ca32.name) - 1] = '\0';
196
+ memcpy(ca.name, ca32.name, 128);
188197
189
- arg = (unsigned long) uca;
198
+ csock = sockfd_lookup(ca.ctrl_sock, &err);
199
+ if (!csock)
200
+ return err;
190201
191
- /* Fall through. We don't actually write back any _changes_
192
- to the structure anyway, so there's no need to copy back
193
- into the original compat version */
202
+ isock = sockfd_lookup(ca.intr_sock, &err);
203
+ if (!isock) {
204
+ sockfd_put(csock);
205
+ return err;
206
+ }
207
+
208
+ err = hidp_connection_add(&ca, csock, isock);
209
+ if (!err && copy_to_user(argp, &ca32, sizeof(ca32)))
210
+ err = -EFAULT;
211
+
212
+ sockfd_put(csock);
213
+ sockfd_put(isock);
214
+
215
+ return err;
194216 }
195217
196218 return hidp_sock_ioctl(sock, cmd, arg);
....@@ -211,8 +233,6 @@
211233 .recvmsg = sock_no_recvmsg,
212234 .listen = sock_no_listen,
213235 .shutdown = sock_no_shutdown,
214
- .setsockopt = sock_no_setsockopt,
215
- .getsockopt = sock_no_getsockopt,
216236 .connect = sock_no_connect,
217237 .socketpair = sock_no_socketpair,
218238 .accept = sock_no_accept,