new file mode 100644
@@ -0,0 +1,7 @@
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_NATIVE_CALL)
+extern char *native_lib_path;
+/* Check if the native-bypass option is enabled. */
+#define native_bypass_enabled() (native_lib_path != NULL)
+#else
+#define native_bypass_enabled() false
+#endif
@@ -60,6 +60,11 @@
#include "semihosting/semihost.h"
#endif
+#if defined(CONFIG_NATIVE_CALL)
+#include "native/native.h"
+char *native_lib_path;
+#endif
+
#ifndef AT_FLAGS_PRESERVE_ARGV0
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
@@ -293,6 +298,17 @@ static void handle_arg_set_env(const char *arg)
free(r);
}
+#if defined(CONFIG_NATIVE_CALL)
+static void handle_arg_native_bypass(const char *arg)
+{
+ if (!g_file_test(arg, G_FILE_TEST_IS_REGULAR)) {
+ fprintf(stderr, "native library %s does not exist\n", arg);
+ exit(EXIT_FAILURE);
+ }
+ native_lib_path = g_strdup(arg);
+}
+#endif
+
static void handle_arg_unset_env(const char *arg)
{
char *r, *p, *token;
@@ -522,6 +538,10 @@ static const struct qemu_argument arg_table[] = {
"", "Generate a /tmp/perf-${pid}.map file for perf"},
{"jitdump", "QEMU_JITDUMP", false, handle_arg_jitdump,
"", "Generate a jit-${pid}.dump file for perf"},
+#if defined(CONFIG_NATIVE_CALL)
+ {"native-bypass", "QEMU_NATIVE_BYPASS", true, handle_arg_native_bypass,
+ "", "native bypass for library calls"},
+#endif
{NULL, NULL, false, NULL, NULL, NULL}
};
@@ -143,6 +143,7 @@
#include "fd-trans.h"
#include "tcg/tcg.h"
#include "cpu_loop-common.h"
+#include "native/native.h"
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
@@ -8503,6 +8504,40 @@ static int open_hardware(CPUArchState *cpu_env, int fd)
}
#endif
+#if defined(CONFIG_NATIVE_CALL)
+static int is_ld_so_preload(const char *filename, const char *entry)
+{
+ if (native_bypass_enabled() && !strcmp(filename, entry)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* This function is only called when the "native-bypass" option is provided. */
+static int open_ld_so_preload(CPUArchState *cpu_env, int fd)
+{
+ FILE *fp;
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read;
+
+ dprintf(fd, "%s\n", native_lib_path);
+ fp = fopen("/etc/ld.so.preload", "r");
+ if (fp == NULL) {
+ return 0;
+ }
+
+ while ((read = getline(&line, &len, fp)) != -1) {
+ dprintf(fd, "%s", line);
+ }
+
+ free(line);
+ fclose(fp);
+
+ return 0;
+}
+#endif
+
int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname,
int flags, mode_t mode, bool safe)
{
@@ -8527,6 +8562,9 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname,
#endif
#if defined(TARGET_M68K)
{ "/proc/hardware", open_hardware, is_proc },
+#endif
+#if defined(CONFIG_NATIVE_CALL)
+ { "/etc/ld.so.preload", open_ld_so_preload, is_ld_so_preload },
#endif
{ NULL, NULL, NULL }
};
@@ -9523,6 +9561,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return -TARGET_EFAULT;
}
ret = get_errno(access(path(p), arg2));
+ if (ret != 0 && native_bypass_enabled()) {
+ if (strcmp(p, "/etc/ld.so.preload") == 0 && arg2 == R_OK) {
+ return 0;
+ }
+ }
unlock_user(p, arg1, 0);
return ret;
#endif
@@ -9532,6 +9575,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return -TARGET_EFAULT;
}
ret = get_errno(faccessat(arg1, p, arg3, 0));
+ if (ret != 0 && native_bypass_enabled()) {
+ if (strcmp(p, "/etc/ld.so.preload") == 0 && arg1 == AT_FDCWD &&
+ arg3 == R_OK) {
+ return 0;
+ }
+ }
unlock_user(p, arg2, 0);
return ret;
#endif
@@ -9541,6 +9590,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return -TARGET_EFAULT;
}
ret = get_errno(faccessat(arg1, p, arg3, arg4));
+ if (ret != 0 && native_bypass_enabled()) {
+ if (strcmp(p, "/etc/ld.so.preload") == 0 && arg1 == AT_FDCWD &&
+ arg3 == R_OK) {
+ return 0;
+ }
+ }
unlock_user(p, arg2, 0);
return ret;
#endif
This commit implements support for the native-bypass option in linux-user. By utilizing this functionality, the specified shared library can be loaded into the user program. This is achieved by dynamically modifying the /etc/ld.so.preload file, enabling the user program to load the shared library effortlessly. Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com> --- include/native/native.h | 7 ++++++ linux-user/main.c | 20 +++++++++++++++ linux-user/syscall.c | 55 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 include/native/native.h