[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 06/24] linux-user: fix readlink handling with magic e
From: |
riku . voipio |
Subject: |
[Qemu-devel] [PULL 06/24] linux-user: fix readlink handling with magic exe symlink |
Date: |
Fri, 15 Aug 2014 14:01:24 +0300 |
From: Mike Frysinger <address@hidden>
The current code always returns the length of the path when it should
be returning the number of bytes it wrote to the output string.
Further, readlink is not supposed to append a NUL byte, but the current
snprintf logic will always do just that.
Even further, if you pass in a length of 0, you're suppoesd to get back
an error (EINVAL), but the current logic just returns 0.
Further still, if there was an error reading the symlink, we should not
go ahead and try to read the target buffer as it is garbage.
Simple test for the first two issues:
$ cat test.c
int main() {
char buf[50];
size_t len;
for (len = 0; len < 10; ++len) {
memset(buf, '!', sizeof(buf));
ssize_t ret = readlink("/proc/self/exe", buf, len);
buf[20] = '\0';
printf("readlink(/proc/self/exe, {%s}, %zu) = %zi\n", buf, len, ret);
}
return 0;
}
Now compare the output of the native:
$ gcc test.c -o /tmp/x
$ /tmp/x
$ strace /tmp/x
With what qemu does:
$ armv7a-cros-linux-gnueabi-gcc test.c -o /tmp/x -static
$ qemu-arm /tmp/x
$ qemu-arm -strace /tmp/x
Signed-off-by: Mike Frysinger <address@hidden>
Signed-off-by: Riku Voipio <address@hidden>
---
linux-user/syscall.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fccf9f0..7c108ab 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6636,11 +6636,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
if (!p || !p2) {
ret = -TARGET_EFAULT;
+ } else if (!arg3) {
+ /* Short circuit this for the magic exe check. */
+ ret = -TARGET_EINVAL;
} else if (is_proc_myself((const char *)p, "exe")) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
- ret = temp == NULL ? get_errno(-1) : strlen(real) ;
- snprintf((char *)p2, arg3, "%s", real);
+ /* Return value is # of bytes that we wrote to the buffer. */
+ if (temp == NULL) {
+ ret = get_errno(-1);
+ } else {
+ /* Don't worry about sign mismatch as earlier mapping
+ * logic would have thrown a bad address error. */
+ ret = MIN(strlen(real), arg3);
+ /* We cannot NUL terminate the string. */
+ memcpy(p2, real, ret);
+ }
} else {
ret = get_errno(readlink(path(p), p2, arg3));
}
--
2.0.1
- [Qemu-devel] [PULL 00/24] Linux-user updates, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 02/24] linux-user: redirect openat calls, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 09/24] linux-user: support {name_to, open_by}_handle_at syscalls, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 06/24] linux-user: fix readlink handling with magic exe symlink,
riku . voipio <=
- [Qemu-devel] [PULL 16/24] linux-user: Detect Negative Message Sizes in msgsnd System Call, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 07/24] linux-user: support timerfd_{create, gettime, settime} syscalls, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 11/24] linux-user: PPC64 semid_ds Doesnt Include _unused1 and _unused2, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 13/24] linux-user: Properly Handle semun Structure In Cross-Endian Situations, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 17/24] linux-user: Handle NULL sched_param argument to sched_*, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 05/24] linux-user: Fix conversion of sigevent argument to timer_create, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 14/24] linux-user: Make ipc syscall's third argument an abi_long, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 03/24] linux-user: make binfmt flag O require P, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 10/24] linux-user: add setns and unshare, riku . voipio, 2014/08/15
- [Qemu-devel] [PULL 08/24] linux-user: support ioprio_{get, set} syscalls, riku . voipio, 2014/08/15