diff --git a/minix/kernel/proto.h b/minix/kernel/proto.h index fd1f6f081..e0161879b 100644 --- a/minix/kernel/proto.h +++ b/minix/kernel/proto.h @@ -107,6 +107,9 @@ 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); +int priv_add_irq(struct proc *rp, int irq); +int priv_add_io(struct proc *rp, struct io_range *ior); +int priv_add_mem(struct proc *rp, struct minix_mem_range *memr); /* system/do_vtimer.c */ void vtimer_check(struct proc *rp); diff --git a/minix/kernel/system.c b/minix/kernel/system.c index 4cf9fdcea..ddf2d8f9e 100644 --- a/minix/kernel/system.c +++ b/minix/kernel/system.c @@ -841,3 +841,86 @@ int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e, return allow; } +/*===========================================================================* + * priv_add_irq * + *===========================================================================*/ +int priv_add_irq(struct proc *rp, int irq) +{ + struct priv *priv = priv(rp); + int i; + + priv->s_flags |= CHECK_IRQ; /* Check IRQ */ + + /* When restarting a driver, check if it already has the permission */ + for (i = 0; i < priv->s_nr_irq; i++) { + if (priv->s_irq_tab[i] == irq) + return OK; + } + + i= priv->s_nr_irq; + if (i >= NR_IRQ) { + printf("do_privctl: %d already has %d irq's.\n", + rp->p_endpoint, i); + return ENOMEM; + } + priv->s_irq_tab[i]= irq; + priv->s_nr_irq++; + return OK; +} + +/*===========================================================================* + * priv_add_io * + *===========================================================================*/ +int priv_add_io(struct proc *rp, struct io_range *ior) +{ + struct priv *priv = priv(rp); + int i; + + priv->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */ + + for (i = 0; i < priv->s_nr_io_range; i++) { + if (priv->s_io_tab[i].ior_base == ior->ior_base && + priv->s_io_tab[i].ior_limit == ior->ior_limit) + return OK; + } + + i= priv->s_nr_io_range; + if (i >= NR_IO_RANGE) { + printf("do_privctl: %d already has %d i/o ranges.\n", + rp->p_endpoint, i); + return ENOMEM; + } + + priv->s_io_tab[i] = *ior; + priv->s_nr_io_range++; + return OK; +} + +/*===========================================================================* + * priv_add_mem * + *===========================================================================*/ +int priv_add_mem(struct proc *rp, struct minix_mem_range *memr) +{ + struct priv *priv = priv(rp); + int i; + + priv->s_flags |= CHECK_MEM; /* Check memory mappings */ + + /* When restarting a driver, check if it already has the permission */ + for (i = 0; i < priv->s_nr_mem_range; i++) { + if (priv->s_mem_tab[i].mr_base == memr->mr_base && + priv->s_mem_tab[i].mr_limit == memr->mr_limit) + return OK; + } + + i= priv->s_nr_mem_range; + if (i >= NR_MEM_RANGE) { + printf("do_privctl: %d already has %d mem ranges.\n", + rp->p_endpoint, i); + return ENOMEM; + } + priv->s_mem_tab[i]= *memr; + priv->s_nr_mem_range++; + return OK; +} + diff --git a/minix/kernel/system/do_privctl.c b/minix/kernel/system/do_privctl.c index 0fc6c3118..188cea939 100644 --- a/minix/kernel/system/do_privctl.c +++ b/minix/kernel/system/do_privctl.c @@ -198,26 +198,8 @@ int do_privctl(struct proc * caller, message * m_ptr) /* Get the I/O range */ data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL, (vir_bytes) &io_range, sizeof(io_range)); - priv(rp)->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */ - - for (i = 0; i < priv(rp)->s_nr_io_range; i++) { - if (priv(rp)->s_io_tab[i].ior_base == io_range.ior_base && - priv(rp)->s_io_tab[i].ior_limit == io_range.ior_limit) - return OK; - } - - i= priv(rp)->s_nr_io_range; - if (i >= NR_IO_RANGE) { - printf("do_privctl: %d already has %d i/o ranges.\n", - rp->p_endpoint, i); - return ENOMEM; - } - - priv(rp)->s_io_tab[i].ior_base= io_range.ior_base; - priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit; - priv(rp)->s_nr_io_range++; - - return OK; + /* Add the I/O range */ + return priv_add_io(rp, &io_range); case SYS_PRIV_ADD_MEM: if (RTS_ISSET(rp, RTS_NO_PRIV)) @@ -228,27 +210,8 @@ int do_privctl(struct proc * caller, message * m_ptr) m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL, (vir_bytes) &mem_range, sizeof(mem_range))) != OK) return r; - priv(rp)->s_flags |= CHECK_MEM; /* Check memory mappings */ - - /* When restarting a driver, check if it already has the permission */ - for (i = 0; i < priv(rp)->s_nr_mem_range; i++) { - if (priv(rp)->s_mem_tab[i].mr_base == mem_range.mr_base && - priv(rp)->s_mem_tab[i].mr_limit == mem_range.mr_limit) - return OK; - } - - i= priv(rp)->s_nr_mem_range; - if (i >= NR_MEM_RANGE) { - printf("do_privctl: %d already has %d mem ranges.\n", - rp->p_endpoint, i); - return ENOMEM; - } - - priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base; - priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit; - priv(rp)->s_nr_mem_range++; - - return OK; + /* Add the memory range */ + return priv_add_mem(rp, &mem_range); case SYS_PRIV_ADD_IRQ: if (RTS_ISSET(rp, RTS_NO_PRIV)) @@ -261,24 +224,9 @@ int do_privctl(struct proc * caller, message * m_ptr) #endif data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL, (vir_bytes) &irq, sizeof(irq)); - priv(rp)->s_flags |= CHECK_IRQ; /* Check IRQs */ + /* Add the IRQ. */ + return priv_add_irq(rp, irq); - /* When restarting a driver, check if it already has the permission */ - for (i = 0; i < priv(rp)->s_nr_irq; i++) { - if (priv(rp)->s_irq_tab[i] == irq) - return OK; - } - - i= priv(rp)->s_nr_irq; - if (i >= NR_IRQ) { - printf("do_privctl: %d already has %d irq's.\n", - rp->p_endpoint, i); - return ENOMEM; - } - priv(rp)->s_irq_tab[i]= irq; - priv(rp)->s_nr_irq++; - - return OK; case SYS_PRIV_QUERY_MEM: { phys_bytes addr, limit; diff --git a/minix/kernel/system/do_update.c b/minix/kernel/system/do_update.c index 36559156e..14792c92e 100644 --- a/minix/kernel/system/do_update.c +++ b/minix/kernel/system/do_update.c @@ -20,6 +20,9 @@ (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \ || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING))) +static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp); +static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp); +static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp); static void adjust_proc_slot(struct proc *rp, struct proc *from_rp); static void adjust_priv_slot(struct priv *privp, struct priv *from_privp); @@ -42,7 +45,7 @@ int do_update(struct proc * caller, message * m_ptr) struct proc orig_dst_proc; struct priv orig_src_priv; struct priv orig_dst_priv; - int i; + int i, r; /* Lookup slots for source and destination process. */ src_e = m_ptr->SYS_UPD_SRC_ENDPT; @@ -82,6 +85,20 @@ int do_update(struct proc * caller, message * m_ptr) printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint); #endif + /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */ + r = inherit_priv_irq(src_rp, dst_rp); + if(r != OK) { + return r; + } + r = inherit_priv_io(src_rp, dst_rp); + if(r != OK) { + return r; + } + r = inherit_priv_mem(src_rp, dst_rp); + if(r != OK) { + return r; + } + /* Let destination inherit the target mask from source. */ for (i=0; i < NR_SYS_PROCS; i++) { if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) { @@ -130,6 +147,54 @@ int do_update(struct proc * caller, message * m_ptr) return OK; } +/*===========================================================================* + * inherit_priv_irq * + *===========================================================================*/ +int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp) +{ + int i, r; + for (i= 0; is_nr_irq; i++) { + r = priv_add_irq(dst_rp, priv(src_rp)->s_irq_tab[i]); + if(r != OK) { + return r; + } + } + + return OK; +} + +/*===========================================================================* + * inherit_priv_io * + *===========================================================================*/ + int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp) +{ + int i, r; + for (i= 0; is_nr_io_range; i++) { + r = priv_add_io(dst_rp, &(priv(src_rp)->s_io_tab[i])); + if(r != OK) { + return r; + } + } + + return OK; +} + +/*===========================================================================* + * inherit_priv_mem * + *===========================================================================*/ +int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp) +{ + int i, r; + for (i= 0; is_nr_mem_range; i++) { + r = priv_add_mem(dst_rp, &(priv(src_rp)->s_mem_tab[i])); + if(r != OK) { + return r; + } + } + + return OK; +} + /*===========================================================================* * adjust_proc_slot * *===========================================================================*/