1/* Copyright (C) 2017-2024 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
31static int
32do_in_chroot_1 (int (*cb)(const char *, int))
33{
34 printf (format: "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 (pty: slavename);
53 int slave = xopen (path: slavename, O_RDWR, 0);
54 if (!doit (fd: slave, testname: "basic smoketest",
55 expected_r: (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 (path: "proc", 0755);
70 xmkdir (path: "dev", 0755);
71 xmkdir (path: "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 (path: "console", mode: 0);
80 touch (path: "dev/console", mode: 0);
81 VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
82
83 xchroot (path: ".");
84
85 char *linkname = xasprintf (format: "/proc/self/fd/%d", slave);
86 char *target = proc_fd_readlink (linkname);
87 VERIFY (strcmp (target, slavename) == 0);
88 free (ptr: linkname);
89
90 _exit (cb (slavename, slave));
91 }
92 int status;
93 xwaitpid (pid, status: &status, flags: 0);
94 VERIFY (WIFEXITED (status));
95 xclose (master);
96 xclose (slave);
97 return WEXITSTATUS (status);
98}
99
100static int
101do_test (void)
102{
103 support_become_root ();
104
105 do_in_chroot_1 (cb: run_chroot_tests);
106
107 return 0;
108}
109
110#include <support/test-driver.c>
111

source code of glibc/sysdeps/unix/sysv/linux/tst-ttyname-direct.c