test_cap.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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. mp->size = sizeof (*mp);
  97. nb = cap_push_bytes (&vars->bufsize, sizeof (vars->bufsize), mp);
  98. test_assert_eq (nb, sizeof (vars->bufsize));
  99. test_assert_eq (mp->bytes_sent, nb);
  100. memset (mem, 'z', 100);
  101. vars->mvme[0].addr = (uintptr_t)mem;
  102. vars->mvme[0].size = vars->mvme[1].size = PAGE_SIZE;
  103. vars->mvme[1].addr = (uintptr_t)mem + PAGE_SIZE;
  104. vars->mcap[0].cap = test_cap_alloc_task (task_self ());
  105. vars->iov = IOVEC (memset (vars->buf, '?', sizeof (vars->buf)), 8);
  106. vars->msg.iov_cnt = 1;
  107. vars->msg.cap_cnt = 1;
  108. vars->msg.vme_cnt = 2;
  109. cap_reply_msg (&vars->msg, 0);
  110. panic ("cap_reply_msg returned");
  111. }
  112. static void
  113. test_cap_receiver (void *arg)
  114. {
  115. struct test_cap_data *data = arg;
  116. struct cap_flow *flow;
  117. data->receiver = task_self ();
  118. data->tag = (uintptr_t)clock_get_time ();
  119. int error = cap_flow_create (&flow, 0, data->tag, (uintptr_t)test_cap_entry);
  120. test_assert_zero (error);
  121. error = cap_channel_create (&data->ch, flow, TEST_CAP_CHANNEL_TAG);
  122. test_assert_zero (error);
  123. _Auto page = vm_page_alloc (0, VM_PAGE_SEL_DIRECTMAP, VM_PAGE_KERNEL, 0);
  124. test_assert_nonnull (page);
  125. vm_page_ref (page);
  126. struct test_cap_vars *vars;
  127. error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), 1);
  128. test_assert_zero (error);
  129. vars->mdata.size = sizeof (vars->mdata);
  130. {
  131. // Test that alerts are delivered in priority order.
  132. strcpy (vars->buf, "abcd");
  133. ssize_t rv = cap_send_alert (flow, vars->buf, 0, 0);
  134. test_assert_ge (rv, 0);
  135. strcpy (vars->buf, "1234");
  136. rv = cap_send_alert (flow, vars->buf, 0, 1);
  137. test_assert_ge (rv, 0);
  138. error = cap_recv_alert (flow, vars->buf, 0, &vars->mdata);
  139. test_assert_zero (error);
  140. test_assert_streq (vars->buf, "1234");
  141. test_assert_eq (vars->mdata.task_id, task_id (thread_self()->task));
  142. test_assert_eq (vars->mdata.thread_id, thread_id (thread_self ()));
  143. test_assert_eq (vars->mdata.tag, data->tag);
  144. error = cap_recv_alert (flow, vars->buf, 0, &vars->mdata);
  145. test_assert_zero (error);
  146. test_assert_streq (vars->buf, "abcd");
  147. test_assert_eq (vars->mdata.task_id, task_id (thread_self()->task));
  148. test_assert_eq (vars->mdata.thread_id, thread_id (thread_self ()));
  149. test_assert_eq (vars->mdata.tag, data->tag);
  150. }
  151. vars->mvme[0] = (struct ipc_msg_vme) { .addr = PAGE_SIZE * 10 };
  152. vars->iov = IOVEC (&vars->bufsize, sizeof (vars->bufsize));
  153. vars->msg = (struct ipc_msg)
  154. {
  155. .size = sizeof (struct ipc_msg),
  156. .iovs = &vars->iov,
  157. .iov_cnt = 1,
  158. .vmes = vars->mvme,
  159. .vme_cnt = 1,
  160. .caps = vars->mcap,
  161. .cap_cnt = 1,
  162. };
  163. vars->mdata.size = sizeof (vars->mdata);
  164. error = cap_flow_add_lpad (flow, (char *)vm_page_direct_ptr (page) +
  165. PAGE_SIZE, PAGE_SIZE, &vars->msg,
  166. &vars->mdata, &vars->info);
  167. test_assert_zero (error);
  168. semaphore_post (&data->send_sem);
  169. semaphore_wait (&data->recv_sem);
  170. vm_page_unref (page);
  171. cap_base_rel (data->ch);
  172. // Test that we receive an alert on a channel closed.
  173. error = cap_recv_alert (flow, &vars->alert, 0, &vars->mdata);
  174. test_assert_zero (error);
  175. test_assert_zero (vars->mdata.task_id);
  176. test_assert_zero (vars->mdata.thread_id);
  177. test_assert_eq (vars->alert.type, CAP_ALERT_CHAN_CLOSED);
  178. test_assert_eq (vars->alert.tag, TEST_CAP_CHANNEL_TAG);
  179. cap_base_rel (flow);
  180. }
  181. static void
  182. test_cap_sender (void *arg)
  183. {
  184. struct test_cap_data *data = arg;
  185. semaphore_wait (&data->send_sem);
  186. void *mem;
  187. int error = vm_map_anon_alloc (&mem, vm_map_self (), PAGE_SIZE * 2);
  188. test_assert_zero (error);
  189. struct
  190. {
  191. struct ipc_msg_vme mvme;
  192. char buf[6];
  193. uint32_t bufsize;
  194. struct iovec iovecs[2];
  195. struct ipc_msg msg;
  196. struct ipc_msg_data mdata;
  197. struct ipc_msg_cap mcap;
  198. struct ipc_msg out_msg;
  199. struct ipc_msg_vme out_vme[2];
  200. struct ipc_msg_cap out_cap[2];
  201. } *vars = (void *)((char *)mem + PAGE_SIZE);
  202. vars->mdata.size = sizeof (vars->mdata);
  203. vars->mvme = (struct ipc_msg_vme)
  204. {
  205. .addr = (uintptr_t)memset (mem, 'x', PAGE_SIZE),
  206. .prot = VM_PROT_READ,
  207. .max_prot = VM_PROT_READ,
  208. .size = PAGE_SIZE
  209. };
  210. vars->mcap = (struct ipc_msg_cap)
  211. {
  212. .cap = test_cap_alloc_task (task_self ()),
  213. .flags = 0
  214. };
  215. strcpy (vars->buf, "hello");
  216. vars->bufsize = sizeof (vars->buf) - 1;
  217. vars->iovecs[0] = IOVEC (&vars->bufsize, sizeof (vars->bufsize));
  218. vars->iovecs[1] = IOVEC (vars->buf, vars->bufsize);
  219. vars->msg = (struct ipc_msg)
  220. {
  221. .size = sizeof (struct ipc_msg),
  222. .iovs = vars->iovecs,
  223. .iov_cnt = 2,
  224. .vmes = &vars->mvme,
  225. .vme_cnt = 1,
  226. .caps = &vars->mcap,
  227. .cap_cnt = 1,
  228. };
  229. vars->out_msg = (struct ipc_msg)
  230. {
  231. .size = sizeof (struct ipc_msg),
  232. .iovs = vars->iovecs,
  233. .iov_cnt = 2,
  234. .vmes = vars->out_vme,
  235. .vme_cnt = 2,
  236. .caps = vars->out_cap,
  237. .cap_cnt = 2
  238. };
  239. ssize_t nb = cap_send_msg (data->ch, &vars->msg,
  240. &vars->out_msg, &vars->mdata);
  241. test_assert_eq (nb, (ssize_t)(sizeof (uint32_t) + sizeof (vars->buf) - 1));
  242. test_assert_eq (vars->bufsize, 'Z');
  243. test_assert_streq (vars->buf, "?????");
  244. test_assert_eq (*(char *)vars->out_vme[0].addr, 'z');
  245. test_assert_eq (vars->mdata.vmes_sent, 1);
  246. test_assert_eq (vars->mdata.vmes_recv, 2);
  247. test_assert_eq (vars->mdata.caps_sent, 1);
  248. test_assert_eq (vars->mdata.caps_recv, 1);
  249. test_assert_ne (vars->mdata.flags & IPC_MSG_TRUNC, 0);
  250. _Auto cap = cspace_get (cspace_self (), vars->out_cap[0].cap);
  251. test_assert_nonnull (cap);
  252. test_assert_eq (cap_type (cap), CAP_TYPE_TASK);
  253. test_assert_eq (((struct cap_task *)cap)->task, data->receiver);
  254. cap_base_rel (cap);
  255. semaphore_post (&data->recv_sem);
  256. }
  257. static void
  258. test_cap_misc (void *arg __unused)
  259. {
  260. struct cap_task *ctask;
  261. int error = cap_task_create (&ctask, task_self ());
  262. test_assert_zero (error);
  263. struct
  264. {
  265. struct task_ipc_msg task_msg;
  266. struct thread_ipc_msg thr_msg;
  267. BITMAP_DECLARE (cpumap, CONFIG_MAX_CPUS);
  268. } *vars;
  269. error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), sizeof (*vars));
  270. test_assert_zero (error);
  271. vars->task_msg.op = TASK_IPC_GET_NAME;
  272. ssize_t rv = cap_send_bytes (ctask, &vars->task_msg, sizeof (vars->task_msg),
  273. &vars->task_msg, sizeof (vars->task_msg));
  274. test_assert_zero (rv);
  275. test_assert_streq (vars->task_msg.name, "cap_misc");
  276. vars->task_msg.op = TASK_IPC_SET_NAME;
  277. strcpy (vars->task_msg.name, "new_name");
  278. rv = cap_send_bytes (ctask, &vars->task_msg, sizeof (vars->task_msg), 0, 0);
  279. test_assert_zero (rv);
  280. test_assert_streq (task_self()->name, "new_name");
  281. cap_base_rel (ctask);
  282. struct cap_thread *cthread;
  283. error = cap_thread_create (&cthread, thread_self ());
  284. vars->thr_msg.op = THREAD_IPC_GET_NAME;
  285. rv = cap_send_bytes (cthread, &vars->thr_msg, sizeof (vars->thr_msg),
  286. &vars->thr_msg, sizeof (vars->thr_msg));
  287. test_assert_zero (rv);
  288. test_assert_streq (vars->thr_msg.name, "cap_misc/0");
  289. thread_pin ();
  290. vars->thr_msg.op = THREAD_IPC_GET_AFFINITY;
  291. vars->thr_msg.cpumap.map = vars->cpumap;
  292. vars->thr_msg.cpumap.size = sizeof (vars->cpumap);
  293. rv = cap_send_bytes (cthread, &vars->thr_msg, sizeof (vars->thr_msg),
  294. &vars->thr_msg, sizeof (vars->thr_msg));
  295. test_assert_zero (rv);
  296. test_assert_ne (bitmap_test (vars->cpumap, cpu_id ()), 0);
  297. thread_unpin ();
  298. cap_base_rel (cthread);
  299. }
  300. static void
  301. test_cap_dead_child (void *arg)
  302. {
  303. semaphore_wait (arg);
  304. }
  305. static void
  306. test_cap_dead_helper (void *arg)
  307. {
  308. struct cap_flow *flow = arg;
  309. struct thread *thr;
  310. struct thread_attr attr;
  311. thread_attr_init (&attr, "cap_dead/2");
  312. thread_attr_set_detached (&attr);
  313. int error = thread_create (&thr, &attr, test_cap_dead_child,
  314. &test_cap_data.dead_sem);
  315. test_assert_zero (error);
  316. error = cap_thread_register (flow, thr);
  317. test_assert_zero (error);
  318. error = cap_thread_unregister (flow, thr);
  319. test_assert_zero (error);
  320. error = cap_thread_register (flow, thread_self ());
  321. test_assert_zero (error);
  322. error = cap_task_register (flow, thread_self()->task);
  323. test_assert_zero (error);
  324. test_cap_dead_child (&test_cap_data.dead_sem);
  325. }
  326. static void
  327. test_cap_dead_notif (void *arg __unused)
  328. {
  329. struct cap_flow *flow;
  330. int error = cap_flow_create (&flow, 0, 0, 0);
  331. test_assert_zero (error);
  332. struct cap_channel *chan;
  333. error = cap_channel_create (&chan, flow, 1234);
  334. test_assert_zero (error);
  335. int capx = cspace_add_free (cspace_self (), CAP (chan), CSPACE_WEAK);
  336. test_assert_ge (capx, 0);
  337. cap_base_rel (chan);
  338. int mark = 0;
  339. chan = (struct cap_channel *)cspace_get_all (cspace_self (), capx, &mark);
  340. test_assert_nonnull (chan);
  341. cap_base_rel (chan);
  342. if (mark)
  343. cap_base_rel (chan);
  344. struct
  345. {
  346. struct cap_kern_alert alert;
  347. char extra[16];
  348. struct ipc_msg_data mdata;
  349. } *buf;
  350. error = vm_map_anon_alloc ((void **)&buf, vm_map_self (), 1);
  351. test_assert_zero (error);
  352. buf->mdata.size = sizeof (buf->mdata);
  353. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  354. test_assert_zero (error);
  355. test_assert_zero (buf->mdata.thread_id);
  356. test_assert_zero (buf->mdata.task_id);
  357. test_assert_eq (buf->alert.type, CAP_ALERT_CHAN_CLOSED);
  358. test_assert_eq (buf->alert.tag, 1234);
  359. struct thread *thr;
  360. error = test_util_create_thr (&thr, test_cap_dead_helper, flow, "cap_dead");
  361. test_assert_zero (error);
  362. int tsk_id = task_id (thr->task), thr_id = thread_id (thr);
  363. int got_task = 0, got_thr = 0;
  364. semaphore_post (&test_cap_data.dead_sem);
  365. semaphore_post (&test_cap_data.dead_sem);
  366. thread_join (thr);
  367. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  368. test_assert_zero (error);
  369. test_assert_zero (buf->mdata.thread_id);
  370. test_assert_zero (buf->mdata.task_id);
  371. if (buf->alert.type == CAP_ALERT_THREAD_DIED &&
  372. buf->alert.thread_id == thr_id)
  373. got_thr = 1;
  374. else if (buf->alert.type == CAP_ALERT_TASK_DIED &&
  375. buf->alert.task_id == tsk_id)
  376. got_task = 1;
  377. else
  378. panic ("got unexpected alert");
  379. error = cap_recv_alert (flow, &buf->alert, 0, &buf->mdata);
  380. test_assert_zero (error);
  381. test_assert_zero (buf->mdata.thread_id);
  382. test_assert_zero (buf->mdata.task_id);
  383. if (buf->alert.type == CAP_ALERT_THREAD_DIED &&
  384. buf->alert.thread_id == thr_id)
  385. ++got_thr;
  386. else if (buf->alert.type == CAP_ALERT_TASK_DIED &&
  387. buf->alert.task_id == tsk_id)
  388. ++got_task;
  389. else
  390. panic ("got unexpected alert");
  391. test_assert_eq (got_thr, 1);
  392. test_assert_eq (got_task, 1);
  393. }
  394. TEST_DEFERRED (cap)
  395. {
  396. _Auto data = &test_cap_data;
  397. semaphore_init (&data->send_sem, 0, 0xff);
  398. semaphore_init (&data->recv_sem, 0, 0xff);
  399. semaphore_init (&data->dead_sem, 0, 0xff);
  400. struct thread *sender, *receiver, *misc, *dead_notif;
  401. int error = test_util_create_thr (&sender, test_cap_sender,
  402. data, "cap_sender");
  403. test_assert_zero (error);
  404. error = test_util_create_thr (&receiver, test_cap_receiver,
  405. data, "cap_receiver");
  406. test_assert_zero (error);
  407. error = test_util_create_thr (&misc, test_cap_misc, NULL, "cap_misc");
  408. test_assert_zero (error);
  409. error = test_util_create_thr (&dead_notif, test_cap_dead_notif,
  410. NULL, "cap_dead");
  411. thread_join (sender);
  412. thread_join (receiver);
  413. thread_join (misc);
  414. thread_join (dead_notif);
  415. return (TEST_OK);
  416. }