diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2006-10-15 17:30:22 +0200 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-15 23:14:27 -0700 |
commit | e9c5702e3c5558dade169949abd730173e87ef9c (patch) | |
tree | 58ec8dcd1497b51e1d6a447d8c4a34a0bd2f108d /net/bluetooth/bnep | |
parent | 39c850863d5e36e72ecf9bc3537ec717bcce97fd (diff) | |
download | kernel-crypto-e9c5702e3c5558dade169949abd730173e87ef9c.tar.gz kernel-crypto-e9c5702e3c5558dade169949abd730173e87ef9c.tar.xz kernel-crypto-e9c5702e3c5558dade169949abd730173e87ef9c.zip |
[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 28c55835422..5d9d6f14b31 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -43,6 +43,7 @@ #include <linux/ioctl.h> #include <linux/file.h> #include <linux/init.h> +#include <linux/compat.h> #include <net/sock.h> #include <asm/system.h> @@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long return 0; } +#ifdef CONFIG_COMPAT +static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + if (cmd == BNEPGETCONNLIST) { + struct bnep_connlist_req cl; + uint32_t uci; + int err; + + if (get_user(cl.cnum, (uint32_t __user *) arg) || + get_user(uci, (u32 __user *) (arg + 4))) + return -EFAULT; + + cl.ci = compat_ptr(uci); + + if (cl.cnum <= 0) + return -EINVAL; + + err = bnep_get_connlist(&cl); + + if (!err && put_user(cl.cnum, (uint32_t __user *) arg)) + err = -EFAULT; + + return err; + } + + return bnep_sock_ioctl(sock, cmd, arg); +} +#endif + static const struct proto_ops bnep_sock_ops = { - .family = PF_BLUETOOTH, - .owner = THIS_MODULE, - .release = bnep_sock_release, - .ioctl = bnep_sock_ioctl, - .bind = sock_no_bind, - .getname = sock_no_getname, - .sendmsg = sock_no_sendmsg, - .recvmsg = sock_no_recvmsg, - .poll = sock_no_poll, - .listen = sock_no_listen, - .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt, - .connect = sock_no_connect, - .socketpair = sock_no_socketpair, - .accept = sock_no_accept, - .mmap = sock_no_mmap + .family = PF_BLUETOOTH, + .owner = THIS_MODULE, + .release = bnep_sock_release, + .ioctl = bnep_sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = bnep_sock_compat_ioctl, +#endif + .bind = sock_no_bind, + .getname = sock_no_getname, + .sendmsg = sock_no_sendmsg, + .recvmsg = sock_no_recvmsg, + .poll = sock_no_poll, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .mmap = sock_no_mmap }; static struct proto bnep_proto = { |