ipc_mig.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. #include <glue/gnulinux.h>
  27. #include <linux/printk.h>
  28. #include <linux/uaccess.h>
  29. #include <mach/boolean.h>
  30. #include <mach/port.h>
  31. #include <mach/message.h>
  32. #include <mach/thread_status.h>
  33. #include <kern/ast.h>
  34. #include <kern/debug.h>
  35. #include <kern/ipc_tt.h>
  36. #include <kern/syscall_subr.h>
  37. #include <kern/thread.h>
  38. #include <kern/task.h>
  39. #include <kern/ipc_kobject.h>
  40. #include <kern/ipc_tt.h>
  41. #include <kern/ipc_mig.h>
  42. #include <vm/vm_map.h>
  43. #include <vm/vm_user.h>
  44. #include <ipc/port.h>
  45. #include <ipc/ipc_kmsg.h>
  46. #include <ipc/ipc_entry.h>
  47. #include <ipc/ipc_object.h>
  48. #include <ipc/ipc_mqueue.h>
  49. #include <ipc/ipc_space.h>
  50. #include <ipc/ipc_port.h>
  51. #include <ipc/ipc_pset.h>
  52. #include <ipc/ipc_thread.h>
  53. #include <ipc/mach_port.h>
  54. #include <device/dev_hdr.h>
  55. #include <device/device_types.h>
  56. #include <device/ds_routines.h>
  57. #if 0
  58. /*
  59. * Routine: mach_msg_send_from_kernel
  60. * Purpose:
  61. * Send a message from the kernel.
  62. *
  63. * This is used by the client side of KernelUser interfaces
  64. * to implement SimpleRoutines. Currently, this includes
  65. * device_reply and memory_object messages.
  66. * Conditions:
  67. * Nothing locked.
  68. * Returns:
  69. * MACH_MSG_SUCCESS Sent the message.
  70. * MACH_SEND_INVALID_DATA Bad destination port.
  71. */
  72. mach_msg_return_t
  73. mach_msg_send_from_kernel(
  74. mach_msg_header_t *msg,
  75. mach_msg_size_t send_size)
  76. {
  77. ipc_kmsg_t kmsg;
  78. mach_msg_return_t mr;
  79. if (!MACH_PORT_VALID(msg->msgh_remote_port))
  80. return MACH_SEND_INVALID_DEST;
  81. mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
  82. if (mr != MACH_MSG_SUCCESS)
  83. panic("mach_msg_send_from_kernel");
  84. ipc_kmsg_copyin_from_kernel(kmsg);
  85. ipc_mqueue_send_always(kmsg);
  86. return MACH_MSG_SUCCESS;
  87. }
  88. mach_msg_return_t
  89. mach_msg_rpc_from_kernel(msg, send_size, reply_size)
  90. const mach_msg_header_t *msg;
  91. mach_msg_size_t send_size;
  92. mach_msg_size_t reply_size;
  93. {
  94. panic("mach_msg_rpc_from_kernel"); /*XXX*/
  95. }
  96. /*
  97. * Routine: mach_msg_abort_rpc
  98. * Purpose:
  99. * Destroy the thread's ith_rpc_reply port.
  100. * This will interrupt a mach_msg_rpc_from_kernel
  101. * with a MACH_RCV_PORT_DIED return code.
  102. * Conditions:
  103. * Nothing locked.
  104. */
  105. void
  106. mach_msg_abort_rpc(ipc_thread_t thread)
  107. {
  108. ipc_port_t reply = IP_NULL;
  109. ith_lock(thread);
  110. if (thread->ith_self != IP_NULL) {
  111. reply = thread->ith_rpc_reply;
  112. thread->ith_rpc_reply = IP_NULL;
  113. }
  114. ith_unlock(thread);
  115. if (reply != IP_NULL)
  116. ipc_port_dealloc_reply(reply);
  117. }
  118. /*
  119. * Routine: mach_msg
  120. * Purpose:
  121. * Like mach_msg_trap except that message buffers
  122. * live in kernel space. Doesn't handle any options.
  123. *
  124. * This is used by in-kernel server threads to make
  125. * kernel calls, to receive request messages, and
  126. * to send reply messages.
  127. * Conditions:
  128. * Nothing locked.
  129. * Returns:
  130. */
  131. mach_msg_return_t
  132. mach_msg(
  133. mach_msg_header_t *msg,
  134. mach_msg_option_t option,
  135. mach_msg_size_t send_size,
  136. mach_msg_size_t rcv_size,
  137. mach_port_t rcv_name,
  138. mach_msg_timeout_t time_out,
  139. mach_port_t notify)
  140. {
  141. ipc_space_t space = current_space();
  142. vm_map_t map = current_map();
  143. ipc_kmsg_t kmsg;
  144. mach_port_seqno_t seqno;
  145. mach_msg_return_t mr;
  146. if (option & MACH_SEND_MSG) {
  147. mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
  148. if (mr != MACH_MSG_SUCCESS)
  149. panic("mach_msg");
  150. mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
  151. if (mr != MACH_MSG_SUCCESS) {
  152. ikm_free(kmsg);
  153. return mr;
  154. }
  155. do
  156. mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
  157. MACH_MSG_TIMEOUT_NONE);
  158. while (mr == MACH_SEND_INTERRUPTED);
  159. assert(mr == MACH_MSG_SUCCESS);
  160. }
  161. if (option & MACH_RCV_MSG) {
  162. do {
  163. ipc_object_t object;
  164. ipc_mqueue_t mqueue;
  165. mr = ipc_mqueue_copyin(space, rcv_name,
  166. &mqueue, &object);
  167. if (mr != MACH_MSG_SUCCESS)
  168. return mr;
  169. /* hold ref for object; mqueue is locked */
  170. mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
  171. MACH_MSG_SIZE_MAX,
  172. MACH_MSG_TIMEOUT_NONE,
  173. FALSE, IMQ_NULL_CONTINUE,
  174. &kmsg, &seqno);
  175. /* mqueue is unlocked */
  176. ipc_object_release(object);
  177. } while (mr == MACH_RCV_INTERRUPTED);
  178. if (mr != MACH_MSG_SUCCESS)
  179. return mr;
  180. kmsg->ikm_header.msgh_seqno = seqno;
  181. if (rcv_size < kmsg->ikm_header.msgh_size) {
  182. ipc_kmsg_copyout_dest(kmsg, space);
  183. ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
  184. return MACH_RCV_TOO_LARGE;
  185. }
  186. mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  187. if (mr != MACH_MSG_SUCCESS) {
  188. if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  189. ipc_kmsg_put_to_kernel(msg, kmsg,
  190. kmsg->ikm_header.msgh_size);
  191. } else {
  192. ipc_kmsg_copyout_dest(kmsg, space);
  193. ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
  194. }
  195. return mr;
  196. }
  197. ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
  198. }
  199. return MACH_MSG_SUCCESS;
  200. }
  201. /*
  202. * Routine: mig_get_reply_port
  203. * Purpose:
  204. * Called by client side interfaces living in the kernel
  205. * to get a reply port. This port is used for
  206. * mach_msg() calls which are kernel calls.
  207. */
  208. mach_port_t
  209. mig_get_reply_port(void)
  210. {
  211. ipc_thread_t self = current_thread();
  212. if (self->ith_mig_reply == MACH_PORT_NULL)
  213. self->ith_mig_reply = mach_reply_port();
  214. return self->ith_mig_reply;
  215. }
  216. /*
  217. * Routine: mig_dealloc_reply_port
  218. * Purpose:
  219. * Called by client side interfaces to get rid of a reply port.
  220. * Shouldn't ever be called inside the kernel, because
  221. * kernel calls shouldn't prompt Mig to call it.
  222. */
  223. void
  224. mig_dealloc_reply_port(
  225. mach_port_t reply_port)
  226. {
  227. panic("mig_dealloc_reply_port");
  228. }
  229. /*
  230. * Routine: mig_put_reply_port
  231. * Purpose:
  232. * Called by client side interfaces after each RPC to
  233. * let the client recycle the reply port if it wishes.
  234. */
  235. void
  236. mig_put_reply_port(
  237. mach_port_t reply_port)
  238. {
  239. }
  240. /*
  241. * mig_strncpy.c - by Joshua Block
  242. *
  243. * mig_strncpy -- Bounded string copy. Does what the library routine
  244. * strncpy does: Copies the (null terminated) string in src into dest,
  245. * a buffer of length len. Returns the length of the destination
  246. * string excluding the terminating null.
  247. *
  248. * Parameters:
  249. *
  250. * dest - Pointer to destination buffer.
  251. *
  252. * src - Pointer to source string.
  253. *
  254. * len - Length of destination buffer.
  255. */
  256. vm_size_t
  257. mig_strncpy(dest, src, len)
  258. char *dest;
  259. const char *src;
  260. int len;
  261. {
  262. char *dest_ = dest;
  263. int i;
  264. if (len <= 0)
  265. return 0;
  266. for (i = 0; i < len; i++) {
  267. if (! (*dest = *src))
  268. break;
  269. dest++;
  270. src++;
  271. }
  272. return dest - dest_;
  273. }
  274. #define fast_send_right_lookup(name, port, abort) \
  275. MACRO_BEGIN \
  276. ipc_space_t space = current_space(); \
  277. ipc_entry_t entry; \
  278. \
  279. is_read_lock(space); \
  280. assert(space->is_active); \
  281. \
  282. entry = ipc_entry_lookup (space, name); \
  283. if (entry == IE_NULL) { \
  284. is_read_unlock (space); \
  285. abort; \
  286. } \
  287. \
  288. if (IE_BITS_TYPE (entry->ie_bits) != MACH_PORT_TYPE_SEND) { \
  289. is_read_unlock (space); \
  290. abort; \
  291. } \
  292. \
  293. port = (ipc_port_t) entry->ie_object; \
  294. assert(port != IP_NULL); \
  295. \
  296. ip_lock(port); \
  297. /* can safely unlock space now that port is locked */ \
  298. is_read_unlock(space); \
  299. MACRO_END
  300. device_t
  301. port_name_to_device(mach_port_t name)
  302. {
  303. ipc_port_t port;
  304. device_t device;
  305. fast_send_right_lookup(name, port, goto abort);
  306. /* port is locked */
  307. /*
  308. * Now map the port object to a device object.
  309. * This is an inline version of dev_port_lookup().
  310. */
  311. if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
  312. device = (device_t) port->ip_kobject;
  313. device_reference(device);
  314. ip_unlock(port);
  315. return device;
  316. }
  317. ip_unlock(port);
  318. return DEVICE_NULL;
  319. /*
  320. * The slow case. The port wasn't easily accessible.
  321. */
  322. abort: {
  323. ipc_port_t kern_port;
  324. kern_return_t kr;
  325. kr = ipc_object_copyin(current_space(), name,
  326. MACH_MSG_TYPE_COPY_SEND,
  327. (ipc_object_t *) &kern_port);
  328. if (kr != KERN_SUCCESS)
  329. return DEVICE_NULL;
  330. device = dev_port_lookup(kern_port);
  331. if (IP_VALID(kern_port))
  332. ipc_port_release_send(kern_port);
  333. return device;
  334. }
  335. }
  336. thread_t
  337. port_name_to_thread(mach_port_t name)
  338. {
  339. ipc_port_t port;
  340. fast_send_right_lookup(name, port, goto abort);
  341. /* port is locked */
  342. if (ip_active(port) &&
  343. (ip_kotype(port) == IKOT_THREAD)) {
  344. thread_t thread;
  345. thread = (thread_t) port->ip_kobject;
  346. assert(thread != THREAD_NULL);
  347. /* thread referencing is a bit complicated,
  348. so don't bother to expand inline */
  349. thread_reference(thread);
  350. ip_unlock(port);
  351. return thread;
  352. }
  353. ip_unlock(port);
  354. return THREAD_NULL;
  355. abort: {
  356. thread_t thread;
  357. ipc_port_t kern_port;
  358. kern_return_t kr;
  359. kr = ipc_object_copyin(current_space(), name,
  360. MACH_MSG_TYPE_COPY_SEND,
  361. (ipc_object_t *) &kern_port);
  362. if (kr != KERN_SUCCESS)
  363. return THREAD_NULL;
  364. thread = convert_port_to_thread(kern_port);
  365. if (IP_VALID(kern_port))
  366. ipc_port_release_send(kern_port);
  367. return thread;
  368. }
  369. }
  370. task_t
  371. port_name_to_task(mach_port_t name)
  372. {
  373. ipc_port_t port;
  374. fast_send_right_lookup(name, port, goto abort);
  375. /* port is locked */
  376. if (ip_active(port) &&
  377. (ip_kotype(port) == IKOT_TASK)) {
  378. task_t task;
  379. task = (task_t) port->ip_kobject;
  380. assert(task != TASK_NULL);
  381. task_lock(task);
  382. /* can safely unlock port now that task is locked */
  383. ip_unlock(port);
  384. task->ref_count++;
  385. task_unlock(task);
  386. return task;
  387. }
  388. ip_unlock(port);
  389. return TASK_NULL;
  390. abort: {
  391. task_t task;
  392. ipc_port_t kern_port;
  393. kern_return_t kr;
  394. kr = ipc_object_copyin(current_space(), name,
  395. MACH_MSG_TYPE_COPY_SEND,
  396. (ipc_object_t *) &kern_port);
  397. if (kr != KERN_SUCCESS)
  398. return TASK_NULL;
  399. task = convert_port_to_task(kern_port);
  400. if (IP_VALID(kern_port))
  401. ipc_port_release_send(kern_port);
  402. return task;
  403. }
  404. }
  405. vm_map_t
  406. port_name_to_map(
  407. mach_port_t name)
  408. {
  409. ipc_port_t port;
  410. fast_send_right_lookup(name, port, goto abort);
  411. /* port is locked */
  412. if (ip_active(port) &&
  413. (ip_kotype(port) == IKOT_TASK)) {
  414. vm_map_t map;
  415. map = ((task_t) port->ip_kobject)->map;
  416. assert(map != VM_MAP_NULL);
  417. simple_lock(&map->ref_lock);
  418. /* can safely unlock port now that map is locked */
  419. ip_unlock(port);
  420. map->ref_count++;
  421. simple_unlock(&map->ref_lock);
  422. return map;
  423. }
  424. ip_unlock(port);
  425. return VM_MAP_NULL;
  426. abort: {
  427. vm_map_t map;
  428. ipc_port_t kern_port;
  429. kern_return_t kr;
  430. kr = ipc_object_copyin(current_space(), name,
  431. MACH_MSG_TYPE_COPY_SEND,
  432. (ipc_object_t *) &kern_port);
  433. if (kr != KERN_SUCCESS)
  434. return VM_MAP_NULL;
  435. map = convert_port_to_map(kern_port);
  436. if (IP_VALID(kern_port))
  437. ipc_port_release_send(kern_port);
  438. return map;
  439. }
  440. }
  441. ipc_space_t
  442. port_name_to_space(mach_port_t name)
  443. {
  444. ipc_port_t port;
  445. fast_send_right_lookup(name, port, goto abort);
  446. /* port is locked */
  447. if (ip_active(port) &&
  448. (ip_kotype(port) == IKOT_TASK)) {
  449. ipc_space_t space;
  450. space = ((task_t) port->ip_kobject)->itk_space;
  451. assert(space != IS_NULL);
  452. simple_lock(&space->is_ref_lock_data);
  453. /* can safely unlock port now that space is locked */
  454. ip_unlock(port);
  455. space->is_references++;
  456. simple_unlock(&space->is_ref_lock_data);
  457. return space;
  458. }
  459. ip_unlock(port);
  460. return IS_NULL;
  461. abort: {
  462. ipc_space_t space;
  463. ipc_port_t kern_port;
  464. kern_return_t kr;
  465. kr = ipc_object_copyin(current_space(), name,
  466. MACH_MSG_TYPE_COPY_SEND,
  467. (ipc_object_t *) &kern_port);
  468. if (kr != KERN_SUCCESS)
  469. return IS_NULL;
  470. space = convert_port_to_space(kern_port);
  471. if (IP_VALID(kern_port))
  472. ipc_port_release_send(kern_port);
  473. return space;
  474. }
  475. }
  476. /*
  477. * Hack to translate a thread port to a thread pointer for calling
  478. * thread_get_state and thread_set_state. This is only necessary
  479. * because the IPC message for these two operations overflows the
  480. * kernel stack.
  481. *
  482. * AARGH!
  483. */
  484. kern_return_t thread_get_state_KERNEL(
  485. mach_port_t thread_port, /* port right for thread */
  486. int flavor,
  487. thread_state_t old_state, /* pointer to OUT array */
  488. natural_t *old_state_count) /* IN/OUT */
  489. {
  490. thread_t thread;
  491. kern_return_t result;
  492. thread = port_name_to_thread(thread_port);
  493. result = thread_get_state(thread, flavor, old_state, old_state_count);
  494. thread_deallocate(thread);
  495. return result;
  496. }
  497. kern_return_t thread_set_state_KERNEL(
  498. mach_port_t thread_port, /* port right for thread */
  499. int flavor,
  500. thread_state_t new_state,
  501. natural_t new_state_count)
  502. {
  503. thread_t thread;
  504. kern_return_t result;
  505. thread = port_name_to_thread(thread_port);
  506. result = thread_set_state(thread, flavor, new_state, new_state_count);
  507. thread_deallocate(thread);
  508. return result;
  509. }
  510. /*
  511. * Things to keep in mind:
  512. *
  513. * The idea here is to duplicate the semantics of the true kernel RPC.
  514. * The destination port/object should be checked first, before anything
  515. * that the user might notice (like ipc_object_copyin). Return
  516. * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
  517. * knows to fall back on an RPC. For other return values, it won't
  518. * retry with an RPC. The retry might get a different (incorrect) rc.
  519. * Return values are only set (and should only be set, with copyout)
  520. * on successful calls.
  521. */
  522. kern_return_t
  523. syscall_vm_map(
  524. mach_port_t target_map,
  525. vm_offset_t *address,
  526. vm_size_t size,
  527. vm_offset_t mask,
  528. boolean_t anywhere,
  529. mach_port_t memory_object,
  530. vm_offset_t offset,
  531. boolean_t copy,
  532. vm_prot_t cur_protection,
  533. vm_prot_t max_protection,
  534. vm_inherit_t inheritance)
  535. {
  536. vm_map_t map;
  537. ipc_port_t port;
  538. vm_offset_t addr;
  539. kern_return_t result;
  540. map = port_name_to_map(target_map);
  541. if (map == VM_MAP_NULL)
  542. return MACH_SEND_INTERRUPTED;
  543. if (MACH_PORT_VALID(memory_object)) {
  544. result = ipc_object_copyin(current_space(), memory_object,
  545. MACH_MSG_TYPE_COPY_SEND,
  546. (ipc_object_t *) &port);
  547. if (result != KERN_SUCCESS) {
  548. vm_map_deallocate(map);
  549. return result;
  550. }
  551. } else
  552. port = (ipc_port_t) memory_object;
  553. copyin(address, &addr, sizeof(vm_offset_t));
  554. result = vm_map(map, &addr, size, mask, anywhere,
  555. port, offset, copy,
  556. cur_protection, max_protection, inheritance);
  557. if (result == KERN_SUCCESS)
  558. copyout(&addr, address, sizeof(vm_offset_t));
  559. if (IP_VALID(port))
  560. ipc_port_release_send(port);
  561. vm_map_deallocate(map);
  562. return result;
  563. }
  564. kern_return_t syscall_vm_allocate(
  565. mach_port_t target_map,
  566. vm_offset_t *address,
  567. vm_size_t size,
  568. boolean_t anywhere)
  569. {
  570. vm_map_t map;
  571. vm_offset_t addr;
  572. kern_return_t result;
  573. map = port_name_to_map(target_map);
  574. if (map == VM_MAP_NULL)
  575. return MACH_SEND_INTERRUPTED;
  576. copyin(address, &addr, sizeof(vm_offset_t));
  577. result = vm_allocate(map, &addr, size, anywhere);
  578. if (result == KERN_SUCCESS)
  579. copyout(&addr, address, sizeof(vm_offset_t));
  580. vm_map_deallocate(map);
  581. return result;
  582. }
  583. kern_return_t syscall_vm_deallocate(
  584. mach_port_t target_map,
  585. vm_offset_t start,
  586. vm_size_t size)
  587. {
  588. vm_map_t map;
  589. kern_return_t result;
  590. map = port_name_to_map(target_map);
  591. if (map == VM_MAP_NULL)
  592. return MACH_SEND_INTERRUPTED;
  593. result = vm_deallocate(map, start, size);
  594. vm_map_deallocate(map);
  595. return result;
  596. }
  597. kern_return_t syscall_task_create(
  598. mach_port_t parent_task,
  599. boolean_t inherit_memory,
  600. mach_port_t *child_task) /* OUT */
  601. {
  602. task_t t, c;
  603. ipc_port_t port;
  604. mach_port_t name;
  605. kern_return_t result;
  606. t = port_name_to_task(parent_task);
  607. if (t == TASK_NULL)
  608. return MACH_SEND_INTERRUPTED;
  609. result = task_create(t, inherit_memory, &c);
  610. if (result == KERN_SUCCESS) {
  611. port = (ipc_port_t) convert_task_to_port(c);
  612. /* always returns a name, even for non-success return codes */
  613. (void) ipc_kmsg_copyout_object(current_space(),
  614. (ipc_object_t) port,
  615. MACH_MSG_TYPE_PORT_SEND, &name);
  616. copyout(&name, child_task,
  617. sizeof(mach_port_t));
  618. }
  619. task_deallocate(t);
  620. return result;
  621. }
  622. kern_return_t syscall_task_terminate(mach_port_t task)
  623. {
  624. task_t t;
  625. kern_return_t result;
  626. t = port_name_to_task(task);
  627. if (t == TASK_NULL)
  628. return MACH_SEND_INTERRUPTED;
  629. result = task_terminate(t);
  630. task_deallocate(t);
  631. return result;
  632. }
  633. kern_return_t syscall_task_suspend(mach_port_t task)
  634. {
  635. task_t t;
  636. kern_return_t result;
  637. t = port_name_to_task(task);
  638. if (t == TASK_NULL)
  639. return MACH_SEND_INTERRUPTED;
  640. result = task_suspend(t);
  641. task_deallocate(t);
  642. return result;
  643. }
  644. kern_return_t syscall_task_set_special_port(
  645. mach_port_t task,
  646. int which_port,
  647. mach_port_t port_name)
  648. {
  649. task_t t;
  650. ipc_port_t port;
  651. kern_return_t result;
  652. t = port_name_to_task(task);
  653. if (t == TASK_NULL)
  654. return MACH_SEND_INTERRUPTED;
  655. if (MACH_PORT_VALID(port_name)) {
  656. result = ipc_object_copyin(current_space(), port_name,
  657. MACH_MSG_TYPE_COPY_SEND,
  658. (ipc_object_t *) &port);
  659. if (result != KERN_SUCCESS) {
  660. task_deallocate(t);
  661. return result;
  662. }
  663. } else
  664. port = (ipc_port_t) port_name;
  665. result = task_set_special_port(t, which_port, port);
  666. if ((result != KERN_SUCCESS) && IP_VALID(port))
  667. ipc_port_release_send(port);
  668. task_deallocate(t);
  669. return result;
  670. }
  671. kern_return_t
  672. syscall_mach_port_allocate(
  673. mach_port_t task,
  674. mach_port_right_t right,
  675. mach_port_t *namep)
  676. {
  677. ipc_space_t space;
  678. mach_port_t name;
  679. kern_return_t kr;
  680. space = port_name_to_space(task);
  681. if (space == IS_NULL)
  682. return MACH_SEND_INTERRUPTED;
  683. kr = mach_port_allocate(space, right, &name);
  684. if (kr == KERN_SUCCESS)
  685. copyout(&name, namep, sizeof(mach_port_t));
  686. is_release(space);
  687. return kr;
  688. }
  689. kern_return_t
  690. syscall_mach_port_allocate_name(
  691. mach_port_t task,
  692. mach_port_right_t right,
  693. mach_port_t name)
  694. {
  695. ipc_space_t space;
  696. kern_return_t kr;
  697. space = port_name_to_space(task);
  698. if (space == IS_NULL)
  699. return MACH_SEND_INTERRUPTED;
  700. kr = mach_port_allocate_name(space, right, name);
  701. is_release(space);
  702. return kr;
  703. }
  704. kern_return_t
  705. syscall_mach_port_deallocate(
  706. mach_port_t task,
  707. mach_port_t name)
  708. {
  709. ipc_space_t space;
  710. kern_return_t kr;
  711. space = port_name_to_space(task);
  712. if (space == IS_NULL)
  713. return MACH_SEND_INTERRUPTED;
  714. kr = mach_port_deallocate(space, name);
  715. is_release(space);
  716. return kr;
  717. }
  718. kern_return_t
  719. syscall_mach_port_insert_right(
  720. mach_port_t task,
  721. mach_port_t name,
  722. mach_port_t right,
  723. mach_msg_type_name_t rightType)
  724. {
  725. ipc_space_t space;
  726. ipc_object_t object;
  727. mach_msg_type_name_t newtype;
  728. kern_return_t kr;
  729. space = port_name_to_space(task);
  730. if (space == IS_NULL)
  731. return MACH_SEND_INTERRUPTED;
  732. if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
  733. is_release(space);
  734. return KERN_INVALID_VALUE;
  735. }
  736. if (MACH_PORT_VALID(right)) {
  737. kr = ipc_object_copyin(current_space(), right, rightType,
  738. &object);
  739. if (kr != KERN_SUCCESS) {
  740. is_release(space);
  741. return kr;
  742. }
  743. } else
  744. object = (ipc_object_t) right;
  745. newtype = ipc_object_copyin_type(rightType);
  746. kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
  747. if ((kr != KERN_SUCCESS) && IO_VALID(object))
  748. ipc_object_destroy(object, newtype);
  749. is_release(space);
  750. return kr;
  751. }
  752. kern_return_t syscall_thread_depress_abort(mach_port_t thread)
  753. {
  754. thread_t t;
  755. kern_return_t result;
  756. t = port_name_to_thread(thread);
  757. if (t == THREAD_NULL)
  758. return MACH_SEND_INTERRUPTED;
  759. result = thread_depress_abort(t);
  760. thread_deallocate(t);
  761. return result;
  762. }
  763. /*
  764. * Device traps -- these are way experimental.
  765. */
  766. io_return_t
  767. syscall_device_write_request(mach_port_t device_name,
  768. mach_port_t reply_name,
  769. dev_mode_t mode,
  770. recnum_t recnum,
  771. vm_offset_t data,
  772. vm_size_t data_count)
  773. {
  774. device_t dev;
  775. /*ipc_port_t reply_port;*/
  776. io_return_t res;
  777. /*
  778. * First try to translate the device name.
  779. *
  780. * If this fails, return KERN_INVALID_CAPABILITY.
  781. * Caller knows that this most likely means that
  782. * device is not local to node and IPC should be used.
  783. *
  784. * If kernel doesn't do device traps, kern_invalid()
  785. * will be called instead of this function which will
  786. * return KERN_INVALID_ARGUMENT.
  787. */
  788. dev = port_name_to_device(device_name);
  789. if (dev == DEVICE_NULL)
  790. return KERN_INVALID_CAPABILITY;
  791. /*
  792. * Translate reply port.
  793. */
  794. /*if (reply_name == MACH_PORT_NULL)
  795. reply_port = IP_NULL;
  796. */
  797. if (reply_name != MACH_PORT_NULL) {
  798. /* Homey don't play that. */
  799. device_deallocate(dev);
  800. return KERN_INVALID_RIGHT;
  801. }
  802. /* note: doesn't take reply_port arg yet. */
  803. res = ds_device_write_trap(dev, /*reply_port,*/
  804. mode, recnum,
  805. data, data_count);
  806. /*
  807. * Give up reference from port_name_to_device.
  808. */
  809. device_deallocate(dev);
  810. return res;
  811. }
  812. io_return_t
  813. syscall_device_writev_request(mach_port_t device_name,
  814. mach_port_t reply_name,
  815. dev_mode_t mode,
  816. recnum_t recnum,
  817. io_buf_vec_t *iovec,
  818. vm_size_t iocount)
  819. {
  820. device_t dev;
  821. /*ipc_port_t reply_port;*/
  822. io_return_t res;
  823. /*
  824. * First try to translate the device name.
  825. *
  826. * If this fails, return KERN_INVALID_CAPABILITY.
  827. * Caller knows that this most likely means that
  828. * device is not local to node and IPC should be used.
  829. *
  830. * If kernel doesn't do device traps, kern_invalid()
  831. * will be called instead of this function which will
  832. * return KERN_INVALID_ARGUMENT.
  833. */
  834. dev = port_name_to_device(device_name);
  835. if (dev == DEVICE_NULL)
  836. return KERN_INVALID_CAPABILITY;
  837. /*
  838. * Translate reply port.
  839. */
  840. /*if (reply_name == MACH_PORT_NULL)
  841. reply_port = IP_NULL;
  842. */
  843. if (reply_name != MACH_PORT_NULL) {
  844. /* Homey don't play that. */
  845. device_deallocate(dev);
  846. return KERN_INVALID_RIGHT;
  847. }
  848. /* note: doesn't take reply_port arg yet. */
  849. res = ds_device_writev_trap(dev, /*reply_port,*/
  850. mode, recnum,
  851. iovec, iocount);
  852. /*
  853. * Give up reference from port_name_to_device.
  854. */
  855. device_deallocate(dev);
  856. return res;
  857. }
  858. #endif