A better implementation of right carried by messages. We now correctly create

the right in the destination process.

This is a small step backward for functionnality: vi does not work anymore
because our right checks cause some spurious errors, but this will be fixed
later.
This commit is contained in:
manu 2003-01-02 12:46:06 +00:00
parent 050140988d
commit 2c04ce0604
6 changed files with 267 additions and 225 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_bootstrap.c,v 1.3 2002/12/17 18:42:55 manu Exp $ */
/* $NetBSD: mach_bootstrap.c,v 1.4 2003/01/02 12:46:06 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_bootstrap.c,v 1.3 2002/12/17 18:42:55 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_bootstrap.c,v 1.4 2003/01/02 12:46:06 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: mach_bootstrap.c,v 1.3 2002/12/17 18:42:55 manu Exp
#include <compat/mach/mach_types.h>
#include <compat/mach/mach_message.h>
#include <compat/mach/mach_port.h>
#include <compat/mach/mach_bootstrap.h>
#include <compat/mach/mach_errno.h>
@ -56,9 +57,11 @@ mach_bootstrap_look_up(args)
{
mach_bootstrap_look_up_request_t *req = args->smsg;
mach_bootstrap_look_up_reply_t *rep = args->rmsg;
struct proc *p = args->p;
size_t *msglen = args->rsize;
const char service_name[] = "lookup\21"; /* XXX Why */
int service_name_len;
struct mach_right *mr;
/* The trailer is word aligned */
service_name_len = (sizeof(service_name) + 1) & ~0x7UL;
@ -66,6 +69,8 @@ mach_bootstrap_look_up(args)
sizeof(rep->rep_bootstrap_port) + service_name_len *
sizeof(rep->rep_trailer);
mr = mach_right_get(NULL, p, MACH_PORT_TYPE_DEAD_NAME, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
@ -73,7 +78,7 @@ mach_bootstrap_look_up(args)
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_count = 1; /* XXX Why? */
rep->rep_bootstrap_port = 0x21b; /* XXX Why? */
rep->rep_bootstrap_port = mr->mr_name;
strcpy((char *)&rep->rep_service_name, service_name);
/* XXX This is the trailer. We should find something better */
rep->rep_service_name[service_name_len + 7] = 8;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exec.c,v 1.22 2003/01/01 15:18:25 manu Exp $ */
/* $NetBSD: mach_exec.c,v 1.23 2003/01/02 12:46:06 manu Exp $ */
/*-
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.22 2003/01/01 15:18:25 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.23 2003/01/02 12:46:06 manu Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -231,7 +231,13 @@ mach_e_proc_init(p, vmspace)
med->med_p = 0;
LIST_INIT(&med->med_right);
med->med_nextright = 0x60b;
/*
* For debugging purpose, it's convenient to have each process
* using distinct port names, so we prefix the first port name
* by the PID. Darwin does not do that, but we can remove it
* when we want, it will not hurt.
*/
med->med_nextright = p->p_pid << 16;
med->med_kernel = mach_port_get();
med->med_host = mach_port_get();
@ -261,7 +267,7 @@ mach_e_proc_exit(p)
lockmgr(&mach_right_list_lock, LK_EXCLUSIVE, NULL);
while ((mr = LIST_FIRST(&med->med_right)) != NULL)
mach_right_put_exclocked(mr);
mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
lockmgr(&mach_right_list_lock, LK_RELEASE, NULL);
if (--med->med_bootstrap->mp_refcount == 0)

View File

@ -1,7 +1,7 @@
/* $NetBSD: mach_message.c,v 1.18 2002/12/31 15:47:37 manu Exp $ */
/* $NetBSD: mach_message.c,v 1.19 2003/01/02 12:46:06 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.18 2002/12/31 15:47:37 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.19 2003/01/02 12:46:06 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
@ -70,9 +70,6 @@ __KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.18 2002/12/31 15:47:37 manu Exp $
/* Mach message pool */
static struct pool mach_message_pool;
static int mach_move_right(int, mach_msg_header_t *, struct mach_right *,
struct mach_right *, struct proc *);
int
mach_sys_msg_overwrite_trap(p, v, retval)
struct proc *p;
@ -92,10 +89,11 @@ mach_sys_msg_overwrite_trap(p, v, retval)
} */ *uap = v;
struct mach_emuldata *med;
struct mach_port *mp;
struct mach_right *mr;
size_t send_size, rcv_size;
int error = 0;
*retval = 0;
send_size = SCARG(uap, send_size);
rcv_size = SCARG(uap, rcv_size);
@ -150,9 +148,8 @@ mach_sys_msg_overwrite_trap(p, v, retval)
ln = sm->msgh_local_port;
rn = sm->msgh_remote_port;
lr = mach_right_check_all(ln, MACH_PORT_TYPE_ALL_RIGHTS);
rr = mach_right_check_all(rn, MACH_PORT_TYPE_ALL_RIGHTS);
lr = mach_right_check(ln, p, MACH_PORT_TYPE_ALL_RIGHTS);
rr = mach_right_check(rn, p, MACH_PORT_TYPE_ALL_RIGHTS);
if (rr == NULL) {
#ifdef DEBUG_MACH
printf("msg id %d: invalid dest\n", sm->msgh_id);
@ -161,13 +158,6 @@ mach_sys_msg_overwrite_trap(p, v, retval)
goto out1;
}
bits = MACH_MSGH_LOCAL_BITS(sm->msgh_bits);
if ((*retval = mach_move_right(bits, sm, lr, rr, p)) != 0)
goto out1;
bits = MACH_MSGH_REMOTE_BITS(sm->msgh_bits);
if ((*retval = mach_move_right(bits, sm, rr, rr, p)) != 0)
goto out1;
/*
* Check that the process has send a send right on
@ -191,6 +181,15 @@ mach_sys_msg_overwrite_trap(p, v, retval)
struct mach_trap_args args;
mach_msg_header_t *rm;
/*
* Check that the local port is valid, else
* we will not be able to send the reply
*/
if (lr == NULL) {
*retval = MACH_SEND_INVALID_REPLY;
goto out3;
}
/*
* Look for the function that will handle it,
* using the message id.
@ -248,7 +247,7 @@ mach_sys_msg_overwrite_trap(p, v, retval)
* Queue the reply
*/
mp = lr->mr_port;
(void)mach_message_get(rm, rcv_size, mp);
(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,
@ -265,28 +264,69 @@ out3: free(sm, M_EMULDATA);
} else {
/*
* The message is not to be handled by the kernel.
* First, swap local and remote ports.
*/
sm->msgh_local_port = rn;
sm->msgh_remote_port = ln;
/*
* Queue the message in the remote port, and wakeup
* any process that would be sleeping for it.
* Queue the message in the remote port.
*/
mp = rr->mr_port;
(void)mach_message_get(sm, send_size, mp);
(void)mach_message_get(sm, send_size, mp, p);
#ifdef DEBUG_MACH_MSG
printf("pid %d: message queued on port %p (%d) [%p]\n",
p->p_pid, mp, sm->msgh_id,
mp->mp_recv->mr_sethead);
#endif
/*
* Drop any right carried by the message
*/
bits = MACH_MSGH_LOCAL_BITS(sm->msgh_bits);
switch (bits) {
case MACH_MSG_TYPE_MOVE_SEND:
rights = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
rights = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_RECEIVE:
rights = MACH_PORT_TYPE_RECEIVE;
break;
case MACH_MSG_TYPE_MAKE_SEND:
case MACH_MSG_TYPE_COPY_SEND:
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
default:
rights = 0;
break;
}
if ((lr != NULL) && (rights != 0))
mach_right_put(lr, rights);
bits = MACH_MSGH_REMOTE_BITS(sm->msgh_bits);
switch (bits) {
case MACH_MSG_TYPE_MOVE_SEND:
rights = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
rights = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_RECEIVE:
rights = MACH_PORT_TYPE_RECEIVE;
break;
case MACH_MSG_TYPE_MAKE_SEND:
case MACH_MSG_TYPE_COPY_SEND:
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
default:
rights = 0;
break;
}
if ((rr != NULL) && (rights != 0))
mach_right_put(rr, rights);
/*
* Wakeup any process awaiting for this message
*/
wakeup(mp->mp_recv->mr_sethead);
}
out1:
if (error != 0) {
if (*retval != 0) {
free(sm, M_EMULDATA);
return 0;
}
@ -298,9 +338,13 @@ out1:
if (SCARG(uap, option) & MACH_RCV_MSG) {
struct mach_message *mm;
mach_port_t mn;
mach_port_t tmp;
struct mach_right *cmr;
struct mach_right *mr;
struct mach_right *nmr;
mach_msg_header_t *urm;
int timeout;
int bits, nr, or;
/*
* Find a buffer for the reply
@ -495,6 +539,124 @@ out1:
goto unlock;
}
/*
* Get rights carried by the message if it is not a
* reply from the kernel.
*/
if (mm->mm_p != NULL) {
#ifdef DEBUG_MACH
printf("mach_msg: non kernel-reply message\n");
#endif
bits = MACH_MSGH_LOCAL_BITS(mm->mm_msg->msgh_bits);
switch (bits) {
case MACH_MSG_TYPE_MAKE_SEND:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_COPY_SEND:
case MACH_MSG_TYPE_MOVE_SEND:
or = MACH_PORT_TYPE_SEND;
nr = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
or = MACH_PORT_TYPE_SEND_ONCE;
nr = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_RECEIVE:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_RECEIVE;
break;
default:
or = 0;
nr = 0;
break;
}
mr = NULL;
if (nr != 0) {
mn = mm->mm_msg->msgh_local_port;
mr = mach_right_check(mn, mm->mm_p, or);
}
if (mr != NULL) {
nmr = mach_right_get(mr->mr_port, p, nr, 0);
mm->mm_msg->msgh_local_port = nmr->mr_name;
} else {
mm->mm_msg->msgh_local_port = 0;
}
bits = MACH_MSGH_REMOTE_BITS(mm->mm_msg->msgh_bits);
switch (bits) {
case MACH_MSG_TYPE_MAKE_SEND:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_COPY_SEND:
case MACH_MSG_TYPE_MOVE_SEND:
or = MACH_PORT_TYPE_SEND;
nr = MACH_PORT_TYPE_SEND;
break;
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
or = MACH_PORT_TYPE_SEND_ONCE;
nr = MACH_PORT_TYPE_SEND_ONCE;
break;
case MACH_MSG_TYPE_MOVE_RECEIVE:
or = MACH_PORT_TYPE_RECEIVE;
nr = MACH_PORT_TYPE_RECEIVE;
break;
default:
or = 0;
nr = 0;
break;
}
mr = NULL;
if (nr != 0) {
mn = mm->mm_msg->msgh_remote_port;
mr = mach_right_check(mn, mm->mm_p, or);
}
if (mr != NULL) {
nmr = mach_right_get(mr->mr_port, p, nr, 0);
mm->mm_msg->msgh_remote_port = nmr->mr_name;
} else {
mm->mm_msg->msgh_remote_port = 0;
}
/*
* swap local and remote ports, and
* corresponding bits as well.
*/
bits = (bits & 0xffff0000) |
((bits & 0xff00) >> 8) |
((bits & 0x00ff) << 8);
tmp = mm->mm_msg->msgh_remote_port;
mm->mm_msg->msgh_remote_port =
mm->mm_msg->msgh_local_port;
mm->mm_msg->msgh_local_port = tmp;
}
/*
* Copy the message to userland
*/
if ((error = copyout(mm->mm_msg, urm, mm->mm_size)) != 0) {
*retval = MACH_RCV_INVALID_DATA;
goto unlock;
@ -553,10 +715,11 @@ mach_message_init(void)
}
struct mach_message *
mach_message_get(msgh, size, mp)
mach_message_get(msgh, size, mp, p)
mach_msg_header_t *msgh;
size_t size;
struct mach_port *mp;
struct proc *p;
{
struct mach_message *mm;
@ -565,6 +728,7 @@ mach_message_get(msgh, size, mp)
mm->mm_msg = msgh;
mm->mm_size = size;
mm->mm_port = mp;
mm->mm_p = p;
lockmgr(&mp->mp_msglock, LK_EXCLUSIVE, NULL);
TAILQ_INSERT_TAIL(&mp->mp_msglist, mm, mm_list);
@ -620,137 +784,6 @@ mach_message_put_exclocked(mm)
return;
}
/*
* Move port according to what was specified in the message.
*/
static int
mach_move_right(bits, msgh, mr, tr, p)
int bits;
mach_msg_header_t *msgh;
struct mach_right *mr;
struct mach_right *tr;
struct proc *p;
{
struct mach_right *nmr;
struct mach_port *mp;
mach_port_t mn;
struct proc *tp;
int rights;
if (mr == NULL) {
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right: mr = NULL\n");
#endif
return 0;
}
if ((tr->mr_port == NULL) ||
(tr->mr_port->mp_recv == NULL) ||
(tr->mr_port->mp_recv->mr_p == NULL)) {
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right: cannot find target proc, "
"msg id %d, tr = %p, tr->mr_port = %p ",
msgh->msgh_id, tr, tr->mr_port);
if (tr->mr_port == NULL)
goto cr;
printf("tr->mr_port->mp_recv = %p ",
tr->mr_port->mp_recv);
if (tr->mr_port->mp_recv == NULL)
goto cr;
printf("tr->mr_port->mp_recv->mr_p = %p ",
tr->mr_port->mp_recv->mr_p);
cr:
printf("\n");
#endif
return 0;
}
tp = tr->mr_port->mp_recv->mr_p;
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right: msg id %d, local pid = %d, target pid = %d\n",
msgh->msgh_id, p->p_pid, tp->p_pid);
#endif
switch (bits) {
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
case MACH_MSG_TYPE_MAKE_SEND:
case MACH_MSG_TYPE_MOVE_RECEIVE:
rights = MACH_PORT_TYPE_RECEIVE;
break;
case MACH_MSG_TYPE_COPY_SEND:
rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_DEAD_NAME);
break;
case MACH_MSG_TYPE_MOVE_SEND:
rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_DEAD_NAME);
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
rights = (MACH_PORT_TYPE_SEND_ONCE | MACH_PORT_TYPE_DEAD_NAME);
break;
default:
return MACH_SEND_INVALID_HEADER;
break;
}
if ((mr->mr_type & rights) == 0) {
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right: right %x missing for %p in pid %d\n",
rights, mr, p->p_pid);
#endif
return 0;
}
mp = mr->mr_port;
mn = mr->mr_name;
switch (bits) {
case MACH_MSG_TYPE_MAKE_SEND:
case MACH_MSG_TYPE_COPY_SEND:
nmr = mach_right_get(mp, tp, MACH_PORT_TYPE_SEND, mn);
break;
case MACH_MSG_TYPE_MOVE_SEND:
nmr = mach_right_get(mp, tp, MACH_PORT_TYPE_SEND, mn);
/* mach_right_put(mr); */
break;
case MACH_MSG_TYPE_MAKE_SEND_ONCE:
nmr = mach_right_get(mp, tp, MACH_PORT_TYPE_SEND_ONCE, mn);
break;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
nmr = mach_right_get(mp, tp, MACH_PORT_TYPE_SEND_ONCE, mn);
/* mach_right_put(mr); */
break;
case MACH_MSG_TYPE_MOVE_RECEIVE:
nmr = mach_right_get(mp, tp, MACH_PORT_TYPE_RECEIVE, mn);
mach_right_put(mr);
break;
default:
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right, invalid bits = %d\n", bits);
#endif
return MACH_SEND_INVALID_HEADER;
break;
}
#ifdef DEBUG_MACH_RIGHT
printf("mach_move_right finished, nmr = %p(%x)", nmr, nmr->mr_type);
if (nmr->mr_port != NULL)
printf("=>%p", nmr->mr_port);
if (nmr->mr_port->mp_recv != NULL)
printf("[%p]", nmr->mr_port->mp_recv->mr_sethead);
printf("\n");
#endif
return 0;
}
#ifdef DEBUG_MACH
void
mach_debug_message(void)

