firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases
A message that is not in the archive (sent off-list or not yet received): CADmzSSh_gRKxjGNk7c938mhZQhe3N-18KJrqq4UpG8L6FcCQDQ@mail.gmail.com
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): 20110809221719.74e29be5@stein
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): 20110810163444.768d583d@stein
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): 20110810234635.11ea2ea1@stein
PATCH 1/1 firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases
Clemens points out that we need to use compat_ptr() in order to safely cast from u64 to addresses of a 32-bit usermode client.
Before, our conversion went wrong
- in practice if the client cast from pointer to integer such that sign-extension happened, (libraw1394 and libdc1394 at least were not doing that, IOW were not affected)
or
- in theory on s390 (which doesn't have FireWire though) and on the tile architecture, regardless of what the client does.
The bug would usually be observed as the initial get_info ioctl failing with "Bad address" (EFAULT).
--- drivers/firewire/core-cdev.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
drivers/firewire/core-cdev.c +21 -3
@@ -216,15 +216,33 @@ struct inbound_phy_packet_event {struct fw_cdev_event_phy_packet phy_packet; }; -static inline void __user *u64_to_uptr (__u64 value) +#ifdef CONFIG_COMPAT +static void __user *u64_to_uptr (u64 value) +{ +if (is_compat_task ()) +return compat_ptr (value); +else +return (void __user *)(unsigned long )value; +} + +static u64 uptr_to_u64 (void __user *ptr) +{ +if (is_compat_task ()) +return ptr_to_compat (ptr); +else +return (u64 )(unsigned long )ptr; +} +#else +static inline void __user *u64_to_uptr (u64 value) {return (void __user *)(unsigned long )value; } -static inline __u64 uptr_to_u64 (void __user *ptr) +static inline u64 uptr_to_u64 (void __user *ptr) { -return (__u64 )(unsigned long )ptr; +return (u64 )(unsigned long )ptr; } +#endif /* CONFIG_COMPAT */ static int fw_device_op_open (struct inode *inode,struct file *file) {
Signature · 3 lines
Stefan Richter -=====-==-== =--- -=-=- http://arcgraph.de/sr/