Re: [Qemu-devel] [PATCH] linux-user: hijack open() for thread directories
Hi Shu-Chun Weng via Qemu-devel! We received your email, but were unable to deliver it because it contains content which has been blacklisted by the list admin. Please remove your application/pkcs7-signature attachments and send again. You are also advised to configure your email client to send emails in plain text to avoid additional errors in the future: https://useplaintext.email If you have any questions, please reply to this email to reach the mail admin. We apologise for the inconvenience.
Re: [Qemu-devel] [PATCH] linux-user: hijack open() for thread directories
Ping. Any comments on this? Patchwork: http://patchwork.ozlabs.org/patch/1151167/ On Wed, Aug 21, 2019 at 1:19 PM Shu-Chun Weng wrote: > Besides /proc/self|, files under /proc/thread-self and > /proc/self|/task/ also expose host information to the guest > program. This patch adds them to the hijack infrastracture. Note that > is_proc_myself() does not check if the matches the current thread > and is thus only suitable for procfs files that are identical for all > threads in the same process. > > Behavior verified with guest program: > > long main_thread_tid; > > long gettid() { > return syscall(SYS_gettid); > } > > void print_info(const char* cxt, const char* dir) { > char buf[1024]; > FILE* fp; > > snprintf(buf, sizeof(buf), "%s/cmdline", dir); > fp = fopen(buf, "r"); > > if (fp == NULL) { > printf("%s: can't open %s\n", cxt, buf); > } else { > fgets(buf, sizeof(buf), fp); > printf("%s %s cmd: %s\n", cxt, dir, buf); > fclose(fp); > } > > snprintf(buf, sizeof(buf), "%s/maps", dir); > fp = fopen(buf, "r"); > > if (fp == NULL) { > printf("%s: can't open %s\n", cxt, buf); > } else { > char seen[128][128]; > int n = 0, is_new = 0; > while(fgets(buf, sizeof(buf), fp) != NULL) { > const char* p = strrchr(buf, ' '); > if (p == NULL || *(p + 1) == '\n') { > continue; > } > ++p; > is_new = 1; > for (int i = 0; i < n; ++i) { > if (strncmp(p, seen[i], sizeof(seen[i])) == 0) { > is_new = 0; > break; > } > } > if (is_new) { > printf("%s %s map: %s", cxt, dir, p); > if (n < 128) { > strncpy(seen[n], p, sizeof(seen[n])); > seen[n][sizeof(seen[n]) - 1] = '\0'; > ++n; > } > } > } > fclose(fp); > } > } > > void* thread_main(void* _) { > char buf[1024]; > > print_info("Child", "/proc/thread-self"); > > snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), > main_thread_tid); > print_info("Child", buf); > > snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), (long) > gettid()); > print_info("Child", buf); > > return NULL; > } > > int main() { > char buf[1024]; > pthread_t thread; > int ret; > > print_info("Main", "/proc/thread-self"); > print_info("Main", "/proc/self"); > > snprintf(buf, sizeof(buf), "/proc/%ld", (long) getpid()); > print_info("Main", buf); > > main_thread_tid = gettid(); > snprintf(buf, sizeof(buf), "/proc/self/task/%ld", main_thread_tid); > print_info("Main", buf); > > snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), > main_thread_tid); > print_info("Main", buf); > > if ((ret = pthread_create(, NULL, _main, NULL)) < 0) { > printf("ptherad_create failed: %s (%d)\n", strerror(ret), ret); > } > > pthread_join(thread, NULL); > return 0; > } > > Signed-off-by: Shu-Chun Weng > --- > linux-user/syscall.c | 40 > 1 file changed, 40 insertions(+) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 8367cb138d..73fe82bcc7 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -6968,17 +6968,57 @@ static int open_self_auxv(void *cpu_env, int fd) > return 0; > } > > +static int consume_task_directories(const char **filename) > +{ > +if (!strncmp(*filename, "task/", strlen("task/"))) { > +*filename += strlen("task/"); > +if (**filename < '1' || **filename > '9') { > +return 0; > +} > +/* > + * Don't care about the exact tid. > + * XXX: this allows opening files under /proc/self|/task/ > where > + * is not a valid thread id. Consider checking if the > file > + * actually exists. > + */ > +const char *p = *filename + 1; > +while (*p >= '0' && *p <= '9') { > +++p; > +} > +if (*p == '/') { > +*filename = p + 1; > +return 1; > +} else { > +return 0; > +} > +} > +return 1; > +} > + > +/* > + * Determines if filename refer to a procfs file for the current process > or any > + * thread within the current process. This function should only be used > to check > + * for files that have identical contents in all threads, e.g. exec, > maps, etc. > + */ > 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/"); > +if (!consume_task_directories()) { > +return 0; > +} > +} else if (!strncmp(filename, "thread-self/", > strlen("thread-self/"))) { > +filename += strlen("thread-self/"); > } else if (*filename >= '1' && *filename <= '9') { > char
Re: [Qemu-devel] [PATCH] linux-user: hijack open() for thread directories
Patchew URL: https://patchew.org/QEMU/20190821201921.106902-1-...@google.com/ Hi, This series seems to have some coding style problems. See output below for more information: Type: series Subject: [Qemu-devel] [PATCH] linux-user: hijack open() for thread directories Message-id: 20190821201921.106902-1-...@google.com === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu * [new tag] patchew/20190821201921.106902-1-...@google.com -> patchew/20190821201921.106902-1-...@google.com Submodule 'capstone' (https://git.qemu.org/git/capstone.git) registered for path 'capstone' Submodule 'dtc' (https://git.qemu.org/git/dtc.git) registered for path 'dtc' Submodule 'roms/QemuMacDrivers' (https://git.qemu.org/git/QemuMacDrivers.git) registered for path 'roms/QemuMacDrivers' Submodule 'roms/SLOF' (https://git.qemu.org/git/SLOF.git) registered for path 'roms/SLOF' Submodule 'roms/edk2' (https://git.qemu.org/git/edk2.git) registered for path 'roms/edk2' Submodule 'roms/ipxe' (https://git.qemu.org/git/ipxe.git) registered for path 'roms/ipxe' Submodule 'roms/openbios' (https://git.qemu.org/git/openbios.git) registered for path 'roms/openbios' Submodule 'roms/openhackware' (https://git.qemu.org/git/openhackware.git) registered for path 'roms/openhackware' Submodule 'roms/opensbi' (https://git.qemu.org/git/opensbi.git) registered for path 'roms/opensbi' Submodule 'roms/qemu-palcode' (https://git.qemu.org/git/qemu-palcode.git) registered for path 'roms/qemu-palcode' Submodule 'roms/seabios' (https://git.qemu.org/git/seabios.git/) registered for path 'roms/seabios' Submodule 'roms/seabios-hppa' (https://git.qemu.org/git/seabios-hppa.git) registered for path 'roms/seabios-hppa' Submodule 'roms/sgabios' (https://git.qemu.org/git/sgabios.git) registered for path 'roms/sgabios' Submodule 'roms/skiboot' (https://git.qemu.org/git/skiboot.git) registered for path 'roms/skiboot' Submodule 'roms/u-boot' (https://git.qemu.org/git/u-boot.git) registered for path 'roms/u-boot' Submodule 'roms/u-boot-sam460ex' (https://git.qemu.org/git/u-boot-sam460ex.git) registered for path 'roms/u-boot-sam460ex' Submodule 'slirp' (https://git.qemu.org/git/libslirp.git) registered for path 'slirp' Submodule 'tests/fp/berkeley-softfloat-3' (https://git.qemu.org/git/berkeley-softfloat-3.git) registered for path 'tests/fp/berkeley-softfloat-3' Submodule 'tests/fp/berkeley-testfloat-3' (https://git.qemu.org/git/berkeley-testfloat-3.git) registered for path 'tests/fp/berkeley-testfloat-3' Submodule 'ui/keycodemapdb' (https://git.qemu.org/git/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into 'capstone'... Submodule path 'capstone': checked out '22ead3e0bfdb87516656453336160e0a37b066bf' Cloning into 'dtc'... Submodule path 'dtc': checked out '88f18909db731a627456f26d779445f84e449536' Cloning into 'roms/QemuMacDrivers'... Submodule path 'roms/QemuMacDrivers': checked out '90c488d5f4a407342247b9ea869df1c2d9c8e266' Cloning into 'roms/SLOF'... Submodule path 'roms/SLOF': checked out '7bfe584e321946771692711ff83ad2b5850daca7' Cloning into 'roms/edk2'... Submodule path 'roms/edk2': checked out '20d2e5a125e34fc8501026613a71549b2a1a3e54' Submodule 'SoftFloat' (https://github.com/ucb-bar/berkeley-softfloat-3.git) registered for path 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3' Submodule 'CryptoPkg/Library/OpensslLib/openssl' (https://github.com/openssl/openssl) registered for path 'CryptoPkg/Library/OpensslLib/openssl' Cloning into 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3'... Submodule path 'roms/edk2/ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3': checked out 'b64af41c3276f97f0e181920400ee056b9c88037' Cloning into 'CryptoPkg/Library/OpensslLib/openssl'... Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl': checked out '50eaac9f3337667259de725451f201e784599687' Submodule 'boringssl' (https://boringssl.googlesource.com/boringssl) registered for path 'boringssl' Submodule 'krb5' (https://github.com/krb5/krb5) registered for path 'krb5' Submodule 'pyca.cryptography' (https://github.com/pyca/cryptography.git) registered for path 'pyca-cryptography' Cloning into 'boringssl'... Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl': checked out '2070f8ad9151dc8f3a73bffaa146b5e6937a583f' Cloning into 'krb5'... Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5': checked out 'b9ad6c49505c96a088326b62a52568e3484f2168' Cloning into 'pyca-cryptography'... Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/pyca-cryptography': checked out '09403100de2f6f1cdd0d484dcb8e620f1c335c8f' Cloning into 'roms/ipxe'... Submodul
[Qemu-devel] [PATCH] linux-user: hijack open() for thread directories
Besides /proc/self|, files under /proc/thread-self and /proc/self|/task/ also expose host information to the guest program. This patch adds them to the hijack infrastracture. Note that is_proc_myself() does not check if the matches the current thread and is thus only suitable for procfs files that are identical for all threads in the same process. Behavior verified with guest program: long main_thread_tid; long gettid() { return syscall(SYS_gettid); } void print_info(const char* cxt, const char* dir) { char buf[1024]; FILE* fp; snprintf(buf, sizeof(buf), "%s/cmdline", dir); fp = fopen(buf, "r"); if (fp == NULL) { printf("%s: can't open %s\n", cxt, buf); } else { fgets(buf, sizeof(buf), fp); printf("%s %s cmd: %s\n", cxt, dir, buf); fclose(fp); } snprintf(buf, sizeof(buf), "%s/maps", dir); fp = fopen(buf, "r"); if (fp == NULL) { printf("%s: can't open %s\n", cxt, buf); } else { char seen[128][128]; int n = 0, is_new = 0; while(fgets(buf, sizeof(buf), fp) != NULL) { const char* p = strrchr(buf, ' '); if (p == NULL || *(p + 1) == '\n') { continue; } ++p; is_new = 1; for (int i = 0; i < n; ++i) { if (strncmp(p, seen[i], sizeof(seen[i])) == 0) { is_new = 0; break; } } if (is_new) { printf("%s %s map: %s", cxt, dir, p); if (n < 128) { strncpy(seen[n], p, sizeof(seen[n])); seen[n][sizeof(seen[n]) - 1] = '\0'; ++n; } } } fclose(fp); } } void* thread_main(void* _) { char buf[1024]; print_info("Child", "/proc/thread-self"); snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), main_thread_tid); print_info("Child", buf); snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), (long) gettid()); print_info("Child", buf); return NULL; } int main() { char buf[1024]; pthread_t thread; int ret; print_info("Main", "/proc/thread-self"); print_info("Main", "/proc/self"); snprintf(buf, sizeof(buf), "/proc/%ld", (long) getpid()); print_info("Main", buf); main_thread_tid = gettid(); snprintf(buf, sizeof(buf), "/proc/self/task/%ld", main_thread_tid); print_info("Main", buf); snprintf(buf, sizeof(buf), "/proc/%ld/task/%ld", (long) getpid(), main_thread_tid); print_info("Main", buf); if ((ret = pthread_create(, NULL, _main, NULL)) < 0) { printf("ptherad_create failed: %s (%d)\n", strerror(ret), ret); } pthread_join(thread, NULL); return 0; } Signed-off-by: Shu-Chun Weng --- linux-user/syscall.c | 40 1 file changed, 40 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8367cb138d..73fe82bcc7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6968,17 +6968,57 @@ static int open_self_auxv(void *cpu_env, int fd) return 0; } +static int consume_task_directories(const char **filename) +{ +if (!strncmp(*filename, "task/", strlen("task/"))) { +*filename += strlen("task/"); +if (**filename < '1' || **filename > '9') { +return 0; +} +/* + * Don't care about the exact tid. + * XXX: this allows opening files under /proc/self|/task/ where + * is not a valid thread id. Consider checking if the file + * actually exists. + */ +const char *p = *filename + 1; +while (*p >= '0' && *p <= '9') { +++p; +} +if (*p == '/') { +*filename = p + 1; +return 1; +} else { +return 0; +} +} +return 1; +} + +/* + * Determines if filename refer to a procfs file for the current process or any + * thread within the current process. This function should only be used to check + * for files that have identical contents in all threads, e.g. exec, maps, etc. + */ 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/"); +if (!consume_task_directories()) { +return 0; +} +} else if (!strncmp(filename, "thread-self/", strlen("thread-self/"))) { +filename += strlen("thread-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); +if (!consume_task_directories()) { +return 0; +} } else { return 0; } -- 2.23.0.rc1.153.gdeed80330f-goog