From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51118) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WyUAV-0004y1-Qv for qemu-devel@nongnu.org; Sat, 21 Jun 2014 18:54:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WyUAP-0005aJ-QJ for qemu-devel@nongnu.org; Sat, 21 Jun 2014 18:53:55 -0400 Received: from mail-wi0-x229.google.com ([2a00:1450:400c:c05::229]:56074) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WyUAP-0005ZX-GH for qemu-devel@nongnu.org; Sat, 21 Jun 2014 18:53:49 -0400 Received: by mail-wi0-f169.google.com with SMTP id hi2so2477584wib.4 for ; Sat, 21 Jun 2014 15:53:47 -0700 (PDT) Sender: Paul Burton From: Paul Burton Date: Sat, 21 Jun 2014 23:53:00 +0100 Message-Id: <1403391191-18603-6-git-send-email-paul@archlinuxmips.org> In-Reply-To: <1403391191-18603-1-git-send-email-paul@archlinuxmips.org> References: <1403391191-18603-1-git-send-email-paul@archlinuxmips.org> Subject: [Qemu-devel] [PATCH v2 05/16] 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: Riku Voipio , 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 for good measure. Signed-off-by: Paul Burton --- Changes in v2: - None. --- linux-user/syscall.c | 68 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7da21c7..3861f0f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5563,29 +5563,53 @@ 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 = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL)); + else + ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5))); + + 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