* [PATCH] fixed proc myself (linux user) for musl
@ 2020-08-16 19:58 Андрей Аладьев
2020-08-16 21:42 ` Philippe Mathieu-Daudé
2020-08-17 15:12 ` Laurent Vivier
0 siblings, 2 replies; 5+ messages in thread
From: Андрей Аладьев @ 2020-08-16 19:58 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 14464 bytes --]
From: Andrew Aladjev <aladjev.andrew@gmail.com>
Date: Sun, 16 Aug 2020 22:50:13 +0300
Subject: [PATCH] fixed proc myself (linux user) for musl
Buglink: https://bugs.gentoo.org/587230
Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com>
---
linux-user/Makefile.objs | 5 +-
linux-user/elfload.c | 7 ++-
linux-user/exit.c | 7 ++-
linux-user/main.c | 2 +-
linux-user/qemu.h | 1 +
linux-user/syscall.c | 85 +++++++++++++---------------------
linux-user/syscall_proc.c | 96 +++++++++++++++++++++++++++++++++++++++
linux-user/syscall_proc.h | 8 ++++
8 files changed, 150 insertions(+), 61 deletions(-)
create mode 100644 linux-user/syscall_proc.c
create mode 100644 linux-user/syscall_proc.h
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
index 1940910a73..ad84380738 100644
--- a/linux-user/Makefile.objs
+++ b/linux-user/Makefile.objs
@@ -1,7 +1,8 @@
obj-y = main.o syscall.o strace.o mmap.o signal.o \
elfload.o linuxload.o uaccess.o uname.o \
- safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
- $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o
+ safe-syscall.o syscall_proc.o \
+ $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \
+ exit.o fd-trans.o
obj-$(TARGET_HAS_BFLT) += flatload.o
obj-$(TARGET_I386) += vm86.o
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 619c054cc4..201db61d91 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2319,7 +2319,10 @@ exit_errmsg:
buffer is sufficiently aligned to present no problems to the host
in accessing data at aligned offsets within the buffer.
- On return: INFO values will be filled in, as necessary or available. */
+ On return: INFO values will be filled in, as necessary or available.
+
+ WARNING: this function won't close "image_fd".
+*/
static void load_elf_image(const char *image_name, int image_fd,
struct image_info *info, char **pinterp_name,
@@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name,
int image_fd,
mmap_unlock();
- close(image_fd);
return;
exit_read:
@@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename,
struct image_info *info,
}
load_elf_image(filename, fd, info, NULL, bprm_buf);
+ close(fd);
return;
exit_perror:
diff --git a/linux-user/exit.c b/linux-user/exit.c
index 1594015444..f0626fc432 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -28,12 +28,15 @@ extern void __gcov_dump(void);
void preexit_cleanup(CPUArchState *env, int code)
{
+ close(execfd);
+
#ifdef CONFIG_GPROF
_mcleanup();
#endif
#ifdef CONFIG_GCOV
__gcov_dump();
#endif
- gdb_exit(env, code);
- qemu_plugin_atexit_cb();
+
+ gdb_exit(env, code);
+ qemu_plugin_atexit_cb();
}
diff --git a/linux-user/main.c b/linux-user/main.c
index 22578b1633..9cc6c1e6da 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -48,6 +48,7 @@
#include "crypto/init.h"
char *exec_path;
+int execfd;
int singlestep;
static const char *argv0;
@@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp)
int target_argc;
int i;
int ret;
- int execfd;
int log_mask;
unsigned long max_reserved_va;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 792c74290f..d822f2b9df 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -156,6 +156,7 @@ typedef struct TaskState {
} __attribute__((aligned(16))) TaskState;
extern char *exec_path;
+extern int execfd;
void init_task_state(TaskState *ts);
void task_settid(TaskState *);
void stop_all_tasks(void);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 05f03919ff..483a735c1a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -122,6 +122,7 @@
#include "qapi/error.h"
#include "fd-trans.h"
#include "tcg/tcg.h"
+#include "syscall_proc.h"
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
@@ -1104,7 +1105,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
target_rlim)
{
abi_ulong target_rlim_swap;
rlim_t result;
-
+
target_rlim_swap = tswapal(target_rlim);
if (target_rlim_swap == TARGET_RLIM_INFINITY)
return RLIM_INFINITY;
@@ -1112,7 +1113,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
target_rlim)
result = target_rlim_swap;
if (target_rlim_swap != (rlim_t)result)
return RLIM_INFINITY;
-
+
return result;
}
#endif
@@ -1122,13 +1123,13 @@ static inline abi_ulong host_to_target_rlim(rlim_t
rlim)
{
abi_ulong target_rlim_swap;
abi_ulong result;
-
+
if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
target_rlim_swap = TARGET_RLIM_INFINITY;
else
target_rlim_swap = rlim;
result = tswapal(target_rlim_swap);
-
+
return result;
}
#endif
@@ -1615,9 +1616,9 @@ static inline abi_long target_to_host_cmsg(struct
msghdr *msgh,
abi_ulong target_cmsg_addr;
struct target_cmsghdr *target_cmsg, *target_cmsg_start;
socklen_t space = 0;
-
+
msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
target_cmsg_addr = tswapal(target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen,
1);
@@ -1703,7 +1704,7 @@ static inline abi_long host_to_target_cmsg(struct
target_msghdr *target_msgh,
socklen_t space = 0;
msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
target_cmsg_addr = tswapal(target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
msg_controllen, 0);
@@ -5750,7 +5751,7 @@ abi_long do_set_thread_area(CPUX86State *env,
abi_ulong ptr)
}
unlock_user_struct(target_ldt_info, ptr, 1);
- if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
+ if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
return -TARGET_EINVAL;
seg_32bit = ldt_info.flags & 1;
@@ -5828,7 +5829,7 @@ static abi_long do_get_thread_area(CPUX86State *env,
abi_ulong ptr)
lp = (uint32_t *)(gdt_table + idx);
entry_1 = tswap32(lp[0]);
entry_2 = tswap32(lp[1]);
-
+
read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
contents = (entry_2 >> 10) & 3;
seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
@@ -5844,8 +5845,8 @@ static abi_long do_get_thread_area(CPUX86State *env,
abi_ulong ptr)
(read_exec_only << 3) | (limit_in_pages << 4) |
(seg_not_present << 5) | (useable << 6) | (lm << 7);
limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
- base_addr = (entry_1 >> 16) |
- (entry_2 & 0xff000000) |
+ base_addr = (entry_1 >> 16) |
+ (entry_2 & 0xff000000) |
((entry_2 & 0xff) << 16);
target_ldt_info->base_addr = tswapal(base_addr);
target_ldt_info->limit = tswap32(limit);
@@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd)
return 0;
}
-static int is_proc_myself(const char *filename, const char *entry)
-{
- if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
- filename += strlen("/proc/");
- if (!strncmp(filename, "self/", strlen("self/"))) {
- filename += strlen("self/");
- } else if (*filename >= '1' && *filename <= '9') {
- char myself[80];
- snprintf(myself, sizeof(myself), "%d/", getpid());
- if (!strncmp(filename, myself, strlen(myself))) {
- filename += strlen(myself);
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- if (!strcmp(filename, entry)) {
- return 1;
- }
- }
- return 0;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
- defined(TARGET_SPARC) || defined(TARGET_M68K)
-static int is_proc(const char *filename, const char *entry)
-{
- return strcmp(filename, entry) == 0;
-}
-#endif
-
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
static int open_net_route(void *cpu_env, int fd)
{
@@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd,
const char *pathname, int flags,
{ "auxv", open_self_auxv, is_proc_myself },
{ "cmdline", open_self_cmdline, is_proc_myself },
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
- { "/proc/net/route", open_net_route, is_proc },
+ { "net/route", open_net_route, is_proc },
#endif
#if defined(TARGET_SPARC)
- { "/proc/cpuinfo", open_cpuinfo, is_proc },
+ { "cpuinfo", open_cpuinfo, is_proc },
#endif
#if defined(TARGET_M68K)
- { "/proc/hardware", open_hardware, is_proc },
+ { "hardware", open_hardware, is_proc },
#endif
{ NULL, NULL, NULL }
};
- if (is_proc_myself(pathname, "exe")) {
- int execfd = qemu_getauxval(AT_EXECFD);
- return execfd ? execfd : safe_openat(dirfd, exec_path, flags,
mode);
+ if (is_proc_myself_exe(pathname)) {
+ return execfd;
}
for (fake_open = fakes; fake_open->filename; fake_open++) {
@@ -7728,8 +7696,17 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
return ret;
#endif
case TARGET_NR_close:
- fd_trans_unregister(arg1);
- return get_errno(close(arg1));
+ {
+ int fd = arg1;
+ if (fd == execfd) {
+ // We don't need to close execfd.
+ // It will be closed on qemu exit.
+ return 0;
+ }
+
+ fd_trans_unregister(fd);
+ return get_errno(close(fd));
+ }
case TARGET_NR_brk:
return do_brk(arg1);
@@ -9031,7 +9008,7 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
} else if (!arg3) {
/* Short circuit this for the magic exe check. */
ret = -TARGET_EINVAL;
- } else if (is_proc_myself((const char *)p, "exe")) {
+ } else if (is_proc_myself_exe((const char *)p)) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
/* Return value is # of bytes that we wrote to the buffer.
*/
@@ -9060,7 +9037,7 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!p || !p2) {
ret = -TARGET_EFAULT;
- } else if (is_proc_myself((const char *)p, "exe")) {
+ } else if (is_proc_myself_exe((const char *)p)) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
@@ -10847,7 +10824,7 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
return get_errno(fchown(arg1, low2highuid(arg2),
low2highgid(arg3)));
#if defined(TARGET_NR_fchownat)
case TARGET_NR_fchownat:
- if (!(p = lock_user_string(arg2)))
+ if (!(p = lock_user_string(arg2)))
return -TARGET_EFAULT;
ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
low2highgid(arg4), arg5));
diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c
new file mode 100644
index 0000000000..e85ca99c16
--- /dev/null
+++ b/linux-user/syscall_proc.c
@@ -0,0 +1,96 @@
+#include "qemu/osdep.h"
+#include "elf.h"
+
+#include "syscall_proc.h"
+#include "qemu.h"
+
+#define PROC "/proc/"
+#define SELF "self/"
+
+#define STARTS_WITH(path, CONSTANT) \
+ strlen(path) >= strlen(CONSTANT) && strncmp(path, CONSTANT,
strlen(CONSTANT)) == 0
+
+static inline char *scope_to_proc(const char *path)
+{
+ if (STARTS_WITH(path, PROC)) {
+ return (char *)path + strlen(PROC);
+ }
+
+ return NULL;
+}
+
+static inline char *scope_to_proc_myself(const char *path)
+{
+ char *scope_path = scope_to_proc(path);
+ if (scope_path == NULL) {
+ return NULL;
+ }
+
+ if (STARTS_WITH(scope_path, SELF)) {
+ return scope_path + strlen(SELF);
+ }
+
+ if (strlen(scope_path) >= 1 && *scope_path >= '1' && *scope_path <=
'9') {
+ char pid_path[80];
+ snprintf(pid_path, sizeof(pid_path), "%d/", getpid());
+ if (STARTS_WITH(scope_path, pid_path)) {
+ return scope_path + strlen(pid_path);
+ }
+ }
+
+ return NULL;
+}
+
+int is_proc(const char *path, const char *entry)
+{
+ char *scope_path = scope_to_proc(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ return strcmp(scope_path, entry) == 0;
+}
+
+int is_proc_myself(const char *path, const char *entry)
+{
+ char *scope_path = scope_to_proc_myself(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ return strcmp(scope_path, entry) == 0;
+}
+
+int is_proc_myself_exe(const char *path)
+{
+ char *scope_path = scope_to_proc_myself(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ // Kernel creates "fd/#{number}" link after opening "exe" link.
+ // Both "exe" and "fd/#{number}" can be used by application.
+
+ // Kernel can provide infinite amount of fd numbers.
+ // Qemu is going to always return single global execfd.
+
+ // So we need to check "exe" and "fd/#{execfd}" only.
+
+ if (strcmp(scope_path, "exe") == 0) {
+ return 1;
+ }
+
+ if (STARTS_WITH(scope_path, "fd/")) {
+ scope_path += strlen("fd/");
+
+ if (strlen(scope_path) >= 1 && *scope_path >= '1' && *scope_path
<= '9') {
+ char execfd_path[80];
+ snprintf(execfd_path, sizeof(execfd_path), "%d", execfd);
+ if (strcmp(scope_path, execfd_path) == 0) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
new file mode 100644
index 0000000000..f0e59c0e96
--- /dev/null
+++ b/linux-user/syscall_proc.h
@@ -0,0 +1,8 @@
+#ifndef SYSCALL_PROC_H
+#define SYSCALL_PROC_H
+
+int is_proc(const char *path, const char *entry);
+int is_proc_myself(const char *path, const char *entry);
+int is_proc_myself_exe(const char *path);
+
+#endif
--
2.26.2
[-- Attachment #2: Type: text/html, Size: 17692 bytes --]
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fixed proc myself (linux user) for musl
2020-08-16 19:58 [PATCH] fixed proc myself (linux user) for musl Андрей Аладьев
@ 2020-08-16 21:42 ` Philippe Mathieu-Daudé
2020-08-16 22:21 ` Андрей Аладьев
2020-08-17 15:12 ` Laurent Vivier
1 sibling, 1 reply; 5+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-08-16 21:42 UTC (permalink / raw)
To: Андрей
Аладьев,
qemu-devel, Laurent Vivier, Richard Henderson
Hi Andrew,
Cc'ing the maintainer & Richard.
./scripts/get_maintainer.pl -f linux-user/main.c
Laurent Vivier <laurent@vivier.eu> (maintainer:Linux user)
On 8/16/20 9:58 PM, Андрей Аладьев wrote:
> From: Andrew Aladjev <aladjev.andrew@gmail.com
> <mailto:aladjev.andrew@gmail.com>>
> Date: Sun, 16 Aug 2020 22:50:13 +0300
> Subject: [PATCH] fixed proc myself (linux user) for musl
Your patch has double subject headers...
This link might be helpful:
https://wiki.qemu.org/Contribute/SubmitAPatch#Use_git_format-patch
> Buglink: https://bugs.gentoo.org/587230
> Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com
> <mailto:aladjev.andrew@gmail.com>>
Hmmm did you paste the output of git-format-patch in your
email client?
> ---
> linux-user/Makefile.objs | 5 +-
> linux-user/elfload.c | 7 ++-
> linux-user/exit.c | 7 ++-
> linux-user/main.c | 2 +-
> linux-user/qemu.h | 1 +
> linux-user/syscall.c | 85 +++++++++++++---------------------
> linux-user/syscall_proc.c | 96 +++++++++++++++++++++++++++++++++++++++
> linux-user/syscall_proc.h | 8 ++++
> 8 files changed, 150 insertions(+), 61 deletions(-)
> create mode 100644 linux-user/syscall_proc.c
> create mode 100644 linux-user/syscall_proc.h
>
> diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
> index 1940910a73..ad84380738 100644
> --- a/linux-user/Makefile.objs
> +++ b/linux-user/Makefile.objs
> @@ -1,7 +1,8 @@
> obj-y = main.o syscall.o strace.o mmap.o signal.o \
> elfload.o linuxload.o uaccess.o uname.o \
> - safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
> - $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o
> + safe-syscall.o syscall_proc.o \
> + $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \
> + exit.o fd-trans.o
>
> obj-$(TARGET_HAS_BFLT) += flatload.o
> obj-$(TARGET_I386) += vm86.o
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 619c054cc4..201db61d91 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -2319,7 +2319,10 @@ exit_errmsg:
> buffer is sufficiently aligned to present no problems to the host
> in accessing data at aligned offsets within the buffer.
>
> - On return: INFO values will be filled in, as necessary or available. */
> + On return: INFO values will be filled in, as necessary or available.
> +
> + WARNING: this function won't close "image_fd".
> +*/
>
> static void load_elf_image(const char *image_name, int image_fd,
> struct image_info *info, char **pinterp_name,
> @@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name,
> int image_fd,
>
> mmap_unlock();
>
> - close(image_fd);
> return;
>
> exit_read:
> @@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename,
> struct image_info *info,
> }
>
> load_elf_image(filename, fd, info, NULL, bprm_buf);
> + close(fd);
> return;
>
> exit_perror:
> diff --git a/linux-user/exit.c b/linux-user/exit.c
> index 1594015444..f0626fc432 100644
> --- a/linux-user/exit.c
> +++ b/linux-user/exit.c
> @@ -28,12 +28,15 @@ extern void __gcov_dump(void);
>
> void preexit_cleanup(CPUArchState *env, int code)
> {
> + close(execfd);
> +
> #ifdef CONFIG_GPROF
> _mcleanup();
> #endif
> #ifdef CONFIG_GCOV
> __gcov_dump();
> #endif
> - gdb_exit(env, code);
> - qemu_plugin_atexit_cb();
> +
> + gdb_exit(env, code);
> + qemu_plugin_atexit_cb();
> }
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 22578b1633..9cc6c1e6da 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -48,6 +48,7 @@
> #include "crypto/init.h"
>
> char *exec_path;
> +int execfd;
>
> int singlestep;
> static const char *argv0;
> @@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp)
> int target_argc;
> int i;
> int ret;
> - int execfd;
> int log_mask;
> unsigned long max_reserved_va;
>
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 792c74290f..d822f2b9df 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -156,6 +156,7 @@ typedef struct TaskState {
> } __attribute__((aligned(16))) TaskState;
>
> extern char *exec_path;
> +extern int execfd;
> void init_task_state(TaskState *ts);
> void task_settid(TaskState *);
> void stop_all_tasks(void);
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 05f03919ff..483a735c1a 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -122,6 +122,7 @@
> #include "qapi/error.h"
> #include "fd-trans.h"
> #include "tcg/tcg.h"
> +#include "syscall_proc.h"
>
> #ifndef CLONE_IO
> #define CLONE_IO 0x80000000 /* Clone io context */
> @@ -1104,7 +1105,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> target_rlim)
> {
> abi_ulong target_rlim_swap;
> rlim_t result;
> -
> +
> target_rlim_swap = tswapal(target_rlim);
> if (target_rlim_swap == TARGET_RLIM_INFINITY)
> return RLIM_INFINITY;
> @@ -1112,7 +1113,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> target_rlim)
> result = target_rlim_swap;
> if (target_rlim_swap != (rlim_t)result)
> return RLIM_INFINITY;
> -
> +
> return result;
> }
> #endif
> @@ -1122,13 +1123,13 @@ static inline abi_ulong
> host_to_target_rlim(rlim_t rlim)
> {
> abi_ulong target_rlim_swap;
> abi_ulong result;
> -
> +
> if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
> target_rlim_swap = TARGET_RLIM_INFINITY;
> else
> target_rlim_swap = rlim;
> result = tswapal(target_rlim_swap);
> -
> +
> return result;
> }
> #endif
> @@ -1615,9 +1616,9 @@ static inline abi_long target_to_host_cmsg(struct
> msghdr *msgh,
> abi_ulong target_cmsg_addr;
> struct target_cmsghdr *target_cmsg, *target_cmsg_start;
> socklen_t space = 0;
> -
> +
> msg_controllen = tswapal(target_msgh->msg_controllen);
> - if (msg_controllen < sizeof (struct target_cmsghdr))
> + if (msg_controllen < sizeof (struct target_cmsghdr))
> goto the_end;
> target_cmsg_addr = tswapal(target_msgh->msg_control);
> target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr,
> msg_controllen, 1);
> @@ -1703,7 +1704,7 @@ static inline abi_long host_to_target_cmsg(struct
> target_msghdr *target_msgh,
> socklen_t space = 0;
>
> msg_controllen = tswapal(target_msgh->msg_controllen);
> - if (msg_controllen < sizeof (struct target_cmsghdr))
> + if (msg_controllen < sizeof (struct target_cmsghdr))
> goto the_end;
> target_cmsg_addr = tswapal(target_msgh->msg_control);
> target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
> msg_controllen, 0);
> @@ -5750,7 +5751,7 @@ abi_long do_set_thread_area(CPUX86State *env,
> abi_ulong ptr)
> }
> unlock_user_struct(target_ldt_info, ptr, 1);
>
> - if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> + if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
> return -TARGET_EINVAL;
> seg_32bit = ldt_info.flags & 1;
> @@ -5828,7 +5829,7 @@ static abi_long do_get_thread_area(CPUX86State
> *env, abi_ulong ptr)
> lp = (uint32_t *)(gdt_table + idx);
> entry_1 = tswap32(lp[0]);
> entry_2 = tswap32(lp[1]);
> -
> +
> read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
> contents = (entry_2 >> 10) & 3;
> seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
> @@ -5844,8 +5845,8 @@ static abi_long do_get_thread_area(CPUX86State
> *env, abi_ulong ptr)
> (read_exec_only << 3) | (limit_in_pages << 4) |
> (seg_not_present << 5) | (useable << 6) | (lm << 7);
> limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
> - base_addr = (entry_1 >> 16) |
> - (entry_2 & 0xff000000) |
> + base_addr = (entry_1 >> 16) |
> + (entry_2 & 0xff000000) |
> ((entry_2 & 0xff) << 16);
> target_ldt_info->base_addr = tswapal(base_addr);
> target_ldt_info->limit = tswap32(limit);
> @@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd)
> return 0;
> }
>
> -static int is_proc_myself(const char *filename, const char *entry)
> -{
> - if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
> - filename += strlen("/proc/");
> - if (!strncmp(filename, "self/", strlen("self/"))) {
> - filename += strlen("self/");
> - } else if (*filename >= '1' && *filename <= '9') {
> - char myself[80];
> - snprintf(myself, sizeof(myself), "%d/", getpid());
> - if (!strncmp(filename, myself, strlen(myself))) {
> - filename += strlen(myself);
> - } else {
> - return 0;
> - }
> - } else {
> - return 0;
> - }
> - if (!strcmp(filename, entry)) {
> - return 1;
> - }
> - }
> - return 0;
> -}
> -
> -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
> - defined(TARGET_SPARC) || defined(TARGET_M68K)
> -static int is_proc(const char *filename, const char *entry)
> -{
> - return strcmp(filename, entry) == 0;
> -}
> -#endif
> -
> #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> static int open_net_route(void *cpu_env, int fd)
> {
> @@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd,
> const char *pathname, int flags,
> { "auxv", open_self_auxv, is_proc_myself },
> { "cmdline", open_self_cmdline, is_proc_myself },
> #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> - { "/proc/net/route", open_net_route, is_proc },
> + { "net/route", open_net_route, is_proc },
> #endif
> #if defined(TARGET_SPARC)
> - { "/proc/cpuinfo", open_cpuinfo, is_proc },
> + { "cpuinfo", open_cpuinfo, is_proc },
> #endif
> #if defined(TARGET_M68K)
> - { "/proc/hardware", open_hardware, is_proc },
> + { "hardware", open_hardware, is_proc },
> #endif
> { NULL, NULL, NULL }
> };
>
> - if (is_proc_myself(pathname, "exe")) {
> - int execfd = qemu_getauxval(AT_EXECFD);
> - return execfd ? execfd : safe_openat(dirfd, exec_path, flags,
> mode);
> + if (is_proc_myself_exe(pathname)) {
> + return execfd;
> }
>
> for (fake_open = fakes; fake_open->filename; fake_open++) {
> @@ -7728,8 +7696,17 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> return ret;
> #endif
> case TARGET_NR_close:
> - fd_trans_unregister(arg1);
> - return get_errno(close(arg1));
> + {
> + int fd = arg1;
> + if (fd == execfd) {
> + // We don't need to close execfd.
> + // It will be closed on qemu exit.
> + return 0;
> + }
> +
> + fd_trans_unregister(fd);
> + return get_errno(close(fd));
> + }
>
> case TARGET_NR_brk:
> return do_brk(arg1);
> @@ -9031,7 +9008,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> } else if (!arg3) {
> /* Short circuit this for the magic exe check. */
> ret = -TARGET_EINVAL;
> - } else if (is_proc_myself((const char *)p, "exe")) {
> + } else if (is_proc_myself_exe((const char *)p)) {
> char real[PATH_MAX], *temp;
> temp = realpath(exec_path, real);
> /* Return value is # of bytes that we wrote to the
> buffer. */
> @@ -9060,7 +9037,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
> if (!p || !p2) {
> ret = -TARGET_EFAULT;
> - } else if (is_proc_myself((const char *)p, "exe")) {
> + } else if (is_proc_myself_exe((const char *)p)) {
> char real[PATH_MAX], *temp;
> temp = realpath(exec_path, real);
> ret = temp == NULL ? get_errno(-1) : strlen(real) ;
> @@ -10847,7 +10824,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> return get_errno(fchown(arg1, low2highuid(arg2),
> low2highgid(arg3)));
> #if defined(TARGET_NR_fchownat)
> case TARGET_NR_fchownat:
> - if (!(p = lock_user_string(arg2)))
> + if (!(p = lock_user_string(arg2)))
> return -TARGET_EFAULT;
> ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
> low2highgid(arg4), arg5));
> diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c
> new file mode 100644
> index 0000000000..e85ca99c16
> --- /dev/null
> +++ b/linux-user/syscall_proc.c
> @@ -0,0 +1,96 @@
> +#include "qemu/osdep.h"
> +#include "elf.h"
> +
> +#include "syscall_proc.h"
> +#include "qemu.h"
> +
> +#define PROC "/proc/"
> +#define SELF "self/"
> +
> +#define STARTS_WITH(path, CONSTANT) \
> + strlen(path) >= strlen(CONSTANT) && strncmp(path, CONSTANT,
> strlen(CONSTANT)) == 0
> +
> +static inline char *scope_to_proc(const char *path)
> +{
> + if (STARTS_WITH(path, PROC)) {
> + return (char *)path + strlen(PROC);
> + }
> +
> + return NULL;
> +}
> +
> +static inline char *scope_to_proc_myself(const char *path)
> +{
> + char *scope_path = scope_to_proc(path);
> + if (scope_path == NULL) {
> + return NULL;
> + }
> +
> + if (STARTS_WITH(scope_path, SELF)) {
> + return scope_path + strlen(SELF);
> + }
> +
> + if (strlen(scope_path) >= 1 && *scope_path >= '1' && *scope_path <=
> '9') {
> + char pid_path[80];
> + snprintf(pid_path, sizeof(pid_path), "%d/", getpid());
> + if (STARTS_WITH(scope_path, pid_path)) {
> + return scope_path + strlen(pid_path);
> + }
> + }
> +
> + return NULL;
> +}
> +
> +int is_proc(const char *path, const char *entry)
> +{
> + char *scope_path = scope_to_proc(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + return strcmp(scope_path, entry) == 0;
> +}
> +
> +int is_proc_myself(const char *path, const char *entry)
> +{
> + char *scope_path = scope_to_proc_myself(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + return strcmp(scope_path, entry) == 0;
> +}
> +
> +int is_proc_myself_exe(const char *path)
> +{
> + char *scope_path = scope_to_proc_myself(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + // Kernel creates "fd/#{number}" link after opening "exe" link.
> + // Both "exe" and "fd/#{number}" can be used by application.
> +
> + // Kernel can provide infinite amount of fd numbers.
> + // Qemu is going to always return single global execfd.
> +
> + // So we need to check "exe" and "fd/#{execfd}" only.
QEMU coding style is /* this */ (here you'd use a multi-block comment),
see:
https://wiki.qemu.org/Contribute/SubmitAPatch#Use_the_QEMU_coding_style
Regards,
Phil.
> +
> + if (strcmp(scope_path, "exe") == 0) {
> + return 1;
> + }
> +
> + if (STARTS_WITH(scope_path, "fd/")) {
> + scope_path += strlen("fd/");
> +
> + if (strlen(scope_path) >= 1 && *scope_path >= '1' &&
> *scope_path <= '9') {
> + char execfd_path[80];
> + snprintf(execfd_path, sizeof(execfd_path), "%d", execfd);
> + if (strcmp(scope_path, execfd_path) == 0) {
> + return 1;
> + }
> + }
> + }
> +
> + return 0;
> +}
> diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
> new file mode 100644
> index 0000000000..f0e59c0e96
> --- /dev/null
> +++ b/linux-user/syscall_proc.h
> @@ -0,0 +1,8 @@
> +#ifndef SYSCALL_PROC_H
> +#define SYSCALL_PROC_H
> +
> +int is_proc(const char *path, const char *entry);
> +int is_proc_myself(const char *path, const char *entry);
> +int is_proc_myself_exe(const char *path);
> +
> +#endif
> --
> 2.26.2
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fixed proc myself (linux user) for musl
2020-08-16 21:42 ` Philippe Mathieu-Daudé
@ 2020-08-16 22:21 ` Андрей Аладьев
0 siblings, 0 replies; 5+ messages in thread
From: Андрей Аладьев @ 2020-08-16 22:21 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: Richard Henderson, qemu-devel, Laurent Vivier
[-- Attachment #1: Type: text/plain, Size: 10955 bytes --]
From 738f6ec4598b4618acd7ecbd11e5d250a82f28b7 Mon Sep 17 00:00:00 2001
From: Andrew Aladjev <aladjev.andrew@gmail.com>
Date: Mon, 17 Aug 2020 01:20:03 +0300
Subject: [PATCH] fixed proc myself (linux user) for musl
Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com>
---
linux-user/Makefile.objs | 5 +-
linux-user/elfload.c | 7 ++-
linux-user/exit.c | 7 ++-
linux-user/main.c | 2 +-
linux-user/qemu.h | 1 +
linux-user/syscall.c | 63 ++++++++---------------
linux-user/syscall_proc.c | 102 ++++++++++++++++++++++++++++++++++++++
linux-user/syscall_proc.h | 8 +++
8 files changed, 146 insertions(+), 49 deletions(-)
create mode 100644 linux-user/syscall_proc.c
create mode 100644 linux-user/syscall_proc.h
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
index 1940910a73..ad84380738 100644
--- a/linux-user/Makefile.objs
+++ b/linux-user/Makefile.objs
@@ -1,7 +1,8 @@
obj-y = main.o syscall.o strace.o mmap.o signal.o \
elfload.o linuxload.o uaccess.o uname.o \
- safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
- $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o
+ safe-syscall.o syscall_proc.o \
+ $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \
+ exit.o fd-trans.o
obj-$(TARGET_HAS_BFLT) += flatload.o
obj-$(TARGET_I386) += vm86.o
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 619c054cc4..201db61d91 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2319,7 +2319,10 @@ exit_errmsg:
buffer is sufficiently aligned to present no problems to the host
in accessing data at aligned offsets within the buffer.
- On return: INFO values will be filled in, as necessary or available. */
+ On return: INFO values will be filled in, as necessary or available.
+
+ WARNING: this function won't close "image_fd".
+*/
static void load_elf_image(const char *image_name, int image_fd,
struct image_info *info, char **pinterp_name,
@@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name,
int image_fd,
mmap_unlock();
- close(image_fd);
return;
exit_read:
@@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename,
struct image_info *info,
}
load_elf_image(filename, fd, info, NULL, bprm_buf);
+ close(fd);
return;
exit_perror:
diff --git a/linux-user/exit.c b/linux-user/exit.c
index 1594015444..f0626fc432 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -28,12 +28,15 @@ extern void __gcov_dump(void);
void preexit_cleanup(CPUArchState *env, int code)
{
+ close(execfd);
+
#ifdef CONFIG_GPROF
_mcleanup();
#endif
#ifdef CONFIG_GCOV
__gcov_dump();
#endif
- gdb_exit(env, code);
- qemu_plugin_atexit_cb();
+
+ gdb_exit(env, code);
+ qemu_plugin_atexit_cb();
}
diff --git a/linux-user/main.c b/linux-user/main.c
index 22578b1633..9cc6c1e6da 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -48,6 +48,7 @@
#include "crypto/init.h"
char *exec_path;
+int execfd;
int singlestep;
static const char *argv0;
@@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp)
int target_argc;
int i;
int ret;
- int execfd;
int log_mask;
unsigned long max_reserved_va;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 792c74290f..d822f2b9df 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -156,6 +156,7 @@ typedef struct TaskState {
} __attribute__((aligned(16))) TaskState;
extern char *exec_path;
+extern int execfd;
void init_task_state(TaskState *ts);
void task_settid(TaskState *);
void stop_all_tasks(void);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 05f03919ff..af86385281 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -122,6 +122,7 @@
#include "qapi/error.h"
#include "fd-trans.h"
#include "tcg/tcg.h"
+#include "syscall_proc.h"
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
@@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd)
return 0;
}
-static int is_proc_myself(const char *filename, const char *entry)
-{
- if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
- filename += strlen("/proc/");
- if (!strncmp(filename, "self/", strlen("self/"))) {
- filename += strlen("self/");
- } else if (*filename >= '1' && *filename <= '9') {
- char myself[80];
- snprintf(myself, sizeof(myself), "%d/", getpid());
- if (!strncmp(filename, myself, strlen(myself))) {
- filename += strlen(myself);
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- if (!strcmp(filename, entry)) {
- return 1;
- }
- }
- return 0;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
- defined(TARGET_SPARC) || defined(TARGET_M68K)
-static int is_proc(const char *filename, const char *entry)
-{
- return strcmp(filename, entry) == 0;
-}
-#endif
-
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
static int open_net_route(void *cpu_env, int fd)
{
@@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd,
const char *pathname, int flags,
{ "auxv", open_self_auxv, is_proc_myself },
{ "cmdline", open_self_cmdline, is_proc_myself },
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
- { "/proc/net/route", open_net_route, is_proc },
+ { "net/route", open_net_route, is_proc },
#endif
#if defined(TARGET_SPARC)
- { "/proc/cpuinfo", open_cpuinfo, is_proc },
+ { "cpuinfo", open_cpuinfo, is_proc },
#endif
#if defined(TARGET_M68K)
- { "/proc/hardware", open_hardware, is_proc },
+ { "hardware", open_hardware, is_proc },
#endif
{ NULL, NULL, NULL }
};
- if (is_proc_myself(pathname, "exe")) {
- int execfd = qemu_getauxval(AT_EXECFD);
- return execfd ? execfd : safe_openat(dirfd, exec_path, flags,
mode);
+ if (is_proc_myself_exe(pathname)) {
+ return execfd;
}
for (fake_open = fakes; fake_open->filename; fake_open++) {
@@ -7728,8 +7696,19 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
return ret;
#endif
case TARGET_NR_close:
- fd_trans_unregister(arg1);
- return get_errno(close(arg1));
+ {
+ int fd = arg1;
+ if (fd == execfd) {
+ /*
+ * We don't need to close execfd.
+ * It will be closed on QEMU exit.
+ */
+ return 0;
+ }
+
+ fd_trans_unregister(fd);
+ return get_errno(close(fd));
+ }
case TARGET_NR_brk:
return do_brk(arg1);
@@ -9031,7 +9010,7 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
} else if (!arg3) {
/* Short circuit this for the magic exe check. */
ret = -TARGET_EINVAL;
- } else if (is_proc_myself((const char *)p, "exe")) {
+ } else if (is_proc_myself_exe((const char *)p)) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
/* Return value is # of bytes that we wrote to the buffer.
*/
@@ -9060,7 +9039,7 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!p || !p2) {
ret = -TARGET_EFAULT;
- } else if (is_proc_myself((const char *)p, "exe")) {
+ } else if (is_proc_myself_exe((const char *)p)) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c
new file mode 100644
index 0000000000..8688459c7d
--- /dev/null
+++ b/linux-user/syscall_proc.c
@@ -0,0 +1,102 @@
+#include "qemu/osdep.h"
+#include "elf.h"
+
+#include "syscall_proc.h"
+#include "qemu.h"
+
+#define PROC "/proc/"
+#define SELF "self/"
+
+#define STARTS_WITH(path, CONSTANT) ( \
+ strlen(path) >= strlen(CONSTANT) && \
+ strncmp(path, CONSTANT, strlen(CONSTANT)) == 0 \
+)
+
+static inline char *scope_to_proc(const char *path)
+{
+ if (STARTS_WITH(path, PROC)) {
+ return (char *)path + strlen(PROC);
+ }
+
+ return NULL;
+}
+
+static inline char *scope_to_proc_myself(const char *path)
+{
+ char *scope_path = scope_to_proc(path);
+ if (scope_path == NULL) {
+ return NULL;
+ }
+
+ if (STARTS_WITH(scope_path, SELF)) {
+ return scope_path + strlen(SELF);
+ }
+
+ if (strlen(scope_path) >= 1 &&
+ *scope_path >= '1' && *scope_path <= '9') {
+ char pid_path[80];
+ snprintf(pid_path, sizeof(pid_path), "%d/", getpid());
+ if (STARTS_WITH(scope_path, pid_path)) {
+ return scope_path + strlen(pid_path);
+ }
+ }
+
+ return NULL;
+}
+
+int is_proc(const char *path, const char *entry)
+{
+ char *scope_path = scope_to_proc(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ return strcmp(scope_path, entry) == 0;
+}
+
+int is_proc_myself(const char *path, const char *entry)
+{
+ char *scope_path = scope_to_proc_myself(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ return strcmp(scope_path, entry) == 0;
+}
+
+/*
+ * Kernel creates "fd/#{number}" link after opening "exe" link.
+ * Both "exe" and "fd/#{number}" can be used by application.
+ *
+ * Kernel can provide infinite amount of fd numbers.
+ * QEMU is going to always return single global execfd.
+ *
+ * So we need to check "exe" and "fd/#{execfd}" only.
+ */
+
+int is_proc_myself_exe(const char *path)
+{
+ char *scope_path = scope_to_proc_myself(path);
+ if (scope_path == NULL) {
+ return 0;
+ }
+
+ if (strcmp(scope_path, "exe") == 0) {
+ return 1;
+ }
+
+ if (STARTS_WITH(scope_path, "fd/")) {
+ scope_path += strlen("fd/");
+
+ if (strlen(scope_path) >= 1 &&
+ *scope_path >= '1' && *scope_path <= '9') {
+ char execfd_path[80];
+ snprintf(execfd_path, sizeof(execfd_path), "%d", execfd);
+ if (strcmp(scope_path, execfd_path) == 0) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
new file mode 100644
index 0000000000..f0e59c0e96
--- /dev/null
+++ b/linux-user/syscall_proc.h
@@ -0,0 +1,8 @@
+#ifndef SYSCALL_PROC_H
+#define SYSCALL_PROC_H
+
+int is_proc(const char *path, const char *entry);
+int is_proc_myself(const char *path, const char *entry);
+int is_proc_myself_exe(const char *path);
+
+#endif
--
2.26.2
[-- Attachment #2: Type: text/html, Size: 13494 bytes --]
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fixed proc myself (linux user) for musl
2020-08-16 19:58 [PATCH] fixed proc myself (linux user) for musl Андрей Аладьев
2020-08-16 21:42 ` Philippe Mathieu-Daudé
@ 2020-08-17 15:12 ` Laurent Vivier
2020-08-18 9:38 ` Андрей Аладьев
1 sibling, 1 reply; 5+ messages in thread
From: Laurent Vivier @ 2020-08-17 15:12 UTC (permalink / raw)
To: Андрей
Аладьев,
qemu-devel
Hi,
it seems your patch does several things.
Could you split it into several patches?
Could you add a description of what the patches do?
Could you use a tool like "git send-email" or "git publish" to send your
series?
For the patch moving code from syscall.c to syscall_proc.c, write a
patch that moves the code without modifying it. And then you can follow
with a patch fixing what you want.
Thanks,
Laurent
Le 16/08/2020 à 21:58, Андрей Аладьев a écrit :
> From: Andrew Aladjev <aladjev.andrew@gmail.com
> <mailto:aladjev.andrew@gmail.com>>
> Date: Sun, 16 Aug 2020 22:50:13 +0300
> Subject: [PATCH] fixed proc myself (linux user) for musl
> Buglink: https://bugs.gentoo.org/587230
> Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com
> <mailto:aladjev.andrew@gmail.com>>
> ---
> linux-user/Makefile.objs | 5 +-
> linux-user/elfload.c | 7 ++-
> linux-user/exit.c | 7 ++-
> linux-user/main.c | 2 +-
> linux-user/qemu.h | 1 +
> linux-user/syscall.c | 85 +++++++++++++---------------------
> linux-user/syscall_proc.c | 96 +++++++++++++++++++++++++++++++++++++++
> linux-user/syscall_proc.h | 8 ++++
> 8 files changed, 150 insertions(+), 61 deletions(-)
> create mode 100644 linux-user/syscall_proc.c
> create mode 100644 linux-user/syscall_proc.h
>
> diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
> index 1940910a73..ad84380738 100644
> --- a/linux-user/Makefile.objs
> +++ b/linux-user/Makefile.objs
> @@ -1,7 +1,8 @@
> obj-y = main.o syscall.o strace.o mmap.o signal.o \
> elfload.o linuxload.o uaccess.o uname.o \
> - safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
> - $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o
> + safe-syscall.o syscall_proc.o \
> + $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \
> + exit.o fd-trans.o
>
> obj-$(TARGET_HAS_BFLT) += flatload.o
> obj-$(TARGET_I386) += vm86.o
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 619c054cc4..201db61d91 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -2319,7 +2319,10 @@ exit_errmsg:
> buffer is sufficiently aligned to present no problems to the host
> in accessing data at aligned offsets within the buffer.
>
> - On return: INFO values will be filled in, as necessary or available. */
> + On return: INFO values will be filled in, as necessary or available.
> +
> + WARNING: this function won't close "image_fd".
> +*/
>
> static void load_elf_image(const char *image_name, int image_fd,
> struct image_info *info, char **pinterp_name,
> @@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name,
> int image_fd,
>
> mmap_unlock();
>
> - close(image_fd);
> return;
>
> exit_read:
> @@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename,
> struct image_info *info,
> }
>
> load_elf_image(filename, fd, info, NULL, bprm_buf);
> + close(fd);
> return;
>
> exit_perror:
> diff --git a/linux-user/exit.c b/linux-user/exit.c
> index 1594015444..f0626fc432 100644
> --- a/linux-user/exit.c
> +++ b/linux-user/exit.c
> @@ -28,12 +28,15 @@ extern void __gcov_dump(void);
>
> void preexit_cleanup(CPUArchState *env, int code)
> {
> + close(execfd);
> +
> #ifdef CONFIG_GPROF
> _mcleanup();
> #endif
> #ifdef CONFIG_GCOV
> __gcov_dump();
> #endif
> - gdb_exit(env, code);
> - qemu_plugin_atexit_cb();
> +
> + gdb_exit(env, code);
> + qemu_plugin_atexit_cb();
> }
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 22578b1633..9cc6c1e6da 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -48,6 +48,7 @@
> #include "crypto/init.h"
>
> char *exec_path;
> +int execfd;
>
> int singlestep;
> static const char *argv0;
> @@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp)
> int target_argc;
> int i;
> int ret;
> - int execfd;
> int log_mask;
> unsigned long max_reserved_va;
>
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 792c74290f..d822f2b9df 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -156,6 +156,7 @@ typedef struct TaskState {
> } __attribute__((aligned(16))) TaskState;
>
> extern char *exec_path;
> +extern int execfd;
> void init_task_state(TaskState *ts);
> void task_settid(TaskState *);
> void stop_all_tasks(void);
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 05f03919ff..483a735c1a 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -122,6 +122,7 @@
> #include "qapi/error.h"
> #include "fd-trans.h"
> #include "tcg/tcg.h"
> +#include "syscall_proc.h"
>
> #ifndef CLONE_IO
> #define CLONE_IO 0x80000000 /* Clone io context */
> @@ -1104,7 +1105,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> target_rlim)
> {
> abi_ulong target_rlim_swap;
> rlim_t result;
> -
> +
> target_rlim_swap = tswapal(target_rlim);
> if (target_rlim_swap == TARGET_RLIM_INFINITY)
> return RLIM_INFINITY;
> @@ -1112,7 +1113,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> target_rlim)
> result = target_rlim_swap;
> if (target_rlim_swap != (rlim_t)result)
> return RLIM_INFINITY;
> -
> +
> return result;
> }
> #endif
> @@ -1122,13 +1123,13 @@ static inline abi_ulong
> host_to_target_rlim(rlim_t rlim)
> {
> abi_ulong target_rlim_swap;
> abi_ulong result;
> -
> +
> if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
> target_rlim_swap = TARGET_RLIM_INFINITY;
> else
> target_rlim_swap = rlim;
> result = tswapal(target_rlim_swap);
> -
> +
> return result;
> }
> #endif
> @@ -1615,9 +1616,9 @@ static inline abi_long target_to_host_cmsg(struct
> msghdr *msgh,
> abi_ulong target_cmsg_addr;
> struct target_cmsghdr *target_cmsg, *target_cmsg_start;
> socklen_t space = 0;
> -
> +
> msg_controllen = tswapal(target_msgh->msg_controllen);
> - if (msg_controllen < sizeof (struct target_cmsghdr))
> + if (msg_controllen < sizeof (struct target_cmsghdr))
> goto the_end;
> target_cmsg_addr = tswapal(target_msgh->msg_control);
> target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr,
> msg_controllen, 1);
> @@ -1703,7 +1704,7 @@ static inline abi_long host_to_target_cmsg(struct
> target_msghdr *target_msgh,
> socklen_t space = 0;
>
> msg_controllen = tswapal(target_msgh->msg_controllen);
> - if (msg_controllen < sizeof (struct target_cmsghdr))
> + if (msg_controllen < sizeof (struct target_cmsghdr))
> goto the_end;
> target_cmsg_addr = tswapal(target_msgh->msg_control);
> target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
> msg_controllen, 0);
> @@ -5750,7 +5751,7 @@ abi_long do_set_thread_area(CPUX86State *env,
> abi_ulong ptr)
> }
> unlock_user_struct(target_ldt_info, ptr, 1);
>
> - if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> + if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
> return -TARGET_EINVAL;
> seg_32bit = ldt_info.flags & 1;
> @@ -5828,7 +5829,7 @@ static abi_long do_get_thread_area(CPUX86State
> *env, abi_ulong ptr)
> lp = (uint32_t *)(gdt_table + idx);
> entry_1 = tswap32(lp[0]);
> entry_2 = tswap32(lp[1]);
> -
> +
> read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
> contents = (entry_2 >> 10) & 3;
> seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
> @@ -5844,8 +5845,8 @@ static abi_long do_get_thread_area(CPUX86State
> *env, abi_ulong ptr)
> (read_exec_only << 3) | (limit_in_pages << 4) |
> (seg_not_present << 5) | (useable << 6) | (lm << 7);
> limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
> - base_addr = (entry_1 >> 16) |
> - (entry_2 & 0xff000000) |
> + base_addr = (entry_1 >> 16) |
> + (entry_2 & 0xff000000) |
> ((entry_2 & 0xff) << 16);
> target_ldt_info->base_addr = tswapal(base_addr);
> target_ldt_info->limit = tswap32(limit);
> @@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd)
> return 0;
> }
>
> -static int is_proc_myself(const char *filename, const char *entry)
> -{
> - if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
> - filename += strlen("/proc/");
> - if (!strncmp(filename, "self/", strlen("self/"))) {
> - filename += strlen("self/");
> - } else if (*filename >= '1' && *filename <= '9') {
> - char myself[80];
> - snprintf(myself, sizeof(myself), "%d/", getpid());
> - if (!strncmp(filename, myself, strlen(myself))) {
> - filename += strlen(myself);
> - } else {
> - return 0;
> - }
> - } else {
> - return 0;
> - }
> - if (!strcmp(filename, entry)) {
> - return 1;
> - }
> - }
> - return 0;
> -}
> -
> -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
> - defined(TARGET_SPARC) || defined(TARGET_M68K)
> -static int is_proc(const char *filename, const char *entry)
> -{
> - return strcmp(filename, entry) == 0;
> -}
> -#endif
> -
> #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> static int open_net_route(void *cpu_env, int fd)
> {
> @@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd,
> const char *pathname, int flags,
> { "auxv", open_self_auxv, is_proc_myself },
> { "cmdline", open_self_cmdline, is_proc_myself },
> #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> - { "/proc/net/route", open_net_route, is_proc },
> + { "net/route", open_net_route, is_proc },
> #endif
> #if defined(TARGET_SPARC)
> - { "/proc/cpuinfo", open_cpuinfo, is_proc },
> + { "cpuinfo", open_cpuinfo, is_proc },
> #endif
> #if defined(TARGET_M68K)
> - { "/proc/hardware", open_hardware, is_proc },
> + { "hardware", open_hardware, is_proc },
> #endif
> { NULL, NULL, NULL }
> };
>
> - if (is_proc_myself(pathname, "exe")) {
> - int execfd = qemu_getauxval(AT_EXECFD);
> - return execfd ? execfd : safe_openat(dirfd, exec_path, flags,
> mode);
> + if (is_proc_myself_exe(pathname)) {
> + return execfd;
> }
>
> for (fake_open = fakes; fake_open->filename; fake_open++) {
> @@ -7728,8 +7696,17 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> return ret;
> #endif
> case TARGET_NR_close:
> - fd_trans_unregister(arg1);
> - return get_errno(close(arg1));
> + {
> + int fd = arg1;
> + if (fd == execfd) {
> + // We don't need to close execfd.
> + // It will be closed on qemu exit.
> + return 0;
> + }
> +
> + fd_trans_unregister(fd);
> + return get_errno(close(fd));
> + }
>
> case TARGET_NR_brk:
> return do_brk(arg1);
> @@ -9031,7 +9008,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> } else if (!arg3) {
> /* Short circuit this for the magic exe check. */
> ret = -TARGET_EINVAL;
> - } else if (is_proc_myself((const char *)p, "exe")) {
> + } else if (is_proc_myself_exe((const char *)p)) {
> char real[PATH_MAX], *temp;
> temp = realpath(exec_path, real);
> /* Return value is # of bytes that we wrote to the
> buffer. */
> @@ -9060,7 +9037,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
> if (!p || !p2) {
> ret = -TARGET_EFAULT;
> - } else if (is_proc_myself((const char *)p, "exe")) {
> + } else if (is_proc_myself_exe((const char *)p)) {
> char real[PATH_MAX], *temp;
> temp = realpath(exec_path, real);
> ret = temp == NULL ? get_errno(-1) : strlen(real) ;
> @@ -10847,7 +10824,7 @@ static abi_long do_syscall1(void *cpu_env, int
> num, abi_long arg1,
> return get_errno(fchown(arg1, low2highuid(arg2),
> low2highgid(arg3)));
> #if defined(TARGET_NR_fchownat)
> case TARGET_NR_fchownat:
> - if (!(p = lock_user_string(arg2)))
> + if (!(p = lock_user_string(arg2)))
> return -TARGET_EFAULT;
> ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
> low2highgid(arg4), arg5));
> diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c
> new file mode 100644
> index 0000000000..e85ca99c16
> --- /dev/null
> +++ b/linux-user/syscall_proc.c
> @@ -0,0 +1,96 @@
> +#include "qemu/osdep.h"
> +#include "elf.h"
> +
> +#include "syscall_proc.h"
> +#include "qemu.h"
> +
> +#define PROC "/proc/"
> +#define SELF "self/"
> +
> +#define STARTS_WITH(path, CONSTANT) \
> + strlen(path) >= strlen(CONSTANT) && strncmp(path, CONSTANT,
> strlen(CONSTANT)) == 0
> +
> +static inline char *scope_to_proc(const char *path)
> +{
> + if (STARTS_WITH(path, PROC)) {
> + return (char *)path + strlen(PROC);
> + }
> +
> + return NULL;
> +}
> +
> +static inline char *scope_to_proc_myself(const char *path)
> +{
> + char *scope_path = scope_to_proc(path);
> + if (scope_path == NULL) {
> + return NULL;
> + }
> +
> + if (STARTS_WITH(scope_path, SELF)) {
> + return scope_path + strlen(SELF);
> + }
> +
> + if (strlen(scope_path) >= 1 && *scope_path >= '1' && *scope_path <=
> '9') {
> + char pid_path[80];
> + snprintf(pid_path, sizeof(pid_path), "%d/", getpid());
> + if (STARTS_WITH(scope_path, pid_path)) {
> + return scope_path + strlen(pid_path);
> + }
> + }
> +
> + return NULL;
> +}
> +
> +int is_proc(const char *path, const char *entry)
> +{
> + char *scope_path = scope_to_proc(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + return strcmp(scope_path, entry) == 0;
> +}
> +
> +int is_proc_myself(const char *path, const char *entry)
> +{
> + char *scope_path = scope_to_proc_myself(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + return strcmp(scope_path, entry) == 0;
> +}
> +
> +int is_proc_myself_exe(const char *path)
> +{
> + char *scope_path = scope_to_proc_myself(path);
> + if (scope_path == NULL) {
> + return 0;
> + }
> +
> + // Kernel creates "fd/#{number}" link after opening "exe" link.
> + // Both "exe" and "fd/#{number}" can be used by application.
> +
> + // Kernel can provide infinite amount of fd numbers.
> + // Qemu is going to always return single global execfd.
> +
> + // So we need to check "exe" and "fd/#{execfd}" only.
> +
> + if (strcmp(scope_path, "exe") == 0) {
> + return 1;
> + }
> +
> + if (STARTS_WITH(scope_path, "fd/")) {
> + scope_path += strlen("fd/");
> +
> + if (strlen(scope_path) >= 1 && *scope_path >= '1' &&
> *scope_path <= '9') {
> + char execfd_path[80];
> + snprintf(execfd_path, sizeof(execfd_path), "%d", execfd);
> + if (strcmp(scope_path, execfd_path) == 0) {
> + return 1;
> + }
> + }
> + }
> +
> + return 0;
> +}
> diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
> new file mode 100644
> index 0000000000..f0e59c0e96
> --- /dev/null
> +++ b/linux-user/syscall_proc.h
> @@ -0,0 +1,8 @@
> +#ifndef SYSCALL_PROC_H
> +#define SYSCALL_PROC_H
> +
> +int is_proc(const char *path, const char *entry);
> +int is_proc_myself(const char *path, const char *entry);
> +int is_proc_myself_exe(const char *path);
> +
> +#endif
> --
> 2.26.2
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fixed proc myself (linux user) for musl
2020-08-17 15:12 ` Laurent Vivier
@ 2020-08-18 9:38 ` Андрей Аладьев
0 siblings, 0 replies; 5+ messages in thread
From: Андрей Аладьев @ 2020-08-18 9:38 UTC (permalink / raw)
To: Laurent Vivier; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 17547 bytes --]
I've sent 3 separate patches using "git send email", please review.
пн, 17 авг. 2020 г. в 18:12, Laurent Vivier <laurent@vivier.eu>:
> Hi,
>
> it seems your patch does several things.
>
> Could you split it into several patches?
> Could you add a description of what the patches do?
> Could you use a tool like "git send-email" or "git publish" to send your
> series?
>
> For the patch moving code from syscall.c to syscall_proc.c, write a
> patch that moves the code without modifying it. And then you can follow
> with a patch fixing what you want.
>
> Thanks,
> Laurent
>
> Le 16/08/2020 à 21:58, Андрей Аладьев a écrit :
> > From: Andrew Aladjev <aladjev.andrew@gmail.com
> > <mailto:aladjev.andrew@gmail.com>>
> > Date: Sun, 16 Aug 2020 22:50:13 +0300
> > Subject: [PATCH] fixed proc myself (linux user) for musl
> > Buglink: https://bugs.gentoo.org/587230
> > Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com
> > <mailto:aladjev.andrew@gmail.com>>
> > ---
> > linux-user/Makefile.objs | 5 +-
> > linux-user/elfload.c | 7 ++-
> > linux-user/exit.c | 7 ++-
> > linux-user/main.c | 2 +-
> > linux-user/qemu.h | 1 +
> > linux-user/syscall.c | 85 +++++++++++++---------------------
> > linux-user/syscall_proc.c | 96 +++++++++++++++++++++++++++++++++++++++
> > linux-user/syscall_proc.h | 8 ++++
> > 8 files changed, 150 insertions(+), 61 deletions(-)
> > create mode 100644 linux-user/syscall_proc.c
> > create mode 100644 linux-user/syscall_proc.h
> >
> > diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
> > index 1940910a73..ad84380738 100644
> > --- a/linux-user/Makefile.objs
> > +++ b/linux-user/Makefile.objs
> > @@ -1,7 +1,8 @@
> > obj-y = main.o syscall.o strace.o mmap.o signal.o \
> > elfload.o linuxload.o uaccess.o uname.o \
> > - safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
> > - $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o
> > + safe-syscall.o syscall_proc.o \
> > + $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \
> > + exit.o fd-trans.o
> >
> > obj-$(TARGET_HAS_BFLT) += flatload.o
> > obj-$(TARGET_I386) += vm86.o
> > diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> > index 619c054cc4..201db61d91 100644
> > --- a/linux-user/elfload.c
> > +++ b/linux-user/elfload.c
> > @@ -2319,7 +2319,10 @@ exit_errmsg:
> > buffer is sufficiently aligned to present no problems to the host
> > in accessing data at aligned offsets within the buffer.
> >
> > - On return: INFO values will be filled in, as necessary or available.
> */
> > + On return: INFO values will be filled in, as necessary or available.
> > +
> > + WARNING: this function won't close "image_fd".
> > +*/
> >
> > static void load_elf_image(const char *image_name, int image_fd,
> > struct image_info *info, char **pinterp_name,
> > @@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name,
> > int image_fd,
> >
> > mmap_unlock();
> >
> > - close(image_fd);
> > return;
> >
> > exit_read:
> > @@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename,
> > struct image_info *info,
> > }
> >
> > load_elf_image(filename, fd, info, NULL, bprm_buf);
> > + close(fd);
> > return;
> >
> > exit_perror:
> > diff --git a/linux-user/exit.c b/linux-user/exit.c
> > index 1594015444..f0626fc432 100644
> > --- a/linux-user/exit.c
> > +++ b/linux-user/exit.c
> > @@ -28,12 +28,15 @@ extern void __gcov_dump(void);
> >
> > void preexit_cleanup(CPUArchState *env, int code)
> > {
> > + close(execfd);
> > +
> > #ifdef CONFIG_GPROF
> > _mcleanup();
> > #endif
> > #ifdef CONFIG_GCOV
> > __gcov_dump();
> > #endif
> > - gdb_exit(env, code);
> > - qemu_plugin_atexit_cb();
> > +
> > + gdb_exit(env, code);
> > + qemu_plugin_atexit_cb();
> > }
> > diff --git a/linux-user/main.c b/linux-user/main.c
> > index 22578b1633..9cc6c1e6da 100644
> > --- a/linux-user/main.c
> > +++ b/linux-user/main.c
> > @@ -48,6 +48,7 @@
> > #include "crypto/init.h"
> >
> > char *exec_path;
> > +int execfd;
> >
> > int singlestep;
> > static const char *argv0;
> > @@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp)
> > int target_argc;
> > int i;
> > int ret;
> > - int execfd;
> > int log_mask;
> > unsigned long max_reserved_va;
> >
> > diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> > index 792c74290f..d822f2b9df 100644
> > --- a/linux-user/qemu.h
> > +++ b/linux-user/qemu.h
> > @@ -156,6 +156,7 @@ typedef struct TaskState {
> > } __attribute__((aligned(16))) TaskState;
> >
> > extern char *exec_path;
> > +extern int execfd;
> > void init_task_state(TaskState *ts);
> > void task_settid(TaskState *);
> > void stop_all_tasks(void);
> > diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> > index 05f03919ff..483a735c1a 100644
> > --- a/linux-user/syscall.c
> > +++ b/linux-user/syscall.c
> > @@ -122,6 +122,7 @@
> > #include "qapi/error.h"
> > #include "fd-trans.h"
> > #include "tcg/tcg.h"
> > +#include "syscall_proc.h"
> >
> > #ifndef CLONE_IO
> > #define CLONE_IO 0x80000000 /* Clone io context */
> > @@ -1104,7 +1105,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> > target_rlim)
> > {
> > abi_ulong target_rlim_swap;
> > rlim_t result;
> > -
> > +
> > target_rlim_swap = tswapal(target_rlim);
> > if (target_rlim_swap == TARGET_RLIM_INFINITY)
> > return RLIM_INFINITY;
> > @@ -1112,7 +1113,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong
> > target_rlim)
> > result = target_rlim_swap;
> > if (target_rlim_swap != (rlim_t)result)
> > return RLIM_INFINITY;
> > -
> > +
> > return result;
> > }
> > #endif
> > @@ -1122,13 +1123,13 @@ static inline abi_ulong
> > host_to_target_rlim(rlim_t rlim)
> > {
> > abi_ulong target_rlim_swap;
> > abi_ulong result;
> > -
> > +
> > if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
> > target_rlim_swap = TARGET_RLIM_INFINITY;
> > else
> > target_rlim_swap = rlim;
> > result = tswapal(target_rlim_swap);
> > -
> > +
> > return result;
> > }
> > #endif
> > @@ -1615,9 +1616,9 @@ static inline abi_long target_to_host_cmsg(struct
> > msghdr *msgh,
> > abi_ulong target_cmsg_addr;
> > struct target_cmsghdr *target_cmsg, *target_cmsg_start;
> > socklen_t space = 0;
> > -
> > +
> > msg_controllen = tswapal(target_msgh->msg_controllen);
> > - if (msg_controllen < sizeof (struct target_cmsghdr))
> > + if (msg_controllen < sizeof (struct target_cmsghdr))
> > goto the_end;
> > target_cmsg_addr = tswapal(target_msgh->msg_control);
> > target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr,
> > msg_controllen, 1);
> > @@ -1703,7 +1704,7 @@ static inline abi_long host_to_target_cmsg(struct
> > target_msghdr *target_msgh,
> > socklen_t space = 0;
> >
> > msg_controllen = tswapal(target_msgh->msg_controllen);
> > - if (msg_controllen < sizeof (struct target_cmsghdr))
> > + if (msg_controllen < sizeof (struct target_cmsghdr))
> > goto the_end;
> > target_cmsg_addr = tswapal(target_msgh->msg_control);
> > target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
> > msg_controllen, 0);
> > @@ -5750,7 +5751,7 @@ abi_long do_set_thread_area(CPUX86State *env,
> > abi_ulong ptr)
> > }
> > unlock_user_struct(target_ldt_info, ptr, 1);
> >
> > - if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> > + if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
> > ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
> > return -TARGET_EINVAL;
> > seg_32bit = ldt_info.flags & 1;
> > @@ -5828,7 +5829,7 @@ static abi_long do_get_thread_area(CPUX86State
> > *env, abi_ulong ptr)
> > lp = (uint32_t *)(gdt_table + idx);
> > entry_1 = tswap32(lp[0]);
> > entry_2 = tswap32(lp[1]);
> > -
> > +
> > read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
> > contents = (entry_2 >> 10) & 3;
> > seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
> > @@ -5844,8 +5845,8 @@ static abi_long do_get_thread_area(CPUX86State
> > *env, abi_ulong ptr)
> > (read_exec_only << 3) | (limit_in_pages << 4) |
> > (seg_not_present << 5) | (useable << 6) | (lm << 7);
> > limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
> > - base_addr = (entry_1 >> 16) |
> > - (entry_2 & 0xff000000) |
> > + base_addr = (entry_1 >> 16) |
> > + (entry_2 & 0xff000000) |
> > ((entry_2 & 0xff) << 16);
> > target_ldt_info->base_addr = tswapal(base_addr);
> > target_ldt_info->limit = tswap32(limit);
> > @@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd)
> > return 0;
> > }
> >
> > -static int is_proc_myself(const char *filename, const char *entry)
> > -{
> > - if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
> > - filename += strlen("/proc/");
> > - if (!strncmp(filename, "self/", strlen("self/"))) {
> > - filename += strlen("self/");
> > - } else if (*filename >= '1' && *filename <= '9') {
> > - char myself[80];
> > - snprintf(myself, sizeof(myself), "%d/", getpid());
> > - if (!strncmp(filename, myself, strlen(myself))) {
> > - filename += strlen(myself);
> > - } else {
> > - return 0;
> > - }
> > - } else {
> > - return 0;
> > - }
> > - if (!strcmp(filename, entry)) {
> > - return 1;
> > - }
> > - }
> > - return 0;
> > -}
> > -
> > -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) ||
> \
> > - defined(TARGET_SPARC) || defined(TARGET_M68K)
> > -static int is_proc(const char *filename, const char *entry)
> > -{
> > - return strcmp(filename, entry) == 0;
> > -}
> > -#endif
> > -
> > #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> > static int open_net_route(void *cpu_env, int fd)
> > {
> > @@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd,
> > const char *pathname, int flags,
> > { "auxv", open_self_auxv, is_proc_myself },
> > { "cmdline", open_self_cmdline, is_proc_myself },
> > #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
> > - { "/proc/net/route", open_net_route, is_proc },
> > + { "net/route", open_net_route, is_proc },
> > #endif
> > #if defined(TARGET_SPARC)
> > - { "/proc/cpuinfo", open_cpuinfo, is_proc },
> > + { "cpuinfo", open_cpuinfo, is_proc },
> > #endif
> > #if defined(TARGET_M68K)
> > - { "/proc/hardware", open_hardware, is_proc },
> > + { "hardware", open_hardware, is_proc },
> > #endif
> > { NULL, NULL, NULL }
> > };
> >
> > - if (is_proc_myself(pathname, "exe")) {
> > - int execfd = qemu_getauxval(AT_EXECFD);
> > - return execfd ? execfd : safe_openat(dirfd, exec_path, flags,
> > mode);
> > + if (is_proc_myself_exe(pathname)) {
> > + return execfd;
> > }
> >
> > for (fake_open = fakes; fake_open->filename; fake_open++) {
> > @@ -7728,8 +7696,17 @@ static abi_long do_syscall1(void *cpu_env, int
> > num, abi_long arg1,
> > return ret;
> > #endif
> > case TARGET_NR_close:
> > - fd_trans_unregister(arg1);
> > - return get_errno(close(arg1));
> > + {
> > + int fd = arg1;
> > + if (fd == execfd) {
> > + // We don't need to close execfd.
> > + // It will be closed on qemu exit.
> > + return 0;
> > + }
> > +
> > + fd_trans_unregister(fd);
> > + return get_errno(close(fd));
> > + }
> >
> > case TARGET_NR_brk:
> > return do_brk(arg1);
> > @@ -9031,7 +9008,7 @@ static abi_long do_syscall1(void *cpu_env, int
> > num, abi_long arg1,
> > } else if (!arg3) {
> > /* Short circuit this for the magic exe check. */
> > ret = -TARGET_EINVAL;
> > - } else if (is_proc_myself((const char *)p, "exe")) {
> > + } else if (is_proc_myself_exe((const char *)p)) {
> > char real[PATH_MAX], *temp;
> > temp = realpath(exec_path, real);
> > /* Return value is # of bytes that we wrote to the
> > buffer. */
> > @@ -9060,7 +9037,7 @@ static abi_long do_syscall1(void *cpu_env, int
> > num, abi_long arg1,
> > p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
> > if (!p || !p2) {
> > ret = -TARGET_EFAULT;
> > - } else if (is_proc_myself((const char *)p, "exe")) {
> > + } else if (is_proc_myself_exe((const char *)p)) {
> > char real[PATH_MAX], *temp;
> > temp = realpath(exec_path, real);
> > ret = temp == NULL ? get_errno(-1) : strlen(real) ;
> > @@ -10847,7 +10824,7 @@ static abi_long do_syscall1(void *cpu_env, int
> > num, abi_long arg1,
> > return get_errno(fchown(arg1, low2highuid(arg2),
> > low2highgid(arg3)));
> > #if defined(TARGET_NR_fchownat)
> > case TARGET_NR_fchownat:
> > - if (!(p = lock_user_string(arg2)))
> > + if (!(p = lock_user_string(arg2)))
> > return -TARGET_EFAULT;
> > ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
> > low2highgid(arg4), arg5));
> > diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c
> > new file mode 100644
> > index 0000000000..e85ca99c16
> > --- /dev/null
> > +++ b/linux-user/syscall_proc.c
> > @@ -0,0 +1,96 @@
> > +#include "qemu/osdep.h"
> > +#include "elf.h"
> > +
> > +#include "syscall_proc.h"
> > +#include "qemu.h"
> > +
> > +#define PROC "/proc/"
> > +#define SELF "self/"
> > +
> > +#define STARTS_WITH(path, CONSTANT) \
> > + strlen(path) >= strlen(CONSTANT) && strncmp(path, CONSTANT,
> > strlen(CONSTANT)) == 0
> > +
> > +static inline char *scope_to_proc(const char *path)
> > +{
> > + if (STARTS_WITH(path, PROC)) {
> > + return (char *)path + strlen(PROC);
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > +static inline char *scope_to_proc_myself(const char *path)
> > +{
> > + char *scope_path = scope_to_proc(path);
> > + if (scope_path == NULL) {
> > + return NULL;
> > + }
> > +
> > + if (STARTS_WITH(scope_path, SELF)) {
> > + return scope_path + strlen(SELF);
> > + }
> > +
> > + if (strlen(scope_path) >= 1 && *scope_path >= '1' && *scope_path <=
> > '9') {
> > + char pid_path[80];
> > + snprintf(pid_path, sizeof(pid_path), "%d/", getpid());
> > + if (STARTS_WITH(scope_path, pid_path)) {
> > + return scope_path + strlen(pid_path);
> > + }
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > +int is_proc(const char *path, const char *entry)
> > +{
> > + char *scope_path = scope_to_proc(path);
> > + if (scope_path == NULL) {
> > + return 0;
> > + }
> > +
> > + return strcmp(scope_path, entry) == 0;
> > +}
> > +
> > +int is_proc_myself(const char *path, const char *entry)
> > +{
> > + char *scope_path = scope_to_proc_myself(path);
> > + if (scope_path == NULL) {
> > + return 0;
> > + }
> > +
> > + return strcmp(scope_path, entry) == 0;
> > +}
> > +
> > +int is_proc_myself_exe(const char *path)
> > +{
> > + char *scope_path = scope_to_proc_myself(path);
> > + if (scope_path == NULL) {
> > + return 0;
> > + }
> > +
> > + // Kernel creates "fd/#{number}" link after opening "exe" link.
> > + // Both "exe" and "fd/#{number}" can be used by application.
> > +
> > + // Kernel can provide infinite amount of fd numbers.
> > + // Qemu is going to always return single global execfd.
> > +
> > + // So we need to check "exe" and "fd/#{execfd}" only.
> > +
> > + if (strcmp(scope_path, "exe") == 0) {
> > + return 1;
> > + }
> > +
> > + if (STARTS_WITH(scope_path, "fd/")) {
> > + scope_path += strlen("fd/");
> > +
> > + if (strlen(scope_path) >= 1 && *scope_path >= '1' &&
> > *scope_path <= '9') {
> > + char execfd_path[80];
> > + snprintf(execfd_path, sizeof(execfd_path), "%d", execfd);
> > + if (strcmp(scope_path, execfd_path) == 0) {
> > + return 1;
> > + }
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
> > new file mode 100644
> > index 0000000000..f0e59c0e96
> > --- /dev/null
> > +++ b/linux-user/syscall_proc.h
> > @@ -0,0 +1,8 @@
> > +#ifndef SYSCALL_PROC_H
> > +#define SYSCALL_PROC_H
> > +
> > +int is_proc(const char *path, const char *entry);
> > +int is_proc_myself(const char *path, const char *entry);
> > +int is_proc_myself_exe(const char *path);
> > +
> > +#endif
> > --
> > 2.26.2
> >
>
>
[-- Attachment #2: Type: text/html, Size: 22332 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-08-18 9:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-16 19:58 [PATCH] fixed proc myself (linux user) for musl Андрей Аладьев
2020-08-16 21:42 ` Philippe Mathieu-Daudé
2020-08-16 22:21 ` Андрей Аладьев
2020-08-17 15:12 ` Laurent Vivier
2020-08-18 9:38 ` Андрей Аладьев
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).