htl: Add tcb-offsets.sym for x86_64
[glibc.git] / posix / tst-wordexp-nocmd.c
blobbf343c7adbdc298cee01fe3e254b35353760e5e0
1 /* Test for (lack of) command execution in wordexp.
2 Copyright (C) 1997-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* This test optionally counts PIDs in a PID namespace to detect
20 forks. Without kernel support for that, it will merely look at the
21 error codes from wordexp to check that no command execution
22 happens. */
24 #include <sched.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <support/check.h>
29 #include <support/namespace.h>
30 #include <support/xunistd.h>
31 #include <wordexp.h>
33 /* Set to true if the test runs in a PID namespace and can therefore
34 use next_pid below. */
35 static bool pid_tests_supported;
37 /* The next PID, as returned from next_pid below. Only meaningful if
38 pid_tests_supported. */
39 static pid_t expected_pid;
41 /* Allocate the next PID and return it. The process is terminated.
42 Note that the test itself advances the next PID. */
43 static pid_t
44 next_pid (void)
46 pid_t pid = xfork ();
47 if (pid == 0)
48 _exit (0);
49 xwaitpid (pid, NULL, 0);
50 return pid;
53 /* Check that evaluating PATTERN with WRDE_NOCMD results in
54 EXPECTED_ERROR. */
55 static void
56 expect_failure (const char *pattern, int expected_error)
58 printf ("info: testing pattern: %s\n", pattern);
59 wordexp_t w;
60 TEST_COMPARE (wordexp (pattern, &w, WRDE_NOCMD), expected_error);
61 if (pid_tests_supported)
62 TEST_COMPARE (expected_pid++, next_pid ());
65 /* Run all the tests. Invoked with different IFS values. */
66 static void
67 run_tests (void)
69 /* Integer overflow in division. */
71 static const char *const numbers[] = {
72 "0",
73 "1",
74 "65536",
75 "2147483648",
76 "4294967296"
77 "9223372036854775808",
78 "18446744073709551616",
79 "170141183460469231731687303715884105728",
80 "340282366920938463463374607431768211456",
81 NULL
84 for (const char *const *num = numbers; *num != NULL; ++num)
86 wordexp_t w;
87 char pattern[256];
88 snprintf (pattern, sizeof (pattern), "$[(-%s)/(-1)]", *num);
89 int ret = wordexp (pattern, &w, WRDE_NOCMD);
90 if (ret == 0)
92 /* If the call is successful, the result must match the
93 original number. */
94 TEST_COMPARE (w.we_wordc, 1);
95 TEST_COMPARE_STRING (w.we_wordv[0], *num);
96 TEST_COMPARE_STRING (w.we_wordv[1], NULL);
97 wordfree (&w);
99 else
100 /* Otherwise, the test must fail with a syntax error. */
101 TEST_COMPARE (ret, WRDE_SYNTAX);
103 /* In both cases, command execution is not permitted. */
104 if (pid_tests_supported)
105 TEST_COMPARE (expected_pid++, next_pid ());
109 /* (Lack of) command execution tests. */
111 expect_failure ("$(ls)", WRDE_CMDSUB);
113 /* Test for CVE-2014-7817. We test 3 combinations of command
114 substitution inside an arithmetic expression to make sure that
115 no commands are executed and error is returned. */
116 expect_failure ("$((`echo 1`))", WRDE_CMDSUB);
117 expect_failure ("$((1+`echo 1`))", WRDE_CMDSUB);
118 expect_failure ("$((1+$((`echo 1`))))", WRDE_CMDSUB);
120 expect_failure ("$[1/0]", WRDE_SYNTAX); /* BZ 18100. */
123 static void
124 subprocess (void *closure)
126 expected_pid = 2;
127 if (pid_tests_supported)
128 TEST_COMPARE (expected_pid++, next_pid ());
130 /* Check that triggering command execution via wordexp results in a
131 PID increase. */
132 if (pid_tests_supported)
134 wordexp_t w;
135 TEST_COMPARE (wordexp ("$(echo Test)", &w, 0), 0);
136 TEST_COMPARE (w.we_wordc, 1);
137 TEST_COMPARE_STRING (w.we_wordv[0], "Test");
138 TEST_COMPARE_STRING (w.we_wordv[1], NULL);
139 wordfree (&w);
141 pid_t n = next_pid ();
142 printf ("info: self-test resulted in PID %d (processes created: %d)\n",
143 (int) n, (int) (n - expected_pid));
144 TEST_VERIFY (n > expected_pid);
145 expected_pid = n + 1;
148 puts ("info: testing without IFS");
149 unsetenv ("IFS");
150 run_tests ();
152 puts ("info: testing with IFS");
153 TEST_COMPARE (setenv ("IFS", " \t\n", 1), 0);
154 run_tests ();
157 static int
158 do_test (void)
160 support_become_root ();
162 #ifdef CLONE_NEWPID
163 if (unshare (CLONE_NEWPID) != 0)
164 printf ("warning: unshare (CLONE_NEWPID) failed: %m\n"
165 "warning: This leads to reduced test coverage.\n");
166 else
167 pid_tests_supported = true;
168 #else
169 printf ("warning: CLONE_NEWPID not available.\n"
170 "warning: This leads to reduced test coverage.\n");
171 #endif
173 /* CLONE_NEWPID only has an effect after fork. */
174 support_isolate_in_subprocess (subprocess, NULL);
176 return 0;
179 #include <support/test-driver.c>