test_cap.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /*
  2. * Copyright (c) 2023 Agustina Arzille.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * This test module tests the capability API.
  18. */
  19. #include <stdio.h>
  20. #include <kern/clock.h>
  21. #include <kern/cspace.h>
  22. #include <kern/intr.h>
  23. #include <kern/semaphore.h>
  24. #include <kern/task.h>
  25. #include <kern/thread.h>
  26. #include <test/test.h>
  27. #include <vm/map.h>
  28. #include <vm/page.h>
  29. #define TEST_CAP_CHANNEL_TAG ((uintptr_t)1234)
  30. struct test_cap_data
  31. {
  32. uintptr_t tag;
  33. struct cap_channel *ch;
  34. struct task *receiver;
  35. struct semaphore recv_sem;
  36. struct semaphore send_sem;
  37. struct semaphore dead_sem;
  38. };
  39. struct test_cap_vars
  40. {
  41. struct ipc_msg msg;
  42. struct ipc_msg_data mdata;
  43. char buf[16];
  44. uint32_t bufsize;
  45. struct iovec iov;
  46. struct ipc_msg_vme mvme[2];
  47. struct ipc_msg_cap mcap[2];
  48. struct cap_thread_info info;
  49. struct cap_kern_alert alert;
  50. };
  51. static struct test_cap_data test_cap_data;
  52. static int
  53. test_cap_alloc_task (struct task *task)
  54. {
  55. struct cap_task *ctask;
  56. int error = cap_task_create (&ctask, task);
  57. test_assert_eq (error, 0);
  58. int capx = cap_intern (ctask, 0);
  59. test_assert_ge (capx, 0);
  60. cap_base_rel (ctask);
  61. return (capx);
  62. }
  63. #if !defined (__LP64__) && defined (__i386__)
  64. __attribute__ ((regparm (2)))
  65. #endif
  66. static void
  67. test_cap_entry (struct ipc_msg *msg, struct ipc_msg_data *mdata)
  68. {
  69. test_assert_eq (mdata->bytes_recv, sizeof (uint32_t));
  70. test_assert_eq (mdata->vmes_recv, 1);
  71. test_assert_eq (mdata->caps_recv, 1);
  72. test_assert_eq (mdata->tag, TEST_CAP_CHANNEL_TAG);
  73. test_assert_eq (mdata->task_id, task_id (thread_self()->task));
  74. test_assert_eq (mdata->thread_id, thread_id (thread_self ()));
  75. _Auto vars = structof (msg, struct test_cap_vars, msg);
  76. test_assert_ne (vars->bufsize, 0);
  77. ssize_t nb = cap_pull_bytes (vars->buf, vars->bufsize, mdata);
  78. test_assert_gt (nb, 0);
  79. test_assert_eq (nb, (ssize_t)vars->bufsize);
  80. test_assert_streq (vars->buf, "hello");
  81. _Auto entry = vm_map_find (vm_map_self (), vars->mvme[0].addr);
  82. test_assert_nonnull (entry);
  83. test_assert_eq (VM_MAP_PROT (entry->flags), VM_PROT_READ);
  84. test_assert_eq (*(char *)vars->mvme[0].addr, 'x');
  85. vm_map_entry_put (entry);
  86. _Auto cap = cspace_get (cspace_self (), vars->mcap[0].cap);
  87. test_assert_nonnull (cap);
  88. test_assert_eq (cap_type (cap), CAP_TYPE_TASK);
  89. test_assert_eq (((struct cap_task *)cap)->task, thread_self()->task);
  90. cap_base_rel (cap);
  91. vars->bufsize = 'Z';
  92. void *mem;
  93. int error = vm_map_anon_alloc (&mem, vm_map_self (), PAGE_SIZE * 2);
  94. test_assert_zero (error);
  95. _Auto mp = (struct ipc_msg_data *)mem + 1;
  96. nb = cap_push_bytes (&vars->bufsize, sizeof (vars->bufsize), mp);
  97. test_assert_eq (nb, sizeof (vars->bufsize));
  98. test_assert_eq (mp->bytes_sent, nb);
  99. memset (mem, 'z', 100);
  100. vars->mvme[0].addr = (uintptr_t)mem;
  101. vars->mvme[0].size = vars->mvme[1].size = PAGE_SIZE;
  102. vars->mvme[1].addr = (uintptr_t)mem + PAGE_SIZE;
  103. vars->mcap[0].cap = test_cap_alloc_task (task_self ());
  104. vars->iov = IOVEC (memset (vars->buf, '?', sizeof (vars->buf)), 8);
  105. vars->msg.iov_cnt = 1;
  106. vars->msg.cap_cnt = 1;
  107. vars->msg.vme_cnt = 2;
  108. cap_reply_msg (&vars->msg, 0);
  109. panic ("cap_reply_msg returned");
  110. }
  111. static void
  112. test_cap_receiver (void *arg)
  113. {
  114. struct test_cap_data *data = arg;
  115. struct cap_flow *flow;
  116. data->receiver = task_self ();
  117. data->tag = (uintptr_t)clock_get_time ();
  118. int error = cap_flow_create (&flow, 0, data->tag, (uintptr_t)test_cap_entry);
  119. test_assert_zero (error);
  120. error = cap_channel_create (&data->ch, flow, TEST_CAP_CHANNEL_TAG);
  121. test_assert_zero (error);
  122. _Auto page = vm_page_alloc (0, VM_PAGE_SEL_DIRECTMAP, VM_PAGE_KERNEL, 0);
  123. test_assert_nonnull (page);
  124. vm_page_ref (page);
  125. struct test_cap_vars *vars;
  126. error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), 1);
  127. test_assert_zero (error);
  128. vars->mdata.size = sizeof (vars->mdata);
  129. {
  130. // Test that alerts are delivered in priority order.
  131. strcpy (vars->buf, "abcd");
  132. ssize_t rv = cap_send_alert (flow, vars->buf, 0, 0);
  133. test_assert_ge (rv, 0);
  134. strcpy (vars->buf, "1234");
  135. rv = cap_send_alert (flow, vars->buf, 0, 1);
  136. test_assert_ge (rv, 0);
  137. error = cap_recv_alert (flow, vars->buf, 0, &vars->mdata);
  138. test_assert_zero (error);
  139. test_assert_streq (vars->buf, "1234");
  140. test_assert_eq (vars->mdata.task_id, task_id (thread_self()->task));
  141. test_assert_eq (vars->mdata.thread_id, thread_id (thread_self ()));
  142. test_assert_eq (vars->mdata.tag, data->tag);
  143. error = cap_recv_alert (flow, vars->buf, 0, &vars->mdata);
  144. test_assert_zero (error);
  145. test_assert_streq (vars->buf, "abcd");
  146. test_assert_eq (vars->mdata.task_id, task_id (thread_self()->task));
  147. test_assert_eq (vars->mdata.thread_id, thread_id (thread_self ()));
  148. test_assert_eq (vars->mdata.tag, data->tag);
  149. }
  150. vars->mvme[0] = (struct ipc_msg_vme) { .addr = PAGE_SIZE * 10 };
  151. vars->iov = IOVEC (&vars->bufsize, sizeof (vars->bufsize));
  152. vars->msg = (struct ipc_msg)
  153. {
  154. .size = sizeof (struct ipc_msg),
  155. .iovs = &vars->iov,
  156. .iov_cnt = 1,
  157. .vmes = vars->mvme,
  158. .vme_cnt = 1,
  159. .caps = vars->mcap,
  160. .cap_cnt = 1,
  161. };
  162. vars->mdata.size = sizeof (vars->mdata);
  163. error = cap_flow_add_lpad (flow, (char *)vm_page_direct_ptr (page) +
  164. PAGE_SIZE, PAGE_SIZE, &vars->msg,
  165. &vars->mdata, &vars->info);
  166. test_assert_zero (error);
  167. semaphore_post (&data->send_sem);
  168. semaphore_wait (&data->recv_sem);
  169. vm_page_unref (page);
  170. cap_base_rel (data->ch);
  171. // Test that we receive an alert on a channel closed.
  172. error = cap_recv_alert (flow, &vars->alert, 0, &vars->mdata);
  173. test_assert_zero (error);
  174. test_assert_zero (vars->mdata.task_id);
  175. test_assert_zero (vars->mdata.thread_id);
  176. test_assert_eq (vars->alert.type, CAP_ALERT_CHAN_CLOSED);
  177. test_assert_eq (vars->alert.tag, TEST_CAP_CHANNEL_TAG);
  178. cap_base_rel (flow);
  179. }
  180. static void
  181. test_cap_sender (void *arg)
  182. {
  183. struct test_cap_data *data = arg;
  184. semaphore_wait (&data->send_sem);
  185. void *mem;
  186. int error = vm_map_anon_alloc (&mem, vm_map_self (), PAGE_SIZE * 2);
  187. test_assert_zero (error);
  188. struct
  189. {
  190. struct ipc_msg_vme mvme;
  191. char buf[6];
  192. uint32_t bufsize;
  193. struct iovec iovecs[2];
  194. struct ipc_msg msg;
  195. struct ipc_msg_data mdata;
  196. struct ipc_msg_cap mcap;
  197. struct ipc_msg out_msg;
  198. struct ipc_msg_vme out_vme[2];
  199. struct ipc_msg_cap out_cap[2];
  200. } *vars = (void *)((char *)mem + PAGE_SIZE);
  201. vars->mdata.size = sizeof (vars->mdata);
  202. vars->mvme = (struct ipc_msg_vme)
  203. {
  204. .addr = (uintptr_t)memset (mem, 'x', PAGE_SIZE),
  205. .prot = VM_PROT_READ,
  206. .max_prot = VM_PROT_READ,
  207. .size = PAGE_SIZE
  208. };
  209. vars->mcap = (struct ipc_msg_cap)
  210. {
  211. .cap = test_cap_alloc_task (task_self ()),
  212. .flags = 0
  213. };
  214. strcpy (vars->buf, "hello");
  215. vars->bufsize = sizeof (vars->buf) - 1;
  216. vars->iovecs[0] = IOVEC (&vars->bufsize, sizeof (vars->bufsize));
  217. vars->iovecs[1] = IOVEC (vars->buf, vars->bufsize);
  218. vars->msg = (struct ipc_msg)
  219. {
  220. .size = sizeof (struct ipc_msg),
  221. .iovs = vars->iovecs,
  222. .iov_cnt = 2,
  223. .vmes = &vars->mvme,
  224. .vme_cnt = 1,
  225. .caps = &vars->mcap,
  226. .cap_cnt = 1,
  227. };
  228. vars->out_msg = (struct ipc_msg)
  229. {
  230. .size = sizeof (struct ipc_msg),
  231. .iovs = vars->iovecs,
  232. .iov_cnt = 2,
  233. .vmes = vars->out_vme,
  234. .vme_cnt = 2,
  235. .caps = vars->out_cap,
  236. .cap_cnt = 2
  237. };
  238. ssize_t nb = cap_send_msg (data->ch, &vars->msg,
  239. &vars->out_msg, &vars->mdata);
  240. test_assert_eq (nb, (ssize_t)(sizeof (uint32_t) + sizeof (vars->buf) - 1));
  241. test_assert_eq (vars->bufsize, 'Z');
  242. test_assert_streq (vars->buf, "?????");
  243. test_assert_eq (*(char *)vars->out_vme[0].addr, 'z');
  244. test_assert_eq (vars->mdata.vmes_sent, 1);
  245. test_assert_eq (vars->mdata.vmes_recv, 2);
  246. test_assert_eq (vars->mdata.caps_sent, 1);
  247. test_assert_eq (vars->mdata.caps_recv, 1);
  248. test_assert_ne (vars->mdata.flags & IPC_MSG_TRUNC, 0);
  249. _Auto cap = cspace_get (cspace_self (), vars->out_cap[0].cap);
  250. test_assert_nonnull (cap);
  251. test_assert_eq (cap_type (cap), CAP_TYPE_TASK);
  252. test_assert_eq (((struct cap_task *)cap)->task, data->receiver);
  253. cap_base_rel (cap);
  254. semaphore_post (&data->recv_sem);
  255. }
  256. static void
  257. test_cap_misc (void *arg __unused)
  258. {
  259. struct cap_task *ctask;
  260. int error = cap_task_create (&ctask, task_self ());
  261. test_assert_zero (error);
  262. struct
  263. {
  264. struct task_ipc_msg task_msg;
  265. struct thread_ipc_msg thr_msg;
  266. BITMAP_DECLARE (cpumap, CONFIG_MAX_CPUS);
  267. } *vars;
  268. error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), sizeof (*vars));
  269. test_assert_zero (error);
  270. vars->task_msg.op = TASK_IPC_GET_NAME;
  271. ssize_t rv = cap_send_bytes (ctask, &vars->task_msg, sizeof (vars->task_msg),
  272. &vars->task_msg, sizeof (vars->task_msg));
  273. test_assert_zero (rv);
  274. test_assert_streq (vars->task_msg.name, "cap_misc");
  275. vars->task_msg.op = TASK_IPC_SET_NAME;
  276. strcpy (vars->task_msg.name, "new_name");
  277. rv = cap_send_bytes (ctask, &vars->task_msg, sizeof (vars->task_msg), 0, 0);
  278. test_assert_zero (rv);
  279. test_assert_streq (task_self()->name, "new_name");
  280. cap_base_rel (ctask);
  281. struct cap_thread *cthread;
  282. error = cap_thread_create (&cthread, thread_self ());
  283. vars->thr_msg.op = THREAD_IPC_GET_NAME;
  284. rv = cap_send_bytes (cthread, &vars->thr_msg, sizeof (vars->thr_msg),
  285. &vars->thr_msg, sizeof (vars->thr_msg));
  286. test_assert_zero (rv);
  287. test_assert_streq (vars->thr_msg.name, "cap_misc/0");
  288. thread_pin ();
  289. vars->thr_msg.op = THREAD_IPC_GET_AFFINITY;
  290. vars->thr_msg.cpumap.map = vars->cpumap;
  291. vars->thr_msg.cpumap.size = sizeof (vars->cpumap);
  292. rv = cap_send_bytes (cthread, &vars->thr_msg, sizeof (vars->thr_msg),
  293. &vars->thr_msg, sizeof (vars->thr_msg));
  294. test_assert_zero (rv);
  295. test_assert_ne (bitmap_test (vars->cpumap, cpu_id ()), 0);
  296. thread_unpin ();
  297. cap_base_rel (cthread);
  298. }
  299. static void
  300. test_cap_dead_child (void *arg)
  301. {
  302. semaphore_wait (arg);
  303. }
  304. static void
  305. test_cap_dead_helper (void *arg)
  306. {
  307. struct cap_flow *flow = arg;
  308. struct thread *thr;
  309. struct thread_attr attr;
  310. thread_attr_init (&attr, "cap_dead/2");
  311. thread_attr_set_detached (&attr);
  312. int error = thread_create (&thr, &attr, test_cap_dead_child,
  313. &test_cap_data.dead_sem);
  314. test_assert_zero (error);
  315. error = cap_thread_register (flow, thr);
  316. test_assert_zero (error);
  317. error = cap_thread_unregister (flow, thr);
  318. test_assert_zero (error);
  319. error = cap_thread_register (flow, thread_self ());
  320. test_assert_zero (error);
  321. error = cap_task_register (flow, thread_self()->task);
  322. test_assert_zero (error);
  323. test_cap_dead_child (&test_cap_data.dead_sem);
  324. }
  325. static void
  326. test_cap_dead_notif (void *arg __unused)
  327. {
  328. struct cap_flow *flow;
  329. int error = cap_flow_create (&flow, 0, 0, 0);
  330. test_assert_zero (error);
  331. struct cap_channel *chan;
  332. error = cap_channel_create (&chan, flow, 1234);
  333. test_assert_zero (error);
  334. int capx = cspace_add_free (cspace_self (), CAP (chan), CSPACE_WEAK);
  335. test_assert_ge (capx, 0);
  336. cap_base_rel (chan);
  337. int mark = 0;
  338. chan = (struct cap_channel *)cspace_get_all (cspace_self (), capx, &mark);
  339. test_assert_nonnull (chan);
  340. cap_base_rel (chan);
  341. if (mark)
  342. cap_base_rel (chan);
  343. struct
  344. {
  345. struct cap_kern_alert alert;
  346. char extra[16];
  347. struct ipc_msg_data mdata;
  348. } *buf;
  349. error = vm_map_anon_alloc ((void **)&buf, vm_map_self (), 1);
  350. test_assert_zero (error);
  351. buf->mdata.size = sizeof (buf->mdata);
  352. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  353. test_assert_zero (error);
  354. test_assert_zero (buf->mdata.thread_id);
  355. test_assert_zero (buf->mdata.task_id);
  356. test_assert_eq (buf->alert.type, CAP_ALERT_CHAN_CLOSED);
  357. test_assert_eq (buf->alert.tag, 1234);
  358. struct thread *thr;
  359. error = test_util_create_thr (&thr, test_cap_dead_helper, flow, "cap_dead");
  360. test_assert_zero (error);
  361. int tsk_id = task_id (thr->task), thr_id = thread_id (thr);
  362. int got_task = 0, got_thr = 0;
  363. semaphore_post (&test_cap_data.dead_sem);
  364. semaphore_post (&test_cap_data.dead_sem);
  365. thread_join (thr);
  366. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  367. test_assert_zero (error);
  368. test_assert_zero (buf->mdata.thread_id);
  369. test_assert_zero (buf->mdata.task_id);
  370. if (buf->alert.type == CAP_ALERT_THREAD_DIED &&
  371. buf->alert.thread_id == thr_id)
  372. got_thr = 1;
  373. else if (buf->alert.type == CAP_ALERT_TASK_DIED &&
  374. buf->alert.task_id == tsk_id)
  375. got_task = 1;
  376. else
  377. panic ("got unexpected alert");
  378. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  379. test_assert_zero (error);
  380. test_assert_zero (buf->mdata.thread_id);
  381. test_assert_zero (buf->mdata.task_id);
  382. if (buf->alert.type == CAP_ALERT_THREAD_DIED &&
  383. buf->alert.thread_id == thr_id)
  384. ++got_thr;
  385. else if (buf->alert.type == CAP_ALERT_TASK_DIED &&
  386. buf->alert.task_id == tsk_id)
  387. ++got_task;
  388. else
  389. panic ("got unexpected alert");
  390. test_assert_eq (got_thr, 1);
  391. test_assert_eq (got_task, 1);
  392. }
  393. TEST_DEFERRED (cap)
  394. {
  395. _Auto data = &test_cap_data;
  396. semaphore_init (&data->send_sem, 0, 0xff);
  397. semaphore_init (&data->recv_sem, 0, 0xff);
  398. semaphore_init (&data->dead_sem, 0, 0xff);
  399. struct thread *sender, *receiver, *misc, *dead_notif;
  400. int error = test_util_create_thr (&sender, test_cap_sender,
  401. data, "cap_sender");
  402. test_assert_zero (error);
  403. error = test_util_create_thr (&receiver, test_cap_receiver,
  404. data, "cap_receiver");
  405. test_assert_zero (error);
  406. error = test_util_create_thr (&misc, test_cap_misc, NULL, "cap_misc");
  407. test_assert_zero (error);
  408. error = test_util_create_thr (&dead_notif, test_cap_dead_notif,
  409. NULL, "cap_dead");
  410. thread_join (sender);
  411. thread_join (receiver);
  412. thread_join (misc);
  413. thread_join (dead_notif);
  414. return (TEST_OK);
  415. }