1 /*
2 * This file is part of execve strace test.
3 *
4 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <unistd.h>
15
16 #include "secontext.h"
17
18 static const char *errstr;
19
20 static int
21 call_execve(const char *pathname, char *const *argv, char *const *envp)
22 {
23 int rc = execve(pathname, argv, envp);
24 errstr = sprintrc(rc);
25 return rc;
26 }
27
28 #define FILENAME "test.execve\nfilename"
29 #define Q_FILENAME "test.execve\\nfilename"
30
31 static const char * const argv[] = {
32 FILENAME, "first", "second", (const char *) -1L,
33 (const char *) -2L, (const char *) -3L
34 };
35 static const char * const q_argv[] = {
36 Q_FILENAME, "first", "second"
37 };
38
39 static const char * const envp[] = {
40 "foobar=1", "foo\nbar=2", (const char *) -1L,
41 (const char *) -2L, (const char *) -3L
42 };
43 static const char * const q_envp[] = {
44 "foobar=1", "foo\\nbar=2"
45 };
46
47 int
48 main(void)
49 {
50 /*
51 * Make sure the current workdir of the tracee
52 * is different from the current workdir of the tracer.
53 */
54 create_and_enter_subdir("execve_subdir");
55
56 char ** const tail_argv = tail_memdup(argv, sizeof(argv));
57 char ** const tail_envp = tail_memdup(envp, sizeof(envp));
58 char *my_secontext = SECONTEXT_PID_MY();
59
60 (void) unlink(FILENAME);
61 if (open(FILENAME, O_RDONLY | O_CREAT, 0400) < 0)
62 perror_msg_and_fail("open");
63
64 char *FILENAME_secontext = SECONTEXT_FILE(FILENAME);
65
66 call_execve(FILENAME, tail_argv, tail_envp);
67 printf("%s%s(\"%s\"%s"
68 ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ... /* %p */]"
69 #if VERBOSE
70 ", [\"%s\", \"%s\", %p, %p, %p, ... /* %p */]"
71 #else
72 ", %p /* 5 vars, unterminated */"
73 #endif
74 ") = %s\n",
75 my_secontext, "execve",
76 Q_FILENAME, FILENAME_secontext,
77 q_argv[0], q_argv[1], q_argv[2],
78 argv[3], argv[4], argv[5], (char *) tail_argv + sizeof(argv)
79 #if VERBOSE
80 , q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
81 (char *) tail_envp + sizeof(envp)
82 #else
83 , tail_envp
84 #endif
85 , errstr);
86
87 tail_argv[ARRAY_SIZE(q_argv)] = NULL;
88 tail_envp[ARRAY_SIZE(q_envp)] = NULL;
89 (void) q_envp; /* workaround for clang bug #33068 */
90
91 call_execve(FILENAME, tail_argv, tail_envp);
92 printf("%s%s(\"%s\"%s, [\"%s\", \"%s\", \"%s\"]"
93 #if VERBOSE
94 ", [\"%s\", \"%s\"]"
95 #else
96 ", %p /* 2 vars */"
97 #endif
98 ") = %s\n",
99 my_secontext, "execve",
100 Q_FILENAME, FILENAME_secontext,
101 q_argv[0], q_argv[1], q_argv[2]
102 #if VERBOSE
103 , q_envp[0], q_envp[1]
104 #else
105 , tail_envp
106 #endif
107 , errstr);
108
109 call_execve(FILENAME, tail_argv + 2, tail_envp + 1);
110 printf("%s%s(\"%s\"%s, [\"%s\"]"
111 #if VERBOSE
112 ", [\"%s\"]"
113 #else
114 ", %p /* 1 var */"
115 #endif
116 ") = %s\n",
117 my_secontext, "execve",
118 Q_FILENAME, FILENAME_secontext,
119 q_argv[2]
120 #if VERBOSE
121 , q_envp[1]
122 #else
123 , tail_envp + 1
124 #endif
125 , errstr);
126
127 TAIL_ALLOC_OBJECT_CONST_PTR(char *, empty);
128 char **const efault = empty + 1;
129 *empty = NULL;
130
131 call_execve(FILENAME, empty, empty);
132 printf("%s%s(\"%s\"%s, []"
133 #if VERBOSE
134 ", []"
135 #else
136 ", %p /* 0 vars */"
137 #endif
138 ") = %s\n",
139 my_secontext, "execve",
140 Q_FILENAME, FILENAME_secontext
141 #if !VERBOSE
142 , empty
143 #endif
144 , errstr);
145
146 char *const str_a = tail_alloc(DEFAULT_STRLEN + 2);
147 fill_memory_ex(str_a, DEFAULT_STRLEN + 1, '0', 10);
148 str_a[DEFAULT_STRLEN + 1] = '\0';
149
150 char *const str_b = tail_alloc(DEFAULT_STRLEN + 2);
151 fill_memory_ex(str_b, DEFAULT_STRLEN + 1, '_', 32);
152 str_b[DEFAULT_STRLEN + 1] = '\0';
153
154 char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
155 char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
156 unsigned int i;
157 for (i = 0; i <= DEFAULT_STRLEN; ++i) {
158 a[i] = &str_a[i];
159 b[i] = &str_b[i];
160 }
161 a[i] = b[i] = NULL;
162
163 call_execve(FILENAME, a, b);
164 printf("%s%s(\"%s\"%s, [\"%.*s\"...",
165 my_secontext, "execve",
166 Q_FILENAME, FILENAME_secontext,
167 DEFAULT_STRLEN, a[0]);
168 for (i = 1; i < DEFAULT_STRLEN; ++i)
169 printf(", \"%s\"", a[i]);
170 #if VERBOSE
171 printf(", \"%s\"", a[i]);
172 #else
173 printf(", ...");
174 #endif
175 #if VERBOSE
176 printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
177 for (i = 1; i <= DEFAULT_STRLEN; ++i)
178 printf(", \"%s\"", b[i]);
179 printf("]");
180 #else
181 printf("], %p /* %u vars */", b, DEFAULT_STRLEN + 1);
182 #endif
183 printf(") = %s\n", errstr);
184
185 call_execve(FILENAME, a + 1, b + 1);
186 printf("%s%s(\"%s\"%s, [\"%s\"",
187 my_secontext, "execve",
188 Q_FILENAME, FILENAME_secontext,
189 a[1]);
190 for (i = 2; i <= DEFAULT_STRLEN; ++i)
191 printf(", \"%s\"", a[i]);
192 #if VERBOSE
193 printf("], [\"%s\"", b[1]);
194 for (i = 2; i <= DEFAULT_STRLEN; ++i)
195 printf(", \"%s\"", b[i]);
196 printf("]");
197 #else
198 printf("], %p /* %d vars */", b + 1, DEFAULT_STRLEN);
199 #endif
200 printf(") = %s\n", errstr);
201
202 if (unlink(FILENAME))
203 perror_msg_and_fail("unlink");
204
205 call_execve(FILENAME, (char **) tail_argv[ARRAY_SIZE(q_argv)], efault);
206 printf("%s%s(\"%s\", NULL, %p) = %s\n",
207 my_secontext, "execve",
208 Q_FILENAME, efault, errstr);
209
210 call_execve(FILENAME, efault, NULL);
211 printf("%s%s(\"%s\", %p, NULL) = %s\n",
212 my_secontext, "execve",
213 Q_FILENAME, efault, errstr);
214
215 leave_and_remove_subdir();
216
217 return 0;
218 }