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 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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
Loading…
Reference in a new issue