ipc_object.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 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. /*
  27. * File: ipc/ipc_object.c
  28. * Author: Rich Draves
  29. * Date: 1989
  30. *
  31. * Functions to manipulate IPC objects.
  32. */
  33. #pragma GCC diagnostic error "-Wundef"
  34. #include <glue/gnulinux.h>
  35. #include <string.h>
  36. #include <mach/boolean.h>
  37. #include <mach/kern_return.h>
  38. #include <mach/port.h>
  39. #include <mach/message.h>
  40. #include <ipc/port.h>
  41. #include <ipc/ipc_space.h>
  42. #include <ipc/ipc_entry.h>
  43. #include <ipc/ipc_object.h>
  44. #include <ipc/ipc_right.h>
  45. #include <ipc/ipc_notify.h>
  46. #include <ipc/ipc_pset.h>
  47. #include <kern/debug.h>
  48. #include <kern/printf.h>
  49. #include <kern/slab.h>
  50. #if MACH_KDB
  51. #include <ddb/db_output.h>
  52. #endif /* MACH_KDB */
  53. struct gnu_kmem_cache ipc_object_caches[IOT_NUMBER];
  54. /*
  55. * Routine: ipc_object_reference
  56. * Purpose:
  57. * Take a reference to an object.
  58. */
  59. void
  60. ipc_object_reference(
  61. ipc_object_t object)
  62. {
  63. io_lock(object);
  64. assert(object->io_references > 0);
  65. io_reference(object);
  66. io_unlock(object);
  67. }
  68. /*
  69. * Routine: ipc_object_release
  70. * Purpose:
  71. * Release a reference to an object.
  72. */
  73. void
  74. ipc_object_release(
  75. ipc_object_t object)
  76. {
  77. io_lock(object);
  78. assert(object->io_references > 0);
  79. io_release(object);
  80. io_check_unlock(object);
  81. }
  82. /*
  83. * Routine: ipc_object_translate
  84. * Purpose:
  85. * Look up an object in a space.
  86. * Conditions:
  87. * Nothing locked before. If successful, the object
  88. * is returned locked. The caller doesn't get a ref.
  89. * Returns:
  90. * KERN_SUCCESS Objected returned locked.
  91. * KERN_INVALID_TASK The space is dead.
  92. * KERN_INVALID_NAME The name doesn't denote a right.
  93. * KERN_INVALID_RIGHT Name doesn't denote the correct right.
  94. */
  95. kern_return_t
  96. ipc_object_translate(
  97. ipc_space_t space,
  98. mach_port_t name,
  99. mach_port_right_t right,
  100. ipc_object_t *objectp)
  101. {
  102. ipc_entry_t entry;
  103. ipc_object_t object;
  104. kern_return_t kr;
  105. kr = ipc_right_lookup_read(space, name, &entry);
  106. if (kr != KERN_SUCCESS)
  107. return kr;
  108. /* space is read-locked and active */
  109. if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) {
  110. is_read_unlock(space);
  111. return KERN_INVALID_RIGHT;
  112. }
  113. object = entry->ie_object;
  114. assert(object != IO_NULL);
  115. io_lock(object);
  116. is_read_unlock(space);
  117. *objectp = object;
  118. return KERN_SUCCESS;
  119. }
  120. /*
  121. * Routine: ipc_object_alloc_dead
  122. * Purpose:
  123. * Allocate a dead-name entry.
  124. * Conditions:
  125. * Nothing locked.
  126. * Returns:
  127. * KERN_SUCCESS The dead name is allocated.
  128. * KERN_INVALID_TASK The space is dead.
  129. * KERN_NO_SPACE No room for an entry in the space.
  130. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  131. */
  132. kern_return_t
  133. ipc_object_alloc_dead(
  134. ipc_space_t space,
  135. mach_port_t *namep)
  136. {
  137. ipc_entry_t entry;
  138. kern_return_t kr;
  139. is_write_lock(space);
  140. kr = ipc_entry_alloc(space, namep, &entry);
  141. if (kr != KERN_SUCCESS) {
  142. is_write_unlock(space);
  143. return kr;
  144. }
  145. /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
  146. assert(entry->ie_object == IO_NULL);
  147. entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
  148. is_write_unlock(space);
  149. return KERN_SUCCESS;
  150. }
  151. /*
  152. * Routine: ipc_object_alloc_dead_name
  153. * Purpose:
  154. * Allocate a dead-name entry, with a specific name.
  155. * Conditions:
  156. * Nothing locked.
  157. * Returns:
  158. * KERN_SUCCESS The dead name is allocated.
  159. * KERN_INVALID_TASK The space is dead.
  160. * KERN_NAME_EXISTS The name already denotes a right.
  161. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  162. */
  163. kern_return_t
  164. ipc_object_alloc_dead_name(
  165. ipc_space_t space,
  166. mach_port_t name)
  167. {
  168. ipc_entry_t entry;
  169. kern_return_t kr;
  170. is_write_lock(space);
  171. kr = ipc_entry_alloc_name(space, name, &entry);
  172. if (kr != KERN_SUCCESS) {
  173. is_write_unlock(space);
  174. return kr;
  175. }
  176. if (ipc_right_inuse(space, name, entry))
  177. return KERN_NAME_EXISTS;
  178. /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
  179. assert(entry->ie_object == IO_NULL);
  180. entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
  181. is_write_unlock(space);
  182. return KERN_SUCCESS;
  183. }
  184. /*
  185. * Routine: ipc_object_alloc
  186. * Purpose:
  187. * Allocate an object.
  188. * Conditions:
  189. * Nothing locked. If successful, the object is returned locked.
  190. * The caller doesn't get a reference for the object.
  191. * Returns:
  192. * KERN_SUCCESS The object is allocated.
  193. * KERN_INVALID_TASK The space is dead.
  194. * KERN_NO_SPACE No room for an entry in the space.
  195. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  196. */
  197. kern_return_t
  198. ipc_object_alloc(
  199. ipc_space_t space,
  200. ipc_object_type_t otype,
  201. mach_port_type_t type,
  202. mach_port_urefs_t urefs,
  203. mach_port_t *namep,
  204. ipc_object_t *objectp)
  205. {
  206. ipc_object_t object;
  207. ipc_entry_t entry;
  208. kern_return_t kr;
  209. assert(otype < IOT_NUMBER);
  210. assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
  211. assert(type != MACH_PORT_TYPE_NONE);
  212. assert(urefs <= MACH_PORT_UREFS_MAX);
  213. object = io_alloc(otype);
  214. if (object == IO_NULL)
  215. return KERN_RESOURCE_SHORTAGE;
  216. if (otype == IOT_PORT) {
  217. ipc_port_t port = (ipc_port_t)object;
  218. memset(port, 0, sizeof(*port));
  219. } else if (otype == IOT_PORT_SET) {
  220. ipc_pset_t pset = (ipc_pset_t)object;
  221. memset(pset, 0, sizeof(*pset));
  222. }
  223. is_write_lock(space);
  224. kr = ipc_entry_alloc(space, namep, &entry);
  225. if (kr != KERN_SUCCESS) {
  226. is_write_unlock(space);
  227. io_free(otype, object);
  228. return kr;
  229. }
  230. entry->ie_bits |= type | urefs;
  231. entry->ie_object = object;
  232. io_lock_init(object);
  233. io_lock(object);
  234. is_write_unlock(space);
  235. object->io_references = 1; /* for entry, not caller */
  236. object->io_bits = io_makebits(TRUE, otype, 0);
  237. *objectp = object;
  238. return KERN_SUCCESS;
  239. }
  240. /*
  241. * Routine: ipc_object_alloc_name
  242. * Purpose:
  243. * Allocate an object, with a specific name.
  244. * Conditions:
  245. * Nothing locked. If successful, the object is returned locked.
  246. * The caller doesn't get a reference for the object.
  247. * Returns:
  248. * KERN_SUCCESS The object is allocated.
  249. * KERN_INVALID_TASK The space is dead.
  250. * KERN_NAME_EXISTS The name already denotes a right.
  251. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  252. */
  253. kern_return_t
  254. ipc_object_alloc_name(
  255. ipc_space_t space,
  256. ipc_object_type_t otype,
  257. mach_port_type_t type,
  258. mach_port_urefs_t urefs,
  259. mach_port_t name,
  260. ipc_object_t *objectp)
  261. {
  262. ipc_object_t object;
  263. ipc_entry_t entry;
  264. kern_return_t kr;
  265. assert(otype < IOT_NUMBER);
  266. assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
  267. assert(type != MACH_PORT_TYPE_NONE);
  268. assert(urefs <= MACH_PORT_UREFS_MAX);
  269. object = io_alloc(otype);
  270. if (object == IO_NULL)
  271. return KERN_RESOURCE_SHORTAGE;
  272. if (otype == IOT_PORT) {
  273. ipc_port_t port = (ipc_port_t)object;
  274. memset(port, 0, sizeof(*port));
  275. } else if (otype == IOT_PORT_SET) {
  276. ipc_pset_t pset = (ipc_pset_t)object;
  277. memset(pset, 0, sizeof(*pset));
  278. }
  279. is_write_lock(space);
  280. kr = ipc_entry_alloc_name(space, name, &entry);
  281. if (kr != KERN_SUCCESS) {
  282. is_write_unlock(space);
  283. io_free(otype, object);
  284. return kr;
  285. }
  286. if (ipc_right_inuse(space, name, entry)) {
  287. io_free(otype, object);
  288. return KERN_NAME_EXISTS;
  289. }
  290. entry->ie_bits |= type | urefs;
  291. entry->ie_object = object;
  292. io_lock_init(object);
  293. io_lock(object);
  294. is_write_unlock(space);
  295. object->io_references = 1; /* for entry, not caller */
  296. object->io_bits = io_makebits(TRUE, otype, 0);
  297. *objectp = object;
  298. return KERN_SUCCESS;
  299. }
  300. /*
  301. * Routine: ipc_object_copyin_type
  302. * Purpose:
  303. * Convert a send type name to a received type name.
  304. */
  305. mach_msg_type_name_t
  306. ipc_object_copyin_type(
  307. mach_msg_type_name_t msgt_name)
  308. {
  309. switch (msgt_name) {
  310. case 0:
  311. return 0;
  312. case MACH_MSG_TYPE_MOVE_RECEIVE:
  313. return MACH_MSG_TYPE_PORT_RECEIVE;
  314. case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  315. case MACH_MSG_TYPE_MAKE_SEND_ONCE:
  316. return MACH_MSG_TYPE_PORT_SEND_ONCE;
  317. case MACH_MSG_TYPE_MOVE_SEND:
  318. case MACH_MSG_TYPE_MAKE_SEND:
  319. case MACH_MSG_TYPE_COPY_SEND:
  320. return MACH_MSG_TYPE_PORT_SEND;
  321. default:
  322. #if MACH_ASSERT
  323. assert(!"ipc_object_copyin_type: strange rights");
  324. #else
  325. panic("ipc_object_copyin_type: strange rights");
  326. #endif
  327. return 0; /* in case assert/panic returns */
  328. }
  329. }
  330. /*
  331. * Routine: ipc_object_copyin
  332. * Purpose:
  333. * Copyin a capability from a space.
  334. * If successful, the caller gets a ref
  335. * for the resulting object, unless it is IO_DEAD.
  336. * Conditions:
  337. * Nothing locked.
  338. * Returns:
  339. * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
  340. * KERN_INVALID_TASK The space is dead.
  341. * KERN_INVALID_NAME Name doesn't exist in space.
  342. * KERN_INVALID_RIGHT Name doesn't denote correct right.
  343. */
  344. kern_return_t
  345. ipc_object_copyin(
  346. ipc_space_t space,
  347. mach_port_t name,
  348. mach_msg_type_name_t msgt_name,
  349. ipc_object_t *objectp)
  350. {
  351. ipc_entry_t entry;
  352. ipc_port_t soright;
  353. kern_return_t kr;
  354. /*
  355. * Could first try a read lock when doing
  356. * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
  357. * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
  358. */
  359. kr = ipc_right_lookup_write(space, name, &entry);
  360. if (kr != KERN_SUCCESS)
  361. return kr;
  362. /* space is write-locked and active */
  363. kr = ipc_right_copyin(space, name, entry,
  364. msgt_name, TRUE,
  365. objectp, &soright);
  366. if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
  367. ipc_entry_dealloc(space, name, entry);
  368. is_write_unlock(space);
  369. if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
  370. ipc_notify_port_deleted(soright, name);
  371. return kr;
  372. }
  373. /*
  374. * Routine: ipc_object_copyin_from_kernel
  375. * Purpose:
  376. * Copyin a naked capability from the kernel.
  377. *
  378. * MACH_MSG_TYPE_MOVE_RECEIVE
  379. * The receiver must be ipc_space_kernel.
  380. * Consumes the naked receive right.
  381. * MACH_MSG_TYPE_COPY_SEND
  382. * A naked send right must be supplied.
  383. * The port gains a reference, and a send right
  384. * if the port is still active.
  385. * MACH_MSG_TYPE_MAKE_SEND
  386. * The receiver must be ipc_space_kernel.
  387. * The port gains a reference and a send right.
  388. * MACH_MSG_TYPE_MOVE_SEND
  389. * Consumes a naked send right.
  390. * MACH_MSG_TYPE_MAKE_SEND_ONCE
  391. * The receiver must be ipc_space_kernel.
  392. * The port gains a reference and a send-once right.
  393. * MACH_MSG_TYPE_MOVE_SEND_ONCE
  394. * Consumes a naked send-once right.
  395. * Conditions:
  396. * Nothing locked.
  397. */
  398. void
  399. ipc_object_copyin_from_kernel(
  400. ipc_object_t object,
  401. mach_msg_type_name_t msgt_name)
  402. {
  403. assert(IO_VALID(object));
  404. switch (msgt_name) {
  405. case MACH_MSG_TYPE_MOVE_RECEIVE: {
  406. ipc_port_t port = (ipc_port_t) object;
  407. ip_lock(port);
  408. assert(ip_active(port));
  409. assert(port->ip_receiver_name != MACH_PORT_NULL);
  410. assert(port->ip_receiver == ipc_space_kernel);
  411. /* relevant part of ipc_port_clear_receiver */
  412. ipc_port_set_mscount(port, 0);
  413. port->ip_receiver_name = MACH_PORT_NULL;
  414. port->ip_destination = IP_NULL;
  415. ipc_port_flag_protected_payload_clear(port);
  416. ip_unlock(port);
  417. break;
  418. }
  419. case MACH_MSG_TYPE_COPY_SEND: {
  420. ipc_port_t port = (ipc_port_t) object;
  421. ip_lock(port);
  422. if (ip_active(port)) {
  423. assert(port->ip_srights > 0);
  424. port->ip_srights++;
  425. }
  426. ip_reference(port);
  427. ip_unlock(port);
  428. break;
  429. }
  430. case MACH_MSG_TYPE_MAKE_SEND: {
  431. ipc_port_t port = (ipc_port_t) object;
  432. ip_lock(port);
  433. assert(ip_active(port));
  434. assert(port->ip_receiver_name != MACH_PORT_NULL);
  435. assert(port->ip_receiver == ipc_space_kernel);
  436. ip_reference(port);
  437. port->ip_mscount++;
  438. port->ip_srights++;
  439. ip_unlock(port);
  440. break;
  441. }
  442. case MACH_MSG_TYPE_MOVE_SEND:
  443. /* move naked send right into the message */
  444. break;
  445. case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
  446. ipc_port_t port = (ipc_port_t) object;
  447. ip_lock(port);
  448. assert(ip_active(port));
  449. assert(port->ip_receiver_name != MACH_PORT_NULL);
  450. assert(port->ip_receiver == ipc_space_kernel);
  451. ip_reference(port);
  452. port->ip_sorights++;
  453. ip_unlock(port);
  454. break;
  455. }
  456. case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  457. /* move naked send-once right into the message */
  458. break;
  459. default:
  460. #if MACH_ASSERT
  461. assert(!"ipc_object_copyin_from_kernel: strange rights");
  462. #else
  463. panic("ipc_object_copyin_from_kernel: strange rights");
  464. #endif
  465. }
  466. }
  467. /*
  468. * Routine: ipc_object_destroy
  469. * Purpose:
  470. * Destroys a naked capability.
  471. * Consumes a ref for the object.
  472. *
  473. * A receive right should be in limbo or in transit.
  474. * Conditions:
  475. * Nothing locked.
  476. */
  477. void
  478. ipc_object_destroy(
  479. ipc_object_t object,
  480. mach_msg_type_name_t msgt_name)
  481. {
  482. assert(IO_VALID(object));
  483. assert(io_otype(object) == IOT_PORT);
  484. switch (msgt_name) {
  485. case MACH_MSG_TYPE_PORT_SEND:
  486. ipc_port_release_send((ipc_port_t) object);
  487. break;
  488. case MACH_MSG_TYPE_PORT_SEND_ONCE:
  489. ipc_notify_send_once((ipc_port_t) object);
  490. break;
  491. case MACH_MSG_TYPE_PORT_RECEIVE:
  492. ipc_port_release_receive((ipc_port_t) object);
  493. break;
  494. default:
  495. panic("ipc_object_destroy: strange rights");
  496. }
  497. }
  498. /*
  499. * Routine: ipc_object_copyout
  500. * Purpose:
  501. * Copyout a capability, placing it into a space.
  502. * If successful, consumes a ref for the object.
  503. * Conditions:
  504. * Nothing locked.
  505. * Returns:
  506. * KERN_SUCCESS Copied out object, consumed ref.
  507. * KERN_INVALID_TASK The space is dead.
  508. * KERN_INVALID_CAPABILITY The object is dead.
  509. * KERN_NO_SPACE No room in space for another right.
  510. * KERN_RESOURCE_SHORTAGE No memory available.
  511. * KERN_UREFS_OVERFLOW Urefs limit exceeded
  512. * and overflow wasn't specified.
  513. */
  514. kern_return_t
  515. ipc_object_copyout(
  516. ipc_space_t space,
  517. ipc_object_t object,
  518. mach_msg_type_name_t msgt_name,
  519. boolean_t overflow,
  520. mach_port_t *namep)
  521. {
  522. mach_port_t name;
  523. ipc_entry_t entry;
  524. kern_return_t kr;
  525. assert(IO_VALID(object));
  526. assert(io_otype(object) == IOT_PORT);
  527. is_write_lock(space);
  528. for (;;) {
  529. if (!space->is_active) {
  530. is_write_unlock(space);
  531. return KERN_INVALID_TASK;
  532. }
  533. if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
  534. ipc_right_reverse(space, object, &name, &entry)) {
  535. /* object is locked and active */
  536. assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
  537. break;
  538. }
  539. kr = ipc_entry_alloc(space, &name, &entry);
  540. if (kr != KERN_SUCCESS) {
  541. is_write_unlock(space);
  542. return kr;
  543. }
  544. assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
  545. assert(entry->ie_object == IO_NULL);
  546. io_lock(object);
  547. if (!io_active(object)) {
  548. io_unlock(object);
  549. ipc_entry_dealloc(space, name, entry);
  550. is_write_unlock(space);
  551. return KERN_INVALID_CAPABILITY;
  552. }
  553. entry->ie_object = object;
  554. break;
  555. }
  556. /* space is write-locked and active, object is locked and active */
  557. kr = ipc_right_copyout(space, name, entry,
  558. msgt_name, overflow, object);
  559. /* object is unlocked */
  560. is_write_unlock(space);
  561. if (kr == KERN_SUCCESS)
  562. *namep = name;
  563. return kr;
  564. }
  565. #if 0
  566. /* XXX same, but don't check for already-existing send rights */
  567. kern_return_t
  568. ipc_object_copyout_multiname(space, object, namep)
  569. ipc_space_t space;
  570. ipc_object_t object;
  571. mach_port_t *namep;
  572. {
  573. mach_port_t name;
  574. ipc_entry_t entry;
  575. kern_return_t kr;
  576. assert(IO_VALID(object));
  577. assert(io_otype(object) == IOT_PORT);
  578. is_write_lock(space);
  579. for (;;) {
  580. if (!space->is_active) {
  581. is_write_unlock(space);
  582. return KERN_INVALID_TASK;
  583. }
  584. kr = ipc_entry_alloc(space, &name, &entry);
  585. if (kr != KERN_SUCCESS) {
  586. is_write_unlock(space);
  587. return kr; /* space is unlocked */
  588. }
  589. assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
  590. assert(entry->ie_object == IO_NULL);
  591. io_lock(object);
  592. if (!io_active(object)) {
  593. io_unlock(object);
  594. ipc_entry_dealloc(space, name, entry);
  595. is_write_unlock(space);
  596. return KERN_INVALID_CAPABILITY;
  597. }
  598. entry->ie_object = object;
  599. break;
  600. }
  601. /* space is write-locked and active, object is locked and active */
  602. kr = ipc_right_copyout_multiname(space, name, entry, object);
  603. /* object is unlocked */
  604. is_write_unlock(space);
  605. if (kr == KERN_SUCCESS)
  606. *namep = name;
  607. return kr;
  608. }
  609. #endif /* 0 */
  610. /*
  611. * Routine: ipc_object_copyout_name
  612. * Purpose:
  613. * Copyout a capability, placing it into a space.
  614. * The specified name is used for the capability.
  615. * If successful, consumes a ref for the object.
  616. * Conditions:
  617. * Nothing locked.
  618. * Returns:
  619. * KERN_SUCCESS Copied out object, consumed ref.
  620. * KERN_INVALID_TASK The space is dead.
  621. * KERN_INVALID_CAPABILITY The object is dead.
  622. * KERN_RESOURCE_SHORTAGE No memory available.
  623. * KERN_UREFS_OVERFLOW Urefs limit exceeded
  624. * and overflow wasn't specified.
  625. * KERN_RIGHT_EXISTS Space has rights under another name.
  626. * KERN_NAME_EXISTS Name is already used.
  627. */
  628. kern_return_t
  629. ipc_object_copyout_name(
  630. ipc_space_t space,
  631. ipc_object_t object,
  632. mach_msg_type_name_t msgt_name,
  633. boolean_t overflow,
  634. mach_port_t name)
  635. {
  636. mach_port_t oname;
  637. ipc_entry_t oentry;
  638. ipc_entry_t entry;
  639. kern_return_t kr;
  640. assert(IO_VALID(object));
  641. assert(io_otype(object) == IOT_PORT);
  642. is_write_lock(space);
  643. kr = ipc_entry_alloc_name(space, name, &entry);
  644. if (kr != KERN_SUCCESS) {
  645. is_write_unlock(space);
  646. return kr;
  647. }
  648. if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
  649. ipc_right_reverse(space, object, &oname, &oentry)) {
  650. /* object is locked and active */
  651. if (name != oname) {
  652. io_unlock(object);
  653. if (IE_BITS_TYPE(entry->ie_bits)
  654. == MACH_PORT_TYPE_NONE)
  655. ipc_entry_dealloc(space, name, entry);
  656. is_write_unlock(space);
  657. return KERN_RIGHT_EXISTS;
  658. }
  659. assert(entry == oentry);
  660. assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
  661. } else {
  662. if (ipc_right_inuse(space, name, entry))
  663. return KERN_NAME_EXISTS;
  664. assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
  665. assert(entry->ie_object == IO_NULL);
  666. io_lock(object);
  667. if (!io_active(object)) {
  668. io_unlock(object);
  669. ipc_entry_dealloc(space, name, entry);
  670. is_write_unlock(space);
  671. return KERN_INVALID_CAPABILITY;
  672. }
  673. entry->ie_object = object;
  674. }
  675. /* space is write-locked and active, object is locked and active */
  676. kr = ipc_right_copyout(space, name, entry,
  677. msgt_name, overflow, object);
  678. /* object is unlocked */
  679. is_write_unlock(space);
  680. return kr;
  681. }
  682. /*
  683. * Routine: ipc_object_copyout_dest
  684. * Purpose:
  685. * Translates/consumes the destination right of a message.
  686. * This is unlike normal copyout because the right is consumed
  687. * in a funny way instead of being given to the receiving space.
  688. * The receiver gets his name for the port, if he has receive
  689. * rights, otherwise MACH_PORT_NULL.
  690. * Conditions:
  691. * The object is locked and active. Nothing else locked.
  692. * The object is unlocked and loses a reference.
  693. */
  694. void
  695. ipc_object_copyout_dest(
  696. ipc_space_t space,
  697. ipc_object_t object,
  698. mach_msg_type_name_t msgt_name,
  699. mach_port_t *namep)
  700. {
  701. mach_port_t name;
  702. assert(IO_VALID(object));
  703. assert(io_active(object));
  704. io_release(object);
  705. /*
  706. * If the space is the receiver/owner of the object,
  707. * then we quietly consume the right and return
  708. * the space's name for the object. Otherwise
  709. * we destroy the right and return MACH_PORT_NULL.
  710. */
  711. switch (msgt_name) {
  712. case MACH_MSG_TYPE_PORT_SEND: {
  713. ipc_port_t port = (ipc_port_t) object;
  714. ipc_port_t nsrequest = IP_NULL;
  715. mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
  716. assert(port->ip_srights > 0);
  717. if (--port->ip_srights == 0) {
  718. nsrequest = port->ip_nsrequest;
  719. if (nsrequest != IP_NULL) {
  720. port->ip_nsrequest = IP_NULL;
  721. mscount = port->ip_mscount;
  722. }
  723. }
  724. if (port->ip_receiver == space)
  725. name = port->ip_receiver_name;
  726. else
  727. name = MACH_PORT_NULL;
  728. ip_unlock(port);
  729. if (nsrequest != IP_NULL)
  730. ipc_notify_no_senders(nsrequest, mscount);
  731. break;
  732. }
  733. case MACH_MSG_TYPE_PORT_SEND_ONCE: {
  734. ipc_port_t port = (ipc_port_t) object;
  735. assert(port->ip_sorights > 0);
  736. if (port->ip_receiver == space) {
  737. /* quietly consume the send-once right */
  738. port->ip_sorights--;
  739. name = port->ip_receiver_name;
  740. ip_unlock(port);
  741. } else {
  742. /*
  743. * A very bizarre case. The message
  744. * was received, but before this copyout
  745. * happened the space lost receive rights.
  746. * We can't quietly consume the soright
  747. * out from underneath some other task,
  748. * so generate a send-once notification.
  749. */
  750. ip_reference(port); /* restore ref */
  751. ip_unlock(port);
  752. ipc_notify_send_once(port);
  753. name = MACH_PORT_NULL;
  754. }
  755. break;
  756. }
  757. default:
  758. #if MACH_ASSERT
  759. assert(!"ipc_object_copyout_dest: strange rights");
  760. #else
  761. panic("ipc_object_copyout_dest: strange rights");
  762. #endif
  763. }
  764. *namep = name;
  765. }
  766. /*
  767. * Routine: ipc_object_rename
  768. * Purpose:
  769. * Rename an entry in a space.
  770. * Conditions:
  771. * Nothing locked.
  772. * Returns:
  773. * KERN_SUCCESS Renamed the entry.
  774. * KERN_INVALID_TASK The space was dead.
  775. * KERN_INVALID_NAME oname didn't denote an entry.
  776. * KERN_NAME_EXISTS nname already denoted an entry.
  777. * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
  778. */
  779. kern_return_t
  780. ipc_object_rename(
  781. ipc_space_t space,
  782. mach_port_t oname,
  783. mach_port_t nname)
  784. {
  785. ipc_entry_t oentry, nentry;
  786. kern_return_t kr;
  787. is_write_lock(space);
  788. kr = ipc_entry_alloc_name(space, nname, &nentry);
  789. if (kr != KERN_SUCCESS) {
  790. is_write_unlock(space);
  791. return kr;
  792. }
  793. if (ipc_right_inuse(space, nname, nentry)) {
  794. /* space is unlocked */
  795. return KERN_NAME_EXISTS;
  796. }
  797. /* don't let ipc_entry_lookup see the uninitialized new entry */
  798. if ((oname == nname) ||
  799. ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
  800. ipc_entry_dealloc(space, nname, nentry);
  801. is_write_unlock(space);
  802. return KERN_INVALID_NAME;
  803. }
  804. kr = ipc_right_rename(space, oname, oentry, nname, nentry);
  805. /* space is unlocked */
  806. return kr;
  807. }
  808. #if MACH_KDB
  809. #define printf kdbprintf
  810. /*
  811. * Routine: ipc_object_print
  812. * Purpose:
  813. * Pretty-print an object for kdb.
  814. */
  815. char *ikot_print_array[IKOT_MAX_TYPE] = {
  816. "(NONE) ",
  817. "(THREAD) ",
  818. "(TASK) ",
  819. "(HOST) ",
  820. "(HOST_PRIV) ",
  821. "(PROCESSOR) ",
  822. "(PSET) ",
  823. "(PSET_NAME) ",
  824. "(PAGER) ",
  825. "(PAGER_REQUEST) ",
  826. "(DEVICE) ", /* 10 */
  827. "(XMM_OBJECT) ",
  828. "(XMM_PAGER) ",
  829. "(XMM_KERNEL) ",
  830. "(XMM_REPLY) ",
  831. "(PAGER_TERMINATING)",
  832. "(PAGING_NAME) ",
  833. "(HOST_SECURITY) ",
  834. "(LEDGER) ",
  835. "(MASTER_DEVICE) ",
  836. "(ACTIVATION) ", /* 20 */
  837. "(SUBSYSTEM) ",
  838. "(IO_DONE_QUEUE) ",
  839. "(SEMAPHORE) ",
  840. "(LOCK_SET) ",
  841. "(CLOCK) ",
  842. "(CLOCK_CTRL) ",
  843. "(PAGER_PROXY) ", /* 27 */
  844. /* << new entries here */
  845. "(UNKNOWN) " /* magic catchall */
  846. }; /* Please keep in sync with kern/ipc_kobject.h */
  847. void
  848. ipc_object_print(
  849. const ipc_object_t object)
  850. {
  851. int kotype;
  852. iprintf("%s", io_active(object) ? "active" : "dead");
  853. printf(", refs=%d", object->io_references);
  854. printf(", otype=%d", io_otype(object));
  855. kotype = io_kotype(object);
  856. if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
  857. printf(", kotype=%d %s\n", io_kotype(object),
  858. ikot_print_array[kotype]);
  859. else
  860. printf(", kotype=0x%x %s\n", io_kotype(object),
  861. ikot_print_array[IKOT_UNKNOWN]);
  862. }
  863. #endif /* MACH_KDB */