capability.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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. * Interfaces for capabilities.
  18. */
  19. #ifndef KERN_CAP_H
  20. #define KERN_CAP_H
  21. #include <assert.h>
  22. #include <stdint.h>
  23. #include <kern/hlist.h>
  24. #include <kern/init.h>
  25. #include <kern/ipc.h>
  26. #include <kern/list.h>
  27. #include <kern/pqueue.h>
  28. #include <kern/slist.h>
  29. #include <kern/spinlock.h>
  30. #include <kern/sref.h>
  31. #include <kern/user.h>
  32. struct task;
  33. struct thread;
  34. // Capability types.
  35. enum
  36. {
  37. CAP_TYPE_CHANNEL,
  38. CAP_TYPE_FLOW,
  39. CAP_TYPE_TASK,
  40. CAP_TYPE_THREAD,
  41. CAP_TYPE_KERNEL,
  42. CAP_TYPE_MAX,
  43. };
  44. // Size of an alert message, in bytes.
  45. #define CAP_ALERT_SIZE 16
  46. // Alert types.
  47. enum
  48. {
  49. CAP_ALERT_USER,
  50. CAP_ALERT_INTR,
  51. CAP_ALERT_THREAD_DIED,
  52. CAP_ALERT_TASK_DIED,
  53. CAP_ALERT_CHAN_CLOSED,
  54. };
  55. // Kernel-sent alert.
  56. struct cap_kern_alert
  57. {
  58. int type;
  59. union
  60. {
  61. struct
  62. {
  63. uint32_t irq;
  64. uint32_t count;
  65. } intr;
  66. int thread_id;
  67. int task_id;
  68. int any_id;
  69. uintptr_t tag;
  70. };
  71. };
  72. static_assert (sizeof (struct cap_kern_alert) <= CAP_ALERT_SIZE,
  73. "struct cap_kern_alert is too big");
  74. static_assert (OFFSETOF (struct cap_kern_alert, intr.irq) ==
  75. OFFSETOF (struct cap_kern_alert, thread_id) &&
  76. OFFSETOF (struct cap_kern_alert, thread_id) ==
  77. OFFSETOF (struct cap_kern_alert, task_id),
  78. "invalid layout for cap_kern_alert");
  79. struct cap_base
  80. {
  81. uintptr_t tflags;
  82. struct sref_counter sref;
  83. };
  84. // Kernel capabilities.
  85. enum
  86. {
  87. CAP_KERNEL_MEMORY, // Allows mapping physical memory.
  88. CAP_KERNEL_DEVICE, // Allows registering interrupts.
  89. CAP_KERNEL_MAX,
  90. };
  91. struct cap_thread_info
  92. {
  93. uint32_t size;
  94. struct futex_td *futex_td;
  95. void *thread_ptr;
  96. int signal;
  97. int pinned;
  98. };
  99. #define CAPABILITY struct cap_base base
  100. // Flags used in 'cap_flow_create'.
  101. #define CAP_FLOW_HANDLE_INTR 0x01 // Flow can handle interrupts.
  102. #define CAP_FLOW_EXT_PAGER 0x02 // Flow is an external pager.
  103. #define CAP_FLOW_PAGER_FLUSHES 0x04 // Pager needs to flush dirty pages.
  104. struct vm_object;
  105. struct vm_page;
  106. struct cap_flow
  107. {
  108. CAPABILITY;
  109. uintptr_t tag;
  110. uintptr_t entry;
  111. struct
  112. {
  113. struct spinlock lock;
  114. struct list receivers;
  115. struct hlist alloc;
  116. struct pqueue pending;
  117. } alerts;
  118. struct
  119. {
  120. struct cap_lpad *free_list;
  121. struct list waiters;
  122. struct spinlock lock;
  123. } lpads;
  124. };
  125. struct cap_channel
  126. {
  127. CAPABILITY;
  128. struct cap_flow *flow;
  129. uintptr_t tag;
  130. struct vm_object *vmobj;
  131. };
  132. struct cap_task
  133. {
  134. CAPABILITY;
  135. struct task *task;
  136. };
  137. struct cap_thread
  138. {
  139. CAPABILITY;
  140. struct thread *thread;
  141. };
  142. struct cap_kernel
  143. {
  144. CAPABILITY;
  145. int kind;
  146. };
  147. // Triplet of iterators.
  148. struct cap_iters
  149. {
  150. struct ipc_iov_iter iov;
  151. struct ipc_cap_iter cap;
  152. struct ipc_vme_iter vme;
  153. };
  154. struct bulletin;
  155. // Cast a capability to the base type.
  156. #define CAP_BASE(x) ((struct cap_base *)(x))
  157. #define CAP(x) \
  158. _Generic (x, \
  159. struct cap_kernel * : CAP_BASE (x), \
  160. struct cap_thread * : CAP_BASE (x), \
  161. struct cap_task * : CAP_BASE (x), \
  162. struct cap_channel *: CAP_BASE (x), \
  163. struct cap_flow * : CAP_BASE (x), \
  164. default: (x))
  165. // Flags for the read/clean page interfaces.
  166. #define CAP_PAGES_MORE 0x01 // There are more pages for the object.
  167. #define CAP_PAGES_ADV_SKIP 0x02 // Advance iovec if page is not dirty.
  168. struct cap_page_info
  169. {
  170. uint32_t size;
  171. uint32_t flags;
  172. uintptr_t tag;
  173. uint32_t offset_cnt;
  174. uint64_t *offsets;
  175. struct iovec *iovs;
  176. uint32_t iov_cnt;
  177. struct ipc_msg_vme vme;
  178. };
  179. // Get a capability's type.
  180. static inline uint32_t
  181. cap_type (const struct cap_base *cap)
  182. {
  183. return ((uint32_t)(cap->tflags >> (sizeof (uintptr_t) * 8 - 8)));
  184. }
  185. #define cap_type(cap) (cap_type)(CAP (cap))
  186. // Acquire or release a reference on a capability.
  187. static inline void
  188. cap_base_acq (struct cap_base *cap)
  189. {
  190. sref_counter_inc (&cap->sref);
  191. }
  192. static inline void
  193. cap_base_rel (struct cap_base *cap)
  194. {
  195. sref_counter_dec (&cap->sref);
  196. }
  197. #define cap_base_acq(cap) (cap_base_acq) (CAP (cap))
  198. #define cap_base_rel(cap) (cap_base_rel) (CAP (cap))
  199. // Flags for the 'cap_recv_alert' function.
  200. #define CAP_ALERT_NONBLOCK 0x01 // Don't block when sending an alert.
  201. /*
  202. * Intern a capability within the local space. Returns the new capability
  203. * index, or a negated errno value on error.
  204. */
  205. int cap_intern (struct cap_base *cap, uint32_t flags);
  206. #define cap_intern(cap, flags) (cap_intern) (CAP (cap), (flags))
  207. // Create a flow.
  208. int cap_flow_create (struct cap_flow **outp, uint32_t flags,
  209. uintptr_t tag, uintptr_t entry);
  210. // Create a channel for a flow.
  211. int cap_channel_create (struct cap_channel **outp, struct cap_flow *flow,
  212. uintptr_t tag);
  213. // Create a capability representing a task.
  214. int cap_task_create (struct cap_task **outp, struct task *task);
  215. // Create a capability representing a thread.
  216. int cap_thread_create (struct cap_thread **outp, struct thread *thread);
  217. // Get a capability's tag (Used for channels and flows).
  218. int cap_get_tag (const struct cap_base *cap, uintptr_t *tagp);
  219. #define cap_get_tag(cap, tagp) (cap_get_tag) (CAP (cap), (tagp))
  220. // Hook a channel to a remote flow in a task.
  221. int cap_flow_hook (struct cap_channel **outp, struct task *task, int cap_idx);
  222. // Send and receive iterator triplets to a capability.
  223. ssize_t cap_send_iters (struct cap_base *cap, struct cap_iters *in_it,
  224. struct cap_iters *out_it, struct ipc_msg_data *data,
  225. uint32_t xflags);
  226. // Reply to the current message with an iterator triplet or error value.
  227. ssize_t cap_reply_iters (struct cap_iters *it, int rv);
  228. // Pull an iterator triplet from the current message.
  229. ssize_t cap_pull_iters (struct cap_iters *it, struct ipc_msg_data *data);
  230. // Push an iterator triplet to the current message.
  231. ssize_t cap_push_iters (struct cap_iters *it, struct ipc_msg_data *data);
  232. // Receive an alert from a flow.
  233. int cap_recv_alert (struct cap_flow *flow, void *buf,
  234. uint32_t flags, struct ipc_msg_data *mdata);
  235. // Send an alert to a flow.
  236. int cap_send_alert (struct cap_base *cap, const void *buf,
  237. uint32_t flags, uint32_t prio);
  238. #define cap_send_alert(cap, buf, flags, prio) \
  239. (cap_send_alert) (CAP (cap), buf, flags, prio)
  240. // Add and remove a landing pad to/from a flow.
  241. int cap_flow_add_lpad (struct cap_flow *flow, void *stack, size_t size,
  242. struct ipc_msg *msg, struct ipc_msg_data *mdata,
  243. struct cap_thread_info *info);
  244. int cap_flow_rem_lpad (struct cap_flow *flow, uintptr_t stack, bool unmap);
  245. // Register a flow for interrupt handling.
  246. int cap_intr_register (struct cap_flow *flow, uint32_t irq);
  247. // Unregister a flow for interrupt handling.
  248. int cap_intr_unregister (struct cap_flow *flow, uint32_t irq);
  249. // Register a thread on a flow to notify on its death.
  250. int cap_thread_register (struct cap_flow *flow, struct thread *thread);
  251. // Register a task on a flow to notify on its death.
  252. int cap_task_register (struct cap_flow *flow, struct task *task);
  253. // Unregister a thread.
  254. int cap_thread_unregister (struct cap_flow *flow, struct thread *thread);
  255. // Unregister a task.
  256. int cap_task_unregister (struct cap_flow *flow, struct task *task);
  257. // Traverse a list of dead notifications.
  258. void cap_notify_dead (struct bulletin *bulletin);
  259. // Request pages from a channel.
  260. ssize_t cap_request_pages (struct cap_channel *chp, uint64_t off,
  261. uint32_t nr_pages, struct vm_page **pages);
  262. // Reply with pages to a channel.
  263. ssize_t cap_reply_pagereq (const uintptr_t *src, uint32_t cnt);
  264. /*
  265. * Get the VM object associated to a channel.
  266. *
  267. * The VM object is typically constructed when a mapping request is made,
  268. * such as for the 'mmap' system call. Note that once constructed and until
  269. * it's destroyed, the object will be the same.
  270. */
  271. struct vm_object* cap_channel_get_vmobj (struct cap_channel *ch);
  272. // Unreference a VM object obtained from a channel.
  273. void cap_channel_put_vmobj (struct cap_channel *chp);
  274. // Mark a channel as being shared.
  275. bool cap_channel_mark_shared (struct cap_base *cap);
  276. #define cap_iters_init_impl(it, buf, size, iov_init) \
  277. do \
  278. { \
  279. iov_init (&(it)->iov, (void *)(buf), size); \
  280. ipc_cap_iter_init (&(it)->cap, 0, 0); \
  281. ipc_vme_iter_init (&(it)->vme, 0, 0); \
  282. } \
  283. while (0)
  284. // Initialize a capability's iterators with a plain buffer and size.
  285. #define cap_iters_init_buf(it, buf, size) \
  286. cap_iters_init_impl (it, buf, size, ipc_iov_iter_init_buf)
  287. // Initialize a capability's iterators with a number of iovecs.
  288. #define cap_iters_init_iov(it, iovs, nr_iovs) \
  289. cap_iters_init_impl (it, iovs, nr_iovs, ipc_iov_iter_init)
  290. // Initialize a capability's iterators with a message structure.
  291. #define cap_iters_init_msg(it, msg) \
  292. do \
  293. { \
  294. ipc_iov_iter_init (&(it)->iov, (msg)->iovs, (msg)->iov_cnt); \
  295. ipc_cap_iter_init (&(it)->cap, (msg)->caps, (msg)->cap_cnt); \
  296. ipc_vme_iter_init (&(it)->vme, (msg)->vmes, (msg)->vme_cnt); \
  297. } \
  298. while (0)
  299. // Send raw bytes to a capability and receive the reply.
  300. static inline ssize_t
  301. cap_send_bytes (struct cap_base *cap, const void *src, size_t src_size,
  302. void *dst, size_t dst_size)
  303. {
  304. struct cap_iters in, out;
  305. cap_iters_init_buf (&in, src, src_size);
  306. cap_iters_init_buf (&out, dst, dst_size);
  307. return (cap_send_iters (cap, &in, &out, NULL, 0));
  308. }
  309. #define cap_send_bytes(cap, src, src_size, dst, dst_size) \
  310. (cap_send_bytes) (CAP (cap), (src), (src_size), (dst), (dst_size))
  311. // Send bytes in iovecs and receive the reply.
  312. static inline ssize_t
  313. cap_send_iov (struct cap_base *cap, const struct iovec *src, uint32_t nr_src,
  314. struct iovec *dst, uint32_t nr_dst)
  315. {
  316. if (!user_check_range (src, nr_src * sizeof (*src)) ||
  317. !user_check_range (dst, nr_dst * sizeof (*dst)))
  318. return (-EFAULT);
  319. struct cap_iters in, out;
  320. cap_iters_init_iov (&in, src, nr_src);
  321. cap_iters_init_iov (&out, dst, nr_dst);
  322. return (cap_send_iters (cap, &in, &out, NULL, 0));
  323. }
  324. #define cap_send_iov(cap, src, nr_src, dst, nr_dst) \
  325. (cap_send_iov) (CAP (cap), (src), (nr_src), (dst), (nr_dst))
  326. // Send and receive full messages and also the metadata.
  327. static inline ssize_t
  328. cap_send_msg (struct cap_base *cap, const struct ipc_msg *src,
  329. struct ipc_msg *dst, struct ipc_msg_data *data)
  330. {
  331. if (!user_check_struct (src, sizeof (*src)) ||
  332. !user_check_struct (dst, sizeof (*dst)))
  333. return (-EFAULT);
  334. struct cap_iters in, out;
  335. cap_iters_init_msg (&in, src);
  336. cap_iters_init_msg (&out, dst);
  337. return (cap_send_iters (cap, &in, &out, data, 0));
  338. }
  339. #define cap_send_msg(cap, src, dst, data) \
  340. (cap_send_msg) (CAP (cap), (src), (dst), (data))
  341. // Reply to the current message with raw bytes or an error.
  342. static inline int
  343. cap_reply_bytes (const void *src, size_t bytes, int err)
  344. {
  345. struct cap_iters it;
  346. cap_iters_init_buf (&it, src, bytes);
  347. return (cap_reply_iters (&it, err));
  348. }
  349. // Reply to the current message with bytes in iovecs or an error.
  350. static inline int
  351. cap_reply_iov (const struct iovec *iov, uint32_t nr_iov, int err)
  352. {
  353. if (!user_check_range (iov, nr_iov * sizeof (*iov)))
  354. return (-EFAULT);
  355. struct cap_iters it;
  356. cap_iters_init_iov (&it, iov, nr_iov);
  357. return (cap_reply_iters (&it, err));
  358. }
  359. // Reply to the current message with a full IPC message or an error.
  360. static inline int
  361. cap_reply_msg (const struct ipc_msg *msg, int err)
  362. {
  363. if (!user_check_struct (msg, sizeof (*msg)))
  364. return (-EFAULT);
  365. struct cap_iters it;
  366. cap_iters_init_msg (&it, msg);
  367. return (cap_reply_iters (&it, err));
  368. }
  369. // Pull raw bytes from the current message.
  370. static inline ssize_t
  371. cap_pull_bytes (void *dst, size_t bytes, struct ipc_msg_data *mdata)
  372. {
  373. struct cap_iters it;
  374. cap_iters_init_buf (&it, dst, bytes);
  375. return (cap_pull_iters (&it, mdata));
  376. }
  377. // Pull iovecs from the current message.
  378. static inline ssize_t
  379. cap_pull_iov (struct iovec *iovs, uint32_t nr_iovs, struct ipc_msg_data *mdata)
  380. {
  381. if (!user_check_range (iovs, nr_iovs * sizeof (*iovs)))
  382. return (-EFAULT);
  383. struct cap_iters it;
  384. cap_iters_init_iov (&it, iovs, nr_iovs);
  385. return (cap_pull_iters (&it, mdata));
  386. }
  387. // Pull an IPC message from the current message.
  388. static inline ssize_t
  389. cap_pull_msg (struct ipc_msg *msg, struct ipc_msg_data *mdata)
  390. {
  391. if (!user_check_struct (msg, sizeof (*msg)))
  392. return (-EFAULT);
  393. struct cap_iters it;
  394. cap_iters_init_msg (&it, msg);
  395. return (cap_pull_iters (&it, mdata));
  396. }
  397. // Push raw bytes into the current message.
  398. static inline ssize_t
  399. cap_push_bytes (const void *src, size_t bytes, struct ipc_msg_data *mdata)
  400. {
  401. struct cap_iters it;
  402. cap_iters_init_buf (&it, src, bytes);
  403. return (cap_push_iters (&it, mdata));
  404. }
  405. // Push iovecs into the current message.
  406. static inline ssize_t
  407. cap_push_iov (const struct iovec *iovs, uint32_t nr_iovs,
  408. struct ipc_msg_data *mdata)
  409. {
  410. if (!user_check_range (iovs, nr_iovs * sizeof (*iovs)))
  411. return (-EFAULT);
  412. struct cap_iters it;
  413. cap_iters_init_iov (&it, iovs, nr_iovs);
  414. return (cap_push_iters (&it, mdata));
  415. }
  416. // Push an IPC message to the current message.
  417. static inline ssize_t
  418. cap_push_msg (const struct ipc_msg *msg, struct ipc_msg_data *mdata)
  419. {
  420. if (!user_check_struct (msg, sizeof (*msg)))
  421. return (-EFAULT);
  422. struct cap_iters it;
  423. cap_iters_init_msg (&it, msg);
  424. return (cap_push_iters (&it, mdata));
  425. }
  426. /*
  427. * This init operation provides :
  428. * - capabilities fully operational.
  429. */
  430. INIT_OP_DECLARE (cap_setup);
  431. #endif