public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Improve tst-ttyname within containers
@ 2023-06-12 18:30 Adhemerval Zanella
  2023-06-12 18:30 ` [PATCH 1/2] linux: Split tst-ttyname Adhemerval Zanella
  2023-06-12 18:30 ` [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace Adhemerval Zanella
  0 siblings, 2 replies; 5+ messages in thread
From: Adhemerval Zanella @ 2023-06-12 18:30 UTC (permalink / raw)
  To: libc-alpha

The test might fail depending on how the container is configure,
its capabilities, and/or which LSM is enabled and how it is
configured (check the discussion on libc-alpha [1]).

[1] https://sourceware.org/pipermail/libc-alpha/2023-June/148747.html

Adhemerval Zanella (2):
  linux: Split tst-ttyname
  linux: Return unsupported if procfs can not be mount on
    tst-ttyname-namespace

 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   | 147 +++++++++++++
 4 files changed, 263 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

-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] linux: Split tst-ttyname
  2023-06-12 18:30 [PATCH 0/2] Improve tst-ttyname within containers Adhemerval Zanella
@ 2023-06-12 18:30 ` Adhemerval Zanella
  2023-06-27 14:04   ` Siddhesh Poyarekar
  2023-06-12 18:30 ` [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace Adhemerval Zanella
  1 sibling, 1 reply; 5+ messages in thread
From: Adhemerval Zanella @ 2023-06-12 18:30 UTC (permalink / raw)
  To: 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.
---
 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 <errno.h>
 #include <fcntl.h>
 #include <limits.h>
-#include <sched.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mount.h>
-#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
 #include <sys/resource.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <support/check.h>
-#include <support/namespace.h>
 #include <support/support.h>
 #include <support/temp_file.h>
 #include <support/test-driver.h>
@@ -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 <support/test-driver.c>
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 <https://www.gnu.org/licenses/>.  */
+
+#include <sched.h>
+#include <sys/prctl.h>
+
+#include <support/namespace.h>
+
+#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 <support/test-driver.c>
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 <https://www.gnu.org/licenses/>.  */
+
+#include <sched.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+
+#include <support/namespace.h>
+
+#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 <support/test-driver.c>
-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace
  2023-06-12 18:30 [PATCH 0/2] Improve tst-ttyname within containers Adhemerval Zanella
  2023-06-12 18:30 ` [PATCH 1/2] linux: Split tst-ttyname Adhemerval Zanella
@ 2023-06-12 18:30 ` Adhemerval Zanella
  2023-06-27 14:03   ` Siddhesh Poyarekar
  1 sibling, 1 reply; 5+ messages in thread
From: Adhemerval Zanella @ 2023-06-12 18:30 UTC (permalink / raw)
  To: libc-alpha

Trying to mount procfs can fail due multiples reasons: proc is locked
due the container configuration, mount syscall is filtered by a
Linux Secuirty Module, or any other security or hardening mechanism
that Linux might eventually add.

The tests does require a new procfs without binding to parent, and
to fully fix it would require to change how the container was created
(which is out of the scope of the test itself).  Instead of trying to
foresee any possible scenario, if procfs can not be mount fail with
unsupported.

Checked on aarch64-linux-gnu.
---
 .../unix/sysv/linux/tst-ttyname-namespace.c   | 28 +++++++++++--------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
index 1f38442747..cd5e79d39b 100644
--- a/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
+++ b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
@@ -94,8 +94,17 @@ do_in_chroot_2 (int (*cb)(const char *, int))
           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);
+	  if (mount ("proc", "/proc", "proc",
+		     MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
+	    {
+	      /* This happens if we're trying to create a nested container,
+		 like if the build is running under podman, and we lack
+		 priviledges.  */
+	      if (errno == EPERM)
+		_exit (EXIT_UNSUPPORTED);
+	      else
+		_exit (EXIT_FAILURE);
+	    }
 
           char *linkname = xasprintf ("/proc/self/fd/%d", slave);
           char *target = proc_fd_readlink (linkname);
@@ -104,8 +113,9 @@ do_in_chroot_2 (int (*cb)(const char *, int))
 
           _exit (cb (slavename, slave));
         }
-      xwrite (pid_pipe[1], &pid, sizeof pid);
-      _exit (0);
+      int status;
+      xwaitpid (pid, &status, 0);
+      _exit (WEXITSTATUS (status));
     }
   xclose (pid_pipe[1]);
   xclose (exit_pipe[0]);
@@ -117,17 +127,11 @@ do_in_chroot_2 (int (*cb)(const char *, int))
   VERIFY (WIFEXITED (status));
   int ret = WEXITSTATUS (status);
   if (ret != 0)
-    return ret;
+    FAIL_UNSUPPORTED ("unable to mount /proc on inner child process");
 
