Better error reporting in mach_msg_trap: this system call does not use the
standard error codes.
This commit is contained in:
parent
4d3d28af57
commit
b2a7ace594
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mach_errno.c,v 1.9 2002/12/17 18:42:56 manu Exp $ */
|
||||
/* $NetBSD: mach_errno.c,v 1.10 2002/12/24 15:54:26 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_errno.c,v 1.9 2002/12/17 18:42:56 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_errno.c,v 1.10 2002/12/24 15:54:26 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -157,5 +157,5 @@ mach_msg_error(args, error)
|
|||
|
||||
*msglen = sizeof(*rep);
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mach_message.c,v 1.7 2002/12/22 21:51:56 manu Exp $ */
|
||||
/* $NetBSD: mach_message.c,v 1.8 2002/12/24 15:54:26 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.7 2002/12/22 21:51:56 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.8 2002/12/24 15:54:26 manu Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
|
||||
|
@ -97,11 +97,10 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
int timeout;
|
||||
|
||||
/*
|
||||
* Catch unhandled options
|
||||
* If neither send nor recieve, do nothing.
|
||||
*/
|
||||
if (SCARG(uap, option) & ~(MACH_SEND_MSG | MACH_RCV_MSG))
|
||||
uprintf("mach_msg: unhandled option 0x%x\n",
|
||||
SCARG(uap, option));
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* XXX Sanity check on the message size. This is not an accurate
|
||||
|
@ -111,24 +110,31 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
*/
|
||||
send_size = SCARG(uap, send_size);
|
||||
rcv_size = SCARG(uap, rcv_size);
|
||||
if ((send_size > MACH_MAX_MSG_LEN) || (rcv_size > MACH_MAX_MSG_LEN))
|
||||
return E2BIG;
|
||||
if ((send_size > MACH_MAX_MSG_LEN) || (rcv_size > MACH_MAX_MSG_LEN)) {
|
||||
*retval = MACH_SEND_TOO_LARGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two options: receive or send. If both are
|
||||
* set, we must send, and then receive.
|
||||
* set, we must send, and then receive. If
|
||||
* send fail, then we skip recieve.
|
||||
*/
|
||||
if (SCARG(uap, option) & MACH_SEND_MSG) {
|
||||
if (SCARG(uap, msg) == NULL)
|
||||
return EINVAL;
|
||||
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)
|
||||
if ((error = copyin(SCARG(uap, msg), sm, send_size)) != 0) {
|
||||
*retval = MACH_SEND_INVALID_DATA;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
#ifdef KTRACE
|
||||
/* Dump the Mach message */
|
||||
|
@ -142,7 +148,7 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
*/
|
||||
if (mach_right_check((struct mach_right *)sm->msgh_remote_port,
|
||||
p, MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_SEND_ONCE) == 0) {
|
||||
error = EPERM;
|
||||
*retval = MACH_SEND_INVALID_RIGHT;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
|
@ -169,7 +175,7 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
if (map->map_handler == NULL) {
|
||||
uprintf("No mach trap handler for id = %d\n",
|
||||
sm->msgh_id);
|
||||
error = EINVAL;
|
||||
*retval = MACH_SEND_INVALID_DEST;
|
||||
goto out3;
|
||||
}
|
||||
#ifdef KTRACE
|
||||
|
@ -193,14 +199,15 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
args.smsg = sm;
|
||||
args.rmsg = rm;
|
||||
args.rsize = &rcv_size;
|
||||
if ((error = (*map->map_handler)(&args)) != 0)
|
||||
if ((*retval = (*map->map_handler)(&args)) != 0)
|
||||
goto out2;
|
||||
|
||||
/*
|
||||
* Catch potential bug in the handler
|
||||
*/
|
||||
if (rcv_size > SCARG(uap, rcv_size)) {
|
||||
uprintf("mach_msg: reply too big\n");
|
||||
uprintf("mach_msg: reply too big in %s\n",
|
||||
map->map_name);
|
||||
rcv_size = SCARG(uap, rcv_size);
|
||||
}
|
||||
|
||||
|
@ -213,8 +220,10 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
urm = SCARG(uap, rcv_msg);
|
||||
else
|
||||
urm = SCARG(uap, msg);
|
||||
if ((error = copyout(rm, urm, rcv_size)) != 0)
|
||||
if ((error = copyout(rm, urm, rcv_size)) != 0) {
|
||||
*retval = MACH_RCV_INVALID_DATA;
|
||||
goto out2;
|
||||
}
|
||||
#ifdef KTRACE
|
||||
/* Dump the Mach message */
|
||||
if (KTRPOINT(p, KTR_MMSG))
|
||||
|
@ -224,7 +233,7 @@ mach_sys_msg_overwrite_trap(p, v, retval)
|
|||
out2: free(rm, M_EMULDATA);
|
||||
out3: free(sm, M_EMULDATA);
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -252,7 +261,7 @@ out3: free(sm, M_EMULDATA);
|
|||
out1:
|
||||
if (error != 0) {
|
||||
free(sm, M_EMULDATA);
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,8 +276,10 @@ out1:
|
|||
urm = SCARG(uap, rcv_msg);
|
||||
else if (SCARG(uap, msg) != NULL)
|
||||
urm = SCARG(uap, msg);
|
||||
else
|
||||
return EINVAL;
|
||||
else {
|
||||
*retval = MACH_RCV_INVALID_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SCARG(uap, option) & MACH_RCV_TIMEOUT)
|
||||
timeout = SCARG(uap, timeout) * hz / 1000;
|
||||
|
@ -285,8 +296,10 @@ out1:
|
|||
* Is it a port set?
|
||||
*/
|
||||
if ((mach_right_check(mr, p,
|
||||
MACH_PORT_TYPE_PORT_SET)) == 0)
|
||||
return EPERM;
|
||||
MACH_PORT_TYPE_PORT_SET)) == 0) {
|
||||
*retval = MACH_RCV_INVALID_NAME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a port set. For each port in the
|
||||
|
@ -295,8 +308,10 @@ out1:
|
|||
*/
|
||||
LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) {
|
||||
if ((mach_right_check(cmr, p,
|
||||
MACH_PORT_TYPE_RECEIVE)) == 0)
|
||||
return EPERM;
|
||||
MACH_PORT_TYPE_RECEIVE)) == 0) {
|
||||
*retval = MACH_RCV_INVALID_NAME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mp = cmr->mr_port;
|
||||
#ifdef DEBUG_MACH
|
||||
|
@ -315,17 +330,35 @@ out1:
|
|||
*/
|
||||
if (cmr == NULL) {
|
||||
error = tsleep(mr, PZERO, "mach_msg", timeout);
|
||||
if ((error == ERESTART) || (error == EINTR))
|
||||
return EINTR;
|
||||
if ((error == ERESTART) || (error == EINTR)) {
|
||||
*retval = MACH_RCV_INTERRUPTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we did not loose the receive right
|
||||
* while we were sleeping.
|
||||
*/
|
||||
if ((mach_right_check(mr, p,
|
||||
MACH_PORT_TYPE_PORT_SET)) == 0) {
|
||||
*retval = MACH_RCV_PORT_DIED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there any pending message for
|
||||
* a port in the port set?
|
||||
*/
|
||||
LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) {
|
||||
mp = cmr->mr_port;
|
||||
if (mp->mp_count != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmr == NULL)
|
||||
return ETIMEDOUT;
|
||||
if (cmr == NULL) {
|
||||
*retval = MACH_RCV_TIMED_OUT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -347,12 +380,26 @@ out1:
|
|||
"port/right\n");
|
||||
#endif
|
||||
if (mp->mp_count == 0) {
|
||||
error = tsleep(mp->mp_recv, PZERO,
|
||||
"mach_msg", timeout);
|
||||
if ((error == ERESTART) || (error == EINTR))
|
||||
return EINTR;
|
||||
if (mp->mp_count == 0)
|
||||
return ETIMEDOUT;
|
||||
error = tsleep(mr, PZERO, "mach_msg", timeout);
|
||||
if ((error == ERESTART) || (error == EINTR)) {
|
||||
*retval = MACH_RCV_INTERRUPTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we did not loose the receive right
|
||||
* while we were sleeping.
|
||||
*/
|
||||
if ((mach_right_check(mr, p,
|
||||
MACH_PORT_TYPE_RECEIVE)) == 0) {
|
||||
*retval = MACH_RCV_PORT_DIED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mp->mp_count == 0) {
|
||||
*retval = MACH_RCV_TIMED_OUT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,13 +413,22 @@ out1:
|
|||
mm = TAILQ_FIRST(&mp->mp_msglist);
|
||||
|
||||
if (mm->mm_size > rcv_size) {
|
||||
lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
|
||||
return ENOBUFS;
|
||||
/*
|
||||
* If MACH_RCV_LARGE was not set, destroy the
|
||||
* message. If it was set, just notice that
|
||||
* the message is too big.
|
||||
*/
|
||||
if ((SCARG(uap, option) & MACH_RCV_LARGE) == 0) {
|
||||
free(mm->mm_msg, M_EMULDATA);
|
||||
mach_message_put_shlocked(mm);
|
||||
}
|
||||
*retval = MACH_RCV_TOO_LARGE;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if ((error = copyout(mm->mm_msg, urm, mm->mm_size)) != 0) {
|
||||
lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
|
||||
return error;
|
||||
*retval = MACH_RCV_INVALID_DATA;
|
||||
goto unlock;
|
||||
}
|
||||
#ifdef KTRACE
|
||||
/* Dump the Mach message */
|
||||
|
@ -382,6 +438,7 @@ out1:
|
|||
|
||||
free(mm->mm_msg, M_EMULDATA);
|
||||
mach_message_put_shlocked(mm); /* decrease mp_count */
|
||||
unlock:
|
||||
lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mach_message.h,v 1.9 2002/12/17 18:42:57 manu Exp $ */
|
||||
/* $NetBSD: mach_message.h,v 1.10 2002/12/24 15:54:26 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -64,6 +64,52 @@ typedef unsigned int mach_msg_type_number_t;
|
|||
#define MACH_SEND_ALWAYS 0x00010000
|
||||
#define MACH_SEND_TRAILER 0x00020000
|
||||
|
||||
/* mach_msg error codes */
|
||||
#define MACH_MSG_SUCCESS 0x00000000
|
||||
#define MACH_MSG_MASK 0x00003e00
|
||||
#define MACH_MSG_IPC_SPACE 0x00002000
|
||||
#define MACH_MSG_VM_SPACE 0x00001000
|
||||
#define MACH_MSG_IPC_KERNEL 0x00000800
|
||||
#define MACH_MSG_VM_KERNEL 0x00000400
|
||||
#define MACH_SEND_MSG 0x00000001
|
||||
#define MACH_SEND_TIMEOUT 0x00000010
|
||||
#define MACH_SEND_INTERRUPT 0x00000040
|
||||
#define MACH_SEND_CANCEL 0x00000080
|
||||
#define MACH_SEND_ALWAYS 0x00010000
|
||||
#define MACH_SEND_TRAILER 0x00020000
|
||||
#define MACH_SEND_IN_PROGRESS 0x10000001
|
||||
#define MACH_SEND_INVALID_DATA 0x10000002
|
||||
#define MACH_SEND_INVALID_DEST 0x10000003
|
||||
#define MACH_SEND_TIMED_OUT 0x10000004
|
||||
#define MACH_SEND_INTERRUPTED 0x10000007
|
||||
#define MACH_SEND_MSG_TOO_SMALL 0x10000008
|
||||
#define MACH_SEND_INVALID_REPLY 0x10000009
|
||||
#define MACH_SEND_INVALID_RIGHT 0x1000000a
|
||||
#define MACH_SEND_INVALID_NOTIFY 0x1000000b
|
||||
#define MACH_SEND_INVALID_MEMORY 0x1000000c
|
||||
#define MACH_SEND_NO_BUFFER 0x1000000d
|
||||
#define MACH_SEND_TOO_LARGE 0x1000000e
|
||||
#define MACH_SEND_INVALID_TYPE 0x1000000f
|
||||
#define MACH_SEND_INVALID_HEADER 0x10000010
|
||||
#define MACH_SEND_INVALID_TRAILER 0x10000011
|
||||
#define MACH_SEND_INVALID_RT_OOL_SIZE 0x10000015
|
||||
#define MACH_RCV_IN_PROGRESS 0x10004001
|
||||
#define MACH_RCV_INVALID_NAME 0x10004002
|
||||
#define MACH_RCV_TIMED_OUT 0x10004003
|
||||
#define MACH_RCV_TOO_LARGE 0x10004004
|
||||
#define MACH_RCV_INTERRUPTED 0x10004005
|
||||
#define MACH_RCV_PORT_CHANGED 0x10004006
|
||||
#define MACH_RCV_INVALID_NOTIFY 0x10004007
|
||||
#define MACH_RCV_INVALID_DATA 0x10004008
|
||||
#define MACH_RCV_PORT_DIED 0x10004009
|
||||
#define MACH_RCV_IN_SET 0x1000400a
|
||||
#define MACH_RCV_HEADER_ERROR 0x1000400b
|
||||
#define MACH_RCV_BODY_ERROR 0x1000400c
|
||||
#define MACH_RCV_INVALID_TYPE 0x1000400d
|
||||
#define MACH_RCV_SCATTER_SMALL 0x1000400e
|
||||
#define MACH_RCV_INVALID_TRAILER 0x1000400f
|
||||
#define MACH_RCV_IN_PROGRESS_TIMED 0x10004011
|
||||
|
||||
#define MACH_MSG_OPTION_BITS "\177\20" \
|
||||
"b\00send_msg\0b\01rcv_msg\0" \
|
||||
"b\02rcv_large\0b\03invalid[0x8]\0" \
|
||||
|
|
Loading…
Reference in New Issue