854d244b76
for update_git.sh OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=62
86 lines
2.8 KiB
Diff
86 lines
2.8 KiB
Diff
From a1508f441692e958ee11ac10648ed7941c242be8 Mon Sep 17 00:00:00 2001
|
|
From: Alexander Graf <agraf@suse.de>
|
|
Date: Wed, 2 Nov 2011 09:23:23 +0000
|
|
Subject: [PATCH] linux-user: add open() hijack infrastructure
|
|
|
|
There are a number of files in /proc that expose host information
|
|
to the guest program. This patch adds infrastructure to override
|
|
the open() syscall for guest programs to enable us to on the fly
|
|
generate guest sensible files.
|
|
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
linux-user/syscall.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++--
|
|
1 files changed, 49 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
|
index f170724..1ecc0e1 100644
|
|
--- a/linux-user/syscall.c
|
|
+++ b/linux-user/syscall.c
|
|
@@ -4603,6 +4603,52 @@ int get_osversion(void)
|
|
return osversion;
|
|
}
|
|
|
|
+static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
|
+{
|
|
+ struct fake_open {
|
|
+ const char *filename;
|
|
+ int (*fill)(void *cpu_env, int fd);
|
|
+ };
|
|
+ const struct fake_open *fake_open;
|
|
+ static const struct fake_open fakes[] = {
|
|
+ { NULL, NULL }
|
|
+ };
|
|
+
|
|
+ for (fake_open = fakes; fake_open->filename; fake_open++) {
|
|
+ if (!strncmp(pathname, fake_open->filename,
|
|
+ strlen(fake_open->filename))) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (fake_open->filename) {
|
|
+ const char *tmpdir;
|
|
+ char filename[PATH_MAX];
|
|
+ int fd, r;
|
|
+
|
|
+ /* create temporary file to map stat to */
|
|
+ tmpdir = getenv("TMPDIR");
|
|
+ if (!tmpdir)
|
|
+ tmpdir = "/tmp";
|
|
+ snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
|
|
+ fd = mkstemp(filename);
|
|
+ if (fd < 0) {
|
|
+ return fd;
|
|
+ }
|
|
+ unlink(filename);
|
|
+
|
|
+ if ((r = fake_open->fill(cpu_env, fd))) {
|
|
+ close(fd);
|
|
+ return r;
|
|
+ }
|
|
+ lseek(fd, 0, SEEK_SET);
|
|
+
|
|
+ return fd;
|
|
+ }
|
|
+
|
|
+ return get_errno(open(path(pathname), flags, mode));
|
|
+}
|
|
+
|
|
/* do_syscall() should always have a single exit point at the end so
|
|
that actions, such as logging of syscall results, can be performed.
|
|
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
|
@@ -4688,9 +4734,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
case TARGET_NR_open:
|
|
if (!(p = lock_user_string(arg1)))
|
|
goto efault;
|
|
- ret = get_errno(open(path(p),
|
|
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
|
- arg3));
|
|
+ ret = get_errno(do_open(cpu_env, p,
|
|
+ target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
|
+ arg3));
|
|
unlock_user(p, arg1, 0);
|
|
break;
|
|
#if defined(TARGET_NR_openat) && defined(__NR_openat)
|