Edited by David van Moolenbroek.
Change-Id: Ia0052c42a0f218d011dd2da1e3db6c5b2107adc7
./usr/include/minix/ioctl.h minix-sys
./usr/include/minix/ipcconst.h minix-sys
./usr/include/minix/ipc.h minix-sys
+./usr/include/minix/ipc_filter.h minix-sys
./usr/include/minix/keymap.h minix-sys
./usr/include/minix/libminixfs.h minix-sys
./usr/include/minix/log.h minix-sys
driver.h drivers.h drvlib.h ds.h \
endpoint.h fb.h fsdriver.h fslib.h gpio.h gcov.h hash.h \
hgfs.h i2c.h i2cdriver.h ioctl.h input.h \
- inputdriver.h ipc.h ipcconst.h \
+ inputdriver.h ipc.h ipc_filter.h ipcconst.h \
keymap.h log.h mmio.h mthread.h minlib.h \
netdriver.h optset.h padconf.h partition.h portio.h \
priv.h procfs.h profile.h queryparam.h \
/* Subfunctions for SYS_STATECTL */
#define SYS_STATE_CLEAR_IPC_REFS 1 /* clear IPC references */
#define SYS_STATE_SET_STATE_TABLE 2 /* set state map */
+#define SYS_STATE_ADD_IPC_BL_FILTER 3 /* set IPC blacklist filter */
+#define SYS_STATE_ADD_IPC_WL_FILTER 4 /* set IPC whitelist filter */
+#define SYS_STATE_CLEAR_IPC_FILTERS 5 /* clear IPC filters */
/* Subfunctions for SYS_SCHEDCTL */
# define SCHEDCTL_FLAG_KERNEL 1 /* mark kernel scheduler and remove
--- /dev/null
+/* IPC filter definitions. */
+
+#ifndef _MINIX_IPC_FILTER_H
+#define _MINIX_IPC_FILTER_H
+
+#include <minix/com.h>
+#include <minix/config.h>
+
+/* Special message sources, allowed in IPC filters only. */
+#define ANY_USR _ENDPOINT(1, _ENDPOINT_P(ANY))
+#define ANY_SYS _ENDPOINT(2, _ENDPOINT_P(ANY))
+#define ANY_TSK _ENDPOINT(3, _ENDPOINT_P(ANY))
+
+/* IPC filter constants. */
+#define IPCF_MAX_ELEMENTS NR_SYS_PROCS
+
+/* IPC filter flags. */
+#define IPCF_MATCH_M_SOURCE 0x1
+#define IPCF_MATCH_M_TYPE 0x2
+#define IPCF_EL_BLACKLIST 0x4
+#define IPCF_EL_WHITELIST 0x8
+
+struct ipc_filter_el_s {
+ int flags;
+ endpoint_t m_source;
+ int m_type;
+};
+typedef struct ipc_filter_el_s ipc_filter_el_t;
+
+#endif /* _MINIX_IPC_FILTER_H */
print_proc_depends(pp, 0);
}
-#if DEBUG_DUMPIPC
+#if DEBUG_DUMPIPC || DEBUG_DUMPIPCF
static const char *mtypename(int mtype, int *possible_callname)
{
char *callname = NULL, *errname = NULL;
}
#endif
-static void printmsg(message *msg, struct proc *src, struct proc *dst,
+void printmsg(message *msg, struct proc *src, struct proc *dst,
char operation, int printparams)
{
const char *name;
*/
#define DEBUG_DUMPIPC 0
+/* DEBUG_DUMPIPCF dumps filtered IPC to serial.
+ */
+#define DEBUG_DUMPIPCF 0
+
/* If defined, restrict DEBUG_DUMPIPC to particular process names */
/* #define DEBUG_DUMPIPC_NAMES { "tty", "inet" } */
#define NON_BLOCKING 0x0080 /* do not block if target not ready */
#define FROM_KERNEL 0x0100 /* message from kernel on behalf of a process */
-#define WILLRECEIVE(target, source_ep) \
- ((RTS_ISSET(target, RTS_RECEIVING) && !RTS_ISSET(target, RTS_SENDING)) && \
- (target->p_getfrom_e == ANY || target->p_getfrom_e == source_ep))
+#define WILLRECEIVE(src_e,dst_ptr,m_src_v,m_src_p) \
+ ((RTS_ISSET(dst_ptr, RTS_RECEIVING) && \
+ !RTS_ISSET(dst_ptr, RTS_SENDING)) && \
+ CANRECEIVE(dst_ptr->p_getfrom_e,src_e,dst_ptr,m_src_v,m_src_p))
+
+#define CANRECEIVE(receive_e,src_e,dst_ptr,m_src_v,m_src_p) \
+ (((receive_e) == ANY || (receive_e) == (src_e)) && \
+ (priv(dst_ptr)->s_ipcf == NULL || \
+ allow_ipc_filtered_msg(dst_ptr,src_e,m_src_v,m_src_p)))
/* IPC status code macros. */
#define IPC_STATUS_GET(p) ((p)->p_reg.IPC_STATUS_REG)
--- /dev/null
+#ifndef IPC_FILTER_H
+#define IPC_FILTER_H
+
+/* Declaration of the ipc filter structure. It provides a framework to
+ * selectively allow/disallow ipc messages a process agrees to receive. To this
+ * end, a single ipc filter can be specified at a given time for any recipient
+ * to blacklist/whitelist a set of ipc messages identified by sender or message
+ * type.
+ */
+#include <minix/ipc_filter.h>
+
+/* IPC filter types. */
+#define IPCF_NONE 0 /* no ipc filter */
+#define IPCF_BLACKLIST 1 /* blacklist filter type */
+#define IPCF_WHITELIST 2 /* whitelist filter type */
+
+/* IPC filter element macros. */
+EXTERN int _ipcf_nr;
+#define IPCF_EL_CHECK(E) \
+ ((((E)->flags & IPCF_MATCH_M_TYPE) || \
+ ((E)->flags & IPCF_MATCH_M_SOURCE)) && \
+ (!((E)->flags & IPCF_MATCH_M_SOURCE) || \
+ IPCF_IS_ANY_EP((E)->m_source) || isokendpt((E)->m_source, &_ipcf_nr)))
+#define IPCF_IS_USR_EP(EP) \
+ (!(priv(proc_addr(_ENDPOINT_P((EP))))->s_flags & SYS_PROC))
+#define IPCF_IS_TSK_EP(EP) (iskerneln(_ENDPOINT_P((EP))))
+#define IPCF_IS_SYS_EP(EP) (!IPCF_IS_USR_EP(EP) && !IPCF_IS_TSK_EP(EP))
+#define IPCF_IS_ANY_EP(EP) \
+ ((EP) == ANY_USR || (EP) == ANY_SYS || (EP) == ANY_TSK)
+#define IPCF_EL_MATCH_M_TYPE(E,M) \
+ (!((E)->flags & IPCF_MATCH_M_TYPE) || (E)->m_type == (M)->m_type)
+#define IPCF_EL_MATCH_M_SOURCE(E,M) \
+ (!((E)->flags & IPCF_MATCH_M_SOURCE) || \
+ (E)->m_source == (M)->m_source || \
+ IPCF_EL_MATCH_M_SOURCE_ANY_EP((E)->m_source,(M)->m_source))
+#define IPCF_EL_MATCH_M_SOURCE_ANY_EP(ES,MS) \
+ (((ES) == ANY_USR && IPCF_IS_USR_EP(MS)) || \
+ ((ES) == ANY_SYS && IPCF_IS_SYS_EP(MS)) || \
+ ((ES) == ANY_TSK && IPCF_IS_TSK_EP(MS)))
+#define IPCF_EL_MATCH(E,M) \
+ (IPCF_EL_MATCH_M_TYPE(E,M) && IPCF_EL_MATCH_M_SOURCE(E,M))
+
+struct ipc_filter_s {
+ int type;
+ int num_elements;
+ int flags;
+ struct ipc_filter_s *next;
+ ipc_filter_el_t elements[IPCF_MAX_ELEMENTS];
+};
+typedef struct ipc_filter_s ipc_filter_t;
+
+/* IPC filter pool. */
+#define IPCF_POOL_SIZE (2*NR_SYS_PROCS)
+EXTERN ipc_filter_t ipc_filter_pool[IPCF_POOL_SIZE];
+
+/* IPC filter pool macros. */
+#define IPCF_POOL_FREE_SLOT(S) ((S)->type = IPCF_NONE)
+#define IPCF_POOL_IS_FREE_SLOT(S) ((S)->type == IPCF_NONE)
+#define IPCF_POOL_ALLOCATE_SLOT(T,S) \
+ do { \
+ int i; \
+ *(S) = NULL; \
+ for (i = 0; i < IPCF_POOL_SIZE; i++) { \
+ if (IPCF_POOL_IS_FREE_SLOT(&ipc_filter_pool[i])) { \
+ *(S) = &ipc_filter_pool[i]; \
+ (*(S))->type = T; \
+ break; \
+ } \
+ } \
+ } while(0)
+#define IPCF_POOL_INIT(S) memset(&ipc_filter_pool,0,sizeof(ipc_filter_pool))
+
+#endif /* !IPC_FILTER_H */
DEBUGEXTRA(("main()\n"));
- proc_init();
+ /* Clear the process table. Anounce each slot as empty and set up mappings
+ * for proc_addr() and proc_nr() macros. Do the same for the table with
+ * privilege structures for the system processes and the ipc filter pool.
+ */
+ proc_init();
+ IPCF_POOL_INIT();
if(NR_BOOT_MODULES != kinfo.mbi.mi_mods_count)
panic("expecting %d boot processes/modules, found %d",
#include <minix/priv.h>
#include "kernel/const.h"
#include "kernel/type.h"
+#include "kernel/ipc_filter.h"
struct priv {
proc_nr_t s_proc_nr; /* number of associated process */
sys_map_t s_asyn_pending; /* bit map with pending asyn messages */
irq_id_t s_int_pending; /* pending hardware interrupts */
sigset_t s_sig_pending; /* pending signals */
+ ipc_filter_t *s_ipcf; /* ipc filter (NULL when no filter is set) */
minix_timer_t s_alarm_timer; /* synchronous alarm timer */
reg_t *s_stack_guard; /* stack guard word for kernel tasks */
#define nr_to_id(nr) priv(proc_addr(nr))->s_id
#define may_send_to(rp, nr) (get_sys_bit(priv(rp)->s_ipc_to, nr_to_id(nr)))
+#define may_asynsend_to(rp, nr) (may_send_to(rp, nr) || (rp)->p_nr == nr)
/* The system structures table and pointers to individual table slots. The
* pointers allow faster access because now a process entry can be found by
*m_ptr, int flags);
*/
static int mini_receive(struct proc *caller_ptr, endpoint_t src,
- message *m_ptr, int flags);
+ message *m_buff_usr, int flags);
static int mini_senda(struct proc *caller_ptr, asynmsg_t *table, size_t
size);
static int deadlock(int function, register struct proc *caller,
endpoint_t src_dst_e);
static int try_async(struct proc *caller_ptr);
-static int try_one(struct proc *src_ptr, struct proc *dst_ptr);
+static int try_one(endpoint_t receive_e, struct proc *src_ptr,
+ struct proc *dst_ptr);
static struct proc * pick_proc(void);
static void enqueue_head(struct proc *rp);
break; \
}
+static message m_notify_buff = { 0, NOTIFY_MESSAGE };
+
void proc_init(void)
{
struct proc * rp;
/* Check if 'dst' is blocked waiting for this message. The destination's
* RTS_SENDING flag may be set when its SENDREC call blocked while sending.
*/
- if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint)) {
+ if (WILLRECEIVE(caller_ptr->p_endpoint, dst_ptr, (vir_bytes)m_ptr, NULL)) {
int call;
/* Destination is indeed waiting for this message. */
assert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG));
* is available block the caller.
*/
register struct proc **xpp;
- int r, src_id, src_proc_nr, src_p;
+ int r, src_id, found, src_proc_nr, src_p;
+ endpoint_t sender_e;
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
if (! (caller_ptr->p_misc_flags & MF_REPLY_PEND)) {
/* Check for pending notifications */
- if ((src_id = has_pending_notify(caller_ptr, src_p)) != NULL_PRIV_ID) {
- endpoint_t hisep;
-
+ src_id = has_pending_notify(caller_ptr, src_p);
+ found = src_id != NULL_PRIV_ID;
+ if(found) {
src_proc_nr = id_to_nr(src_id); /* get source proc */
+ sender_e = proc_addr(src_proc_nr)->p_endpoint;
+ }
+
+ if (found && CANRECEIVE(src_e, sender_e, caller_ptr, 0,
+ &m_notify_buff)) {
+
#if DEBUG_ENABLE_IPC_WARNINGS
if(src_proc_nr == NONE) {
printf("mini_receive: sending notify from NONE\n");
unset_notify_pending(caller_ptr, src_id); /* no longer pending */
/* Found a suitable source, deliver the notification message. */
- hisep = proc_addr(src_proc_nr)->p_endpoint;
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
- assert(src_e == ANY || hisep == src_e);
+ assert(src_e == ANY || sender_e == src_e);
/* assemble message */
BuildNotifyMessage(&caller_ptr->p_delivermsg, src_proc_nr, caller_ptr);
- caller_ptr->p_delivermsg.m_source = hisep;
+ caller_ptr->p_delivermsg.m_source = sender_e;
caller_ptr->p_misc_flags |= MF_DELIVERMSG;
IPC_STATUS_ADD_CALL(caller_ptr, NOTIFY);
/* Check for pending asynchronous messages */
if (has_pending_asend(caller_ptr, src_p) != NULL_PRIV_ID) {
if (src_p != ANY)
- r = try_one(proc_addr(src_p), caller_ptr);
+ r = try_one(src_e, proc_addr(src_p), caller_ptr);
else
r = try_async(caller_ptr);
xpp = &caller_ptr->p_caller_q;
while (*xpp) {
struct proc * sender = *xpp;
+ endpoint_t sender_e = sender->p_endpoint;
- if (src_e == ANY || src_p == proc_nr(sender)) {
+ if (CANRECEIVE(src_e, sender_e, caller_ptr, 0, &sender->p_sendmsg)) {
int call;
assert(!RTS_ISSET(sender, RTS_SLOT_FREE));
assert(!RTS_ISSET(sender, RTS_NO_ENDPOINT));
/* Check to see if target is blocked waiting for this message. A process
* can be both sending and receiving during a SENDREC system call.
*/
- if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint) &&
- ! (dst_ptr->p_misc_flags & MF_REPLY_PEND)) {
+ if (WILLRECEIVE(caller_ptr->p_endpoint, dst_ptr, 0, &m_notify_buff) &&
+ !(dst_ptr->p_misc_flags & MF_REPLY_PEND)) {
/* Destination is indeed waiting for a message. Assemble a notification
* message and deliver it. Copy from pseudo-source HARDWARE, since the
* message is in the kernel's address space.
r = EFAULT; \
goto asyn_error; \
} \
+ else if(tabent.dst == SELF) { \
+ tabent.dst = caller_ptr->p_endpoint; \
+ } \
} while(0)
#define A_INSRT(entry) do { \
struct priv *privp;
asynmsg_t tabent;
const vir_bytes table_v = (vir_bytes) table;
+ message *m_ptr = NULL;
privp = priv(caller_ptr);
r = EDEADSRCDST; /* Bad destination, report the error */
else if (iskerneln(dst_p))
r = ECALLDENIED; /* Asyn sends to the kernel are not allowed */
- else if (!may_send_to(caller_ptr, dst_p))
+ else if (!may_asynsend_to(caller_ptr, dst_p))
r = ECALLDENIED; /* Send denied by IPC mask */
else /* r == OK */
dst_ptr = proc_addr(dst_p);
* If AMF_NOREPLY is set, do not satisfy the receiving part of
* a SENDREC.
*/
- if (r == OK && WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint) &&
+ if (r == OK && WILLRECEIVE(caller_ptr->p_endpoint, dst_ptr,
+ (vir_bytes)&table[i].msg, NULL) &&
(!(flags&AMF_NOREPLY) || !(dst_ptr->p_misc_flags&MF_REPLY_PEND))) {
/* Destination is indeed waiting for this message. */
dst_ptr->p_delivermsg = tabent.msg;
#endif
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
- if ((r = try_one(src_ptr, caller_ptr)) == OK)
+ if ((r = try_one(ANY, src_ptr, caller_ptr)) == OK)
return(r);
}
/*===========================================================================*
* try_one *
*===========================================================================*/
-static int try_one(struct proc *src_ptr, struct proc *dst_ptr)
+static int try_one(endpoint_t receive_e, struct proc *src_ptr,
+ struct proc *dst_ptr)
{
/* Try to receive an asynchronous message from 'src_ptr' */
int r = EAGAIN, done, do_notify;
unsigned int flags, i;
size_t size;
- endpoint_t dst;
+ endpoint_t dst, src_e;
struct proc *caller_ptr;
struct priv *privp;
asynmsg_t tabent;
unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
if (size == 0) return(EAGAIN);
- if (!may_send_to(src_ptr, proc_nr(dst_ptr))) return(ECALLDENIED);
+ if (!may_asynsend_to(src_ptr, proc_nr(dst_ptr))) return (ECALLDENIED);
caller_ptr = src_ptr; /* Needed for A_ macros later on */
+ src_e = src_ptr->p_endpoint;
/* Scan the table */
do_notify = FALSE;
/* Message must be directed at receiving end */
if (dst != dst_ptr->p_endpoint) continue;
+ if (!CANRECEIVE(receive_e, src_e, dst_ptr,
+ table_v + i*sizeof(asynmsg_t) + offsetof(struct asynmsg,msg),
+ NULL)) {
+ continue;
+ }
+
/* If AMF_NOREPLY is set, then this message is not a reply to a
* SENDREC and thus should not satisfy the receiving part of the
* SENDREC. This message is to be delivered later.
/* Struct declarations. */
struct proc;
+struct ipc_filter_s;
/* clock.c */
clock_t get_realtime(void);
void clear_ipc_refs(struct proc *rc, int caller_ret);
void kernel_call_resume(struct proc *p);
int sched_proc(struct proc *rp, int priority, int quantum, int cpu);
+int add_ipc_filter(struct proc *rp, int type,
+ vir_bytes address, size_t length);
+void clear_ipc_filters(struct proc *rp);
+int check_ipc_filter(struct ipc_filter_s *ipcf, int fill_flags);
+int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e,
+ vir_bytes m_src_v, message *m_src_p);
/* system/do_vtimer.c */
void vtimer_check(struct proc *rp);
void print_proc(struct proc *pp);
/* prints the given process and recursively all processes it depends on */
void print_proc_recursive(struct proc *pp);
+void printmsg(message *msg, struct proc *src, struct proc *dst,
+ char operation, int printparams);
#if DEBUG_IPC_HOOK
void hook_ipc_msgrecv(message *msg, struct proc *src, struct proc *dst);
void hook_ipc_msgsend(message *msg, struct proc *src, struct proc *dst);
#include "kernel/vm.h"
#include "kernel/clock.h"
#include <stdlib.h>
+#include <stddef.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
return OK;
}
+/*===========================================================================*
+ * add_ipc_filter *
+ *===========================================================================*/
+int add_ipc_filter(struct proc *rp, int type, vir_bytes address,
+ size_t length)
+{
+ int num_elements, r;
+ ipc_filter_t *ipcf, **ipcfp;
+
+ /* Validate arguments. */
+ if (type != IPCF_BLACKLIST && type != IPCF_WHITELIST)
+ return EINVAL;
+
+ if (length % sizeof(ipc_filter_el_t) != 0)
+ return EINVAL;
+
+ num_elements = length / sizeof(ipc_filter_el_t);
+ if (num_elements <= 0 || num_elements > IPCF_MAX_ELEMENTS)
+ return E2BIG;
+
+ /* Allocate a new IPC filter slot. */
+ IPCF_POOL_ALLOCATE_SLOT(type, &ipcf);
+ if (ipcf == NULL)
+ return ENOMEM;
+
+ /* Fill details. */
+ ipcf->num_elements = num_elements;
+ ipcf->next = NULL;
+ r = data_copy(rp->p_endpoint, address,
+ KERNEL, (vir_bytes)ipcf->elements, length);
+ if (r == OK)
+ r = check_ipc_filter(ipcf, TRUE /*fill_flags*/);
+ if (r != OK) {
+ IPCF_POOL_FREE_SLOT(ipcf);
+ return r;
+ }
+
+ /* Add the new filter at the end of the IPC filter chain. */
+ for (ipcfp = &priv(rp)->s_ipcf; *ipcfp != NULL;
+ ipcfp = &(*ipcfp)->next)
+ ;
+ *ipcfp = ipcf;
+
+ return OK;
+}
+
+/*===========================================================================*
+ * clear_ipc_filters *
+ *===========================================================================*/
+void clear_ipc_filters(struct proc *rp)
+{
+ ipc_filter_t *curr_ipcf, *ipcf;
+
+ ipcf = priv(rp)->s_ipcf;
+ while (ipcf != NULL) {
+ curr_ipcf = ipcf;
+ ipcf = ipcf->next;
+ IPCF_POOL_FREE_SLOT(curr_ipcf);
+ }
+
+ priv(rp)->s_ipcf = NULL;
+}
+
+/*===========================================================================*
+ * check_ipc_filter *
+ *===========================================================================*/
+int check_ipc_filter(ipc_filter_t *ipcf, int fill_flags)
+{
+ ipc_filter_el_t *ipcf_el;
+ int i, num_elements, flags;
+
+ if (ipcf == NULL)
+ return OK;
+
+ num_elements = ipcf->num_elements;
+ flags = 0;
+ for (i = 0; i < num_elements; i++) {
+ ipcf_el = &ipcf->elements[i];
+ if (!IPCF_EL_CHECK(ipcf_el))
+ return EINVAL;
+ flags |= ipcf_el->flags;
+ }
+
+ if (fill_flags)
+ ipcf->flags = flags;
+ else if (ipcf->flags != flags)
+ return EINVAL;
+ return OK;
+}
+
+/*===========================================================================*
+ * allow_ipc_filtered_msg *
+ *===========================================================================*/
+int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e,
+ vir_bytes m_src_v, message *m_src_p)
+{
+ int i, r, num_elements, get_mtype, allow;
+ ipc_filter_t *ipcf;
+ ipc_filter_el_t *ipcf_el;
+ message m_buff;
+
+ ipcf = priv(rp)->s_ipcf;
+ if (ipcf == NULL)
+ return TRUE; /* no IPC filters, always allow */
+
+ if (m_src_p == NULL) {
+ assert(m_src_v != 0);
+
+ /* Should we copy in the message type? */
+ get_mtype = FALSE;
+ do {
+#if DEBUG_DUMPIPCF
+ if (TRUE) {
+#else
+ if (ipcf->flags & IPCF_MATCH_M_TYPE) {
+#endif
+ get_mtype = TRUE;
+ break;
+ }
+ ipcf = ipcf->next;
+ } while (ipcf);
+ ipcf = priv(rp)->s_ipcf; /* reset to start */
+
+ /* If so, copy it in from the process. */
+ if (get_mtype) {
+ r = data_copy(src_e,
+ m_src_v + offsetof(message, m_type), KERNEL,
+ (vir_bytes)&m_buff.m_type, sizeof(m_buff.m_type));
+ if (r != OK) {
+ /* allow for now, this will fail later anyway */
+#if DEBUG_DUMPIPCF
+ printf("KERNEL: allow_ipc_filtered_msg: data "
+ "copy error %d, allowing message...\n", r);
+#endif
+ return TRUE;
+ }
+ }
+ m_src_p = &m_buff;
+ }
+
+ m_src_p->m_source = src_e;
+
+ /* See if the message is allowed. */
+ allow = (ipcf->type == IPCF_BLACKLIST);
+ do {
+ if (allow != (ipcf->type == IPCF_WHITELIST)) {
+ num_elements = ipcf->num_elements;
+ for (i = 0; i < num_elements; i++) {
+ ipcf_el = &ipcf->elements[i];
+ if (IPCF_EL_MATCH(ipcf_el, m_src_p)) {
+ allow = (ipcf->type == IPCF_WHITELIST);
+ break;
+ }
+ }
+ }
+ ipcf = ipcf->next;
+ } while (ipcf);
+
+#if DEBUG_DUMPIPCF
+ printmsg(m_src_p, proc_addr(_ENDPOINT_P(src_e)), rp, allow ? '+' : '-',
+ TRUE /*printparams*/);
+#endif
+
+ return allow;
+}
+
priv(rp)->s_bak_sig_mgr = NONE;
/* Set defaults for resources: no I/O resources, no memory resources,
- * no IRQs, no grant table
+ * no IRQs, no grant table, no ipc filter
*/
priv(rp)->s_nr_io_range= 0;
priv(rp)->s_nr_mem_range= 0;
priv(rp)->s_grant_entries= 0;
priv(rp)->s_state_table= 0;
priv(rp)->s_state_entries= 0;
+ priv(rp)->s_ipcf= 0;
/* Override defaults if the caller has supplied a privilege structure. */
if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
priv(caller)->s_state_table = (vir_bytes) m_ptr->m_lsys_krn_sys_statectl.address;
priv(caller)->s_state_entries = m_ptr->m_lsys_krn_sys_statectl.length;
return(OK);
+ case SYS_STATE_ADD_IPC_BL_FILTER:
+ /* Add an IPC blacklist filter for the caller. */
+ return add_ipc_filter(caller, IPCF_BLACKLIST,
+ (vir_bytes) m_ptr->m_lsys_krn_sys_statectl.address,
+ m_ptr->m_lsys_krn_sys_statectl.length);
+ case SYS_STATE_ADD_IPC_WL_FILTER:
+ /* Add an IPC whitelist filter for the caller. */
+ return add_ipc_filter(caller, IPCF_WHITELIST,
+ (vir_bytes) m_ptr->m_lsys_krn_sys_statectl.address,
+ m_ptr->m_lsys_krn_sys_statectl.length);
+ case SYS_STATE_CLEAR_IPC_FILTERS:
+ /* Clear any IPC filter for the caller. */
+ clear_ipc_filters(caller);
+ return OK;
default:
printf("do_statectl: bad request %d\n",
m_ptr->m_lsys_krn_sys_statectl.request);