Bug Summary

File:obj/../kern/ipc_mig.c
Location:line 1004, column 3
Description:Value stored to 'reply_port' is never read

Annotated Source Code

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
71mach_msg_return_t
72mach_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
92mach_msg_return_t
93mach_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
111void
112mach_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
142mach_msg_return_t
143mach_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
233mach_port_t
234mig_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
252void
253mig_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 */
265void
266mig_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 */
287void mig_strncpy(dest, src, len)
288char *dest, *src;
289int 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); }); ; ; })
\({
305MACRO_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); \})
327MACRO_END})
328
329device_t
330port_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
373thread_t
374port_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
419task_t
420port_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
467vm_map_t
468port_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
515ipc_space_t
516port_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
572kern_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
589kern_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
619kern_return_t
620syscall_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
666kern_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
689kern_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
707kern_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
736kern_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
752kern_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
768kern_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
800kern_return_t
801syscall_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
822kern_return_t
823syscall_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
841kern_return_t
842syscall_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
859kern_return_t
860syscall_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
899kern_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
919extern io_return_t ds_device_write_trap();
920extern io_return_t ds_device_writev_trap();
921
922io_return_t
923syscall_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
973io_return_t
974syscall_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}