1  /* Copyright (C) 2017-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; see the file COPYING.LIB.  If
      16     not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <sched.h>
      19  #include <sys/prctl.h>
      20  
      21  #include <support/namespace.h>
      22  
      23  #include "tst-ttyname-common.c"
      24  
      25  /* These chroot setup functions put the TTY at at "/console" (where it
      26     won't be found by ttyname), and create "/dev/console" as an
      27     ordinary file.  This way, it's easier to write test-cases that
      28     expect ttyname to fail; test-cases that expect it to succeed need
      29     to explicitly remount it at "/dev/console".  */
      30  
      31  static int
      32  do_in_chroot_1 (int (*cb)(const char *, int))
      33  {
      34    printf ("info:  entering chroot 1\n");
      35  
      36    /* Open the PTS that we'll be testing on.  */
      37    int master;
      38    char *slavename;
      39    master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK);
      40    if (master < 0)
      41      {
      42        if (errno == ENOENT)
      43  	FAIL_UNSUPPORTED ("posix_openpt: %m");
      44        else
      45  	FAIL_EXIT1 ("posix_openpt: %m");
      46      }
      47    VERIFY ((slavename = ptsname (master)));
      48    VERIFY (unlockpt (master) == 0);
      49    if (strncmp (slavename, "/dev/pts/", 9) != 0)
      50      FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s",
      51                        slavename);
      52    adjust_file_limit (slavename);
      53    int slave = xopen (slavename, O_RDWR, 0);
      54    if (!doit (slave, "basic smoketest",
      55               (struct result_r){.name=slavename, .ret=0, .err=0}))
      56      return 1;
      57  
      58    pid_t pid = xfork ();
      59    if (pid == 0)
      60      {
      61        xclose (master);
      62  
      63        if (!support_enter_mount_namespace ())
      64  	FAIL_UNSUPPORTED ("could not enter new mount namespace");
      65  
      66        VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0);
      67        VERIFY (chdir (chrootdir) == 0);
      68  
      69        xmkdir ("proc", 0755);
      70        xmkdir ("dev", 0755);
      71        xmkdir ("dev/pts", 0755);
      72  
      73        VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0);
      74        VERIFY (mount ("devpts", "dev/pts", "devpts",
      75                       MS_NOSUID|MS_NOEXEC,
      76                       "newinstance,ptmxmode=0666,mode=620") == 0);
      77        VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0);
      78  
      79        touch ("console", 0);
      80        touch ("dev/console", 0);
      81        VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
      82  
      83        xchroot (".");
      84  
      85        char *linkname = xasprintf ("/proc/self/fd/%d", slave);
      86        char *target = proc_fd_readlink (linkname);
      87        VERIFY (strcmp (target, slavename) == 0);
      88        free (linkname);
      89  
      90        _exit (cb (slavename, slave));
      91      }
      92    int status;
      93    xwaitpid (pid, &status, 0);
      94    VERIFY (WIFEXITED (status));
      95    xclose (master);
      96    xclose (slave);
      97    return WEXITSTATUS (status);
      98  }
      99  
     100  static int
     101  do_test (void)
     102  {
     103    support_become_root ();
     104  
     105    do_in_chroot_1 (run_chroot_tests);
     106  
     107    return 0;
     108  }
     109  
     110  #include <support/test-driver.c>