Seccomp_test.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "benc/String.h"
  16. #include "util/log/FileWriterLog.h"
  17. #include "memory/Allocator.h"
  18. #include "util/Seccomp.h"
  19. #include "util/events/EventBase.h"
  20. #include "util/events/Process.h"
  21. #include "util/events/PipeServer.h"
  22. #include "util/events/Pipe.h"
  23. #include "util/events/Timeout.h"
  24. #include "util/CString.h"
  25. #include "crypto/random/Random.h"
  26. #include <unistd.h>
  27. struct Context
  28. {
  29. struct Iface iface;
  30. struct Allocator* alloc;
  31. struct EventBase* eventBase;
  32. Identity
  33. };
  34. static void childComplete(void* vEventBase)
  35. {
  36. EventBase_endLoop((struct EventBase*)vEventBase);
  37. }
  38. struct ChildCtx
  39. {
  40. struct EventBase* base;
  41. struct Log* log;
  42. struct Pipe* pipe;
  43. struct Allocator* alloc;
  44. Identity
  45. };
  46. static void onConnectionChild(struct Pipe* pipe, int status)
  47. {
  48. struct ChildCtx* child = Identity_check((struct ChildCtx*) pipe->userData);
  49. Er_assert(Seccomp_dropPermissions(child->alloc, child->log));
  50. Assert_true(Seccomp_isWorking());
  51. struct Message* ok = Message_new(0, 512, child->alloc);
  52. Er_assert(Message_epush(ok, "OK", 3));
  53. struct Iface iface = { .send = NULL };
  54. Iface_plumb(&pipe->iface, &iface);
  55. Iface_send(&iface, ok);
  56. // just set a timeout long enough that we're pretty sure the parent will get the message
  57. // before we quit.
  58. Timeout_setInterval(childComplete, child->base, 10, child->base, child->alloc);
  59. }
  60. static void timeout(void* vNULL)
  61. {
  62. Assert_true(!"timed out");
  63. }
  64. static void timeout2(void* vNULL)
  65. {
  66. Assert_true(!"time out 2");
  67. }
  68. static int child(char* pipeName, struct Allocator* alloc, struct Log* logger)
  69. {
  70. struct ChildCtx* ctx = Allocator_calloc(alloc, sizeof(struct ChildCtx), 1);
  71. ctx->base = EventBase_new(alloc);
  72. ctx->alloc = alloc;
  73. ctx->log = logger;
  74. ctx->pipe = Er_assert(Pipe_named(pipeName, ctx->base, logger, alloc));
  75. ctx->pipe->onConnection = onConnectionChild;
  76. ctx->pipe->userData = ctx;
  77. Identity_set(ctx);
  78. Timeout_setTimeout(timeout, ctx->base, 2000, ctx->base, alloc);
  79. EventBase_beginLoop(ctx->base);
  80. return 0;
  81. }
  82. static Iface_DEFUN receiveMessageParent(struct Message* msg, struct Iface* iface)
  83. {
  84. struct Context* ctx = Identity_check((struct Context*) iface);
  85. // PipeServer pushes a uint32 identifier of the client who sent the message
  86. Er_assert(AddrIface_popAddr(msg));
  87. Assert_true(Message_getLength(msg) == 3);
  88. Assert_true(!Bits_memcmp(msg->msgbytes, "OK", 3));
  89. EventBase_endLoop(ctx->eventBase);
  90. return NULL;
  91. }
  92. int main(int argc, char** argv)
  93. {
  94. struct Allocator* alloc = Allocator_new(20000);
  95. struct Log* logger = FileWriterLog_new(stdout, alloc);
  96. if (!Seccomp_exists()) {
  97. Log_debug(logger, "Seccomp not supported on this system");
  98. return 0;
  99. }
  100. if (argc > 3 && !CString_strcmp("Seccomp_test", argv[1]) && !CString_strcmp("child", argv[2])) {
  101. child(argv[3], alloc, logger);
  102. /* Allocator_free(alloc); */
  103. /* above line leads to error while `gdb -ex 'set follow-fork-mode child' -ex 'run Seccomp_test' ./target/release/testcjdroute`:
  104. GNU gdb (Ubuntu 12.0.90-0ubuntu1) 12.0.90
  105. Copyright (C) 2022 Free Software Foundation, Inc.
  106. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  107. This is free software: you are free to change and redistribute it.
  108. There is NO WARRANTY, to the extent permitted by law.
  109. Type "show copying" and "show warranty" for details.
  110. This GDB was configured as "x86_64-linux-gnu".
  111. Type "show configuration" for configuration details.
  112. For bug reporting instructions, please see:
  113. <https://www.gnu.org/software/gdb/bugs/>.
  114. Find the GDB manual and other documentation resources online at:
  115. <http://www.gnu.org/software/gdb/documentation/>.
  116. For help, type "help".
  117. Type "apropos word" to search for commands related to "word"...
  118. Reading symbols from ./target/release/testcjdroute...
  119. warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts
  120. of file /home/yb/pkt/cjdns-dev/target/release/testcjdroute.
  121. Use `info auto-load python-scripts [REGEXP]' to list them.
  122. Starting program: /home/yb/pkt/cjdns-dev/target/release/testcjdroute Seccomp_test
  123. [Thread debugging using libthread_db enabled]
  124. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
  125. [New Thread 0x7ffff7bff640 (LWP 141592)]
  126. 1704797851 INFO RandomSeed.c:42 Attempting to seed random number generator
  127. 1704797851 INFO RandomSeed.c:50 Trying random seed [/dev/urandom] Success
  128. 1704797851 INFO RandomSeed.c:50 Trying random seed [/proc/sys/kernel/random/uuid (Linux)] Success
  129. 1704797851 INFO RandomSeed.c:50 Trying random seed [sysctl(RANDOM_UUID) (Linux)] Success
  130. 1704797851 INFO RandomSeed.c:50 Trying random seed [getentropy(2)] Success
  131. 1704797851 INFO RandomSeed.c:63 Seeding random number generator succeeded with [4] sources
  132. [Attaching after Thread 0x7ffff7e9ad00 (LWP 141589) vfork to child process 141593]
  133. [New inferior 2 (process 141593)]
  134. [Thread debugging using libthread_db enabled]
  135. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
  136. [Detaching vfork parent process 141589 after child exec]
  137. [Inferior 1 (process 141589) detached]
  138. process 141593 is executing new program: /home/yb/pkt/cjdns-dev/target/release/testcjdroute
  139. warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts
  140. of file /home/yb/pkt/cjdns-dev/target/release/testcjdroute.
  141. Use `info auto-load python-scripts [REGEXP]' to list them.
  142. [Thread debugging using libthread_db enabled]
  143. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
  144. [New Thread 0x7ffff7bff640 (LWP 141594)]
  145. 1704797851 DEBUG Pipe.c:259 Pipe [/tmp/cjdns-test-gthc2tcsht26v4vsmp6fns0637pr5t] established connection
  146. 1704797851 DEBUG Pipe.c:259 Pipe [(null)] established connection
  147. 1704797851 DEBUG Pipe.c:112 Sending message of length [3]
  148. 1704797851 DEBUG Pipe.c:212 Pipe incoming message len [3]
  149. thread 'main' panicked at rust/cjdns_sys/src/rffi/util.rs:32:5:
  150. Assertion failure [Pipe.c:290] [(Identity_ptr->Identity_verifier == ((uintptr_t) 0x1d268b90ed35c9f1ull))]
  151. Thread 2.1 "testcjdroute" received signal SIGSYS, Bad system call.
  152. [Switching to Thread 0x7ffff7e9ad00 (LWP 141593)]
  153. __GI___getcwd (buf=0x5555557c3440 "\340\234\341\367\377\177", size=512) at ../sysdeps/unix/sysv/linux/getcwd.c:80
  154. 80 ../sysdeps/unix/sysv/linux/getcwd.c: No such file or directory.
  155. INS (gdb) bt
  156. #0 __GI___getcwd (buf=0x5555557c3440 "\340\234\341\367\377\177", size=512) at ../sysdeps/unix/sysv/linux/getcwd.c:80
  157. #1 0x00005555556ec728 in std::sys::unix::os::getcwd () at library/std/src/sys/unix/os.rs:160
  158. #2 std::env::current_dir () at library/std/src/env.rs:57
  159. #3 0x00005555556f2cb5 in std::sys_common::backtrace::_print_fmt () at library/std/src/sys_common/backtrace.rs:53
  160. #4 std::sys_common::backtrace::_print::{impl#0}::fmt () at library/std/src/sys_common/backtrace.rs:44
  161. #5 0x000055555571920c in core::fmt::rt::Argument::fmt () at library/core/src/fmt/rt.rs:138
  162. #6 core::fmt::write () at library/core/src/fmt/mod.rs:1114
  163. #7 0x00005555556f022e in std::io::Write::write_fmt<std::sys::unix::stdio::Stderr> () at library/std/src/io/mod.rs:1763
  164. #8 0x00005555556f2be4 in std::sys_common::backtrace::_print () at library/std/src/sys_common/backtrace.rs:47
  165. #9 std::sys_common::backtrace::print () at library/std/src/sys_common/backtrace.rs:34
  166. #10 0x00005555556f45c3 in std::panicking::default_hook::{closure#1} () at library/std/src/panicking.rs:272
  167. #11 0x00005555556f42e4 in std::panicking::default_hook () at library/std/src/panicking.rs:292
  168. #12 0x000055555558c3ee in alloc::boxed::{impl#49}::call<(&core::panic::panic_info::PanicInfo), (dyn core::ops::function::Fn<(&core::panic::panic_info::PanicInfo), Output=()> + core::marker::Send + core::marker::Sync), alloc::alloc::Global> (self=<optimized out>, args=...) at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/alloc/src/boxed.rs:2021
  169. #13 cjdns_sys::rust_main::{async_block#1}::{closure#0} (info=0x200) at rust/cjdns_sys/src/lib.rs:23
  170. #14 0x00005555556f4cc1 in alloc::boxed::{impl#49}::call<(&core::panic::panic_info::PanicInfo), (dyn core::ops::function::Fn<(&core::panic::panic_info::PanicInfo), Output=()> + core::marker::Send + core::marker::Sync), alloc::alloc::Global> () at library/alloc/src/boxed.rs:2021
  171. #15 std::panicking::rust_panic_with_hook () at library/std/src/panicking.rs:735
  172. #16 0x00005555556f4a41 in std::panicking::begin_panic_handler::{closure#0} () at library/std/src/panicking.rs:609
  173. #17 0x00005555556f3326 in std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::{closure_env#0}, !> () at library/std/src/sys_common/backtrace.rs:170
  174. #18 0x00005555556f4792 in std::panicking::begin_panic_handler () at library/std/src/panicking.rs:597
  175. #19 0x000055555557a095 in core::panicking::panic_fmt () at library/core/src/panicking.rs:72
  176. #20 0x000055555559ab36 in core::panicking::panic_display<alloc::borrow::Cow<str>> (x=<optimized out>) at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:168
  177. #21 cjdns_sys::rffi::util::Rffi_panic (msg=msg@entry=0x7fffffffcd40) at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panic.rs:26
  178. #22 0x00005555555a4481 in Assert_failure (format=format@entry=0x555555720f88 "Assertion failure [%s:%d] [%s]\n") at util/Assert.c:38
  179. #23 0x00005555555e5b01 in onFree (job=<optimized out>) at util/events/libuv/Pipe.c:290
  180. #24 0x000055555557dff8 in cjdns_sys::rffi::allocator::free_allocs (allocs=...) at rust/cjdns_sys/src/rffi/allocator.rs:109
  181. #25 cjdns_sys::rffi::allocator::Allocator::free (self=<optimized out>, source=...) at rust/cjdns_sys/src/rffi/allocator.rs:358
  182. #26 0x000055555557e70d in cjdns_sys::rffi::allocator::Rffi_allocator_free (a=a@entry=0x5555557bfbd0, file=file@entry=0x555555724e9e, line=line@entry=118)
  183. at rust/cjdns_sys/src/rffi/allocator.rs:378
  184. #27 0x00005555555a0104 in Allocator__free (alloc=alloc@entry=0x5555557bfbd0, file=file@entry=0x555555724e9e "Seccomp_test.c", line=line@entry=118) at memory/Allocator.c:23
  185. #28 0x00005555555aa31e in Seccomp_test_main (argc=<optimized out>, argv=<optimized out>) at util/test/Seccomp_test.c:118
  186. #29 0x00005555555a0df2 in main2 (detRand=0x5555557bfa10, alloc=0x5555557bf540, argv=0x5555557b3ae0, argc=4) at test/testcjdroute.c:238
  187. #30 testcjdroute_main (argc=4, argv=0x5555557b3ae0) at test/testcjdroute.c:277
  188. #31 0x000055555558c34e in cjdns_sys::rust_main::{async_block#1} () at rust/cjdns_sys/src/lib.rs:26
  189. #32 0x000055555558aad2 in tokio::runtime::park::{impl#4}::block_on::{closure#0}<cjdns_sys::rust_main::{async_block_env#1}> ()
  190. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/park.rs:282
  191. #33 tokio::runtime::coop::with_budget<core::task::poll::Poll<()>, tokio::runtime::park::{impl#4}::block_on::{closure_env#0}<cjdns_sys::rust_main::{async_block_env#1}>> (budget=..., f=...)
  192. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/coop.rs:107
  193. #34 tokio::runtime::coop::budget<core::task::poll::Poll<()>, tokio::runtime::park::{impl#4}::block_on::{closure_env#0}<cjdns_sys::rust_main::{async_block_env#1}>> (f=...)
  194. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/coop.rs:73
  195. #35 tokio::runtime::park::CachedParkThread::block_on<cjdns_sys::rust_main::{async_block_env#1}> (self=0x7fffffffd5ef, f=<error reading variable: Cannot access memory at address 0x10>)
  196. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/park.rs:282
  197. #36 tokio::runtime::context::blocking::BlockingRegionGuard::block_on<cjdns_sys::rust_main::{async_block_env#1}> (self=<optimized out>, f=...)
  198. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/blocking.rs:66
  199. #37 0x000055555558ea7f in tokio::runtime::scheduler::multi_thread::{impl#0}::block_on::{closure#0}<cjdns_sys::rust_main::{async_block_env#1}> (blocking=0x5555557c3440)
  200. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/mod.rs:87
  201. #38 tokio::runtime::context::runtime::enter_runtime<tokio::runtime::scheduler::multi_thread::{impl#0}::block_on::{closure_env#0}<cjdns_sys::rust_main::{async_block_env#1}>, ()> (
  202. handle=0x7fffffffd7f0, allow_block_in_place=<optimized out>, f=...) at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/runtime.rs:65
  203. #39 0x0000555555587452 in tokio::runtime::scheduler::multi_thread::MultiThread::block_on<cjdns_sys::rust_main::{async_block_env#1}> (self=<optimized out>, handle=<optimized out>,
  204. future=<error reading variable: Cannot access memory at address 0x10>)
  205. at /home/yb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/mod.rs:86
  206. #40 tokio::runtime::runtime::Runtime::block_on<cjdns_sys::rust_main::{async_block_env#1}> (self=<optimized out>, future=...)
  207. */
  208. return 0;
  209. }
  210. struct EventBase* eb = EventBase_new(alloc);
  211. struct Random* rand = Random_new(alloc, logger, NULL);
  212. char randName[32] = {0};
  213. Random_base32(rand, (uint8_t*)randName, 31);
  214. String* name = String_printf(alloc, "%s%scjdns-test-%s", Pipe_PATH, Pipe_PATH_SEP, randName);
  215. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  216. Identity_set(ctx);
  217. ctx->alloc = alloc;
  218. ctx->iface.send = receiveMessageParent;
  219. ctx->eventBase = eb;
  220. struct PipeServer* pipe = PipeServer_named(name->bytes, eb, NULL, logger, alloc);
  221. Iface_plumb(&ctx->iface, pipe->iface.iface);
  222. const char* path = Process_getPath(alloc);
  223. const char* args[] = { "Seccomp_test", "child", name->bytes, NULL };
  224. Assert_true(!Process_spawn(path, args, eb, alloc, NULL));
  225. Timeout_setTimeout(timeout2, NULL, 2000, eb, alloc);
  226. EventBase_beginLoop(eb);
  227. unlink(name->bytes);
  228. return 0;
  229. }