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:
parent
9e6b1315c3
commit
56e56d2af2
4 changed files with 158 additions and 59 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; 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 *
|
||||
*===========================================================================*/
|
||||
|
|
Loading…
Reference in a new issue