xref: /aosp_15_r20/external/minijail/util_unittest.cc (revision 4b9c6d91573e8b3a96609339b46361b5476dd0f9)
1 /* Copyright 2018 The ChromiumOS Authors
2  * 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  */
7 
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 
16 #include "bpf.h"
17 #include "test_util.h"
18 #include "util.h"
19 
20 namespace {
21 
dump_env(const char * const * env)22 std::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 
34 // Sanity check for the strip func.
TEST(strip,basic)35 TEST(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.
TEST(tokenize,null_stringp)41 TEST(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.
TEST(tokenize,null_delim)51 TEST(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.
TEST(tokenize,basic)65 TEST(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 }
74 
75 // Check edge case with an empty string.
TEST(tokenize,empty_string)76 TEST(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.
TEST(tokenize,empty_tokens)85 TEST(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 }
100 
101 // Check environment manipulation functions.
TEST(environment,copy_and_modify)102 TEST(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 
161   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 
197   minijail_free_env(env);
198 }
199 
TEST(parse_single_constant,formats)200 TEST(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 
TEST(parse_constant,unsigned)221 TEST(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 
TEST(parse_constant,unsigned_toobig)241 TEST(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 
TEST(parse_constant,signed)263 TEST(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 
TEST(parse_constant,signed_toonegative)271 TEST(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 
TEST(parse_constant,complements)293 TEST(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 
TEST(parse_constant,parenthesized_expresions)319 TEST(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 
TEST(parse_size,complete)347 TEST(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 }
398 
TEST(path_join,basic)399 TEST(path_join, basic) {
400   char *path = path_join("a", "b");
401   ASSERT_EQ(std::string("a/b"), path);
402   free(path);
403 }
404 
TEST(path_is_parent,simple)405 TEST(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 
TEST(getmultiline,basic)419 TEST(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 }
445