-  /* 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);
+  return 0;
 }
 
 static int
-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace
  2023-06-12 18:30 ` [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace Adhemerval Zanella
@ 2023-06-27 14:03   ` Siddhesh Poyarekar
  0 siblings, 0 replies; 5+ messages in thread
From: Siddhesh Poyarekar @ 2023-06-27 14:03 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha



On 2023-06-12 14:30, Adhemerval Zanella via Libc-alpha wrote:
> Trying to mount procfs can fail due multiples reasons: proc is locked
> due the container configuration, mount syscall is filtered by a
> Linux Secuirty Module, or any other security or hardening mechanism
> that Linux might eventually add.
> 
> The tests does require a new procfs without binding to parent, and
> to fully fix it would require to change how the container was created
> (which is out of the scope of the test itself).  Instead of trying to
> foresee any possible scenario, if procfs can not be mount fail with
> unsupported.
> 
> Checked on aarch64-linux-gnu.
> ---

LGTM.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>

>   .../unix/sysv/linux/tst-ttyname-namespace.c   | 28 +++++++++++--------
>   1 file changed, 16 insertions(+), 12 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
> index 1f38442747..cd5e79d39b 100644
> --- a/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
> +++ b/sysdeps/unix/sysv/linux/tst-ttyname-namespace.c
> @@ -94,8 +94,17 @@ do_in_chroot_2 (int (*cb)(const char *, int))
>             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);
> +	  if (mount ("proc", "/proc", "proc",
> +		     MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
> +	    {
> +	      /* This happens if we're trying to create a nested container,
> +		 like if the build is running under podman, and we lack
> +		 priviledges.  */
> +	      if (errno == EPERM)
> +		_exit (EXIT_UNSUPPORTED);
> +	      else
> +		_exit (EXIT_FAILURE);
> +	    }
>   
>             char *linkname = xasprintf ("/proc/self/fd/%d", slave);
>             char *target = proc_fd_readlink (linkname);
> @@ -104,8 +113,9 @@ do_in_chroot_2 (int (*cb)(const char *, int))
>   
>             _exit (cb (slavename, slave));
>           }
> -      xwrite (pid_pipe[1], &pid, sizeof pid);
> -      _exit (0);
> +      int status;
> +      xwaitpid (pid, &status, 0);
> +      _exit (WEXITSTATUS (status));
>       }
>     xclose (pid_pipe[1]);
>     xclose (exit_pipe[0]);
> @@ -117,17 +127,11 @@ do_in_chroot_2 (int (*cb)(const char *, int))
>     VERIFY (WIFEXITED (status));
>     int ret = WEXITSTATUS (status);
>     if (ret != 0)
> -    return ret;
> +    FAIL_UNSUPPORTED ("unable to mount /proc on inner child process");
>   
> -  /* 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);
> +  return 0;
>   }
>   
>   static int

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] linux: Split tst-ttyname
  2023-06-12 18:30 ` [PATCH 1/2] linux: Split tst-ttyname Adhemerval Zanella
@ 2023-06-27 14:04   ` Siddhesh Poyarekar
  0 siblings, 0 replies; 5+ messages in thread
From: Siddhesh Poyarekar @ 2023-06-27 14:04 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha



On 2023-06-12 14:30, Adhemerval Zanella via Libc-alpha wrote:
> 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.
> ---

LGTM.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>

>   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 <errno.h>
>   #include <fcntl.h>
>   #include <limits.h>
> -#include <sched.h>
> +#include <stdbool.h>
>   #include <stdio.h>
>   #include <stdlib.h>
>   #include <string.h>
>   #include <sys/mount.h>
> -#include <sys/prctl.h>
> -#include <sys/stat.h>
> -#include <sys/wait.h>
>   #include <sys/resource.h>
> +#include <sys/stat.h>
>   #include <unistd.h>
>   
>   #include <support/check.h>
> -#include <support/namespace.h>
>   #include <support/support.h>
>   #include <support/temp_file.h>
>   #include <support/test-driver.h>
> @@ -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 <support/test-driver.c>
> 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 <https://www.gnu.org/licenses/>.  */
> +
> +#include <sched.h>
> +#include <sys/prctl.h>
> +
> +#include <support/namespace.h>
> +
> +#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 <support/test-driver.c>
> 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 <https://www.gnu.org/licenses/>.  */
> +
> +#include <sched.h>
> +#include <sys/prctl.h>
> +#include <sys/wait.h>
> +
> +#include <support/namespace.h>
> +
> +#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 <support/test-driver.c>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-06-27 14:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-12 18:30 [PATCH 0/2] Improve tst-ttyname within containers Adhemerval Zanella
2023-06-12 18:30 ` [PATCH 1/2] linux: Split tst-ttyname Adhemerval Zanella
2023-06-27 14:04   ` Siddhesh Poyarekar
2023-06-12 18:30 ` [PATCH 2/2] linux: Return unsupported if procfs can not be mount on tst-ttyname-namespace Adhemerval Zanella
2023-06-27 14:03   ` Siddhesh Poyarekar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).