Commit 356d771b authored by Paul Burton's avatar Paul Burton Committed by Riku Voipio
Browse files

linux-user: allow NULL arguments to mount



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: default avatarPaul Burton <paul@archlinuxmips.org>
Signed-off-by: default avatarRiku Voipio <riku.voipio@linaro.org>
parent 82d0fe6b
Loading
Loading
Loading
Loading
+53 −22
Original line number Diff line number Diff line
@@ -5617,26 +5617,57 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
        {
            /* 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 (!p || !p2 || !p3)
                            ret = -TARGET_EFAULT;
                        else {
                if (!p3) {
                    if (arg1) {
                        unlock_user(p, arg1, 0);
                    }
                    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 (!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;
            }
        }
        break;
#ifdef TARGET_NR_umount
    case TARGET_NR_umount:
        if (!(p = lock_user_string(arg1)))