Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/compat/mach When a task to task message carries ports, t...
details: https://anonhg.NetBSD.org/src/rev/a35dbfeff2fb
branches: trunk
changeset: 556142:a35dbfeff2fb
user: manu <manu%NetBSD.org@localhost>
date: Sun Dec 07 23:44:14 2003 +0000
description:
When a task to task message carries ports, translate the port names into the
receiver namespace.
While we are there, refactor mach_msg_overwrite by splitting it into
several smaller functions. It had grown too big to be easily maintainable.
diffstat:
sys/compat/mach/mach_message.c | 1258 ++++++++++++++++++++-------------------
sys/compat/mach/mach_message.h | 12 +-
2 files changed, 666 insertions(+), 604 deletions(-)
diffs (truncated from 1393 to 300 lines):
diff -r 3e226cc603a0 -r a35dbfeff2fb sys/compat/mach/mach_message.c
--- a/sys/compat/mach/mach_message.c Sun Dec 07 23:16:03 2003 +0000
+++ b/sys/compat/mach/mach_message.c Sun Dec 07 23:44:14 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mach_message.c,v 1.33 2003/12/03 18:18:43 manu Exp $ */
+/* $NetBSD: mach_message.c,v 1.34 2003/12/07 23:44:14 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.33 2003/12/03 18:18:43 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.34 2003/12/07 23:44:14 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
@@ -70,7 +70,17 @@
/* Mach message pool */
static struct pool mach_message_pool;
-static struct lwp *mach_get_target_task(struct lwp *, struct mach_port *);
+static inline
+ int mach_msg_send(struct lwp *, mach_msg_header_t *, int *, size_t);
+static inline int mach_msg_recv(struct lwp *, mach_msg_header_t *,
+ int, size_t, unsigned int, mach_port_t);
+static inline
+ struct lwp *mach_get_target_task(struct lwp *, struct mach_port *);
+static inline void mach_drop_rights(struct mach_right *, int);
+static inline
+ void mach_trade_rights(struct lwp *, struct lwp *, mach_port_t *, int);
+static inline
+ int mach_trade_rights_complex(struct lwp *, struct mach_message *);
int
mach_sys_msg_overwrite_trap(l, v, retval)
@@ -89,672 +99,569 @@
syscallarg(mach_msg_header_t *) rcv_msg;
syscallarg(mach_msg_size_t) scatter_list_size;
} */ *uap = v;
- struct mach_emuldata *med;
- struct mach_port *mp;
- struct proc *p = l->l_proc;
- size_t send_size, rcv_size;
- int error = 0;
+ size_t send_size, recv_size;
+ mach_msg_header_t *msg;
+ int opt;
- *retval = 0;
-
+ *retval = MACH_MSG_SUCCESS;
send_size = SCARG(uap, send_size);
- rcv_size = SCARG(uap, rcv_size);
+ recv_size = SCARG(uap, rcv_size);
+ opt = SCARG(uap, option);
/* XXX not safe enough: lots of big messages will kill us */
if (send_size > MACH_MAX_MSG_LEN) {
*retval = MACH_SEND_TOO_LARGE;
return 0;
}
- if (rcv_size > MACH_MAX_MSG_LEN) {
+ if (recv_size > MACH_MAX_MSG_LEN) {
*retval = MACH_RCV_TOO_LARGE;
return 0;
}
-
/*
* Two options: receive or send. If both are
* set, we must send, and then receive. If
* send fail, then we skip recieve.
*/
- if (SCARG(uap, option) & MACH_SEND_MSG) {
- mach_msg_header_t *sm;
- struct mach_service *srv;
- mach_port_t ln;
- mach_port_t rn;
- struct mach_right *lr = NULL;
- struct mach_right *rr;
- int bits, rights;
-
- if (SCARG(uap, msg) == NULL) {
- *retval = MACH_SEND_INVALID_DATA;
- return 0;
- }
-
- /*
- * Allocate memory for the message and its reply,
- * and copy the whole message in the kernel.
- */
- sm = malloc(send_size, M_EMULDATA, M_WAITOK);
- if ((error = copyin(SCARG(uap, msg), sm, send_size)) != 0) {
- *retval = MACH_SEND_INVALID_DATA;
- goto out1;
- }
-
-#ifdef KTRACE
- /* Dump the Mach message */
- if (KTRPOINT(p, KTR_MMSG))
- ktrmmsg(p, (char *)sm, send_size);
-#endif
- /*
- * Handle rights in the message
- */
- ln = sm->msgh_local_port;
- rn = sm->msgh_remote_port;
-
- lr = mach_right_check(ln, l, MACH_PORT_TYPE_ALL_RIGHTS);
- rr = mach_right_check(rn, l, MACH_PORT_TYPE_ALL_RIGHTS);
- if ((rr == NULL) || (rr->mr_port == NULL)) {
-#ifdef DEBUG_MACH
- printf("msg id %d: invalid dest\n", sm->msgh_id);
-#endif
- *retval = MACH_SEND_INVALID_DEST;
- goto out1;
- }
-
- /*
- * Check that the process has send a send right on
- * the remote port.
- */
- rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_SEND_ONCE);
- if (mach_right_check(rn, l, rights) == NULL) {
- *retval = MACH_SEND_INVALID_RIGHT;
- goto out1;
- }
-
- /*
- * If the remote port is a special port (host, kernel,
- * clock, or io_master), the message will be handled
- * by the kernel.
- */
- med = (struct mach_emuldata *)p->p_emuldata;
- mp = rr->mr_port;
- if (mp->mp_flags & MACH_MP_INKERNEL) {
- struct mach_trap_args args;
- mach_msg_header_t *rm;
- size_t min_reqlen, max_replen;
-
- /*
- * Look for the function that will handle it,
- * using the message id.
- */
- for (srv = mach_services_table; srv->srv_id; srv++)
- if (srv->srv_id == sm->msgh_id)
- break;
-
- /*
- * If no match, give up, and display a warning.
- */
- if (srv->srv_handler == NULL) {
- uprintf("No mach server for id = %d\n",
- sm->msgh_id);
- *retval = MACH_SEND_INVALID_DEST;
- goto out1;
- }
- min_reqlen = srv->srv_reqlen;
- max_replen = srv->srv_replen;
-
- /*
- * Special case when the kernel behaves as
- * the client: replies to exceptions and
- * notifications. There will be no reply,
- * as we already receive a reply.
- * - request and reply are swapped
- * - there will be no reply, so set lr to NULL.
- * - skip the lr == NULL tests
- * XXX This is inelegant.
- */
- if ((sm->msgh_id >= 2501) && (sm->msgh_id <= 2503)) {
- min_reqlen = srv->srv_replen;
- max_replen = srv->srv_reqlen;
- lr = NULL;
- goto skip_null_lr;
- }
-
- /*
- * Check that the local port is valid, else
- * we will not be able to send the reply
- */
- if ((lr == NULL) ||
- (lr->mr_port == NULL) ||
- (lr->mr_port->mp_recv == NULL)) {
-#ifdef DEBUG_MACH
- printf("msg id %d: invalid src\n", sm->msgh_id);
-#endif
- *retval = MACH_SEND_INVALID_REPLY;
- goto out1;
- }
-skip_null_lr:
-
- /*
- * Sanity check message length. We do not want the
- * server to:
- * 1) use kernel memory located after
- * the end of the request message.
- */
- if (send_size < min_reqlen) {
-#ifdef DEBUG_MACH
- printf("mach server %s: smsg overflow: "
- "send = %d, min = %d\n",
- srv->srv_name, send_size, min_reqlen);
-#endif
- *retval = MACH_SEND_MSG_TOO_SMALL;
- goto out1;
- }
-
- /*
- * 2) give away random kernel data to the user program
- * when the reply message is copied out.
- */
- if (rcv_size > max_replen) {
-#ifdef DEBUG_MACH
- printf("mach server %s: rmsg overflow: "
- "recv = %d, max = %d\n",
- srv->srv_name, rcv_size, max_replen);
-#endif
- rcv_size = max_replen;
- }
-
- /*
- * 3) Overwrite kernel memory after the end of the
- * reply message buffer. This check is the
- * responsability of the server.
- */
-
+ msg = SCARG(uap, msg);
+ if (opt & MACH_SEND_MSG)
+ *retval = mach_msg_send(l, msg, &opt, send_size);
- /*
- * Invoke the server. We give it the opportunity
- * to shorten rcv_size if there is less data in
- * the reply than what the sender expected.
- * If lr is NULL, this is a no reply operation.
- */
- if (lr != NULL)
- rm = malloc(max_replen,
- M_EMULDATA, M_WAITOK | M_ZERO);
- else
- rm = NULL;
-
- args.l = l;
- args.tl = mach_get_target_task(l, mp);
- args.smsg = sm;
- args.rmsg = rm;
- args.rsize = &rcv_size;
- args.ssize = send_size;
- if ((*retval = (*srv->srv_handler)(&args)) != 0)
- goto out1;
-
- /*
- * No-reply opration: everything is done.
- */
- if (lr == NULL)
- goto out1;
-
-#ifdef DIAGNOSTIC
- /*
- * Catch potential bug in the server (sanity
- * check #3): did it output a larger message
- * then the one that was allocated?
- */
- if ((SCARG(uap, option) & MACH_RCV_MSG) &&
- (rcv_size > max_replen)) {
- uprintf("mach_msg: reply too big in %s\n",
- srv->srv_name);
- }
-#endif
-
- /*
- * Queue the reply
- */
- mp = lr->mr_port;
- (void)mach_message_get(rm, rcv_size, mp, NULL);
-#ifdef DEBUG_MACH_MSG
- printf("pid %d: message queued on port %p (%d) [%p]\n",
- p->p_pid, mp, rm->msgh_id,
- mp->mp_recv->mr_sethead);
- if (sm->msgh_id == 404)
- printf("*** msg to bootstrap. port = %p, "
- "recv = %p [%p]\n", mach_bootstrap_port,
- mach_bootstrap_port->mp_recv,
- mach_bootstrap_port->mp_recv->mr_sethead);
-#endif
- wakeup(mp->mp_recv->mr_sethead);
- *retval = 0;
-out1:
- free(sm, M_EMULDATA);
- /*
- * Skip the recieve part and return now if
- * - there has been an error in the send part
- * - this is a no-reply operation (lr == NULL)
- */
- if ((*retval != 0) || (lr == NULL))
- return 0;
-
Home |
Main Index |
Thread Index |
Old Index