]> Zhao Yanbai Git Server - minix.git/commitdiff
Initialize priv from user supplied priv structure in SYS_PRIV_INIT.
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 20 Oct 2006 14:42:48 +0000 (14:42 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 20 Oct 2006 14:42:48 +0000 (14:42 +0000)
Added SYS_PRIV_USER call to downgrade a privileged process to a user process.

include/minix/com.h
kernel/system/do_privctl.c

index 39edd36d23cf8ea6ea289b668f48de17f7cf05f6..1705d128b776ac8f48d1fb96852a56aa5d2b6d66 100755 (executable)
 #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 */
index b84ca435b02a60c9c0683f7f06d7a35ce0b723c4..b9943e66be193d1f1f906bf4d6354403017b3bf8 100644 (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);