Store resource lists for drivers. Limited checks to enforce those lists.
This commit is contained in:
parent
ee2253ec52
commit
38a16399f8
@ -16,6 +16,15 @@
|
|||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
|
/* Max. number of I/O ranges that can be assigned to a process */
|
||||||
|
#define NR_IO_RANGE 10
|
||||||
|
|
||||||
|
/* Max. number of device memory ranges that can be assigned to a process */
|
||||||
|
#define NR_MEM_RANGE 10
|
||||||
|
|
||||||
|
/* Max. number of IRQs that can be assigned to a process */
|
||||||
|
#define NR_IRQ 4
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
proc_nr_t s_proc_nr; /* number of associated process */
|
proc_nr_t s_proc_nr; /* number of associated process */
|
||||||
sys_id_t s_id; /* index of this system structure */
|
sys_id_t s_id; /* index of this system structure */
|
||||||
@ -33,6 +42,15 @@ struct priv {
|
|||||||
timer_t s_alarm_timer; /* synchronous alarm timer */
|
timer_t s_alarm_timer; /* synchronous alarm timer */
|
||||||
struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */
|
struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */
|
||||||
reg_t *s_stack_guard; /* stack guard word for kernel tasks */
|
reg_t *s_stack_guard; /* stack guard word for kernel tasks */
|
||||||
|
|
||||||
|
int s_nr_io_range;
|
||||||
|
struct io_range s_io_tab[NR_IO_RANGE];
|
||||||
|
|
||||||
|
int s_nr_mem_range;
|
||||||
|
struct mem_range s_mem_tab[NR_MEM_RANGE];
|
||||||
|
|
||||||
|
int s_nr_irq;
|
||||||
|
int s_irq_tab[NR_IRQ];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Guard word for task stacks. */
|
/* Guard word for task stacks. */
|
||||||
@ -43,6 +61,11 @@ struct priv {
|
|||||||
#define BILLABLE 0x04 /* some processes are not billable */
|
#define BILLABLE 0x04 /* some processes are not billable */
|
||||||
#define SYS_PROC 0x10 /* system processes are privileged */
|
#define SYS_PROC 0x10 /* system processes are privileged */
|
||||||
#define SENDREC_BUSY 0x20 /* sendrec() in progress */
|
#define SENDREC_BUSY 0x20 /* sendrec() in progress */
|
||||||
|
#define CHECK_IO_PORT 0x40 /* Check whether an I/O request is allowed */
|
||||||
|
#define CHECK_MEM 0x80 /* Check whether a (vm) memory map request is
|
||||||
|
* allowed
|
||||||
|
*/
|
||||||
|
#define CHECK_IRQ 0x100 /* Check whether an IRQ can be used */
|
||||||
|
|
||||||
/* Magic system structure table addresses. */
|
/* Magic system structure table addresses. */
|
||||||
#define BEG_PRIV_ADDR (&priv[0])
|
#define BEG_PRIV_ADDR (&priv[0])
|
||||||
|
@ -19,6 +19,46 @@
|
|||||||
PUBLIC int do_devio(m_ptr)
|
PUBLIC int do_devio(m_ptr)
|
||||||
register message *m_ptr; /* pointer to request message */
|
register message *m_ptr; /* pointer to request message */
|
||||||
{
|
{
|
||||||
|
struct proc *rp;
|
||||||
|
struct priv *privp;
|
||||||
|
port_t port;
|
||||||
|
struct io_range *iorp;
|
||||||
|
int i, size, nr_io_range;
|
||||||
|
|
||||||
|
rp= proc_addr(m_ptr->m_source);
|
||||||
|
privp= priv(rp);
|
||||||
|
if (!privp)
|
||||||
|
{
|
||||||
|
kprintf("no priv structure!\n");
|
||||||
|
goto doit;
|
||||||
|
}
|
||||||
|
if (privp->s_flags & CHECK_IO_PORT)
|
||||||
|
{
|
||||||
|
switch (m_ptr->DIO_TYPE)
|
||||||
|
{
|
||||||
|
case DIO_BYTE: size= 1; break;
|
||||||
|
case DIO_WORD: size= 2; break;
|
||||||
|
case DIO_LONG: size= 4; break;
|
||||||
|
default: size= 4; break; /* Be conservative */
|
||||||
|
}
|
||||||
|
port= m_ptr->DIO_PORT;
|
||||||
|
nr_io_range= privp->s_nr_io_range;
|
||||||
|
for (i= 0, iorp= privp->s_io_tab; i<nr_io_range; i++, iorp++)
|
||||||
|
{
|
||||||
|
if (port >= iorp->ior_base && port+size-1 <= iorp->ior_limit)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= nr_io_range)
|
||||||
|
{
|
||||||
|
kprintf(
|
||||||
|
"do_devio: I/O port check failed for proc %d, port 0x%x\n",
|
||||||
|
m_ptr->m_source, port);
|
||||||
|
return EPERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doit:
|
||||||
|
|
||||||
/* Process a single I/O request for byte, word, and long values. */
|
/* Process a single I/O request for byte, word, and long values. */
|
||||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||||
switch (m_ptr->DIO_TYPE) {
|
switch (m_ptr->DIO_TYPE) {
|
||||||
|
@ -26,7 +26,10 @@ register message *m_ptr; /* pointer to request message */
|
|||||||
int irq_hook_id;
|
int irq_hook_id;
|
||||||
int notify_id;
|
int notify_id;
|
||||||
int r = OK;
|
int r = OK;
|
||||||
|
int i;
|
||||||
irq_hook_t *hook_ptr;
|
irq_hook_t *hook_ptr;
|
||||||
|
struct proc *rp;
|
||||||
|
struct priv *privp;
|
||||||
|
|
||||||
/* Hook identifiers start at 1 and end at NR_IRQ_HOOKS. */
|
/* Hook identifiers start at 1 and end at NR_IRQ_HOOKS. */
|
||||||
irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID - 1;
|
irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID - 1;
|
||||||
@ -55,6 +58,29 @@ register message *m_ptr; /* pointer to request message */
|
|||||||
/* Check if IRQ line is acceptable. */
|
/* Check if IRQ line is acceptable. */
|
||||||
if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL);
|
if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL);
|
||||||
|
|
||||||
|
rp= proc_addr(m_ptr->m_source);
|
||||||
|
privp= priv(rp);
|
||||||
|
if (!privp)
|
||||||
|
{
|
||||||
|
kprintf("no priv structure!\n");
|
||||||
|
return EPERM;
|
||||||
|
}
|
||||||
|
if (privp->s_flags & CHECK_IRQ)
|
||||||
|
{
|
||||||
|
for (i= 0; i<privp->s_nr_irq; i++)
|
||||||
|
{
|
||||||
|
if (irq_vec == privp->s_irq_tab[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= privp->s_nr_irq)
|
||||||
|
{
|
||||||
|
kprintf(
|
||||||
|
"do_irqctl: IRQ check failed for proc %d, IRQ %d\n",
|
||||||
|
m_ptr->m_source, irq_vec);
|
||||||
|
return EPERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find a free IRQ hook for this mapping. */
|
/* Find a free IRQ hook for this mapping. */
|
||||||
hook_ptr = NULL;
|
hook_ptr = NULL;
|
||||||
for (irq_hook_id=0; irq_hook_id<NR_IRQ_HOOKS; irq_hook_id++) {
|
for (irq_hook_id=0; irq_hook_id<NR_IRQ_HOOKS; irq_hook_id++) {
|
||||||
|
@ -29,6 +29,9 @@ message *m_ptr; /* pointer to request message */
|
|||||||
int priv_id;
|
int priv_id;
|
||||||
int old_flags;
|
int old_flags;
|
||||||
int i;
|
int i;
|
||||||
|
phys_bytes caller_phys, kernel_phys;
|
||||||
|
struct io_range io_range;
|
||||||
|
struct mem_range mem_range;
|
||||||
|
|
||||||
/* Check whether caller is allowed to make this call. Privileged proceses
|
/* Check whether caller is allowed to make this call. Privileged proceses
|
||||||
* can only update the privileges of processes that are inhibited from
|
* can only update the privileges of processes that are inhibited from
|
||||||
@ -40,11 +43,15 @@ message *m_ptr; /* pointer to request message */
|
|||||||
proc_nr = m_ptr->PR_PROC_NR;
|
proc_nr = m_ptr->PR_PROC_NR;
|
||||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||||
rp = proc_addr(proc_nr);
|
rp = proc_addr(proc_nr);
|
||||||
|
|
||||||
|
switch(m_ptr->CTL_REQUEST)
|
||||||
|
{
|
||||||
|
case SYS_PRIV_INIT:
|
||||||
if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
|
if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
|
||||||
|
|
||||||
/* Make sure this process has its own privileges structure. This may fail,
|
/* Make sure this process has its own privileges structure. This may
|
||||||
* since there are only a limited number of system processes. Then copy the
|
* fail, since there are only a limited number of system processes.
|
||||||
* privileges from the caller and restore some defaults.
|
* Then copy the privileges from the caller and restore some defaults.
|
||||||
*/
|
*/
|
||||||
if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
|
if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
|
||||||
priv_id = priv(rp)->s_id; /* backup privilege id */
|
priv_id = priv(rp)->s_id; /* backup privilege id */
|
||||||
@ -73,11 +80,100 @@ message *m_ptr; /* pointer to request message */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No I/O resources, no memory resources, no IRQs */
|
||||||
|
priv(rp)->s_nr_io_range= 0;
|
||||||
|
priv(rp)->s_nr_mem_range= 0;
|
||||||
|
priv(rp)->s_nr_irq= 0;
|
||||||
|
|
||||||
/* Done. Privileges have been set. Allow process to run again. */
|
/* Done. Privileges have been set. Allow process to run again. */
|
||||||
old_flags = rp->p_rts_flags; /* save value of the flags */
|
old_flags = rp->p_rts_flags; /* save value of the flags */
|
||||||
rp->p_rts_flags &= ~NO_PRIV;
|
rp->p_rts_flags &= ~NO_PRIV;
|
||||||
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
|
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
|
||||||
return(OK);
|
return(OK);
|
||||||
|
case SYS_PRIV_ADD_IO:
|
||||||
|
if (rp->p_rts_flags & NO_PRIV)
|
||||||
|
return(EPERM);
|
||||||
|
|
||||||
|
/* Only system processes get I/O resources? */
|
||||||
|
if (!(priv(rp)->s_flags & SYS_PROC))
|
||||||
|
return EPERM;
|
||||||
|
|
||||||
|
/* Get the I/O range */
|
||||||
|
caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
|
||||||
|
sizeof(io_range));
|
||||||
|
if (caller_phys == 0)
|
||||||
|
return EFAULT;
|
||||||
|
kernel_phys = vir2phys(&io_range);
|
||||||
|
phys_copy(caller_phys, kernel_phys, sizeof(io_range));
|
||||||
|
priv(rp)->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */
|
||||||
|
i= priv(rp)->s_nr_io_range;
|
||||||
|
if (i >= NR_IO_RANGE)
|
||||||
|
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++;
|
||||||
|
|
||||||
|
kprintf("do_privctl: added I/O range [0x%x..0x%x]\n",
|
||||||
|
io_range.ior_base, io_range.ior_limit);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
case SYS_PRIV_ADD_MEM:
|
||||||
|
if (rp->p_rts_flags & NO_PRIV)
|
||||||
|
return(EPERM);
|
||||||
|
|
||||||
|
/* Only system processes get memory resources? */
|
||||||
|
if (!(priv(rp)->s_flags & SYS_PROC))
|
||||||
|
return EPERM;
|
||||||
|
|
||||||
|
/* Get the memory range */
|
||||||
|
caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
|
||||||
|
sizeof(mem_range));
|
||||||
|
if (caller_phys == 0)
|
||||||
|
return EFAULT;
|
||||||
|
kernel_phys = vir2phys(&mem_range);
|
||||||
|
phys_copy(caller_phys, kernel_phys, sizeof(mem_range));
|
||||||
|
priv(rp)->s_flags |= CHECK_MEM; /* Check I/O accesses */
|
||||||
|
i= priv(rp)->s_nr_mem_range;
|
||||||
|
if (i >= NR_MEM_RANGE)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
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++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
kprintf("do_privctl: should add memory range [0x%x..0x%x]\n",
|
||||||
|
mem_range.mr_base, mem_range.mr_limit);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
case SYS_PRIV_ADD_IRQ:
|
||||||
|
if (rp->p_rts_flags & NO_PRIV)
|
||||||
|
return(EPERM);
|
||||||
|
|
||||||
|
/* Only system processes get IRQs? */
|
||||||
|
if (!(priv(rp)->s_flags & SYS_PROC))
|
||||||
|
return EPERM;
|
||||||
|
|
||||||
|
priv(rp)->s_flags |= CHECK_IRQ; /* Check IRQs */
|
||||||
|
|
||||||
|
i= priv(rp)->s_nr_irq;
|
||||||
|
if (i >= NR_IRQ)
|
||||||
|
return ENOMEM;
|
||||||
|
priv(rp)->s_irq_tab[i]= m_ptr->CTL_MM_PRIV;
|
||||||
|
priv(rp)->s_nr_irq++;
|
||||||
|
|
||||||
|
kprintf("do_privctl: adding IRQ %d\n", m_ptr->CTL_MM_PRIV);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
kprintf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_PRIVCTL */
|
#endif /* USE_PRIVCTL */
|
||||||
|
@ -82,6 +82,7 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
|||||||
#define PM_C ~(c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO) | c(SYS_IRQCTL) | c(SYS_INT86))
|
#define PM_C ~(c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO) | c(SYS_IRQCTL) | c(SYS_INT86))
|
||||||
#define FS_C (c(SYS_KILL) | c(SYS_VIRCOPY) | c(SYS_VIRVCOPY) | c(SYS_UMAP) | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM))
|
#define FS_C (c(SYS_KILL) | c(SYS_VIRCOPY) | c(SYS_VIRVCOPY) | c(SYS_UMAP) | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM))
|
||||||
#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO))
|
#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO))
|
||||||
|
#define PCI_C (c(SYS_VIRCOPY) | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO) | c(SYS_PRIVCTL))
|
||||||
#define TTY_C (DRV_C | c(SYS_ABORT) | c(SYS_VM_MAP) | c(SYS_IOPENABLE))
|
#define TTY_C (DRV_C | c(SYS_ABORT) | c(SYS_VM_MAP) | c(SYS_IOPENABLE))
|
||||||
#define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP) | \
|
#define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP) | \
|
||||||
c(SYS_IOPENABLE))
|
c(SYS_IOPENABLE))
|
||||||
@ -107,7 +108,7 @@ PUBLIC struct boot_image image[] = {
|
|||||||
{ MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, MEM_C, "memory"},
|
{ MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, MEM_C, "memory"},
|
||||||
{ LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
|
{ LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
|
||||||
{ DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
|
{ DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
|
||||||
{ PCI_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "pci"},
|
{ PCI_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, PCI_C, "pci"},
|
||||||
{ INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" },
|
{ INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user