From nobody Wed May 1 15:26:12 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1566418828; cv=none; d=zoho.com; s=zohoarc; b=MEj6ADh+rMZFqZHuQoCwWfwUbXbBpjQ4zLxvt24SfQ6etDbwLZsfI4QR+3aMmDUgwcH8XeKOFJiTyGHbzVrcNDbTSAvX9m2YavKM0SVTtnYnVmYGG1pY5V1tqsBJuDnQDf0NhWAKBEXhMI80+3zbqfej6QtZzQn9PR44/bxNfwM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1566418828; h=Content-Type:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To:ARC-Authentication-Results; bh=s+ndl3VqHc//jkjH2CP3u+dZiSg4o9u5DjFzgvWfkBo=; b=bwwginKr9sraLNlXksyNc2vboQ/MGPRY1DnVMoyVlvw3I1d77zw76CLXJggFAaQki84KaQvgKGGkX3O0p3mUM2aFqZInhOJF+MBfcDQm9b9uWDVPrOX5L2vtJ+rGcrLk+U1nEcvvve6vWnI8Mnrta3Z5m4ek3ltSzzWeS6H+L0o= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1566418828656617.8273151275029; Wed, 21 Aug 2019 13:20:28 -0700 (PDT) Received: from localhost ([::1]:54248 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i0X5h-0007rG-T8 for importer@patchew.org; Wed, 21 Aug 2019 16:20:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60471) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <3TqddXQMKCgUxh1lttlqj.htrvjrz-ij0jqstslsz.twl@flex--scw.bounces.google.com>) id 1i0X4t-0007SP-Ak for qemu-devel@nongnu.org; Wed, 21 Aug 2019 16:19:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <3TqddXQMKCgUxh1lttlqj.htrvjrz-ij0jqstslsz.twl@flex--scw.bounces.google.com>) id 1i0X4s-0000h4-2K for qemu-devel@nongnu.org; Wed, 21 Aug 2019 16:19:31 -0400 Received: from mail-yw1-xc49.google.com ([2607:f8b0:4864:20::c49]:48818) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from <3TqddXQMKCgUxh1lttlqj.htrvjrz-ij0jqstslsz.twl@flex--scw.bounces.google.com>) id 1i0X4r-0000gK-ST for qemu-devel@nongnu.org; Wed, 21 Aug 2019 16:19:30 -0400 Received: by mail-yw1-xc49.google.com with SMTP id h22so2301747ywk.15 for ; Wed, 21 Aug 2019 13:19:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=s+ndl3VqHc//jkjH2CP3u+dZiSg4o9u5DjFzgvWfkBo=; b=f/IPOlTXC68gaWZdaAybXxC8mD92sMUN3lIUs/D3mnhFBmS7tnkR4GXl5ZSYAfOTNy UNNE7OSft0y2bte7xaTShrPnHf74uwy79j5C4z48XjtXYm4NDBnV2NWYlhKyC+rTDY7O YO2+Yiphjo0JCODHQOkuRy/TuNzHRUHctW0VoA4RfgeW9xRNF+I3RycZZM9UxElKWyrl Wu3+NFnwdnrd2OdRzgO6oqRLbQ7+GnNWxbYxXARmGFafJ99HxjCDKB7y/kdqBtpgOwXr 2A2rg5vSsrLCV2cx4UpcyA82Q6QIj7JDLC4uxuu0/o7awQu/jnmYeDBaprVJs7NTdOby G4KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=s+ndl3VqHc//jkjH2CP3u+dZiSg4o9u5DjFzgvWfkBo=; b=pTG23VlbmTz3FiTy3hwglBNypK7R7Z5jLa4/Xwybtnz/S+bV8FyENzrKJbOHNCqsMB gF+y9wFQxxwGQfShkOpg47LBhT+PYkrwjpV1nHT8FVxl2klgKnqTNwEIEsSEP8J45es+ XnR6Cfci0z5RBuvWGQ2ZIk4cZV5aqEdk1Ad/m7pGXlrdXixUoVQs0+OkLs0oQvH3HGdp zDUfLoL6AtAYyg57FWl62UpjTyKIDQZHT5XbcIIfSvl6MHjc7sJ3YZPI6E0ozwaQMRFq xF4hl/q51jc+eAYCGoJZ7475flT6z547uVH1OPsdw63ZEajfmkygXaZL4VToPNk3B+iZ A1RA== X-Gm-Message-State: APjAAAXnHbbe7daCwS2P2cUqsZgZx42PhKpHBP6KTrb8fNqvqPMliPWY DjiVqY6C8bRgjBqo9u/rExwK/R8= X-Google-Smtp-Source: APXvYqxmQjvQDNb4FD1GwdXWF8mBZH90ie5+X50odV49sID4k94fNG46JR+51ps3R+W7z2QncksmhkQ= X-Received: by 2002:a0d:df8e:: with SMTP id i136mr26313949ywe.19.1566418766993; Wed, 21 Aug 2019 13:19:26 -0700 (PDT) Date: Wed, 21 Aug 2019 13:19:21 -0700 Message-Id: <20190821201921.106902-1-scw@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.23.0.rc1.153.gdeed80330f-goog To: Laurent Vivier X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::c49 Subject: [Qemu-devel] [PATCH] linux-user: hijack open() for thread directories X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Shu-Chun Weng via Qemu-devel Reply-To: Shu-Chun Weng Cc: Riku Voipio , qemu-devel@nongnu.org, Shu-Chun Weng Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 =3D fopen(buf, "r"); if (fp =3D=3D 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 =3D fopen(buf, "r"); if (fp =3D=3D NULL) { printf("%s: can't open %s\n", cxt, buf); } else { char seen[128][128]; int n =3D 0, is_new =3D 0; while(fgets(buf, sizeof(buf), fp) !=3D NULL) { const char* p =3D strrchr(buf, ' '); if (p =3D=3D NULL || *(p + 1) =3D=3D '\n') { continue; } ++p; is_new =3D 1; for (int i =3D 0; i < n; ++i) { if (strncmp(p, seen[i], sizeof(seen[i])) =3D=3D 0) { is_new =3D 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] =3D '\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_th= read_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 =3D 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_th= read_tid); print_info("Main", buf); if ((ret =3D pthread_create(&thread, NULL, &thread_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; } =20 +static int consume_task_directories(const char **filename) +{ + if (!strncmp(*filename, "task/", strlen("task/"))) { + *filename +=3D 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 =3D *filename + 1; + while (*p >=3D '0' && *p <=3D '9') { + ++p; + } + if (*p =3D=3D '/') { + *filename =3D p + 1; + return 1; + } else { + return 0; + } + } + return 1; +} + +/* + * Determines if filename refer to a procfs file for the current process o= r 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 +=3D strlen("/proc/"); if (!strncmp(filename, "self/", strlen("self/"))) { filename +=3D strlen("self/"); + if (!consume_task_directories(&filename)) { + return 0; + } + } else if (!strncmp(filename, "thread-self/", strlen("thread-self/= "))) { + filename +=3D strlen("thread-self/"); } else if (*filename >=3D '1' && *filename <=3D '9') { char myself[80]; snprintf(myself, sizeof(myself), "%d/", getpid()); if (!strncmp(filename, myself, strlen(myself))) { filename +=3D strlen(myself); + if (!consume_task_directories(&filename)) { + return 0; + } } else { return 0; } --=20 2.23.0.rc1.153.gdeed80330f-goog