File: | obj/../kern/ipc_mig.c |
Location: | line 1004, column 3 |
Description: | Value stored to 'reply_port' is never read |
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 | |
27 | #include <mach/boolean.h> |
28 | #include <mach/port.h> |
29 | #include <mach/message.h> |
30 | #include <mach/thread_status.h> |
31 | #include <machine/locore.h> |
32 | #include <kern/ast.h> |
33 | #include <kern/debug.h> |
34 | #include <kern/ipc_tt.h> |
35 | #include <kern/syscall_subr.h> |
36 | #include <kern/thread.h> |
37 | #include <kern/task.h> |
38 | #include <kern/ipc_kobject.h> |
39 | #include <kern/ipc_tt.h> |
40 | #include <vm/vm_map.h> |
41 | #include <vm/vm_user.h> |
42 | #include <ipc/port.h> |
43 | #include <ipc/ipc_kmsg.h> |
44 | #include <ipc/ipc_entry.h> |
45 | #include <ipc/ipc_object.h> |
46 | #include <ipc/ipc_mqueue.h> |
47 | #include <ipc/ipc_space.h> |
48 | #include <ipc/ipc_port.h> |
49 | #include <ipc/ipc_pset.h> |
50 | #include <ipc/ipc_thread.h> |
51 | #include <ipc/mach_port.h> |
52 | #include <device/dev_hdr.h> |
53 | #include <device/device_types.h> |
54 | #include <device/ds_routines.h> |
55 | |
56 | /* |
57 | * Routine: mach_msg_send_from_kernel |
58 | * Purpose: |
59 | * Send a message from the kernel. |
60 | * |
61 | * This is used by the client side of KernelUser interfaces |
62 | * to implement SimpleRoutines. Currently, this includes |
63 | * device_reply and memory_object messages. |
64 | * Conditions: |
65 | * Nothing locked. |
66 | * Returns: |
67 | * MACH_MSG_SUCCESS Sent the message. |
68 | * MACH_SEND_INVALID_DATA Bad destination port. |
69 | */ |
70 | |
71 | mach_msg_return_t |
72 | mach_msg_send_from_kernel( |
73 | mach_msg_header_t *msg, |
74 | mach_msg_size_t send_size) |
75 | { |
76 | ipc_kmsg_t kmsg; |
77 | mach_msg_return_t mr; |
78 | |
79 | if (!MACH_PORT_VALID(msg->msgh_remote_port)(((msg->msgh_remote_port) != ((mach_port_t) 0)) && ((msg->msgh_remote_port) != ((mach_port_t) ~0)))) |
80 | return MACH_SEND_INVALID_DEST0x10000003; |
81 | |
82 | mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); |
83 | if (mr != MACH_MSG_SUCCESS0x00000000) |
84 | panic("mach_msg_send_from_kernel"); |
85 | |
86 | ipc_kmsg_copyin_from_kernel(kmsg); |
87 | ipc_mqueue_send_always(kmsg)({ mach_msg_return_t mr; mr = ipc_mqueue_send((kmsg), 0x00010000 , ((mach_msg_timeout_t) 0)); ({ if (!(mr == 0x00000000)) Assert ("mr == MACH_MSG_SUCCESS", "../kern/ipc_mig.c", 87); }); }); |
88 | |
89 | return MACH_MSG_SUCCESS0x00000000; |
90 | } |
91 | |
92 | mach_msg_return_t |
93 | mach_msg_rpc_from_kernel(msg, send_size, reply_size) |
94 | mach_msg_header_t *msg; |
95 | mach_msg_size_t send_size; |
96 | mach_msg_size_t reply_size; |
97 | { |
98 | panic("mach_msg_rpc_from_kernel"); /*XXX*/ |
99 | } |
100 | |
101 | /* |
102 | * Routine: mach_msg_abort_rpc |
103 | * Purpose: |
104 | * Destroy the thread's ith_rpc_reply port. |
105 | * This will interrupt a mach_msg_rpc_from_kernel |
106 | * with a MACH_RCV_PORT_DIED return code. |
107 | * Conditions: |
108 | * Nothing locked. |
109 | */ |
110 | |
111 | void |
112 | mach_msg_abort_rpc(thread) |
113 | ipc_thread_t thread; |
114 | { |
115 | ipc_port_t reply = IP_NULL((ipc_port_t) ((ipc_object_t) 0)); |
116 | |
117 | ith_lock(thread); |
118 | if (thread->ith_self != IP_NULL((ipc_port_t) ((ipc_object_t) 0))) { |
119 | reply = thread->ith_rpc_reply; |
120 | thread->ith_rpc_reply = IP_NULL((ipc_port_t) ((ipc_object_t) 0)); |
121 | } |
122 | ith_unlock(thread); |
123 | |
124 | if (reply != IP_NULL((ipc_port_t) ((ipc_object_t) 0))) |
125 | ipc_port_dealloc_reply(reply)ipc_port_dealloc_special((reply), ipc_space_reply); |
126 | } |
127 | |
128 | /* |
129 | * Routine: mach_msg |
130 | * Purpose: |
131 | * Like mach_msg_trap except that message buffers |
132 | * live in kernel space. Doesn't handle any options. |
133 | * |
134 | * This is used by in-kernel server threads to make |
135 | * kernel calls, to receive request messages, and |
136 | * to send reply messages. |
137 | * Conditions: |
138 | * Nothing locked. |
139 | * Returns: |
140 | */ |
141 | |
142 | mach_msg_return_t |
143 | mach_msg(msg, option, send_size, rcv_size, rcv_name, time_out, notify) |
144 | mach_msg_header_t *msg; |
145 | mach_msg_option_t option; |
146 | mach_msg_size_t send_size; |
147 | mach_msg_size_t rcv_size; |
148 | mach_port_t rcv_name; |
149 | mach_msg_timeout_t time_out; |
150 | mach_port_t notify; |
151 | { |
152 | ipc_space_t space = current_space()(((active_threads[(0)])->task)->itk_space); |
153 | vm_map_t map = current_map()(((active_threads[(0)])->task)->map); |
154 | ipc_kmsg_t kmsg; |
155 | mach_port_seqno_t seqno; |
156 | mach_msg_return_t mr; |
157 | |
158 | if (option & MACH_SEND_MSG0x00000001) { |
159 | mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); |
160 | if (mr != MACH_MSG_SUCCESS0x00000000) |
161 | panic("mach_msg"); |
162 | |
163 | mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL((mach_port_t) 0)); |
164 | if (mr != MACH_MSG_SUCCESS0x00000000) { |
165 | ikm_free(kmsg)({ register vm_size_t _size = (kmsg)->ikm_size; if ((integer_t )_size > 0) kfree((vm_offset_t) (kmsg), _size); else ipc_kmsg_free (kmsg); }); |
166 | return mr; |
167 | } |
168 | |
169 | do |
170 | mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE0x00000000, |
171 | MACH_MSG_TIMEOUT_NONE((mach_msg_timeout_t) 0)); |
172 | while (mr == MACH_SEND_INTERRUPTED0x10000007); |
173 | assert(mr == MACH_MSG_SUCCESS)({ if (!(mr == 0x00000000)) Assert("mr == MACH_MSG_SUCCESS", "../kern/ipc_mig.c" , 173); }); |
174 | } |
175 | |
176 | if (option & MACH_RCV_MSG0x00000002) { |
177 | do { |
178 | ipc_object_t object; |
179 | ipc_mqueue_t mqueue; |
180 | |
181 | mr = ipc_mqueue_copyin(space, rcv_name, |
182 | &mqueue, &object); |
183 | if (mr != MACH_MSG_SUCCESS0x00000000) |
184 | return mr; |
185 | /* hold ref for object; mqueue is locked */ |
186 | |
187 | mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE0x00000000, |
188 | MACH_MSG_SIZE_MAX((mach_msg_size_t) ~0), |
189 | MACH_MSG_TIMEOUT_NONE((mach_msg_timeout_t) 0), |
190 | FALSE((boolean_t) 0), IMQ_NULL_CONTINUE((void (*)()) 0), |
191 | &kmsg, &seqno); |
192 | /* mqueue is unlocked */ |
193 | ipc_object_release(object); |
194 | } while (mr == MACH_RCV_INTERRUPTED0x10004005); |
195 | if (mr != MACH_MSG_SUCCESS0x00000000) |
196 | return mr; |
197 | |
198 | kmsg->ikm_header.msgh_seqno = seqno; |
199 | |
200 | if (rcv_size < kmsg->ikm_header.msgh_size) { |
201 | ipc_kmsg_copyout_dest(kmsg, space); |
202 | ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); |
203 | return MACH_RCV_TOO_LARGE0x10004004; |
204 | } |
205 | |
206 | mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL((mach_port_t) 0)); |
207 | if (mr != MACH_MSG_SUCCESS0x00000000) { |
208 | if ((mr &~ MACH_MSG_MASK0x00003c00) == MACH_RCV_BODY_ERROR0x1000400c) { |
209 | ipc_kmsg_put_to_kernel(msg, kmsg, |
210 | kmsg->ikm_header.msgh_size); |
211 | } else { |
212 | ipc_kmsg_copyout_dest(kmsg, space); |
213 | ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); |
214 | } |
215 | |
216 | return mr; |
217 | } |
218 | |
219 | ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size); |
220 | } |
221 | |
222 | return MACH_MSG_SUCCESS0x00000000; |
223 | } |
224 | |
225 | /* |
226 | * Routine: mig_get_reply_port |
227 | * Purpose: |
228 | * Called by client side interfaces living in the kernel |
229 | * to get a reply port. This port is used for |
230 | * mach_msg() calls which are kernel calls. |
231 | */ |
232 | |
233 | mach_port_t |
234 | mig_get_reply_port(void) |
235 | { |
236 | ipc_thread_t self = current_thread()(active_threads[(0)]); |
237 | |
238 | if (self->ith_mig_reply == MACH_PORT_NULL((mach_port_t) 0)) |
239 | self->ith_mig_reply = mach_reply_port(); |
240 | |
241 | return self->ith_mig_reply; |
242 | } |
243 | |
244 | /* |
245 | * Routine: mig_dealloc_reply_port |
246 | * Purpose: |
247 | * Called by client side interfaces to get rid of a reply port. |
248 | * Shouldn't ever be called inside the kernel, because |
249 | * kernel calls shouldn't prompt Mig to call it. |
250 | */ |
251 | |
252 | void |
253 | mig_dealloc_reply_port( |
254 | mach_port_t reply_port) |
255 | { |
256 | panic("mig_dealloc_reply_port"); |
257 | } |
258 | |
259 | /* |
260 | * Routine: mig_put_reply_port |
261 | * Purpose: |
262 | * Called by client side interfaces after each RPC to |
263 | * let the client recycle the reply port if it wishes. |
264 | */ |
265 | void |
266 | mig_put_reply_port( |
267 | mach_port_t reply_port) |
268 | { |
269 | } |
270 | |
271 | /* |
272 | * mig_strncpy.c - by Joshua Block |
273 | * |
274 | * mig_strncp -- Bounded string copy. Does what the library routine strncpy |
275 | * OUGHT to do: Copies the (null terminated) string in src into dest, a |
276 | * buffer of length len. Assures that the copy is still null terminated |
277 | * and doesn't overflow the buffer, truncating the copy if necessary. |
278 | * |
279 | * Parameters: |
280 | * |
281 | * dest - Pointer to destination buffer. |
282 | * |
283 | * src - Pointer to source string. |
284 | * |
285 | * len - Length of destination buffer. |
286 | */ |
287 | void mig_strncpy(dest, src, len) |
288 | char *dest, *src; |
289 | int len; |
290 | { |
291 | int i; |
292 | |
293 | if (len <= 0) |
294 | return; |
295 | |
296 | for (i=1; i<len; i++) |
297 | if (! (*dest++ = *src++)) |
298 | return; |
299 | |
300 | *dest = '\0'; |
301 | return; |
302 | } |
303 | |
304 | #define fast_send_right_lookup(name, port, abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 304); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; abort; } port = (ipc_port_t) entry->ie_object ; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)))) Assert ("port != IP_NULL", "../kern/ipc_mig.c", 304); }); ; ; }) \({ |
305 | MACRO_BEGIN({ \ |
306 | register ipc_space_t space = current_space()(((active_threads[(0)])->task)->itk_space); \ |
307 | register ipc_entry_t entry; \ |
308 | register mach_port_index_t index = MACH_PORT_INDEX(name)(name); \ |
309 | \ |
310 | is_read_lock(space); \ |
311 | assert(space->is_active)({ if (!(space->is_active)) Assert("space->is_active", "../kern/ipc_mig.c" , 311); }); \ |
312 | \ |
313 | if ((index >= space->is_table_size) || \ |
314 | (((entry = &space->is_table[index])->ie_bits & \ |
315 | (IE_BITS_GEN_MASK0|MACH_PORT_TYPE_SEND((mach_port_type_t)(1 << ((((mach_port_right_t) 0))+16) )))) != \ |
316 | (MACH_PORT_GEN(name)0 | MACH_PORT_TYPE_SEND((mach_port_type_t)(1 << ((((mach_port_right_t) 0))+16) ))))) { \ |
317 | is_read_unlock(space); \ |
318 | abort; \ |
319 | } \ |
320 | \ |
321 | port = (ipc_port_t) entry->ie_object; \ |
322 | assert(port != IP_NULL)({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)))) Assert("port != IP_NULL" , "../kern/ipc_mig.c", 322); }); \ |
323 | \ |
324 | ip_lock(port); \ |
325 | /* can safely unlock space now that port is locked */ \ |
326 | is_read_unlock(space); \}) |
327 | MACRO_END}) |
328 | |
329 | device_t |
330 | port_name_to_device(name) |
331 | mach_port_t name; |
332 | { |
333 | register ipc_port_t port; |
334 | register device_t device; |
335 | |
336 | fast_send_right_lookup(name, port, goto abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 336); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; goto abort; } port = (ipc_port_t) entry-> ie_object; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)) )) Assert("port != IP_NULL", "../kern/ipc_mig.c", 336); }); ; ; }); |
337 | /* port is locked */ |
338 | |
339 | /* |
340 | * Now map the port object to a device object. |
341 | * This is an inline version of dev_port_lookup(). |
342 | */ |
343 | if (ip_active(port)((int)(&(port)->ip_target.ipt_object)->io_bits < 0) && (ip_kotype(port)((&(port)->ip_target.ipt_object)->io_bits & 0x0000ffff ) == IKOT_DEVICE10)) { |
344 | device = (device_t) port->ip_kobject; |
345 | device_reference(device); |
346 | ip_unlock(port); |
347 | return device; |
348 | } |
349 | |
350 | ip_unlock(port); |
351 | return DEVICE_NULL((device_t) 0); |
352 | |
353 | /* |
354 | * The slow case. The port wasn't easily accessible. |
355 | */ |
356 | abort: { |
357 | ipc_port_t kern_port; |
358 | kern_return_t kr; |
359 | |
360 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), name, |
361 | MACH_MSG_TYPE_COPY_SEND19, |
362 | (ipc_object_t *) &kern_port); |
363 | if (kr != KERN_SUCCESS0) |
364 | return DEVICE_NULL((device_t) 0); |
365 | |
366 | device = dev_port_lookup(kern_port); |
367 | if (IP_VALID(kern_port)(((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t ) 0)) && ((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t) -1)))) |
368 | ipc_port_release_send(kern_port); |
369 | return device; |
370 | } |
371 | } |
372 | |
373 | thread_t |
374 | port_name_to_thread(name) |
375 | mach_port_t name; |
376 | { |
377 | register ipc_port_t port; |
378 | |
379 | fast_send_right_lookup(name, port, goto abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 379); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; goto abort; } port = (ipc_port_t) entry-> ie_object; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)) )) Assert("port != IP_NULL", "../kern/ipc_mig.c", 379); }); ; ; }); |
380 | /* port is locked */ |
381 | |
382 | if (ip_active(port)((int)(&(port)->ip_target.ipt_object)->io_bits < 0) && |
383 | (ip_kotype(port)((&(port)->ip_target.ipt_object)->io_bits & 0x0000ffff ) == IKOT_THREAD1)) { |
384 | register thread_t thread; |
385 | |
386 | thread = (thread_t) port->ip_kobject; |
387 | assert(thread != THREAD_NULL)({ if (!(thread != ((thread_t) 0))) Assert("thread != THREAD_NULL" , "../kern/ipc_mig.c", 387); }); |
388 | |
389 | /* thread referencing is a bit complicated, |
390 | so don't bother to expand inline */ |
391 | thread_reference(thread); |
392 | ip_unlock(port); |
393 | |
394 | return thread; |
395 | } |
396 | |
397 | ip_unlock(port); |
398 | return THREAD_NULL((thread_t) 0); |
399 | |
400 | abort: { |
401 | thread_t thread; |
402 | ipc_port_t kern_port; |
403 | kern_return_t kr; |
404 | |
405 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), name, |
406 | MACH_MSG_TYPE_COPY_SEND19, |
407 | (ipc_object_t *) &kern_port); |
408 | if (kr != KERN_SUCCESS0) |
409 | return THREAD_NULL((thread_t) 0); |
410 | |
411 | thread = convert_port_to_thread(kern_port); |
412 | if (IP_VALID(kern_port)(((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t ) 0)) && ((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t) -1)))) |
413 | ipc_port_release_send(kern_port); |
414 | |
415 | return thread; |
416 | } |
417 | } |
418 | |
419 | task_t |
420 | port_name_to_task(name) |
421 | mach_port_t name; |
422 | { |
423 | register ipc_port_t port; |
424 | |
425 | fast_send_right_lookup(name, port, goto abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 425); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; goto abort; } port = (ipc_port_t) entry-> ie_object; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)) )) Assert("port != IP_NULL", "../kern/ipc_mig.c", 425); }); ; ; }); |
426 | /* port is locked */ |
427 | |
428 | if (ip_active(port)((int)(&(port)->ip_target.ipt_object)->io_bits < 0) && |
429 | (ip_kotype(port)((&(port)->ip_target.ipt_object)->io_bits & 0x0000ffff ) == IKOT_TASK2)) { |
430 | register task_t task; |
431 | |
432 | task = (task_t) port->ip_kobject; |
433 | assert(task != TASK_NULL)({ if (!(task != ((task_t) 0))) Assert("task != TASK_NULL", "../kern/ipc_mig.c" , 433); }); |
434 | |
435 | task_lock(task); |
436 | /* can safely unlock port now that task is locked */ |
437 | ip_unlock(port); |
438 | |
439 | task->ref_count++; |
440 | task_unlock(task); |
441 | |
442 | return task; |
443 | } |
444 | |
445 | ip_unlock(port); |
446 | return TASK_NULL((task_t) 0); |
447 | |
448 | abort: { |
449 | task_t task; |
450 | ipc_port_t kern_port; |
451 | kern_return_t kr; |
452 | |
453 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), name, |
454 | MACH_MSG_TYPE_COPY_SEND19, |
455 | (ipc_object_t *) &kern_port); |
456 | if (kr != KERN_SUCCESS0) |
457 | return TASK_NULL((task_t) 0); |
458 | |
459 | task = convert_port_to_task(kern_port); |
460 | if (IP_VALID(kern_port)(((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t ) 0)) && ((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t) -1)))) |
461 | ipc_port_release_send(kern_port); |
462 | |
463 | return task; |
464 | } |
465 | } |
466 | |
467 | vm_map_t |
468 | port_name_to_map( |
469 | mach_port_t name) |
470 | { |
471 | register ipc_port_t port; |
472 | |
473 | fast_send_right_lookup(name, port, goto abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 473); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; goto abort; } port = (ipc_port_t) entry-> ie_object; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)) )) Assert("port != IP_NULL", "../kern/ipc_mig.c", 473); }); ; ; }); |
474 | /* port is locked */ |
475 | |
476 | if (ip_active(port)((int)(&(port)->ip_target.ipt_object)->io_bits < 0) && |
477 | (ip_kotype(port)((&(port)->ip_target.ipt_object)->io_bits & 0x0000ffff ) == IKOT_TASK2)) { |
478 | register vm_map_t map; |
479 | |
480 | map = ((task_t) port->ip_kobject)->map; |
481 | assert(map != VM_MAP_NULL)({ if (!(map != ((vm_map_t) 0))) Assert("map != VM_MAP_NULL", "../kern/ipc_mig.c", 481); }); |
482 | |
483 | simple_lock(&map->ref_lock); |
484 | /* can safely unlock port now that map is locked */ |
485 | ip_unlock(port); |
486 | |
487 | map->ref_count++; |
488 | simple_unlock(&map->ref_lock); |
489 | |
490 | return map; |
491 | } |
492 | |
493 | ip_unlock(port); |
494 | return VM_MAP_NULL((vm_map_t) 0); |
495 | |
496 | abort: { |
497 | vm_map_t map; |
498 | ipc_port_t kern_port; |
499 | kern_return_t kr; |
500 | |
501 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), name, |
502 | MACH_MSG_TYPE_COPY_SEND19, |
503 | (ipc_object_t *) &kern_port); |
504 | if (kr != KERN_SUCCESS0) |
505 | return VM_MAP_NULL((vm_map_t) 0); |
506 | |
507 | map = convert_port_to_map(kern_port); |
508 | if (IP_VALID(kern_port)(((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t ) 0)) && ((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t) -1)))) |
509 | ipc_port_release_send(kern_port); |
510 | |
511 | return map; |
512 | } |
513 | } |
514 | |
515 | ipc_space_t |
516 | port_name_to_space(name) |
517 | mach_port_t name; |
518 | { |
519 | register ipc_port_t port; |
520 | |
521 | fast_send_right_lookup(name, port, goto abort)({ register ipc_space_t space = (((active_threads[(0)])->task )->itk_space); register ipc_entry_t entry; register mach_port_index_t index = (name); ; ({ if (!(space->is_active)) Assert("space->is_active" , "../kern/ipc_mig.c", 521); }); if ((index >= space->is_table_size ) || (((entry = &space->is_table[index])->ie_bits & (0|((mach_port_type_t)(1 << ((((mach_port_right_t) 0)) +16))))) != (0 | ((mach_port_type_t)(1 << ((((mach_port_right_t ) 0))+16)))))) { ; goto abort; } port = (ipc_port_t) entry-> ie_object; ({ if (!(port != ((ipc_port_t) ((ipc_object_t) 0)) )) Assert("port != IP_NULL", "../kern/ipc_mig.c", 521); }); ; ; }); |
522 | /* port is locked */ |
523 | |
524 | if (ip_active(port)((int)(&(port)->ip_target.ipt_object)->io_bits < 0) && |
525 | (ip_kotype(port)((&(port)->ip_target.ipt_object)->io_bits & 0x0000ffff ) == IKOT_TASK2)) { |
526 | register ipc_space_t space; |
527 | |
528 | space = ((task_t) port->ip_kobject)->itk_space; |
529 | assert(space != IS_NULL)({ if (!(space != ((ipc_space_t) 0))) Assert("space != IS_NULL" , "../kern/ipc_mig.c", 529); }); |
530 | |
531 | simple_lock(&space->is_ref_lock_data); |
532 | /* can safely unlock port now that space is locked */ |
533 | ip_unlock(port); |
534 | |
535 | space->is_references++; |
536 | simple_unlock(&space->is_ref_lock_data); |
537 | |
538 | return space; |
539 | } |
540 | |
541 | ip_unlock(port); |
542 | return IS_NULL((ipc_space_t) 0); |
543 | |
544 | abort: { |
545 | ipc_space_t space; |
546 | ipc_port_t kern_port; |
547 | kern_return_t kr; |
548 | |
549 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), name, |
550 | MACH_MSG_TYPE_COPY_SEND19, |
551 | (ipc_object_t *) &kern_port); |
552 | if (kr != KERN_SUCCESS0) |
553 | return IS_NULL((ipc_space_t) 0); |
554 | |
555 | space = convert_port_to_space(kern_port); |
556 | if (IP_VALID(kern_port)(((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t ) 0)) && ((&(kern_port)->ip_target.ipt_object) != ((ipc_object_t) -1)))) |
557 | ipc_port_release_send(kern_port); |
558 | |
559 | return space; |
560 | } |
561 | } |
562 | |
563 | /* |
564 | * Hack to translate a thread port to a thread pointer for calling |
565 | * thread_get_state and thread_set_state. This is only necessary |
566 | * because the IPC message for these two operations overflows the |
567 | * kernel stack. |
568 | * |
569 | * AARGH! |
570 | */ |
571 | |
572 | kern_return_t thread_get_state_KERNEL(thread_port, flavor, |
573 | old_state, old_state_count) |
574 | mach_port_t thread_port; /* port right for thread */ |
575 | int flavor; |
576 | thread_state_t old_state; /* pointer to OUT array */ |
577 | natural_t *old_state_count; /* IN/OUT */ |
578 | { |
579 | thread_t thread; |
580 | kern_return_t result; |
581 | |
582 | thread = port_name_to_thread(thread_port); |
583 | result = thread_get_state(thread, flavor, old_state, old_state_count); |
584 | thread_deallocate(thread); |
585 | |
586 | return result; |
587 | } |
588 | |
589 | kern_return_t thread_set_state_KERNEL(thread_port, flavor, |
590 | new_state, new_state_count) |
591 | mach_port_t thread_port; /* port right for thread */ |
592 | int flavor; |
593 | thread_state_t new_state; |
594 | natural_t new_state_count; |
595 | { |
596 | thread_t thread; |
597 | kern_return_t result; |
598 | |
599 | thread = port_name_to_thread(thread_port); |
600 | result = thread_set_state(thread, flavor, new_state, new_state_count); |
601 | thread_deallocate(thread); |
602 | |
603 | return result; |
604 | } |
605 | |
606 | /* |
607 | * Things to keep in mind: |
608 | * |
609 | * The idea here is to duplicate the semantics of the true kernel RPC. |
610 | * The destination port/object should be checked first, before anything |
611 | * that the user might notice (like ipc_object_copyin). Return |
612 | * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub |
613 | * knows to fall back on an RPC. For other return values, it won't |
614 | * retry with an RPC. The retry might get a different (incorrect) rc. |
615 | * Return values are only set (and should only be set, with copyout) |
616 | * on successfull calls. |
617 | */ |
618 | |
619 | kern_return_t |
620 | syscall_vm_map( |
621 | mach_port_t target_map, |
622 | vm_offset_t *address, |
623 | vm_size_t size, |
624 | vm_offset_t mask, |
625 | boolean_t anywhere, |
626 | mach_port_t memory_object, |
627 | vm_offset_t offset, |
628 | boolean_t copy, |
629 | vm_prot_t cur_protection, |
630 | vm_prot_t max_protection, |
631 | vm_inherit_t inheritance) |
632 | { |
633 | vm_map_t map; |
634 | ipc_port_t port; |
635 | vm_offset_t addr; |
636 | kern_return_t result; |
637 | |
638 | map = port_name_to_map(target_map); |
639 | if (map == VM_MAP_NULL((vm_map_t) 0)) |
640 | return MACH_SEND_INTERRUPTED0x10000007; |
641 | |
642 | if (MACH_PORT_VALID(memory_object)(((memory_object) != ((mach_port_t) 0)) && ((memory_object ) != ((mach_port_t) ~0)))) { |
643 | result = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), memory_object, |
644 | MACH_MSG_TYPE_COPY_SEND19, |
645 | (ipc_object_t *) &port); |
646 | if (result != KERN_SUCCESS0) { |
647 | vm_map_deallocate(map); |
648 | return result; |
649 | } |
650 | } else |
651 | port = (ipc_port_t) memory_object; |
652 | |
653 | copyin((char *)address, (char *)&addr, sizeof(vm_offset_t)); |
654 | result = vm_map(map, &addr, size, mask, anywhere, |
655 | port, offset, copy, |
656 | cur_protection, max_protection, inheritance); |
657 | if (result == KERN_SUCCESS0) |
658 | copyout((char *)&addr, (char *)address, sizeof(vm_offset_t)); |
659 | if (IP_VALID(port)(((&(port)->ip_target.ipt_object) != ((ipc_object_t) 0 )) && ((&(port)->ip_target.ipt_object) != ((ipc_object_t ) -1)))) |
660 | ipc_port_release_send(port); |
661 | vm_map_deallocate(map); |
662 | |
663 | return result; |
664 | } |
665 | |
666 | kern_return_t syscall_vm_allocate(target_map, address, size, anywhere) |
667 | mach_port_t target_map; |
668 | vm_offset_t *address; |
669 | vm_size_t size; |
670 | boolean_t anywhere; |
671 | { |
672 | vm_map_t map; |
673 | vm_offset_t addr; |
674 | kern_return_t result; |
675 | |
676 | map = port_name_to_map(target_map); |
677 | if (map == VM_MAP_NULL((vm_map_t) 0)) |
678 | return MACH_SEND_INTERRUPTED0x10000007; |
679 | |
680 | copyin((char *)address, (char *)&addr, sizeof(vm_offset_t)); |
681 | result = vm_allocate(map, &addr, size, anywhere); |
682 | if (result == KERN_SUCCESS0) |
683 | copyout((char *)&addr, (char *)address, sizeof(vm_offset_t)); |
684 | vm_map_deallocate(map); |
685 | |
686 | return result; |
687 | } |
688 | |
689 | kern_return_t syscall_vm_deallocate(target_map, start, size) |
690 | mach_port_t target_map; |
691 | vm_offset_t start; |
692 | vm_size_t size; |
693 | { |
694 | vm_map_t map; |
695 | kern_return_t result; |
696 | |
697 | map = port_name_to_map(target_map); |
698 | if (map == VM_MAP_NULL((vm_map_t) 0)) |
699 | return MACH_SEND_INTERRUPTED0x10000007; |
700 | |
701 | result = vm_deallocate(map, start, size); |
702 | vm_map_deallocate(map); |
703 | |
704 | return result; |
705 | } |
706 | |
707 | kern_return_t syscall_task_create(parent_task, inherit_memory, child_task) |
708 | mach_port_t parent_task; |
709 | boolean_t inherit_memory; |
710 | mach_port_t *child_task; /* OUT */ |
711 | { |
712 | task_t t, c; |
713 | ipc_port_t port; |
714 | mach_port_t name; |
715 | kern_return_t result; |
716 | |
717 | t = port_name_to_task(parent_task); |
718 | if (t == TASK_NULL((task_t) 0)) |
719 | return MACH_SEND_INTERRUPTED0x10000007; |
720 | |
721 | result = task_create(t, inherit_memory, &c); |
722 | if (result == KERN_SUCCESS0) { |
723 | port = (ipc_port_t) convert_task_to_port(c); |
724 | /* always returns a name, even for non-success return codes */ |
725 | (void) ipc_kmsg_copyout_object(current_space()(((active_threads[(0)])->task)->itk_space), |
726 | (ipc_object_t) port, |
727 | MACH_MSG_TYPE_PORT_SEND17, &name); |
728 | copyout((char *)&name, (char *)child_task, |
729 | sizeof(mach_port_t)); |
730 | } |
731 | task_deallocate(t); |
732 | |
733 | return result; |
734 | } |
735 | |
736 | kern_return_t syscall_task_terminate(task) |
737 | mach_port_t task; |
738 | { |
739 | task_t t; |
740 | kern_return_t result; |
741 | |
742 | t = port_name_to_task(task); |
743 | if (t == TASK_NULL((task_t) 0)) |
744 | return MACH_SEND_INTERRUPTED0x10000007; |
745 | |
746 | result = task_terminate(t); |
747 | task_deallocate(t); |
748 | |
749 | return result; |
750 | } |
751 | |
752 | kern_return_t syscall_task_suspend(task) |
753 | mach_port_t task; |
754 | { |
755 | task_t t; |
756 | kern_return_t result; |
757 | |
758 | t = port_name_to_task(task); |
759 | if (t == TASK_NULL((task_t) 0)) |
760 | return MACH_SEND_INTERRUPTED0x10000007; |
761 | |
762 | result = task_suspend(t); |
763 | task_deallocate(t); |
764 | |
765 | return result; |
766 | } |
767 | |
768 | kern_return_t syscall_task_set_special_port(task, which_port, port_name) |
769 | mach_port_t task; |
770 | int which_port; |
771 | mach_port_t port_name; |
772 | { |
773 | task_t t; |
774 | ipc_port_t port; |
775 | kern_return_t result; |
776 | |
777 | t = port_name_to_task(task); |
778 | if (t == TASK_NULL((task_t) 0)) |
779 | return MACH_SEND_INTERRUPTED0x10000007; |
780 | |
781 | if (MACH_PORT_VALID(port_name)(((port_name) != ((mach_port_t) 0)) && ((port_name) != ((mach_port_t) ~0)))) { |
782 | result = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), port_name, |
783 | MACH_MSG_TYPE_COPY_SEND19, |
784 | (ipc_object_t *) &port); |
785 | if (result != KERN_SUCCESS0) { |
786 | task_deallocate(t); |
787 | return result; |
788 | } |
789 | } else |
790 | port = (ipc_port_t) port_name; |
791 | |
792 | result = task_set_special_port(t, which_port, port); |
793 | if ((result != KERN_SUCCESS0) && IP_VALID(port)(((&(port)->ip_target.ipt_object) != ((ipc_object_t) 0 )) && ((&(port)->ip_target.ipt_object) != ((ipc_object_t ) -1)))) |
794 | ipc_port_release_send(port); |
795 | task_deallocate(t); |
796 | |
797 | return result; |
798 | } |
799 | |
800 | kern_return_t |
801 | syscall_mach_port_allocate(task, right, namep) |
802 | mach_port_t task; |
803 | mach_port_right_t right; |
804 | mach_port_t *namep; |
805 | { |
806 | ipc_space_t space; |
807 | mach_port_t name; |
808 | kern_return_t kr; |
809 | |
810 | space = port_name_to_space(task); |
811 | if (space == IS_NULL((ipc_space_t) 0)) |
812 | return MACH_SEND_INTERRUPTED0x10000007; |
813 | |
814 | kr = mach_port_allocate(space, right, &name); |
815 | if (kr == KERN_SUCCESS0) |
816 | copyout((char *)&name, (char *)namep, sizeof(mach_port_t)); |
817 | is_release(space)ipc_space_release(space); |
818 | |
819 | return kr; |
820 | } |
821 | |
822 | kern_return_t |
823 | syscall_mach_port_allocate_name(task, right, name) |
824 | mach_port_t task; |
825 | mach_port_right_t right; |
826 | mach_port_t name; |
827 | { |
828 | ipc_space_t space; |
829 | kern_return_t kr; |
830 | |
831 | space = port_name_to_space(task); |
832 | if (space == IS_NULL((ipc_space_t) 0)) |
833 | return MACH_SEND_INTERRUPTED0x10000007; |
834 | |
835 | kr = mach_port_allocate_name(space, right, name); |
836 | is_release(space)ipc_space_release(space); |
837 | |
838 | return kr; |
839 | } |
840 | |
841 | kern_return_t |
842 | syscall_mach_port_deallocate(task, name) |
843 | mach_port_t task; |
844 | mach_port_t name; |
845 | { |
846 | ipc_space_t space; |
847 | kern_return_t kr; |
848 | |
849 | space = port_name_to_space(task); |
850 | if (space == IS_NULL((ipc_space_t) 0)) |
851 | return MACH_SEND_INTERRUPTED0x10000007; |
852 | |
853 | kr = mach_port_deallocate(space, name); |
854 | is_release(space)ipc_space_release(space); |
855 | |
856 | return kr; |
857 | } |
858 | |
859 | kern_return_t |
860 | syscall_mach_port_insert_right(task, name, right, rightType) |
861 | mach_port_t task; |
862 | mach_port_t name; |
863 | mach_port_t right; |
864 | mach_msg_type_name_t rightType; |
865 | { |
866 | ipc_space_t space; |
867 | ipc_object_t object; |
868 | mach_msg_type_name_t newtype; |
869 | kern_return_t kr; |
870 | |
871 | space = port_name_to_space(task); |
872 | if (space == IS_NULL((ipc_space_t) 0)) |
873 | return MACH_SEND_INTERRUPTED0x10000007; |
874 | |
875 | if (!MACH_MSG_TYPE_PORT_ANY(rightType)(((rightType) >= 16) && ((rightType) <= 21))) { |
876 | is_release(space)ipc_space_release(space); |
877 | return KERN_INVALID_VALUE18; |
878 | } |
879 | |
880 | if (MACH_PORT_VALID(right)(((right) != ((mach_port_t) 0)) && ((right) != ((mach_port_t ) ~0)))) { |
881 | kr = ipc_object_copyin(current_space()(((active_threads[(0)])->task)->itk_space), right, rightType, |
882 | &object); |
883 | if (kr != KERN_SUCCESS0) { |
884 | is_release(space)ipc_space_release(space); |
885 | return kr; |
886 | } |
887 | } else |
888 | object = (ipc_object_t) right; |
889 | newtype = ipc_object_copyin_type(rightType); |
890 | |
891 | kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype); |
892 | if ((kr != KERN_SUCCESS0) && IO_VALID(object)(((object) != ((ipc_object_t) 0)) && ((object) != ((ipc_object_t ) -1)))) |
893 | ipc_object_destroy(object, newtype); |
894 | is_release(space)ipc_space_release(space); |
895 | |
896 | return kr; |
897 | } |
898 | |
899 | kern_return_t syscall_thread_depress_abort(thread) |
900 | mach_port_t thread; |
901 | { |
902 | thread_t t; |
903 | kern_return_t result; |
904 | |
905 | t = port_name_to_thread(thread); |
906 | if (t == THREAD_NULL((thread_t) 0)) |
907 | return MACH_SEND_INTERRUPTED0x10000007; |
908 | |
909 | result = thread_depress_abort(t); |
910 | thread_deallocate(t); |
911 | |
912 | return result; |
913 | } |
914 | |
915 | /* |
916 | * Device traps -- these are way experimental. |
917 | */ |
918 | |
919 | extern io_return_t ds_device_write_trap(); |
920 | extern io_return_t ds_device_writev_trap(); |
921 | |
922 | io_return_t |
923 | syscall_device_write_request(mach_port_t device_name, |
924 | mach_port_t reply_name, |
925 | dev_mode_t mode, |
926 | recnum_t recnum, |
927 | vm_offset_t data, |
928 | vm_size_t data_count) |
929 | { |
930 | device_t dev; |
931 | /*ipc_port_t reply_port;*/ |
932 | io_return_t res; |
933 | |
934 | /* |
935 | * First try to translate the device name. |
936 | * |
937 | * If this fails, return KERN_INVALID_CAPABILITY. |
938 | * Caller knows that this most likely means that |
939 | * device is not local to node and IPC should be used. |
940 | * |
941 | * If kernel doesn't do device traps, kern_invalid() |
942 | * will be called instead of this function which will |
943 | * return KERN_INVALID_ARGUMENT. |
944 | */ |
945 | dev = port_name_to_device(device_name); |
946 | if (dev == DEVICE_NULL((device_t) 0)) |
947 | return KERN_INVALID_CAPABILITY20; |
948 | |
949 | /* |
950 | * Translate reply port. |
951 | */ |
952 | /*if (reply_name == MACH_PORT_NULL) |
953 | reply_port = IP_NULL; |
954 | */ |
955 | if (reply_name != MACH_PORT_NULL((mach_port_t) 0)) { |
956 | /* Homey don't play that. */ |
957 | device_deallocate(dev); |
958 | return KERN_INVALID_RIGHT17; |
959 | } |
960 | |
961 | /* note: doesn't take reply_port arg yet. */ |
962 | res = ds_device_write_trap(dev, /*reply_port,*/ |
963 | mode, recnum, |
964 | data, data_count); |
965 | |
966 | /* |
967 | * Give up reference from port_name_to_device. |
968 | */ |
969 | device_deallocate(dev); |
970 | return res; |
971 | } |
972 | |
973 | io_return_t |
974 | syscall_device_writev_request(mach_port_t device_name, |
975 | mach_port_t reply_name, |
976 | dev_mode_t mode, |
977 | recnum_t recnum, |
978 | io_buf_vec_t *iovec, |
979 | vm_size_t iocount) |
980 | { |
981 | device_t dev; |
982 | ipc_port_t reply_port; |
983 | io_return_t res; |
984 | |
985 | /* |
986 | * First try to translate the device name. |
987 | * |
988 | * If this fails, return KERN_INVALID_CAPABILITY. |
989 | * Caller knows that this most likely means that |
990 | * device is not local to node and IPC should be used. |
991 | * |
992 | * If kernel doesn't do device traps, kern_invalid() |
993 | * will be called instead of this function which will |
994 | * return KERN_INVALID_ARGUMENT. |
995 | */ |
996 | dev = port_name_to_device(device_name); |
997 | if (dev == DEVICE_NULL((device_t) 0)) |
998 | return KERN_INVALID_CAPABILITY20; |
999 | |
1000 | /* |
1001 | * Translate reply port. |
1002 | */ |
1003 | if (reply_name == MACH_PORT_NULL((mach_port_t) 0)) |
1004 | reply_port = IP_NULL((ipc_port_t) ((ipc_object_t) 0)); |
Value stored to 'reply_port' is never read | |
1005 | else { |
1006 | /* Homey don't play that. */ |
1007 | device_deallocate(dev); |
1008 | return KERN_INVALID_RIGHT17; |
1009 | } |
1010 | |
1011 | /* note: doesn't take reply_port arg yet. */ |
1012 | res = ds_device_writev_trap(dev, /*reply_port,*/ |
1013 | mode, recnum, |
1014 | iovec, iocount); |
1015 | |
1016 | /* |
1017 | * Give up reference from port_name_to_device. |
1018 | */ |
1019 | device_deallocate(dev); |
1020 | return res; |
1021 | } |