From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1791) id 7A7013858D35; Wed, 28 Jun 2023 12:19:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7A7013858D35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1687954762; bh=hoeP8HtEfBw9oxZx7ZkBKy4qW14VEJFJouUeFDnsTkg=; h=From:To:Subject:Date:From; b=TFv5m2OKMHwBq4y1T2Xmw0VqZ42w17DBhnP8nlqowXKp59ySF7IJEqlHQC+ieTMSF K0/pTFmBRH6qviPwr9McpjyRd5Vj4pIF5gET/hGYBvt5CMP+Jk0cUFhsOjqVNvZE40 6VEnJcdufqvLbSmlrPoaYuK/W815z0AF76vub/bc= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Adhemerval Zanella To: glibc-cvs@sourceware.org Subject: [glibc] linux: Split tst-ttyname X-Act-Checkin: glibc X-Git-Author: Adhemerval Zanella X-Git-Refname: refs/heads/master X-Git-Oldrev: aaa208502c97707119aea9e03a988bec26ad7817 X-Git-Newrev: a9fed5ea811c3fe3d5186d260494710d424786ef Message-Id: <20230628121922.7A7013858D35@sourceware.org> Date: Wed, 28 Jun 2023 12:19:22 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a9fed5ea811c3fe3d5186d260494710d424786ef commit a9fed5ea811c3fe3d5186d260494710d424786ef Author: Adhemerval Zanella Date: Mon Jun 12 15:30:13 2023 -0300 linux: Split tst-ttyname 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 Diff: --- sysdeps/unix/sysv/linux/Makefile | 3 +- .../linux/{tst-ttyname.c => tst-ttyname-common.c} | 209 +-------------------- sysdeps/unix/sysv/linux/tst-ttyname-direct.c | 110 +++++++++++ sysdeps/unix/sysv/linux/tst-ttyname-namespace.c | 143 ++++++++++++++ 4 files changed, 259 insertions(+), 206 deletions(-) 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..7ee0bc67b1 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 @@ -596,21 +413,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