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: Paul Burton <paul@archlinuxmips.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
parent
82d0fe6b7a
commit
356d771b30
@ -5614,29 +5614,60 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case TARGET_NR_mount:
|
case TARGET_NR_mount:
|
||||||
{
|
{
|
||||||
/* need to look at the data field */
|
/* need to look at the data field */
|
||||||
void *p2, *p3;
|
void *p2, *p3;
|
||||||
p = lock_user_string(arg1);
|
|
||||||
p2 = lock_user_string(arg2);
|
if (arg1) {
|
||||||
p3 = lock_user_string(arg3);
|
p = lock_user_string(arg1);
|
||||||
if (!p || !p2 || !p3)
|
if (!p) {
|
||||||
ret = -TARGET_EFAULT;
|
goto efault;
|
||||||
else {
|
}
|
||||||
/* FIXME - arg5 should be locked, but it isn't clear how to
|
} else {
|
||||||
* do that since it's not guaranteed to be a NULL-terminated
|
p = NULL;
|
||||||
* string.
|
}
|
||||||
*/
|
|
||||||
if ( ! arg5 )
|
p2 = lock_user_string(arg2);
|
||||||
ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL));
|
if (!p2) {
|
||||||
else
|
if (arg1) {
|
||||||
ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
|
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(p, arg1, 0);
|
||||||
unlock_user(p2, arg2, 0);
|
}
|
||||||
unlock_user(p3, arg3, 0);
|
unlock_user(p2, arg2, 0);
|
||||||
break;
|
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
|
#ifdef TARGET_NR_umount
|
||||||
case TARGET_NR_umount:
|
case TARGET_NR_umount:
|
||||||
if (!(p = lock_user_string(arg1)))
|
if (!(p = lock_user_string(arg1)))
|
||||||
|
Loading…
Reference in New Issue
Block a user