diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2006-10-15 11:30:22 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-16 02:14:27 -0400 |
commit | e9c5702e3c5558dade169949abd730173e87ef9c (patch) | |
tree | 58ec8dcd1497b51e1d6a447d8c4a34a0bd2f108d /net/bluetooth/bnep | |
parent | 39c850863d5e36e72ecf9bc3537ec717bcce97fd (diff) |
[Bluetooth] Fix compat ioctl for BNEP, CMTP and HIDP
There exists no attempt do deal with the fact that a structure with
a uint32_t followed by a pointer is going to be different for 32-bit
and 64-bit userspace. Any 32-bit process trying to use it will be
failing with -EFAULT if it's lucky; suffering from having data dumped
at a random address if it's not.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/bnep')
-rw-r--r-- | net/bluetooth/bnep/sock.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 28c55835422a..5d9d6f14b310 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/ioctl.h> | 43 | #include <linux/ioctl.h> |
44 | #include <linux/file.h> | 44 | #include <linux/file.h> |
45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
46 | #include <linux/compat.h> | ||
46 | #include <net/sock.h> | 47 | #include <net/sock.h> |
47 | 48 | ||
48 | #include <asm/system.h> | 49 | #include <asm/system.h> |
@@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long | |||
146 | return 0; | 147 | return 0; |
147 | } | 148 | } |
148 | 149 | ||
150 | #ifdef CONFIG_COMPAT | ||
151 | static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
152 | { | ||
153 | if (cmd == BNEPGETCONNLIST) { | ||
154 | struct bnep_connlist_req cl; | ||
155 | uint32_t uci; | ||
156 | int err; | ||
157 | |||
158 | if (get_user(cl.cnum, (uint32_t __user *) arg) || | ||
159 | get_user(uci, (u32 __user *) (arg + 4))) | ||
160 | return -EFAULT; | ||
161 | |||
162 | cl.ci = compat_ptr(uci); | ||
163 | |||
164 | if (cl.cnum <= 0) | ||
165 | return -EINVAL; | ||
166 | |||
167 | err = bnep_get_connlist(&cl); | ||
168 | |||
169 | if (!err && put_user(cl.cnum, (uint32_t __user *) arg)) | ||
170 | err = -EFAULT; | ||
171 | |||
172 | return err; | ||
173 | } | ||
174 | |||
175 | return bnep_sock_ioctl(sock, cmd, arg); | ||
176 | } | ||
177 | #endif | ||
178 | |||
149 | static const struct proto_ops bnep_sock_ops = { | 179 | static const struct proto_ops bnep_sock_ops = { |
150 | .family = PF_BLUETOOTH, | 180 | .family = PF_BLUETOOTH, |
151 | .owner = THIS_MODULE, | 181 | .owner = THIS_MODULE, |
152 | .release = bnep_sock_release, | 182 | .release = bnep_sock_release, |
153 | .ioctl = bnep_sock_ioctl, | 183 | .ioctl = bnep_sock_ioctl, |
154 | .bind = sock_no_bind, | 184 | #ifdef CONFIG_COMPAT |
155 | .getname = sock_no_getname, | 185 | .compat_ioctl = bnep_sock_compat_ioctl, |
156 | .sendmsg = sock_no_sendmsg, | 186 | #endif |
157 | .recvmsg = sock_no_recvmsg, | 187 | .bind = sock_no_bind, |
158 | .poll = sock_no_poll, | 188 | .getname = sock_no_getname, |
159 | .listen = sock_no_listen, | 189 | .sendmsg = sock_no_sendmsg, |
160 | .shutdown = sock_no_shutdown, | 190 | .recvmsg = sock_no_recvmsg, |
161 | .setsockopt = sock_no_setsockopt, | 191 | .poll = sock_no_poll, |
162 | .getsockopt = sock_no_getsockopt, | 192 | .listen = sock_no_listen, |
163 | .connect = sock_no_connect, | 193 | .shutdown = sock_no_shutdown, |
164 | .socketpair = sock_no_socketpair, | 194 | .setsockopt = sock_no_setsockopt, |
165 | .accept = sock_no_accept, | 195 | .getsockopt = sock_no_getsockopt, |
166 | .mmap = sock_no_mmap | 196 | .connect = sock_no_connect, |
197 | .socketpair = sock_no_socketpair, | ||
198 | .accept = sock_no_accept, | ||
199 | .mmap = sock_no_mmap | ||
167 | }; | 200 | }; |
168 | 201 | ||
169 | static struct proto bnep_proto = { | 202 | static struct proto bnep_proto = { |