From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55667) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wz4Gm-0003iN-Qw for qemu-devel@nongnu.org; Mon, 23 Jun 2014 09:26:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wz4Gd-0001Bg-LW for qemu-devel@nongnu.org; Mon, 23 Jun 2014 09:26:48 -0400 Received: from [2001:4b98:dc0:45:216:3eff:fe3d:166f] (port=37360 helo=afflict.kos.to) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wz4Gd-0001AW-Cg for qemu-devel@nongnu.org; Mon, 23 Jun 2014 09:26:39 -0400 From: riku.voipio@linaro.org Date: Mon, 23 Jun 2014 16:26:23 +0300 Message-Id: In-Reply-To: References: Subject: [Qemu-devel] [PULL 08/19] linux-user: allow NULL arguments to mount List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Paul Burton From: Paul Burton Calls to the mount syscall can legitimately provide NULL as the value for the source of filesystemtype arguments, which QEMU would previously reject & return -EFAULT to the target program. An example of this is remounting an already mounted filesystem with different properties. Instead of rejecting such syscalls with -EFAULT, pass NULL along to the kernel as the target program expects. Additionally this patch fixes a potential memory leak when DEBUG_REMAP is enabled and lock_user_string fails on the target or filesystemtype arguments but a prior argument was non-NULL and already locked. Since the patch already touched most lines of the TARGET_NR_mount case, it fixes the indentation & coding style for good measure. Signed-off-by: Paul Burton Signed-off-by: Riku Voipio --- linux-user/syscall.c | 75 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3971cb5..4e48af6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5614,29 +5614,60 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_mount: - { - /* need to look at the data field */ - void *p2, *p3; - p = lock_user_string(arg1); - p2 = lock_user_string(arg2); - p3 = lock_user_string(arg3); - if (!p || !p2 || !p3) - ret = -TARGET_EFAULT; - else { - /* FIXME - arg5 should be locked, but it isn't clear how to - * do that since it's not guaranteed to be a NULL-terminated - * string. - */ - if ( ! arg5 ) - ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL)); - else - ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5))); - } + { + /* need to look at the data field */ + void *p2, *p3; + + if (arg1) { + p = lock_user_string(arg1); + if (!p) { + goto efault; + } + } else { + p = NULL; + } + + p2 = lock_user_string(arg2); + if (!p2) { + if (arg1) { + unlock_user(p, arg1, 0); + } + goto efault; + } + + if (arg3) { + p3 = lock_user_string(arg3); + if (!p3) { + if (arg1) { unlock_user(p, arg1, 0); - unlock_user(p2, arg2, 0); - unlock_user(p3, arg3, 0); - break; - } + } + unlock_user(p2, arg2, 0); + goto efault; + } + } else { + p3 = NULL; + } + + /* FIXME - arg5 should be locked, but it isn't clear how to + * do that since it's not guaranteed to be a NULL-terminated + * string. + */ + if (!arg5) { + ret = mount(p, p2, p3, (unsigned long)arg4, NULL); + } else { + ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)); + } + ret = get_errno(ret); + + if (arg1) { + unlock_user(p, arg1, 0); + } + unlock_user(p2, arg2, 0); + if (arg3) { + unlock_user(p3, arg3, 0); + } + } + break; #ifdef TARGET_NR_umount case TARGET_NR_umount: if (!(p = lock_user_string(arg1))) -- 2.0.0