blob: b3a235010c26749e3d94f1f6ecd53510364351c8 [file] [log] [blame]
Mike Frysinger4c331892022-09-13 05:17:08 -04001/* Copyright 2018 The ChromiumOS Authors
Mike Frysinger50e31fa2018-01-19 18:59:49 -05002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Test util.[ch] module code using gtest.
6 */
Mike Frysinger32c39922018-01-17 17:09:54 -05007
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/stat.h>
12#include <unistd.h>
13
14#include <gtest/gtest.h>
15
Mike Frysinger70b15b82020-09-03 18:10:57 -040016#include "bpf.h"
Zi Lin2c794452021-10-13 03:07:07 +000017#include "test_util.h"
Mike Frysinger32c39922018-01-17 17:09:54 -050018#include "util.h"
19
Mattias Nisslerb35f2c12020-02-07 13:37:36 +010020namespace {
21
22std::string dump_env(const char *const *env) {
23 std::string result;
24 for (; *env; ++env) {
25 result += *env;
26 result += "\n";
27 }
28
29 return result;
30}
31
32} // namespace
33
Mike Frysinger32c39922018-01-17 17:09:54 -050034// Sanity check for the strip func.
35TEST(strip, basic) {
36 char str[] = " foo\t";
37 ASSERT_EQ("foo", std::string(strip(str)));
38}
39
40// Make sure we don't crash with various "null"-like inputs.
41TEST(tokenize, null_stringp) {
42 ASSERT_EQ(nullptr, tokenize(nullptr, nullptr));
43 ASSERT_EQ(nullptr, tokenize(nullptr, ""));
44 ASSERT_EQ(nullptr, tokenize(nullptr, ","));
45
46 char *p = nullptr;
47 ASSERT_EQ(nullptr, tokenize(&p, nullptr));
48}
49
50// Make sure we don't crash with various "null"-like inputs.
51TEST(tokenize, null_delim) {
52 char str[] = "a,b,c";
53 char *p = str;
54 ASSERT_EQ(str, tokenize(&p, nullptr));
55 ASSERT_EQ(nullptr, p);
56 ASSERT_EQ(str, std::string("a,b,c"));
57
58 p = str;
59 ASSERT_EQ(str, tokenize(&p, ""));
60 ASSERT_EQ(nullptr, p);
61 ASSERT_EQ(str, std::string("a,b,c"));
62}
63
64// Sanity check for the tokenize func.
65TEST(tokenize, basic) {
66 char str[] = "a,b,c";
67 char *p = str;
68 ASSERT_EQ("a", std::string(tokenize(&p, ",")));
69 ASSERT_EQ("b", std::string(tokenize(&p, ",")));
70 ASSERT_EQ("c", std::string(tokenize(&p, ",")));
71 ASSERT_EQ(nullptr, p);
72 ASSERT_EQ(nullptr, tokenize(&p, ","));
73}
Mike Frysingerb4c7e772018-01-17 17:40:15 -050074
75// Check edge case with an empty string.
76TEST(tokenize, empty_string) {
77 char str[] = "";
78 char *p = str;
79 ASSERT_EQ("", std::string(tokenize(&p, ",")));
80 ASSERT_EQ(nullptr, p);
81 ASSERT_EQ(nullptr, tokenize(&p, ","));
82}
83
84// Check behavior with empty tokens at the start/middle/end.
85TEST(tokenize, empty_tokens) {
86 char str[] = ",,a,b,,,c,,";
87 char *p = str;
88 ASSERT_EQ("", std::string(tokenize(&p, ",")));
89 ASSERT_EQ("", std::string(tokenize(&p, ",")));
90 ASSERT_EQ("a", std::string(tokenize(&p, ",")));
91 ASSERT_EQ("b", std::string(tokenize(&p, ",")));
92 ASSERT_EQ("", std::string(tokenize(&p, ",")));
93 ASSERT_EQ("", std::string(tokenize(&p, ",")));
94 ASSERT_EQ("c", std::string(tokenize(&p, ",")));
95 ASSERT_EQ("", std::string(tokenize(&p, ",")));
96 ASSERT_EQ("", std::string(tokenize(&p, ",")));
97 ASSERT_EQ(nullptr, p);
98 ASSERT_EQ(nullptr, tokenize(&p, ","));
99}
Mattias Nisslerb35f2c12020-02-07 13:37:36 +0100100
101// Check environment manipulation functions.
102TEST(environment, copy_and_modify) {
103 minijail_free_env(nullptr);
104
105 char **env = minijail_copy_env(nullptr);
106 EXPECT_EQ("", dump_env(env));
107 minijail_free_env(env);
108
109 const char *const kConstEnv[] = {
110 "val1=1",
111 "val2=2",
112 "dup=1",
113 "dup=2",
114 "empty=",
115 nullptr,
116 };
117
118 // libc unfortunately uses char* const[] as the type for the environment, and
119 // we match that. It's actually missing a const-ness of the chars making up
120 // the environment strings, but we need that to initialize the |kEnv|
121 // constant. Hence, do a cast here to force things into alignment...
122 char* const* kEnv = const_cast<char* const*>(kConstEnv);
123
124 env = minijail_copy_env(kEnv);
125 EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
126 minijail_free_env(env);
127
128 env = minijail_copy_env(kEnv);
129 EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
130
131 EXPECT_EQ(EINVAL, minijail_setenv(nullptr, "val1", "3", 1));
132 char **env_ret = nullptr;
133 EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "val1", "3", 1));
134
135 env_ret = env;
136 EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, nullptr, "3", 1));
137 EXPECT_EQ(env, env_ret);
138 EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", "3", 1));
139 EXPECT_EQ(env, env_ret);
140 EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", nullptr, 1));
141 EXPECT_EQ(env, env_ret);
142
143 EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 0));
144 EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
145 EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 1));
146 EXPECT_EQ("val1=3\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
147 EXPECT_EQ(0, minijail_setenv(&env, "val2", "4", 1));
148 EXPECT_EQ("val1=3\nval2=4\ndup=1\ndup=2\nempty=\n", dump_env(env));
149 EXPECT_EQ(0, minijail_setenv(&env, "dup", "5", 1));
150 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
151 EXPECT_EQ(0, minijail_setenv(&env, "empty", "6", 1));
152 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=6\n", dump_env(env));
153 EXPECT_EQ(0, minijail_setenv(&env, "empty", "", 1));
154 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
155 EXPECT_EQ(0, minijail_setenv(&env, "new1", "7", 0));
156 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
157 EXPECT_EQ(0, minijail_setenv(&env, "new2", "8", 1));
158 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
159 dump_env(env));
160
Stéphane Lesimple66bcc8c2022-01-06 13:11:37 +0100161 EXPECT_EQ(nullptr, minijail_getenv(nullptr, "dup"));
162 EXPECT_EQ(nullptr, minijail_getenv(nullptr, nullptr));
163 EXPECT_EQ(nullptr, minijail_getenv(env, nullptr));
164 EXPECT_EQ(nullptr, minijail_getenv(env, "dup="));
165 EXPECT_EQ(nullptr, minijail_getenv(env, "du"));
166 EXPECT_EQ(std::string("8"), minijail_getenv(env, "new2"));
167 EXPECT_EQ(std::string("3"), minijail_getenv(env, "val1"));
168 EXPECT_EQ(std::string("5"), minijail_getenv(env, "dup"));
169
170 EXPECT_EQ(false, minijail_unsetenv(env, "nonexisting"));
171 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
172 dump_env(env));
173 EXPECT_EQ(false, minijail_unsetenv(env, ""));
174 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
175 dump_env(env));
176 EXPECT_EQ(false, minijail_unsetenv(env, nullptr));
177 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
178 dump_env(env));
179 EXPECT_EQ(false, minijail_unsetenv(nullptr, nullptr));
180 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
181 dump_env(env));
182 EXPECT_EQ(false, minijail_unsetenv(nullptr, "nonexisting"));
183 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
184 dump_env(env));
185 EXPECT_EQ(false, minijail_unsetenv(env, "val1="));
186 EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
187 dump_env(env));
188 EXPECT_EQ(true, minijail_unsetenv(env, "val1"));
189 EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
190 EXPECT_EQ(true, minijail_unsetenv(env, "empty"));
191 EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nnew1=7\n", dump_env(env));
192 EXPECT_EQ(true, minijail_unsetenv(env, "new2"));
193 EXPECT_EQ("new1=7\nval2=4\ndup=5\ndup=2\n", dump_env(env));
194 EXPECT_EQ(true, minijail_unsetenv(env, "new1"));
195 EXPECT_EQ("dup=2\nval2=4\ndup=5\n", dump_env(env));
196
Mattias Nisslerb35f2c12020-02-07 13:37:36 +0100197 minijail_free_env(env);
198}
Mike Frysinger70b15b82020-09-03 18:10:57 -0400199
Mike Frysinger34e327e2020-09-03 18:18:26 -0400200TEST(parse_single_constant, formats) {
201 char *end;
202 long int c = 0;
203 std::string constant;
204
205 // Check base 10 works.
206 constant = "1234";
207 c = parse_constant(const_cast<char*>(constant.data()), &end);
208 EXPECT_EQ(1234, c);
209
210 // Check base 16 works.
211 constant = "0x1234";
212 c = parse_constant(const_cast<char*>(constant.data()), &end);
213 EXPECT_EQ(0x1234, c);
214
215 // Check base 8 works.
216 constant = "01234";
217 c = parse_constant(const_cast<char*>(constant.data()), &end);
218 EXPECT_EQ(01234, c);
219}
220
Mike Frysinger70b15b82020-09-03 18:10:57 -0400221TEST(parse_constant, unsigned) {
222 char *end;
223 long int c = 0;
224 std::string constant;
225
226#if defined(BITS32)
227 constant = "0x80000000";
228 c = parse_constant(const_cast<char*>(constant.data()), &end);
229 EXPECT_EQ(0x80000000U, static_cast<unsigned long int>(c));
230
231#elif defined(BITS64)
232 constant = "0x8000000000000000";
233 c = parse_constant(const_cast<char*>(constant.data()), &end);
234 EXPECT_EQ(0x8000000000000000UL, static_cast<unsigned long int>(c));
235
236#else
237# error "unknown bits!"
238#endif
239}
240
241TEST(parse_constant, unsigned_toobig) {
242 char *end;
243 long int c = 0;
244 std::string constant;
245
246#if defined(BITS32)
247 constant = "0x100000000"; // Too big for 32-bit unsigned long int.
248 c = parse_constant(const_cast<char*>(constant.data()), &end);
249 // Error case should return 0.
250 EXPECT_EQ(0, c);
251
252#elif defined(BITS64)
253 constant = "0x10000000000000000";
254 c = parse_constant(const_cast<char*>(constant.data()), &end);
255 // Error case should return 0.
256 EXPECT_EQ(0, c);
257
258#else
259# error "unknown bits!"
260#endif
261}
262
263TEST(parse_constant, signed) {
264 char *end;
265 long int c = 0;
266 std::string constant = "-1";
267 c = parse_constant(const_cast<char*>(constant.data()), &end);
268 EXPECT_EQ(-1, c);
269}
270
271TEST(parse_constant, signed_toonegative) {
272 char *end;
273 long int c = 0;
274 std::string constant;
275
276#if defined(BITS32)
277 constant = "-0x80000001";
278 c = parse_constant(const_cast<char*>(constant.data()), &end);
279 // Error case should return 0.
280 EXPECT_EQ(0, c);
281
282#elif defined(BITS64)
283 constant = "-0x8000000000000001";
284 c = parse_constant(const_cast<char*>(constant.data()), &end);
285 // Error case should return 0.
286 EXPECT_EQ(0, c);
287
288#else
289# error "unknown bits!"
290#endif
291}
292
293TEST(parse_constant, complements) {
294 char* end;
295 long int c = 0;
296 std::string constant;
297
298#if defined(BITS32)
299 constant = "~0x005AF0FF|~0xFFA50FFF";
300 c = parse_constant(const_cast<char*>(constant.data()), &end);
301 EXPECT_EQ(c, 0xFFFFFF00);
302 constant = "0x0F|~(0x005AF000|0x00A50FFF)|0xF0";
303 c = parse_constant(const_cast<char*>(constant.data()), &end);
304 EXPECT_EQ(c, 0xFF0000FF);
305
306#elif defined(BITS64)
307 constant = "~0x00005A5AF0F0FFFF|~0xFFFFA5A50F0FFFFF";
308 c = parse_constant(const_cast<char*>(constant.data()), &end);
309 EXPECT_EQ(c, 0xFFFFFFFFFFFF0000UL);
310 constant = "0x00FF|~(0x00005A5AF0F00000|0x0000A5A50F0FFFFF)|0xFF00";
311 c = parse_constant(const_cast<char*>(constant.data()), &end);
312 EXPECT_EQ(c, 0xFFFF00000000FFFFUL);
313
314#else
315# error "unknown bits!"
316#endif
317}
318
319TEST(parse_constant, parenthesized_expresions) {
320 char* end;
321
322 const std::vector<const char*> bad_expressions = {
323 "(1", "1)", "(1)1", "|(1)", "(1)|", "()",
324 "(", "((", "(()", "(()1", "1(0)",
325 };
326 for (const auto* expression : bad_expressions) {
327 std::string mutable_expression = expression;
328 long int c =
329 parse_constant(const_cast<char*>(mutable_expression.data()), &end);
330 EXPECT_EQ(reinterpret_cast<const void*>(end),
331 reinterpret_cast<const void*>(mutable_expression.data()));
332 // Error case should return 0.
333 EXPECT_EQ(c, 0) << "For expression: \"" << expression << "\"";
334 }
335
336 const std::vector<const char*> good_expressions = {
337 "(3)", "(1)|2", "1|(2)", "(1)|(2)", "((3))", "0|(1|2)", "(0|1|2)",
338 };
339 for (const auto* expression : good_expressions) {
340 std::string mutable_expression = expression;
341 long int c =
342 parse_constant(const_cast<char*>(mutable_expression.data()), &end);
343 EXPECT_EQ(c, 3) << "For expression: \"" << expression << "\"";
344 }
345}
346
347TEST(parse_size, complete) {
348 size_t size;
349
350 ASSERT_EQ(0, parse_size(&size, "42"));
351 ASSERT_EQ(42U, size);
352
353 ASSERT_EQ(0, parse_size(&size, "16K"));
354 ASSERT_EQ(16384U, size);
355
356 ASSERT_EQ(0, parse_size(&size, "1M"));
357 ASSERT_EQ(1024U * 1024, size);
358
359 uint64_t gigabyte = 1024ULL * 1024 * 1024;
360 ASSERT_EQ(0, parse_size(&size, "3G"));
361 ASSERT_EQ(3U, size / gigabyte);
362 ASSERT_EQ(0U, size % gigabyte);
363
364 ASSERT_EQ(0, parse_size(&size, "4294967294"));
365 ASSERT_EQ(3U, size / gigabyte);
366 ASSERT_EQ(gigabyte - 2, size % gigabyte);
367
368#if __WORDSIZE == 64
369 uint64_t exabyte = gigabyte * 1024 * 1024 * 1024;
370 ASSERT_EQ(0, parse_size(&size, "9E"));
371 ASSERT_EQ(9U, size / exabyte);
372 ASSERT_EQ(0U, size % exabyte);
373
374 ASSERT_EQ(0, parse_size(&size, "15E"));
375 ASSERT_EQ(15U, size / exabyte);
376 ASSERT_EQ(0U, size % exabyte);
377
378 ASSERT_EQ(0, parse_size(&size, "18446744073709551614"));
379 ASSERT_EQ(15U, size / exabyte);
380 ASSERT_EQ(exabyte - 2, size % exabyte);
381
382 ASSERT_EQ(-ERANGE, parse_size(&size, "16E"));
383 ASSERT_EQ(-ERANGE, parse_size(&size, "19E"));
384 ASSERT_EQ(-EINVAL, parse_size(&size, "7GTPE"));
385#elif __WORDSIZE == 32
386 ASSERT_EQ(-ERANGE, parse_size(&size, "5G"));
387 ASSERT_EQ(-ERANGE, parse_size(&size, "9G"));
388 ASSERT_EQ(-ERANGE, parse_size(&size, "9E"));
389 ASSERT_EQ(-ERANGE, parse_size(&size, "7GTPE"));
390#endif
391
392 ASSERT_EQ(-EINVAL, parse_size(&size, ""));
393 ASSERT_EQ(-EINVAL, parse_size(&size, "14u"));
394 ASSERT_EQ(-EINVAL, parse_size(&size, "14.2G"));
395 ASSERT_EQ(-EINVAL, parse_size(&size, "-1G"));
396 ASSERT_EQ(-EINVAL, parse_size(&size, "; /bin/rm -- "));
397}
Zi Lin2c794452021-10-13 03:07:07 +0000398
Mike Frysinger572bab22021-10-27 03:02:44 -0400399TEST(path_join, basic) {
400 char *path = path_join("a", "b");
401 ASSERT_EQ(std::string("a/b"), path);
402 free(path);
403}
404
Jorge Lucangeli Obesa8eef8b2022-07-20 19:20:06 -0400405TEST(path_is_parent, simple) {
406 EXPECT_TRUE(path_is_parent("/dev", "/dev/rtc"));
407 EXPECT_TRUE(path_is_parent("/dev/", "/dev/rtc"));
408 EXPECT_TRUE(path_is_parent("/sys", "/sys/power"));
409 EXPECT_TRUE(path_is_parent("/sys/power", "/sys/power/something"));
410 EXPECT_TRUE(path_is_parent("/sys", "/sys/sys/power"));
411
412 EXPECT_FALSE(path_is_parent("/dev", ""));
413 EXPECT_FALSE(path_is_parent("/dev", "/sys"));
414 EXPECT_FALSE(path_is_parent("/dev", "dev"));
415 EXPECT_FALSE(path_is_parent("/dev", "/sys/dev"));
416 EXPECT_FALSE(path_is_parent("/dev", "/device"));
417}
418
Zi Lin2c794452021-10-13 03:07:07 +0000419TEST(getmultiline, basic) {
420 std::string config =
421 "\n"
422 "mount = none\n"
423 "mount =\\\n"
424 "none\n"
425 "binding = none,/tmp\n"
426 "binding = none,\\\n"
427 "/tmp";
428 FILE *config_file = write_to_pipe(config);
429 ASSERT_NE(config_file, nullptr);
430
431 char *line = NULL;
432 size_t len = 0;
433 ASSERT_EQ(0, getmultiline(&line, &len, config_file));
434 EXPECT_EQ(std::string(line), "");
435 ASSERT_EQ(12, getmultiline(&line, &len, config_file));
436 EXPECT_EQ(std::string(line), "mount = none");
437 ASSERT_EQ(12, getmultiline(&line, &len, config_file));
438 EXPECT_EQ(std::string(line), "mount = none");
439 ASSERT_EQ(19, getmultiline(&line, &len, config_file));
440 EXPECT_EQ(std::string(line), "binding = none,/tmp");
441 ASSERT_EQ(20, getmultiline(&line, &len, config_file));
442 EXPECT_EQ(std::string(line), "binding = none, /tmp");
443 free(line);
444}