memory_object_proxy.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* memory_object_proxy.c - Proxy memory objects for Mach.
  2. Copyright (C) 2005 Free Software Foundation, Inc.
  3. Written by Marcus Brinkmann.
  4. This file is part of GNU Mach.
  5. GNU Mach is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Mach is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
  16. /* A proxy memory object is a kernel port that can be used like a real
  17. memory object in a vm_map call, except that the current and maximum
  18. protection are restricted to the proxy object's maximum protection
  19. at the time the mapping is established. The kernel port will hold
  20. a reference to the real memory object for the life time of the
  21. proxy object.
  22. Note that we don't need to do any reference counting on the proxy
  23. object. Our caller will hold a reference to the proxy object when
  24. looking it up, and is expected to acquire its own reference to the
  25. real memory object if needed before releasing the reference to the
  26. proxy object.
  27. The user provided real memory object and the maximum protection are
  28. not checked for validity. The maximum protection is only used as a
  29. mask, and the memory object is validated at the time the mapping is
  30. established. */
  31. #include <mach/port.h>
  32. #include <mach/kern_return.h>
  33. #include <mach/notify.h>
  34. #include <mach/vm_prot.h>
  35. #include <kern/printf.h>
  36. #include <kern/slab.h>
  37. #include <ipc/ipc_port.h>
  38. #include <ipc/ipc_space.h>
  39. #include <vm/memory_object_proxy.h>
  40. /* The cache which holds our proxy memory objects. */
  41. static struct kmem_cache memory_object_proxy_cache;
  42. struct memory_object_proxy
  43. {
  44. struct ipc_port *port;
  45. ipc_port_t object;
  46. vm_prot_t max_protection;
  47. };
  48. typedef struct memory_object_proxy *memory_object_proxy_t;
  49. void
  50. memory_object_proxy_init (void)
  51. {
  52. kmem_cache_init (&memory_object_proxy_cache, "memory_object_proxy",
  53. sizeof (struct memory_object_proxy), 0, NULL, 0);
  54. }
  55. /* Lookup a proxy memory object by its port. */
  56. static memory_object_proxy_t
  57. memory_object_proxy_port_lookup (ipc_port_t port)
  58. {
  59. memory_object_proxy_t proxy;
  60. if (!IP_VALID(port))
  61. return 0;
  62. ip_lock (port);
  63. if (ip_active (port) && (ip_kotype (port) == IKOT_PAGER_PROXY))
  64. proxy = (memory_object_proxy_t) port->ip_kobject;
  65. else
  66. proxy = 0;
  67. ip_unlock (port);
  68. return proxy;
  69. }
  70. /* Process a no-sender notification for the proxy memory object
  71. port. */
  72. boolean_t
  73. memory_object_proxy_notify (mach_msg_header_t *msg)
  74. {
  75. if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS)
  76. {
  77. memory_object_proxy_t proxy;
  78. mach_no_senders_notification_t *ns;
  79. ns = (mach_no_senders_notification_t *) msg;
  80. proxy = memory_object_proxy_port_lookup
  81. ((ipc_port_t) ns->not_header.msgh_remote_port);
  82. assert (proxy);
  83. ipc_port_release_send (proxy->object);
  84. return TRUE;
  85. }
  86. printf ("memory_object_proxy_notify: strange notification %d\n",
  87. msg->msgh_id);
  88. return FALSE;
  89. }
  90. /* Create a new proxy memory object from [START;START+LEN) in the
  91. given OBJECT at OFFSET in the new object with the maximum
  92. protection MAX_PROTECTION and return it in *PORT. */
  93. kern_return_t
  94. memory_object_create_proxy (const ipc_space_t space, vm_prot_t max_protection,
  95. ipc_port_t *object, natural_t object_count,
  96. const vm_offset_t *offset, natural_t offset_count,
  97. const vm_offset_t *start, natural_t start_count,
  98. const vm_offset_t *len, natural_t len_count,
  99. ipc_port_t *port)
  100. {
  101. memory_object_proxy_t proxy;
  102. ipc_port_t notify;
  103. if (space == IS_NULL)
  104. return KERN_INVALID_TASK;
  105. if (offset_count != object_count || start_count != object_count
  106. || len_count != object_count)
  107. return KERN_INVALID_ARGUMENT;
  108. /* FIXME: Support more than one memory object. */
  109. if (object_count != 1)
  110. return KERN_INVALID_ARGUMENT;
  111. if (!IP_VALID(object[0]))
  112. return KERN_INVALID_NAME;
  113. /* FIXME: Support a different offset from 0. */
  114. if (offset[0] != 0)
  115. return KERN_INVALID_ARGUMENT;
  116. /* FIXME: Support a different range from total. */
  117. if (start[0] != 0 || len[0] != (vm_offset_t) ~0)
  118. return KERN_INVALID_ARGUMENT;
  119. proxy = (memory_object_proxy_t) kmem_cache_alloc (&memory_object_proxy_cache);
  120. /* Allocate port, keeping a reference for it. */
  121. proxy->port = ipc_port_alloc_kernel ();
  122. if (proxy->port == IP_NULL)
  123. {
  124. kmem_cache_free (&memory_object_proxy_cache, (vm_offset_t) proxy);
  125. return KERN_RESOURCE_SHORTAGE;
  126. }
  127. /* Associate the port with the proxy memory object. */
  128. ipc_kobject_set (proxy->port, (ipc_kobject_t) proxy, IKOT_PAGER_PROXY);
  129. /* Request no-senders notifications on the port. */
  130. notify = ipc_port_make_sonce (proxy->port);
  131. ip_lock (proxy->port);
  132. ipc_port_nsrequest (proxy->port, 1, notify, &notify);
  133. assert (notify == IP_NULL);
  134. proxy->object = ipc_port_copy_send (object[0]);
  135. proxy->max_protection = max_protection;
  136. *port = ipc_port_make_send (proxy->port);
  137. return KERN_SUCCESS;
  138. }
  139. /* Lookup the real memory object and maximum protection for the proxy
  140. memory object port PORT, for which the caller holds a reference.
  141. *OBJECT is only guaranteed to be valid as long as the caller holds
  142. the reference to PORT (unless the caller acquires its own reference
  143. to it). If PORT is not a proxy memory object, return
  144. KERN_INVALID_ARGUMENT. */
  145. kern_return_t
  146. memory_object_proxy_lookup (ipc_port_t port, ipc_port_t *object,
  147. vm_prot_t *max_protection)
  148. {
  149. memory_object_proxy_t proxy;
  150. proxy = memory_object_proxy_port_lookup (port);
  151. if (!proxy)
  152. return KERN_INVALID_ARGUMENT;
  153. *object = proxy->object;
  154. *max_protection = proxy->max_protection;
  155. return KERN_SUCCESS;
  156. }