From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1946061Ab2CPXhy (ORCPT ); Fri, 16 Mar 2012 19:37:54 -0400 Received: from mail-pz0-f46.google.com ([209.85.210.46]:49074 "EHLO mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1946031Ab2CPXhu (ORCPT ); Fri, 16 Mar 2012 19:37:50 -0400 Message-Id: <20120316233447.832020745@linuxfoundation.org> User-Agent: quilt/0.60-19.1 Date: Fri, 16 Mar 2012 16:34:53 -0700 From: Greg KH To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Carl Karsten , Clemens Ladisch , Stefan Richter Subject: [ 06/38] firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases In-Reply-To: <20120316233422.GA5461@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.0-stable review patch. If anyone has any objections, please let me know. ------------------ From: Stefan Richter commit 9c1176b6a28850703ea6e3a0f0c703f6d6c61cd3 upstream. 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). Reported-by: Carl Karsten Reported-by: Clemens Ladisch Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/core-cdev.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -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) {