Initialize priv from user supplied priv structure in SYS_PRIV_INIT.

Added SYS_PRIV_USER call to downgrade a privileged process to a user process.
This commit is contained in:
Philip Homburg 2006-10-20 14:42:48 +00:00
parent 1ce2f75627
commit dd3ee082b2
2 changed files with 63 additions and 0 deletions

View file

@ -315,6 +315,9 @@
#define SYS_PRIV_ADD_MEM 3 /* Add memory range (struct mem_range)
*/
#define SYS_PRIV_ADD_IRQ 4 /* Add IRQ */
#define SYS_PRIV_USER 5 /* Make a process an oridinary user
* process.
*/
/* Subfunctions for SYS_SETGRANT */
#define SYS_PARAM_SET_GRANT 1 /* Set address and size of grant table */

View file

@ -32,6 +32,7 @@ message *m_ptr; /* pointer to request message */
phys_bytes caller_phys, kernel_phys;
struct io_range io_range;
struct mem_range mem_range;
struct priv priv;
/* Check whether caller is allowed to make this call. Privileged proceses
* can only update the privileges of processes that are inhibited from
@ -87,11 +88,70 @@ message *m_ptr; /* pointer to request message */
priv(rp)->s_grant_table= 0;
priv(rp)->s_grant_entries= 0;
if (m_ptr->CTL_ARG_PTR)
{
/* Copy privilege structure from caller */
caller_phys = umap_local(caller_ptr, D,
(vir_bytes) m_ptr->CTL_ARG_PTR, sizeof(priv));
if (caller_phys == 0)
return EFAULT;
kernel_phys = vir2phys(&priv);
phys_copy(caller_phys, kernel_phys, sizeof(priv));
/* Copy the call mask */
for (i= 0; i<CALL_MASK_SIZE; i++)
priv(rp)->s_k_call_mask[i]= priv.s_k_call_mask[i];
/* Copy IRQs */
if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
return EINVAL;
priv(rp)->s_nr_irq= priv.s_nr_irq;
for (i= 0; i<priv.s_nr_irq; i++)
{
priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
kprintf("do_privctl: adding IRQ %d\n",
priv(rp)->s_irq_tab[i]);
}
priv(rp)->s_flags |= CHECK_IRQ; /* Check requests for IRQs */
/* Copy I/O ranges */
if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
return EINVAL;
priv(rp)->s_nr_io_range= priv.s_nr_io_range;
for (i= 0; i<priv.s_nr_io_range; i++)
{
priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
kprintf("do_privctl: adding I/O range [%x..%x]\n",
priv(rp)->s_io_tab[i].ior_base,
priv(rp)->s_io_tab[i].ior_limit);
}
/* Check requests for IRQs */
priv(rp)->s_flags |= CHECK_IO_PORT;
memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
sizeof(priv(rp)->s_k_call_mask));
}
/* Done. Privileges have been set. Allow process to run again. */
old_flags = rp->p_rts_flags; /* save value of the flags */
rp->p_rts_flags &= ~NO_PRIV;
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
return(OK);
case SYS_PRIV_USER:
if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
/* Make this process an ordinary user process.
*/
if ((i=get_priv(rp, 0)) != OK) return(i);
/* Done. Privileges have been set. Allow process to run again. */
old_flags = rp->p_rts_flags; /* save value of the flags */
rp->p_rts_flags &= ~NO_PRIV;
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
return(OK);
case SYS_PRIV_ADD_IO:
if (rp->p_rts_flags & NO_PRIV)
return(EPERM);