audit_test.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Landlock tests - Audit
  4. *
  5. * Copyright © 2024-2025 Microsoft Corporation
  6. */
  7. #define _GNU_SOURCE
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <limits.h>
  11. #include <linux/landlock.h>
  12. #include <pthread.h>
  13. #include <stdlib.h>
  14. #include <sys/mount.h>
  15. #include <sys/prctl.h>
  16. #include <sys/types.h>
  17. #include <sys/wait.h>
  18. #include <unistd.h>
  19. #include "audit.h"
  20. #include "common.h"
  21. static int matches_log_signal(struct __test_metadata *const _metadata,
  22. int audit_fd, const pid_t opid, __u64 *domain_id)
  23. {
  24. static const char log_template[] = REGEX_LANDLOCK_PREFIX
  25. " blockers=scope\\.signal opid=%d ocomm=\"audit_test\"$";
  26. char log_match[sizeof(log_template) + 10];
  27. int log_match_len;
  28. log_match_len =
  29. snprintf(log_match, sizeof(log_match), log_template, opid);
  30. if (log_match_len > sizeof(log_match))
  31. return -E2BIG;
  32. return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
  33. domain_id);
  34. }
  35. FIXTURE(audit)
  36. {
  37. struct audit_filter audit_filter;
  38. int audit_fd;
  39. };
  40. FIXTURE_SETUP(audit)
  41. {
  42. disable_caps(_metadata);
  43. set_cap(_metadata, CAP_AUDIT_CONTROL);
  44. self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
  45. EXPECT_LE(0, self->audit_fd)
  46. {
  47. const char *error_msg;
  48. /* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
  49. if (self->audit_fd == -EEXIST)
  50. error_msg = "socket already in use (e.g. auditd)";
  51. else
  52. error_msg = strerror(-self->audit_fd);
  53. TH_LOG("Failed to initialize audit: %s", error_msg);
  54. }
  55. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  56. }
  57. FIXTURE_TEARDOWN(audit)
  58. {
  59. set_cap(_metadata, CAP_AUDIT_CONTROL);
  60. EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter));
  61. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  62. }
  63. TEST_F(audit, layers)
  64. {
  65. const struct landlock_ruleset_attr ruleset_attr = {
  66. .scoped = LANDLOCK_SCOPE_SIGNAL,
  67. };
  68. int status, ruleset_fd, i;
  69. __u64(*domain_stack)[16];
  70. __u64 prev_dom = 3;
  71. pid_t child;
  72. domain_stack = mmap(NULL, sizeof(*domain_stack), PROT_READ | PROT_WRITE,
  73. MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  74. ASSERT_NE(MAP_FAILED, domain_stack);
  75. memset(domain_stack, 0, sizeof(*domain_stack));
  76. ruleset_fd =
  77. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  78. ASSERT_LE(0, ruleset_fd);
  79. EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  80. child = fork();
  81. ASSERT_LE(0, child);
  82. if (child == 0) {
  83. for (i = 0; i < ARRAY_SIZE(*domain_stack); i++) {
  84. __u64 denial_dom = 1;
  85. __u64 allocated_dom = 2;
  86. EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
  87. /* Creates a denial to get the domain ID. */
  88. EXPECT_EQ(-1, kill(getppid(), 0));
  89. EXPECT_EQ(EPERM, errno);
  90. EXPECT_EQ(0,
  91. matches_log_signal(_metadata, self->audit_fd,
  92. getppid(), &denial_dom));
  93. EXPECT_EQ(0, matches_log_domain_allocated(
  94. self->audit_fd, getpid(),
  95. &allocated_dom));
  96. EXPECT_NE(denial_dom, 1);
  97. EXPECT_NE(denial_dom, 0);
  98. EXPECT_EQ(denial_dom, allocated_dom);
  99. /* Checks that the new domain is younger than the previous one. */
  100. EXPECT_GT(allocated_dom, prev_dom);
  101. prev_dom = allocated_dom;
  102. (*domain_stack)[i] = allocated_dom;
  103. }
  104. /* Checks that we reached the maximum number of layers. */
  105. EXPECT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
  106. EXPECT_EQ(E2BIG, errno);
  107. /* Updates filter rules to match the drop record. */
  108. set_cap(_metadata, CAP_AUDIT_CONTROL);
  109. EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
  110. EXPECT_EQ(0,
  111. audit_filter_exe(self->audit_fd, &self->audit_filter,
  112. AUDIT_DEL_RULE));
  113. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  114. _exit(_metadata->exit_code);
  115. return;
  116. }
  117. ASSERT_EQ(child, waitpid(child, &status, 0));
  118. if (WIFSIGNALED(status) || !WIFEXITED(status) ||
  119. WEXITSTATUS(status) != EXIT_SUCCESS)
  120. _metadata->exit_code = KSFT_FAIL;
  121. /* Purges log from deallocated domains. */
  122. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  123. &audit_tv_dom_drop, sizeof(audit_tv_dom_drop)));
  124. for (i = ARRAY_SIZE(*domain_stack) - 1; i >= 0; i--) {
  125. __u64 deallocated_dom = 2;
  126. EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 1,
  127. &deallocated_dom));
  128. EXPECT_EQ((*domain_stack)[i], deallocated_dom)
  129. {
  130. TH_LOG("Failed to match domain %llx (#%d)",
  131. (*domain_stack)[i], i);
  132. }
  133. }
  134. EXPECT_EQ(0, munmap(domain_stack, sizeof(*domain_stack)));
  135. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  136. &audit_tv_default, sizeof(audit_tv_default)));
  137. EXPECT_EQ(0, close(ruleset_fd));
  138. }
  139. struct thread_data {
  140. pid_t parent_pid;
  141. int ruleset_fd, pipe_child, pipe_parent;
  142. };
  143. static void *thread_audit_test(void *arg)
  144. {
  145. const struct thread_data *data = (struct thread_data *)arg;
  146. uintptr_t err = 0;
  147. char buffer;
  148. /* TGID and TID are different for a second thread. */
  149. if (getpid() == gettid()) {
  150. err = 1;
  151. goto out;
  152. }
  153. if (landlock_restrict_self(data->ruleset_fd, 0)) {
  154. err = 2;
  155. goto out;
  156. }
  157. if (close(data->ruleset_fd)) {
  158. err = 3;
  159. goto out;
  160. }
  161. /* Creates a denial to get the domain ID. */
  162. if (kill(data->parent_pid, 0) != -1) {
  163. err = 4;
  164. goto out;
  165. }
  166. if (EPERM != errno) {
  167. err = 5;
  168. goto out;
  169. }
  170. /* Signals the parent to read denial logs. */
  171. if (write(data->pipe_child, ".", 1) != 1) {
  172. err = 6;
  173. goto out;
  174. }
  175. /* Waits for the parent to update audit filters. */
  176. if (read(data->pipe_parent, &buffer, 1) != 1) {
  177. err = 7;
  178. goto out;
  179. }
  180. out:
  181. close(data->pipe_child);
  182. close(data->pipe_parent);
  183. return (void *)err;
  184. }
  185. /* Checks that the PID tied to a domain is not a TID but the TGID. */
  186. TEST_F(audit, thread)
  187. {
  188. const struct landlock_ruleset_attr ruleset_attr = {
  189. .scoped = LANDLOCK_SCOPE_SIGNAL,
  190. };
  191. __u64 denial_dom = 1;
  192. __u64 allocated_dom = 2;
  193. __u64 deallocated_dom = 3;
  194. pthread_t thread;
  195. int pipe_child[2], pipe_parent[2];
  196. char buffer;
  197. struct thread_data child_data;
  198. child_data.parent_pid = getppid();
  199. ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
  200. child_data.pipe_child = pipe_child[1];
  201. ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
  202. child_data.pipe_parent = pipe_parent[0];
  203. child_data.ruleset_fd =
  204. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  205. ASSERT_LE(0, child_data.ruleset_fd);
  206. /* TGID and TID are the same for the initial thread . */
  207. EXPECT_EQ(getpid(), gettid());
  208. EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  209. ASSERT_EQ(0, pthread_create(&thread, NULL, thread_audit_test,
  210. &child_data));
  211. /* Waits for the child to generate a denial. */
  212. ASSERT_EQ(1, read(pipe_child[0], &buffer, 1));
  213. EXPECT_EQ(0, close(pipe_child[0]));
  214. /* Matches the signal log to get the domain ID. */
  215. EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
  216. child_data.parent_pid, &denial_dom));
  217. EXPECT_NE(denial_dom, 1);
  218. EXPECT_NE(denial_dom, 0);
  219. EXPECT_EQ(0, matches_log_domain_allocated(self->audit_fd, getpid(),
  220. &allocated_dom));
  221. EXPECT_EQ(denial_dom, allocated_dom);
  222. /* Updates filter rules to match the drop record. */
  223. set_cap(_metadata, CAP_AUDIT_CONTROL);
  224. EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
  225. EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
  226. AUDIT_DEL_RULE));
  227. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  228. /* Signals the thread to exit, which will generate a domain deallocation. */
  229. ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
  230. EXPECT_EQ(0, close(pipe_parent[1]));
  231. ASSERT_EQ(0, pthread_join(thread, NULL));
  232. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  233. &audit_tv_dom_drop, sizeof(audit_tv_dom_drop)));
  234. EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 1,
  235. &deallocated_dom));
  236. EXPECT_EQ(denial_dom, deallocated_dom);
  237. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  238. &audit_tv_default, sizeof(audit_tv_default)));
  239. }
  240. FIXTURE(audit_flags)
  241. {
  242. struct audit_filter audit_filter;
  243. int audit_fd;
  244. __u64 *domain_id;
  245. };
  246. FIXTURE_VARIANT(audit_flags)
  247. {
  248. const int restrict_flags;
  249. };
  250. /* clang-format off */
  251. FIXTURE_VARIANT_ADD(audit_flags, default) {
  252. /* clang-format on */
  253. .restrict_flags = 0,
  254. };
  255. /* clang-format off */
  256. FIXTURE_VARIANT_ADD(audit_flags, same_exec_off) {
  257. /* clang-format on */
  258. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF,
  259. };
  260. /* clang-format off */
  261. FIXTURE_VARIANT_ADD(audit_flags, subdomains_off) {
  262. /* clang-format on */
  263. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF,
  264. };
  265. /* clang-format off */
  266. FIXTURE_VARIANT_ADD(audit_flags, cross_exec_on) {
  267. /* clang-format on */
  268. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
  269. };
  270. FIXTURE_SETUP(audit_flags)
  271. {
  272. disable_caps(_metadata);
  273. set_cap(_metadata, CAP_AUDIT_CONTROL);
  274. self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
  275. EXPECT_LE(0, self->audit_fd)
  276. {
  277. const char *error_msg;
  278. /* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
  279. if (self->audit_fd == -EEXIST)
  280. error_msg = "socket already in use (e.g. auditd)";
  281. else
  282. error_msg = strerror(-self->audit_fd);
  283. TH_LOG("Failed to initialize audit: %s", error_msg);
  284. }
  285. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  286. self->domain_id = mmap(NULL, sizeof(*self->domain_id),
  287. PROT_READ | PROT_WRITE,
  288. MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  289. ASSERT_NE(MAP_FAILED, self->domain_id);
  290. /* Domain IDs are greater or equal to 2^32. */
  291. *self->domain_id = 1;
  292. }
  293. FIXTURE_TEARDOWN(audit_flags)
  294. {
  295. EXPECT_EQ(0, munmap(self->domain_id, sizeof(*self->domain_id)));
  296. set_cap(_metadata, CAP_AUDIT_CONTROL);
  297. EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter));
  298. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  299. }
  300. TEST_F(audit_flags, signal)
  301. {
  302. int status;
  303. pid_t child;
  304. struct audit_records records;
  305. __u64 deallocated_dom = 2;
  306. child = fork();
  307. ASSERT_LE(0, child);
  308. if (child == 0) {
  309. const struct landlock_ruleset_attr ruleset_attr = {
  310. .scoped = LANDLOCK_SCOPE_SIGNAL,
  311. };
  312. int ruleset_fd;
  313. /* Add filesystem restrictions. */
  314. ruleset_fd = landlock_create_ruleset(&ruleset_attr,
  315. sizeof(ruleset_attr), 0);
  316. ASSERT_LE(0, ruleset_fd);
  317. EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  318. ASSERT_EQ(0, landlock_restrict_self(ruleset_fd,
  319. variant->restrict_flags));
  320. EXPECT_EQ(0, close(ruleset_fd));
  321. /* First signal checks to test log entries. */
  322. EXPECT_EQ(-1, kill(getppid(), 0));
  323. EXPECT_EQ(EPERM, errno);
  324. if (variant->restrict_flags &
  325. LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
  326. EXPECT_EQ(-EAGAIN, matches_log_signal(
  327. _metadata, self->audit_fd,
  328. getppid(), self->domain_id));
  329. EXPECT_EQ(*self->domain_id, 1);
  330. } else {
  331. __u64 allocated_dom = 3;
  332. EXPECT_EQ(0, matches_log_signal(
  333. _metadata, self->audit_fd,
  334. getppid(), self->domain_id));
  335. /* Checks domain information records. */
  336. EXPECT_EQ(0, matches_log_domain_allocated(
  337. self->audit_fd, getpid(),
  338. &allocated_dom));
  339. EXPECT_NE(*self->domain_id, 1);
  340. EXPECT_NE(*self->domain_id, 0);
  341. EXPECT_EQ(*self->domain_id, allocated_dom);
  342. }
  343. /* Second signal checks to test audit_count_records(). */
  344. EXPECT_EQ(-1, kill(getppid(), 0));
  345. EXPECT_EQ(EPERM, errno);
  346. /* Makes sure there is no superfluous logged records. */
  347. EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
  348. if (variant->restrict_flags &
  349. LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
  350. EXPECT_EQ(0, records.access);
  351. } else {
  352. EXPECT_EQ(1, records.access);
  353. }
  354. EXPECT_EQ(0, records.domain);
  355. /* Updates filter rules to match the drop record. */
  356. set_cap(_metadata, CAP_AUDIT_CONTROL);
  357. EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
  358. EXPECT_EQ(0,
  359. audit_filter_exe(self->audit_fd, &self->audit_filter,
  360. AUDIT_DEL_RULE));
  361. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  362. _exit(_metadata->exit_code);
  363. return;
  364. }
  365. ASSERT_EQ(child, waitpid(child, &status, 0));
  366. if (WIFSIGNALED(status) || !WIFEXITED(status) ||
  367. WEXITSTATUS(status) != EXIT_SUCCESS)
  368. _metadata->exit_code = KSFT_FAIL;
  369. if (variant->restrict_flags &
  370. LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
  371. EXPECT_EQ(-EAGAIN,
  372. matches_log_domain_deallocated(self->audit_fd, 0,
  373. &deallocated_dom));
  374. EXPECT_EQ(deallocated_dom, 2);
  375. } else {
  376. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  377. &audit_tv_dom_drop,
  378. sizeof(audit_tv_dom_drop)));
  379. EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 2,
  380. &deallocated_dom));
  381. EXPECT_NE(deallocated_dom, 2);
  382. EXPECT_NE(deallocated_dom, 0);
  383. EXPECT_EQ(deallocated_dom, *self->domain_id);
  384. EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
  385. &audit_tv_default,
  386. sizeof(audit_tv_default)));
  387. }
  388. }
  389. static int matches_log_fs_read_root(int audit_fd)
  390. {
  391. return audit_match_record(
  392. audit_fd, AUDIT_LANDLOCK_ACCESS,
  393. REGEX_LANDLOCK_PREFIX
  394. " blockers=fs\\.read_dir path=\"/\" dev=\"[^\"]\\+\" ino=[0-9]\\+$",
  395. NULL);
  396. }
  397. FIXTURE(audit_exec)
  398. {
  399. struct audit_filter audit_filter;
  400. int audit_fd;
  401. };
  402. FIXTURE_VARIANT(audit_exec)
  403. {
  404. const int restrict_flags;
  405. };
  406. /* clang-format off */
  407. FIXTURE_VARIANT_ADD(audit_exec, default) {
  408. /* clang-format on */
  409. .restrict_flags = 0,
  410. };
  411. /* clang-format off */
  412. FIXTURE_VARIANT_ADD(audit_exec, same_exec_off) {
  413. /* clang-format on */
  414. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF,
  415. };
  416. /* clang-format off */
  417. FIXTURE_VARIANT_ADD(audit_exec, subdomains_off) {
  418. /* clang-format on */
  419. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF,
  420. };
  421. /* clang-format off */
  422. FIXTURE_VARIANT_ADD(audit_exec, cross_exec_on) {
  423. /* clang-format on */
  424. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
  425. };
  426. /* clang-format off */
  427. FIXTURE_VARIANT_ADD(audit_exec, subdomains_off_and_cross_exec_on) {
  428. /* clang-format on */
  429. .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF |
  430. LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
  431. };
  432. FIXTURE_SETUP(audit_exec)
  433. {
  434. disable_caps(_metadata);
  435. set_cap(_metadata, CAP_AUDIT_CONTROL);
  436. self->audit_fd = audit_init();
  437. EXPECT_LE(0, self->audit_fd)
  438. {
  439. const char *error_msg;
  440. /* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
  441. if (self->audit_fd == -EEXIST)
  442. error_msg = "socket already in use (e.g. auditd)";
  443. else
  444. error_msg = strerror(-self->audit_fd);
  445. TH_LOG("Failed to initialize audit: %s", error_msg);
  446. }
  447. /* Applies test filter for the bin_wait_pipe_sandbox program. */
  448. EXPECT_EQ(0, audit_init_filter_exe(&self->audit_filter,
  449. bin_wait_pipe_sandbox));
  450. EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
  451. AUDIT_ADD_RULE));
  452. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  453. }
  454. FIXTURE_TEARDOWN(audit_exec)
  455. {
  456. set_cap(_metadata, CAP_AUDIT_CONTROL);
  457. EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
  458. AUDIT_DEL_RULE));
  459. clear_cap(_metadata, CAP_AUDIT_CONTROL);
  460. EXPECT_EQ(0, close(self->audit_fd));
  461. }
  462. TEST_F(audit_exec, signal_and_open)
  463. {
  464. struct audit_records records;
  465. int pipe_child[2], pipe_parent[2];
  466. char buf_parent;
  467. pid_t child;
  468. int status;
  469. ASSERT_EQ(0, pipe2(pipe_child, 0));
  470. ASSERT_EQ(0, pipe2(pipe_parent, 0));
  471. child = fork();
  472. ASSERT_LE(0, child);
  473. if (child == 0) {
  474. const struct landlock_ruleset_attr layer1 = {
  475. .scoped = LANDLOCK_SCOPE_SIGNAL,
  476. };
  477. char pipe_child_str[12], pipe_parent_str[12];
  478. char *const argv[] = { (char *)bin_wait_pipe_sandbox,
  479. pipe_child_str, pipe_parent_str, NULL };
  480. int ruleset_fd;
  481. /* Passes the pipe FDs to the executed binary. */
  482. EXPECT_EQ(0, close(pipe_child[0]));
  483. EXPECT_EQ(0, close(pipe_parent[1]));
  484. snprintf(pipe_child_str, sizeof(pipe_child_str), "%d",
  485. pipe_child[1]);
  486. snprintf(pipe_parent_str, sizeof(pipe_parent_str), "%d",
  487. pipe_parent[0]);
  488. ruleset_fd =
  489. landlock_create_ruleset(&layer1, sizeof(layer1), 0);
  490. if (ruleset_fd < 0) {
  491. perror("Failed to create a ruleset");
  492. _exit(1);
  493. }
  494. prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
  495. if (landlock_restrict_self(ruleset_fd,
  496. variant->restrict_flags)) {
  497. perror("Failed to restrict self");
  498. _exit(1);
  499. }
  500. close(ruleset_fd);
  501. ASSERT_EQ(0, execve(argv[0], argv, NULL))
  502. {
  503. TH_LOG("Failed to execute \"%s\": %s", argv[0],
  504. strerror(errno));
  505. };
  506. _exit(1);
  507. return;
  508. }
  509. EXPECT_EQ(0, close(pipe_child[1]));
  510. EXPECT_EQ(0, close(pipe_parent[0]));
  511. /* Waits for the child. */
  512. EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
  513. /* Tests that there was no denial until now. */
  514. EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
  515. EXPECT_EQ(0, records.access);
  516. EXPECT_EQ(0, records.domain);
  517. /*
  518. * Wait for the child to do a first denied action by layer1 and
  519. * sandbox itself with layer2.
  520. */
  521. EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
  522. EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
  523. /* Tests that the audit record only matches the child. */
  524. if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) {
  525. /* Matches the current domain. */
  526. EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
  527. getpid(), NULL));
  528. }
  529. /* Checks that we didn't miss anything. */
  530. EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
  531. EXPECT_EQ(0, records.access);
  532. /*
  533. * Wait for the child to do a second denied action by layer1 and
  534. * layer2, and sandbox itself with layer3.
  535. */
  536. EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
  537. EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
  538. /* Tests that the audit record only matches the child. */
  539. if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) {
  540. /* Matches the current domain. */
  541. EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
  542. getpid(), NULL));
  543. }
  544. if (!(variant->restrict_flags &
  545. LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) {
  546. /* Matches the child domain. */
  547. EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd));
  548. }
  549. /* Checks that we didn't miss anything. */
  550. EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
  551. EXPECT_EQ(0, records.access);
  552. /* Waits for the child to terminate. */
  553. EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
  554. ASSERT_EQ(child, waitpid(child, &status, 0));
  555. ASSERT_EQ(1, WIFEXITED(status));
  556. ASSERT_EQ(0, WEXITSTATUS(status));
  557. /* Tests that the audit record only matches the child. */
  558. if (!(variant->restrict_flags &
  559. LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) {
  560. /*
  561. * Matches the child domains, which tests that the
  562. * llcred->domain_exec bitmask is correctly updated with a new
  563. * domain.
  564. */
  565. EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd));
  566. EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
  567. getpid(), NULL));
  568. }
  569. /* Checks that we didn't miss anything. */
  570. EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
  571. EXPECT_EQ(0, records.access);
  572. }
  573. TEST_HARNESS_MAIN