Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 659016 Details for
Bug 587230
app-emulation/qemu - sys-apps/install-xattr segfaults in qemu-arm-user
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
final patch for qemu 5.1.0
execfd.patch (text/plain), 9.20 KB, created by
Andrew Aladjev
on 2020-09-07 18:06:09 UTC
(
hide
)
Description:
final patch for qemu 5.1.0
Filename:
MIME Type:
Creator:
Andrew Aladjev
Created:
2020-09-07 18:06:09 UTC
Size:
9.20 KB
patch
obsolete
>diff --git a/linux-user/elfload.c b/linux-user/elfload.c >index fe9dfe795d..353094da34 100644 >--- a/linux-user/elfload.c >+++ b/linux-user/elfload.c >@@ -2363,6 +2363,7 @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, > > IMAGE_NAME is the filename of the image, to use in error messages. > IMAGE_FD is the open file descriptor for the image. >+ WARNING : IMAGE_FD won't be closed. > > BPRM_BUF is a copy of the beginning of the file; this of course > contains the elf file header at offset 0. It is assumed that this >@@ -2632,7 +2633,6 @@ static void load_elf_image(const char *image_name, int image_fd, > > mmap_unlock(); > >- close(image_fd); > return; > > exit_read: >@@ -2666,6 +2666,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/main.c b/linux-user/main.c >index 75c9785157..29b61d4a09 100644 >--- a/linux-user/main.c >+++ b/linux-user/main.c >@@ -629,6 +629,7 @@ int main(int argc, char **argv, char **envp) > int target_argc; > int i; > int ret; >+ int at_execfd; > int execfd; > int log_mask; > unsigned long max_reserved_va; >@@ -690,13 +691,15 @@ int main(int argc, char **argv, char **envp) > > init_qemu_uname_release(); > >- execfd = qemu_getauxval(AT_EXECFD); >- if (execfd == 0) { >+ at_execfd = qemu_getauxval(AT_EXECFD); >+ if (at_execfd == 0) { > execfd = open(exec_path, O_RDONLY); > if (execfd < 0) { > printf("Error while loading %s: %s\n", exec_path, strerror(errno)); > _exit(EXIT_FAILURE); > } >+ } else { >+ execfd = at_execfd; > } > > if (cpu_model == NULL) { >@@ -811,6 +814,10 @@ int main(int argc, char **argv, char **envp) > > ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs, > info, &bprm); >+ /* We shouldn't close at_execfd, it may be used later. */ >+ if (execfd != at_execfd) { >+ close(execfd); >+ } > if (ret != 0) { > printf("Error while loading %s: %s\n", exec_path, strerror(-ret)); > _exit(EXIT_FAILURE); >diff --git a/linux-user/syscall.c b/linux-user/syscall.c >index 945fc25279..db90ba9dbc 100644 >--- a/linux-user/syscall.c >+++ b/linux-user/syscall.c >@@ -7482,38 +7482,69 @@ 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; >- } >+#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 0; >+ >+ 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; > } > > #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \ > defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA) >-static int is_proc(const char *filename, const char *entry) >+static int is_proc(const char *path, const char *entry) > { >- return strcmp(filename, entry) == 0; >+ char *scope_path = scope_to_proc(path); >+ if (scope_path == NULL) { >+ return 0; >+ } >+ >+ return strcmp(scope_path, entry) == 0; > } > #endif > >+static 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; >+} >+ > #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) > static int open_net_route(void *cpu_env, int fd) > { >@@ -7601,20 +7632,23 @@ 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) || defined(TARGET_HPPA) >- { "/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); >+ /* >+ * We can't use AT_EXECFD here. >+ * User can close provided fd and another user will receive closed fd. >+ */ >+ return safe_openat(dirfd, exec_path, flags, mode); > } > > for (fake_open = fakes; fake_open->filename; fake_open++) { >diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c >index 8a7c15cd31..bd370d973e 100644 >--- a/tests/tcg/multiarch/linux-test.c >+++ b/tests/tcg/multiarch/linux-test.c >@@ -517,6 +517,89 @@ static void test_shm(void) > chk_error(shmdt(ptr)); > } > >+static void test_proc_myself_file(void) >+{ >+ int fd1, fd2; >+ char link1[PATH_MAX], link2[PATH_MAX]; >+ char buf1[PATH_MAX], buf2[PATH_MAX]; >+ int buf1_length, buf2_length; >+ >+ /* We can open any file that will always exist. */ >+ const char *file_path = "/proc/self/comm"; >+ >+ char file_realpath[PATH_MAX]; >+ if (realpath(file_path, file_realpath) == NULL) { >+ error("proc myself: invalid file"); >+ } >+ >+ fd1 = chk_error(open(file_path, O_RDONLY)); >+ sprintf(link1, "/proc/self/fd/%d", fd1); >+ >+ /* Lets try to open same file by first link. */ >+ fd2 = chk_error(open(link1, O_RDONLY)); >+ sprintf(link2, "/proc/self/fd/%d", fd2); >+ >+ /* Two links should point to the same file path. */ >+ buf1_length = chk_error(readlink(link1, buf1, PATH_MAX)); >+ if (strlen(file_realpath) != buf1_length || >+ strncmp(file_realpath, buf1, buf1_length) != 0) { >+ error("proc myself: invalid link"); >+ } >+ buf2_length = chk_error(readlink(link2, buf2, PATH_MAX)); >+ if (strlen(file_realpath) != buf2_length || >+ strncmp(file_realpath, buf2, buf2_length) != 0) { >+ error("proc myself: invalid link"); >+ } >+ >+ /* We should be able to read same data from each fd. */ >+ buf1_length = chk_error(read(fd1, buf1, PATH_MAX)); >+ buf2_length = chk_error(read(fd2, buf2, PATH_MAX)); >+ if (buf1_length == 0 || buf1_length != buf2_length || >+ strncmp(buf1, buf2, buf2_length) != 0) { >+ error("proc myself: invalid file content"); >+ } >+ >+ chk_error(close(fd2)); >+ chk_error(close(fd1)); >+} >+ >+static void test_proc_myself_exe(void) >+{ >+ int fd1, fd2; >+ char link1[PATH_MAX], link2[PATH_MAX]; >+ char buf1[PATH_MAX], buf2[PATH_MAX]; >+ int buf1_length, buf2_length; >+ >+ const char *exe_path = "/proc/self/exe"; >+ >+ char exe_realpath[PATH_MAX]; >+ if (realpath(exe_path, exe_realpath) == NULL) { >+ error("proc myself: invalid exe"); >+ } >+ >+ fd1 = chk_error(open(exe_path, O_RDONLY)); >+ sprintf(link1, "/proc/self/fd/%d", fd1); >+ >+ /* Lets try to open link once again. */ >+ fd2 = chk_error(open(link1, O_RDONLY)); >+ sprintf(link2, "/proc/self/fd/%d", fd2); >+ >+ /* Two links should point to the same exe path. */ >+ buf1_length = chk_error(readlink(link1, buf1, PATH_MAX)); >+ if (strlen(exe_realpath) != buf1_length || >+ strncmp(exe_realpath, buf1, buf1_length) != 0) { >+ error("proc myself: invalid link"); >+ } >+ buf2_length = chk_error(readlink(link2, buf2, PATH_MAX)); >+ if (strlen(exe_realpath) != buf2_length || >+ strncmp(exe_realpath, buf2, buf2_length) != 0) { >+ error("proc myself: invalid link"); >+ } >+ >+ chk_error(close(fd2)); >+ chk_error(close(fd1)); >+} >+ > int main(int argc, char **argv) > { > test_file(); >@@ -532,5 +615,7 @@ int main(int argc, char **argv) > > test_signal(); > test_shm(); >+ test_proc_myself_file(); >+ test_proc_myself_exe(); > return 0; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 587230
:
653834
|
654506
|
654982
| 659016