From patchwork Mon Jun 12 18:30:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 70934 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3B6003857723 for ; Mon, 12 Jun 2023 18:30:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3B6003857723 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1686594650; bh=3UPUuRTI36dOIg9exyQq9KS66i0ggIGtuF6A/IcT+BM=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=J3Zf4XAvSAZeuE5RkZ+2Gz9gYiIRIpExIJbhruwyI+XxdiHOANYk/fS2gNEwkDxtr fPIH5awq3oLJniPVtX1NTm7jtR9bc+qZ48WAc0c96FJ+lJBu43+ZGZ0RVbRcgOCYlB DEMdkvcpY+40cnvyJoiSdjtbTYbYh72I0lfJaRyY= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-oi1-x234.google.com (mail-oi1-x234.google.com [IPv6:2607:f8b0:4864:20::234]) by sourceware.org (Postfix) with ESMTPS id 90C063858CDB for ; Mon, 12 Jun 2023 18:30:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 90C063858CDB Received: by mail-oi1-x234.google.com with SMTP id 5614622812f47-392116ae103so2656578b6e.0 for ; Mon, 12 Jun 2023 11:30:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686594621; x=1689186621; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3UPUuRTI36dOIg9exyQq9KS66i0ggIGtuF6A/IcT+BM=; b=LbdM0NMXwuzhT5v3raVvXW6da3jt+lm/r1EkhH5HR895rs1qEvegxyXgFFBS63Pu4m 7W+Xs2hrky6MmMlgJiizYwsmD+qOhf6F9CAHFAirZ9oPqEiL0bi/gTLCcktjijAN7LrD 6mKeupANjqPxGTf2VbHMQ+TfqHVMlr9eaQo3uVRCJAqt23vXvvBKPPizV48MQUokCyw8 n9onizv7AozkYuXD+AWqOAOCbVQRTDVuTw2HRT8foRY+LNNmPJ6tLueDc0TNBZSKZlnn VG+AQ4Ai5ALwMNtk9ZUBwGBpOXXBnD45evMJobACuSPLoQyRUzri/b7VczoFb0z0sqUA Ui7w== X-Gm-Message-State: AC+VfDxCYK+7mnxfTosdLj+17Yn4jMudkq7AJVUurzgZOGlu/G478qgk M6CQZBssGhFeH+zCyhN9GMPpCoiraNen9qZ6wU0CiA== X-Google-Smtp-Source: ACHHUZ4axQFgTvTG1Sr3nLjJ3/5tW8FhYiiUepYODDmxDi+GCti7dRlKWJyys1EJV6DaU2Qw7Yy0Zg== X-Received: by 2002:aca:120c:0:b0:397:ec35:f5a6 with SMTP id 12-20020aca120c000000b00397ec35f5a6mr4525073ois.57.1686594620766; Mon, 12 Jun 2023 11:30:20 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c2:8501:af26:cdf:f789:4317]) by smtp.gmail.com with ESMTPSA id r5-20020acaf305000000b003896e31867esm4472095oih.49.2023.06.12.11.30.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Jun 2023 11:30:20 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 1/2] linux: Split tst-ttyname Date: Mon, 12 Jun 2023 15:30:13 -0300 Message-Id: <20230612183014.882895-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230612183014.882895-1-adhemerval.zanella@linaro.org> References: <20230612183014.882895-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The tst-ttyname-direct.c checks the ttyname with procfs mounted in bind mode (MS_BIND|MS_REC), while tst-ttyname-namespace.c checks with procfs mount with MS_NOSUID|MS_NOEXEC|MS_NODEV in a new namespace. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reviewed-by: Siddhesh Poyarekar --- sysdeps/unix/sysv/linux/Makefile | 3 +- .../{tst-ttyname.c => tst-ttyname-common.c} | 208 +----------------- sysdeps/unix/sysv/linux/tst-ttyname-direct.c | 110 +++++++++ .../unix/sysv/linux/tst-ttyname-namespace.c | 143 ++++++++++++ 4 files changed, 259 insertions(+), 205 deletions(-) rename sysdeps/unix/sysv/linux/{tst-ttyname.c => tst-ttyname-common.c} (68%) create mode 100644 sysdeps/unix/sysv/linux/tst-ttyname-direct.c create mode 100644 sysdeps/unix/sysv/linux/tst-ttyname-namespace.c diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 594a5dc53e..23a84cf225 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -224,7 +224,8 @@ tests += \ tst-sysvshm-linux \ tst-tgkill \ tst-timerfd \ - tst-ttyname \ + tst-ttyname-direct \ + tst-ttyname-namespace \ # tests # process_madvise requires CAP_SYS_ADMIN. diff --git a/sysdeps/unix/sysv/linux/tst-ttyname.c b/sysdeps/unix/sysv/linux/tst-ttyname-common.c similarity index 68% rename from sysdeps/unix/sysv/linux/tst-ttyname.c rename to sysdeps/unix/sysv/linux/tst-ttyname-common.c index ef55665fbe..3f6d8ee944 100644 --- a/sysdeps/unix/sysv/linux/tst-ttyname.c +++ b/sysdeps/unix/sysv/linux/tst-ttyname-common.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2017-2023 Free Software Foundation, Inc. +/* Common definitions for ttyname tests. + Copyright (C) 2017-2023 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,19 +20,16 @@ #include #include #include -#include +#include #include #include #include #include -#include -#include -#include #include +#include #include #include -#include #include #include #include @@ -266,187 +264,6 @@ adjust_file_limit (const char *pty) } } -/* These chroot setup functions put the TTY at at "/console" (where it - won't be found by ttyname), and create "/dev/console" as an - ordinary file. This way, it's easier to write test-cases that - expect ttyname to fail; test-cases that expect it to succeed need - to explicitly remount it at "/dev/console". */ - -static int -do_in_chroot_1 (int (*cb)(const char *, int)) -{ - printf ("info: entering chroot 1\n"); - - /* Open the PTS that we'll be testing on. */ - int master; - char *slavename; - master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK); - if (master < 0) - { - if (errno == ENOENT) - FAIL_UNSUPPORTED ("posix_openpt: %m"); - else - FAIL_EXIT1 ("posix_openpt: %m"); - } - VERIFY ((slavename = ptsname (master))); - VERIFY (unlockpt (master) == 0); - if (strncmp (slavename, "/dev/pts/", 9) != 0) - FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", - slavename); - adjust_file_limit (slavename); - int slave = xopen (slavename, O_RDWR, 0); - if (!doit (slave, "basic smoketest", - (struct result_r){.name=slavename, .ret=0, .err=0})) - return 1; - - pid_t pid = xfork (); - if (pid == 0) - { - xclose (master); - - if (!support_enter_mount_namespace ()) - FAIL_UNSUPPORTED ("could not enter new mount namespace"); - - VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); - VERIFY (chdir (chrootdir) == 0); - - xmkdir ("proc", 0755); - xmkdir ("dev", 0755); - xmkdir ("dev/pts", 0755); - - VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0); - VERIFY (mount ("devpts", "dev/pts", "devpts", - MS_NOSUID|MS_NOEXEC, - "newinstance,ptmxmode=0666,mode=620") == 0); - VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); - - touch ("console", 0); - touch ("dev/console", 0); - VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); - - xchroot ("."); - - char *linkname = xasprintf ("/proc/self/fd/%d", slave); - char *target = proc_fd_readlink (linkname); - VERIFY (strcmp (target, slavename) == 0); - free (linkname); - - _exit (cb (slavename, slave)); - } - int status; - xwaitpid (pid, &status, 0); - VERIFY (WIFEXITED (status)); - xclose (master); - xclose (slave); - return WEXITSTATUS (status); -} - -static int -do_in_chroot_2 (int (*cb)(const char *, int)) -{ - printf ("info: entering chroot 2\n"); - - int pid_pipe[2]; - xpipe (pid_pipe); - int exit_pipe[2]; - xpipe (exit_pipe); - - /* Open the PTS that we'll be testing on. */ - int master; - char *slavename; - VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0); - VERIFY ((slavename = ptsname (master))); - VERIFY (unlockpt (master) == 0); - if (strncmp (slavename, "/dev/pts/", 9) != 0) - FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", - slavename); - adjust_file_limit (slavename); - /* wait until in a new mount ns to open the slave */ - - /* enable `wait`ing on grandchildren */ - VERIFY (prctl (PR_SET_CHILD_SUBREAPER, 1) == 0); - - pid_t pid = xfork (); /* outer child */ - if (pid == 0) - { - xclose (master); - xclose (pid_pipe[0]); - xclose (exit_pipe[1]); - - if (!support_enter_mount_namespace ()) - FAIL_UNSUPPORTED ("could not enter new mount namespace"); - - int slave = xopen (slavename, O_RDWR, 0); - if (!doit (slave, "basic smoketest", - (struct result_r){.name=slavename, .ret=0, .err=0})) - _exit (1); - - VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); - VERIFY (chdir (chrootdir) == 0); - - xmkdir ("proc", 0755); - xmkdir ("dev", 0755); - xmkdir ("dev/pts", 0755); - - VERIFY (mount ("devpts", "dev/pts", "devpts", - MS_NOSUID|MS_NOEXEC, - "newinstance,ptmxmode=0666,mode=620") == 0); - VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); - - touch ("console", 0); - touch ("dev/console", 0); - VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); - - xchroot ("."); - - if (unshare (CLONE_NEWNS | CLONE_NEWPID) < 0) - FAIL_UNSUPPORTED ("could not enter new PID namespace"); - pid = xfork (); /* inner child */ - if (pid == 0) - { - xclose (pid_pipe[1]); - - /* wait until the outer child has exited */ - char c; - VERIFY (read (exit_pipe[0], &c, 1) == 0); - xclose (exit_pipe[0]); - - VERIFY (mount ("proc", "/proc", "proc", - MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) == 0); - - char *linkname = xasprintf ("/proc/self/fd/%d", slave); - char *target = proc_fd_readlink (linkname); - VERIFY (strcmp (target, strrchr (slavename, '/')) == 0); - free (linkname); - - _exit (cb (slavename, slave)); - } - xwrite (pid_pipe[1], &pid, sizeof pid); - _exit (0); - } - xclose (pid_pipe[1]); - xclose (exit_pipe[0]); - xclose (exit_pipe[1]); - - /* wait for the outer child */ - int status; - xwaitpid (pid, &status, 0); - VERIFY (WIFEXITED (status)); - int ret = WEXITSTATUS (status); - if (ret != 0) - return ret; - - /* set 'pid' to the inner child */ - VERIFY (read (pid_pipe[0], &pid, sizeof pid) == sizeof pid); - xclose (pid_pipe[0]); - - /* wait for the inner child */ - xwaitpid (pid, &status, 0); - VERIFY (WIFEXITED (status)); - xclose (master); - return WEXITSTATUS (status); -} - /* main test */ static int @@ -597,20 +414,3 @@ run_chroot_tests (const char *slavename, int slave) return ok ? 0 : 1; } -static int -do_test (void) -{ - support_become_root (); - - int ret1 = do_in_chroot_1 (run_chroot_tests); - if (ret1 == EXIT_UNSUPPORTED) - return ret1; - - int ret2 = do_in_chroot_2 (run_chroot_tests); - if (ret2 == EXIT_UNSUPPORTED) - return ret2; - - return ret1 | ret2; -} - -#include diff --git a/sysdeps/unix/sysv/linux/tst-ttyname-direct.c b/sysdeps/unix/sysv/linux/tst-ttyname-direct.c new file mode 100644 index 0000000000..04601777d6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-ttyname-direct.c @@ -0,0 +1,110 @@ +/* Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see . */ + +#include +#include + +#include + +#include "tst-ttyname-common.c" + +/* These chroot setup functions put the TTY at at "/console" (where it + won't be found by ttyname), and create "/dev/console" as an + ordinary file. This way, it's easier to write test-cases that + expect ttyname to fail; test-cases that expect it to succeed need + to explicitly remount it at "/dev/console". */ + +static int +do_in_chroot_1 (int (*cb)(const char *, int)) +{ + printf ("info: entering chroot 1\n"); + + /* Open the PTS that we'll be testing on. */ + int master; + char *slavename; + master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK); + if (master < 0) + { + if (errno == ENOENT) + FAIL_UNSUPPORTED ("posix_openpt: %m"); + else + FAIL_EXIT1 ("posix_openpt: %m"); + } + VERIFY ((slavename = ptsname (master))); + VERIFY (unlockpt (master) == 0); + if (strncmp (slavename, "/dev/pts/", 9) != 0) + FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", + slavename); + adjust_file_limit (slavename); + int slave = xopen (slavename, O_RDWR, 0); + if (!doit (slave, "basic smoketest", + (struct result_r){.name=slavename, .ret=0, .err=0})) + return 1; + + pid_t pid = xfork (); + if (pid == 0) + { + xclose (master); + + if (!support_enter_mount_namespace ()) + FAIL_UNSUPPORTED ("could not enter new mount namespace"); + + VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); + VERIFY (chdir (chrootdir) == 0); + + xmkdir ("proc", 0755); + xmkdir ("dev", 0755); + xmkdir ("dev/pts", 0755); + + VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0); + VERIFY (mount ("devpts", "dev/pts", "devpts", + MS_NOSUID|MS_NOEXEC, + "newinstance,ptmxmode=0666,mode=620") == 0); + VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); + + touch ("console", 0); + touch ("dev/console", 0); + VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); + + xchroot ("."); + + char *linkname = xasprintf ("/proc/self/fd/%d", slave); + char *target = proc_fd_readlink (linkname); + VERIFY (strcmp (target, slavename) == 0); + free (linkname); + + _exit (cb (slavename, slave)); + } + int status; + xwaitpid (pid, &status, 0); + VERIFY (WIFEXITED (status)); + xclose (master); + xclose (slave); + return WEXITSTATUS (status); +} + +static int +do_test (void) +{ + support_become_root (); + + do_in_chroot_1 (run_chroot_tests); + + return 0; +} + +#include diff --git a/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c new file mode 100644 index 0000000000..1f38442747 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c @@ -0,0 +1,143 @@ +/* Tests for ttyname/ttyname_r with namespaces. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see . */ + +#include +#include +#include + +#include + +#include "tst-ttyname-common.c" + +static int +do_in_chroot_2 (int (*cb)(const char *, int)) +{ + printf ("info: entering chroot 2\n"); + + int pid_pipe[2]; + xpipe (pid_pipe); + int exit_pipe[2]; + xpipe (exit_pipe); + + /* Open the PTS that we'll be testing on. */ + int master; + char *slavename; + VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0); + VERIFY ((slavename = ptsname (master))); + VERIFY (unlockpt (master) == 0); + if (strncmp (slavename, "/dev/pts/", 9) != 0) + FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s", + slavename); + adjust_file_limit (slavename); + /* wait until in a new mount ns to open the slave */ + + /* enable `wait`ing on grandchildren */ + VERIFY (prctl (PR_SET_CHILD_SUBREAPER, 1) == 0); + + pid_t pid = xfork (); /* outer child */ + if (pid == 0) + { + xclose (master); + xclose (pid_pipe[0]); + xclose (exit_pipe[1]); + + if (!support_enter_mount_namespace ()) + FAIL_UNSUPPORTED ("could not enter new mount namespace"); + + int slave = xopen (slavename, O_RDWR, 0); + if (!doit (slave, "basic smoketest", + (struct result_r){.name=slavename, .ret=0, .err=0})) + _exit (1); + + VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0); + VERIFY (chdir (chrootdir) == 0); + + xmkdir ("proc", 0755); + xmkdir ("dev", 0755); + xmkdir ("dev/pts", 0755); + + VERIFY (mount ("devpts", "dev/pts", "devpts", + MS_NOSUID|MS_NOEXEC, + "newinstance,ptmxmode=0666,mode=620") == 0); + VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0); + + touch ("console", 0); + touch ("dev/console", 0); + VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0); + + xchroot ("."); + + if (unshare (CLONE_NEWNS | CLONE_NEWPID) < 0) + FAIL_UNSUPPORTED ("could not enter new PID namespace"); + pid = xfork (); /* inner child */ + if (pid == 0) + { + xclose (pid_pipe[1]); + + /* wait until the outer child has exited */ + char c; + VERIFY (read (exit_pipe[0], &c, 1) == 0); + xclose (exit_pipe[0]); + + VERIFY (mount ("proc", "/proc", "proc", + MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) == 0); + + char *linkname = xasprintf ("/proc/self/fd/%d", slave); + char *target = proc_fd_readlink (linkname); + VERIFY (strcmp (target, strrchr (slavename, '/')) == 0); + free (linkname); + + _exit (cb (slavename, slave)); + } + xwrite (pid_pipe[1], &pid, sizeof pid); + _exit (0); + } + xclose (pid_pipe[1]); + xclose (exit_pipe[0]); + xclose (exit_pipe[1]); + + /* wait for the outer child */ + int status; + xwaitpid (pid, &status, 0); + VERIFY (WIFEXITED (status)); + int ret = WEXITSTATUS (status); + if (ret != 0) + return ret; + + /* set 'pid' to the inner child */ + VERIFY (read (pid_pipe[0], &pid, sizeof pid) == sizeof pid); + xclose (pid_pipe[0]); + + /* wait for the inner child */ + xwaitpid (pid, &status, 0); + VERIFY (WIFEXITED (status)); + xclose (master); + return WEXITSTATUS (status); +} + +static int +do_test (void) +{ + support_become_root (); + + do_in_chroot_2 (run_chroot_tests); + + return 0; +} + +#include