View File

@ -1,11 +1,11 @@
/* $NetBSD: mach_message.h,v 1.12 2002/12/30 18:44:33 manu Exp $ */
/* $NetBSD: mach_message.h,v 1.13 2003/01/02 12:46:07 manu Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
* by Christos Zoulas and Emmanuel Dreyfus.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -223,11 +223,12 @@ struct mach_message {
TAILQ_ENTRY(mach_message) mm_list;
/* List of pending messages */
struct mach_port *mm_port; /* The port on which msg is queued */
struct proc *mm_p; /* The process that sent it */
};
void mach_message_init(void);
struct mach_message *mach_message_get(mach_msg_header_t *,
size_t, struct mach_port *);
size_t, struct mach_port *, struct proc *);
void mach_message_put(struct mach_message *);
void mach_message_put_shlocked(struct mach_message *);
void mach_message_put_exclocked(struct mach_message *);

View File

@ -1,7 +1,7 @@
/* $NetBSD: mach_port.c,v 1.28 2002/12/31 15:47:38 manu Exp $ */
/* $NetBSD: mach_port.c,v 1.29 2003/01/02 12:46:07 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -39,7 +39,7 @@
#include "opt_compat_darwin.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.28 2002/12/31 15:47:38 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.29 2003/01/02 12:46:07 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -155,7 +155,7 @@ mach_port_deallocate(args)
if ((mr = mach_right_check(mn, p, MACH_PORT_TYPE_PORT_RIGHTS)) == NULL)
return mach_msg_error(args, EINVAL);
mach_right_put(mr);
mach_right_put(mr, MACH_PORT_TYPE_ALL_RIGHTS);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
@ -280,7 +280,7 @@ mach_port_type(args)
struct mach_right *mr;
mn = req->req_name;
if ((mr = mach_right_check(mn, p, MACH_PORT_TYPE_PORT_RIGHTS)) == NULL)
if ((mr = mach_right_check(mn, p, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_msg_error(args, EPERM);
rep->rep_msgh.msgh_bits =
@ -455,6 +455,10 @@ mach_right_get(mp, p, type, hint)
struct mach_emuldata *med;
int rights;
#ifdef DEBUG_MACH
if (type == 0)
uprintf("mach_right_get: right = 0\n");
#endif
med = (struct mach_emuldata *)p->p_emuldata;
/* Send and receive right must return an existing right */
@ -487,10 +491,10 @@ mach_right_get(mp, p, type, hint)
if (mp != NULL)
mp->mp_refcount++;
/* Insert the right in one of the process right lists */
/* Insert the right in the right lists */
if (type & MACH_PORT_TYPE_ALL_RIGHTS) {
mr->mr_name = mach_right_newname(p, hint);
lockmgr(&mach_right_list_lock, LK_EXCLUSIVE, NULL);
mr->mr_name = mach_right_newname(p, hint);
LIST_INSERT_HEAD(&med->med_right, mr, mr_list);
LIST_INSERT_HEAD(&mach_right_list, mr, mr_listall);
lockmgr(&mach_right_list_lock, LK_RELEASE, NULL);
@ -503,56 +507,72 @@ rcvck:
* register the new right.
*/
if (mr->mr_port->mp_recv != NULL)
mach_right_put(mr->mr_port->mp_recv);
mach_right_put(mr->mr_port->mp_recv,
MACH_PORT_TYPE_RECEIVE);
mr->mr_port->mp_recv = mr;
}
return mr;
}
void
mach_right_put(mr)
mach_right_put(mr, right)
struct mach_right *mr;
int right;
{
lockmgr(&mach_right_list_lock, LK_EXCLUSIVE, NULL);
mach_right_put_exclocked(mr);
mach_right_put_exclocked(mr, right);
lockmgr(&mach_right_list_lock, LK_RELEASE, NULL);
return;
}
void
mach_right_put_shlocked(mr)
mach_right_put_shlocked(mr, right)
struct mach_right *mr;
int right;
{
lockmgr(&mach_right_list_lock, LK_UPGRADE, NULL);
mach_right_put_exclocked(mr);
mach_right_put_exclocked(mr, right);
lockmgr(&mach_right_list_lock, LK_DOWNGRADE, NULL);
return;
}
void
mach_right_put_exclocked(mr)
mach_right_put_exclocked(mr, right)
struct mach_right *mr;
int right;
{
struct mach_right *cmr;
#ifdef DEBUG_MACH
if ((mr->mr_type & right) == 0)
printf("mach_right_put: droping nonexistant right %x on %x\n",
right, mr->mr_name);
#endif
mr->mr_type &= ~right;
mr->mr_refcount--;
if (mr->mr_refcount != 0)
if (mr->mr_refcount != 0) {
#ifdef DEBUG_MACH
printf("tried to release right %x, but refcount = %d\n",
mr->mr_name, mr->mr_refcount);
#endif
return;
}
#ifdef DEBUG_MACH_RIGHT
printf("mach_right_put: put right %p, port %p\n", mr, mr->mr_port);
#endif
if (mr->mr_type & MACH_PORT_TYPE_PORT_SET) {
while((cmr = LIST_FIRST(&mr->mr_set)) != NULL)
mach_right_put_exclocked(cmr);
while((cmr = LIST_FIRST(&mr->mr_set)) != NULL) {
LIST_REMOVE(cmr, mr_setlist);
cmr->mr_sethead = cmr;
}
}
if (mr->mr_type & MACH_PORT_TYPE_ALL_RIGHTS) {
LIST_REMOVE(mr, mr_list);
LIST_REMOVE(mr, mr_listall);
}
LIST_REMOVE(mr, mr_list);
LIST_REMOVE(mr, mr_listall);
if (mr->mr_port != NULL) {
mr->mr_port->mp_refcount--;
@ -576,6 +596,9 @@ mach_right_check(mn, p, type)
struct mach_right *cmr;
struct mach_emuldata *med;
if ((mn == 0) || (mn == -1) || (p == NULL))
return NULL;
med = (struct mach_emuldata *)p->p_emuldata;
lockmgr(&mach_right_list_lock, LK_SHARED, NULL);
@ -600,30 +623,9 @@ mach_right_check(mn, p, type)
}
/*
* Check for a right in any process
*/
struct mach_right *
mach_right_check_all(mn, type)
mach_port_t mn;
int type;
{
struct mach_right *cmr;
lockmgr(&mach_right_list_lock, LK_SHARED, NULL);
LIST_FOREACH(cmr, &mach_right_list, mr_listall)
if ((cmr->mr_name == mn) && (cmr->mr_type & type))
break;
lockmgr(&mach_right_list_lock, LK_RELEASE, NULL);
return cmr;
}
/*
* Find an usnused port name in a given process.
* Right list should be locked.
* Right lists should be locked.
*/
mach_port_t
mach_right_newname(p, hint)
@ -648,11 +650,7 @@ mach_right_newname(p, hint)
hint++;
}
if (newname != -1)
med->med_nextright = hint;
else
uprintf("pid %d: cannot allocate new mach port names\n",
p->p_pid);
med->med_nextright = hint;
return newname;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: mach_port.h,v 1.14 2002/12/31 15:47:38 manu Exp $ */
/* $NetBSD: mach_port.h,v 1.15 2003/01/02 12:46:07 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -236,11 +236,10 @@ struct mach_right {
mach_port_t mach_right_newname(struct proc *, mach_port_t);
struct mach_right *mach_right_get(struct mach_port *,
struct proc *, int, mach_port_t);
void mach_right_put(struct mach_right *);
void mach_right_put_shlocked(struct mach_right *);
void mach_right_put_exclocked(struct mach_right *);
void mach_right_put(struct mach_right *, int);
void mach_right_put_shlocked(struct mach_right *, int);
void mach_right_put_exclocked(struct mach_right *, int);
struct mach_right *mach_right_check(mach_port_t, struct proc *, int);
struct mach_right *mach_right_check_all(mach_port_t, int);
/* In-kernel Mach port description */
struct mach_port {