kernel: Inherit allowed memory, IRQ & I/O ranges

Inherit at live update time all the priviledges previously acquired by
the process.

Change-Id: I1fd6ab16680ea85a1f3d8d1c106a7c716bf65e8e
This commit is contained in:
Cristiano Giuffrida 2014-03-11 17:56:03 +01:00 committed by David van Moolenbroek
parent 9e6b1315c3
commit 56e56d2af2
4 changed files with 158 additions and 59 deletions

View file

@ -107,6 +107,9 @@ void clear_ipc_filters(struct proc *rp);
int check_ipc_filter(struct ipc_filter_s *ipcf, int fill_flags); int check_ipc_filter(struct ipc_filter_s *ipcf, int fill_flags);
int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e, int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e,
vir_bytes m_src_v, message *m_src_p); 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 */ /* system/do_vtimer.c */
void vtimer_check(struct proc *rp); void vtimer_check(struct proc *rp);

View file

@ -841,3 +841,86 @@ int allow_ipc_filtered_msg(struct proc *rp, endpoint_t src_e,
return allow; 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;
}

View file

@ -198,26 +198,8 @@ int do_privctl(struct proc * caller, message * m_ptr)
/* Get the I/O range */ /* Get the I/O range */
data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr, data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
KERNEL, (vir_bytes) &io_range, sizeof(io_range)); KERNEL, (vir_bytes) &io_range, sizeof(io_range));
priv(rp)->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */ /* Add the I/O range */
return priv_add_io(rp, &io_range);
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;
case SYS_PRIV_ADD_MEM: case SYS_PRIV_ADD_MEM:
if (RTS_ISSET(rp, RTS_NO_PRIV)) 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, m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
(vir_bytes) &mem_range, sizeof(mem_range))) != OK) (vir_bytes) &mem_range, sizeof(mem_range))) != OK)
return r; return r;
priv(rp)->s_flags |= CHECK_MEM; /* Check memory mappings */ /* Add the memory range */
return priv_add_mem(rp, &mem_range);
/* 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;
case SYS_PRIV_ADD_IRQ: case SYS_PRIV_ADD_IRQ:
if (RTS_ISSET(rp, RTS_NO_PRIV)) if (RTS_ISSET(rp, RTS_NO_PRIV))
@ -261,24 +224,9 @@ int do_privctl(struct proc * caller, message * m_ptr)
#endif #endif
data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr, data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
KERNEL, (vir_bytes) &irq, sizeof(irq)); 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: case SYS_PRIV_QUERY_MEM:
{ {
phys_bytes addr, limit; phys_bytes addr, limit;

View file

@ -20,6 +20,9 @@
(RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \ (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
|| (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING))) || (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_proc_slot(struct proc *rp, struct proc *from_rp);
static void adjust_priv_slot(struct priv *privp, struct priv static void adjust_priv_slot(struct priv *privp, struct priv
*from_privp); *from_privp);
@ -42,7 +45,7 @@ int do_update(struct proc * caller, message * m_ptr)
struct proc orig_dst_proc; struct proc orig_dst_proc;
struct priv orig_src_priv; struct priv orig_src_priv;
struct priv orig_dst_priv; struct priv orig_dst_priv;
int i; int i, r;
/* Lookup slots for source and destination process. */ /* Lookup slots for source and destination process. */
src_e = m_ptr->SYS_UPD_SRC_ENDPT; 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); printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
#endif #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. */ /* Let destination inherit the target mask from source. */
for (i=0; i < NR_SYS_PROCS; i++) { for (i=0; i < NR_SYS_PROCS; i++) {
if (get_sys_bit(priv(src_rp)->s_ipc_to, 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; return OK;
} }
/*===========================================================================*
* inherit_priv_irq *
*===========================================================================*/
int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp)
{
int i, r;
for (i= 0; i<priv(src_rp)->s_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; i<priv(src_rp)->s_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; i<priv(src_rp)->s_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 * * adjust_proc_slot *
*===========================================================================*/ *===========================================================================*/