| .. | .. |
|---|
| 46 | 46 | return 0; |
|---|
| 47 | 47 | } |
|---|
| 48 | 48 | |
|---|
| 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) |
|---|
| 50 | 50 | { |
|---|
| 51 | | - void __user *argp = (void __user *) arg; |
|---|
| 52 | 51 | struct hidp_connadd_req ca; |
|---|
| 53 | 52 | struct hidp_conndel_req cd; |
|---|
| 54 | 53 | struct hidp_connlist_req cl; |
|---|
| .. | .. |
|---|
| 57 | 56 | struct socket *isock; |
|---|
| 58 | 57 | int err; |
|---|
| 59 | 58 | |
|---|
| 60 | | - BT_DBG("cmd %x arg %lx", cmd, arg); |
|---|
| 59 | + BT_DBG("cmd %x arg %p", cmd, argp); |
|---|
| 61 | 60 | |
|---|
| 62 | 61 | switch (cmd) { |
|---|
| 63 | 62 | case HIDPCONNADD: |
|---|
| .. | .. |
|---|
| 123 | 122 | return -EINVAL; |
|---|
| 124 | 123 | } |
|---|
| 125 | 124 | |
|---|
| 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 | + |
|---|
| 126 | 130 | #ifdef CONFIG_COMPAT |
|---|
| 127 | 131 | struct compat_hidp_connadd_req { |
|---|
| 128 | 132 | int ctrl_sock; /* Connected control socket */ |
|---|
| .. | .. |
|---|
| 142 | 146 | |
|---|
| 143 | 147 | static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
|---|
| 144 | 148 | { |
|---|
| 149 | + void __user *argp = compat_ptr(arg); |
|---|
| 150 | + int err; |
|---|
| 151 | + |
|---|
| 145 | 152 | if (cmd == HIDPGETCONNLIST) { |
|---|
| 146 | 153 | struct hidp_connlist_req cl; |
|---|
| 154 | + u32 __user *p = argp; |
|---|
| 147 | 155 | u32 uci; |
|---|
| 148 | | - int err; |
|---|
| 149 | 156 | |
|---|
| 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)) |
|---|
| 152 | 158 | return -EFAULT; |
|---|
| 153 | 159 | |
|---|
| 154 | 160 | cl.ci = compat_ptr(uci); |
|---|
| .. | .. |
|---|
| 158 | 164 | |
|---|
| 159 | 165 | err = hidp_get_connlist(&cl); |
|---|
| 160 | 166 | |
|---|
| 161 | | - if (!err && put_user(cl.cnum, (u32 __user *) arg)) |
|---|
| 167 | + if (!err && put_user(cl.cnum, p)) |
|---|
| 162 | 168 | err = -EFAULT; |
|---|
| 163 | 169 | |
|---|
| 164 | 170 | return err; |
|---|
| 165 | 171 | } 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; |
|---|
| 168 | 176 | |
|---|
| 169 | | - uca = compat_alloc_user_space(sizeof(*uca)); |
|---|
| 177 | + if (!capable(CAP_NET_ADMIN)) |
|---|
| 178 | + return -EPERM; |
|---|
| 170 | 179 | |
|---|
| 171 | | - if (copy_from_user(&ca, (void __user *) arg, sizeof(ca))) |
|---|
| 180 | + if (copy_from_user(&ca32, (void __user *) arg, sizeof(ca32))) |
|---|
| 172 | 181 | return -EFAULT; |
|---|
| 173 | 182 | |
|---|
| 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); |
|---|
| 188 | 197 | |
|---|
| 189 | | - arg = (unsigned long) uca; |
|---|
| 198 | + csock = sockfd_lookup(ca.ctrl_sock, &err); |
|---|
| 199 | + if (!csock) |
|---|
| 200 | + return err; |
|---|
| 190 | 201 | |
|---|
| 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; |
|---|
| 194 | 216 | } |
|---|
| 195 | 217 | |
|---|
| 196 | 218 | return hidp_sock_ioctl(sock, cmd, arg); |
|---|
| .. | .. |
|---|
| 211 | 233 | .recvmsg = sock_no_recvmsg, |
|---|
| 212 | 234 | .listen = sock_no_listen, |
|---|
| 213 | 235 | .shutdown = sock_no_shutdown, |
|---|
| 214 | | - .setsockopt = sock_no_setsockopt, |
|---|
| 215 | | - .getsockopt = sock_no_getsockopt, |
|---|
| 216 | 236 | .connect = sock_no_connect, |
|---|
| 217 | 237 | .socketpair = sock_no_socketpair, |
|---|
| 218 | 238 | .accept = sock_no_accept, |
|---|