merging in memory freeer.
[minix3.git] / kernel / system / do_privctl.c
blobc76706dc921b628aaceb9028723316fda706a37b
1 /* The kernel call implemented in this file:
2 * m_type: SYS_PRIVCTL
4 * The parameters for this kernel call are:
5 * m1_i1: PR_ENDPT (process number of caller)
6 */
8 #include "../system.h"
9 #include "../ipc.h"
10 #include <signal.h>
11 #include <string.h>
13 #if USE_PRIVCTL
15 #define FILLED_MASK (~0)
17 /*===========================================================================*
18 * do_privctl *
19 *===========================================================================*/
20 PUBLIC int do_privctl(m_ptr)
21 message *m_ptr; /* pointer to request message */
23 /* Handle sys_privctl(). Update a process' privileges. If the process is not
24 * yet a system process, make sure it gets its own privilege structure.
26 register struct proc *caller_ptr;
27 register struct proc *rp;
28 register struct priv *sp;
29 int proc_nr;
30 int priv_id;
31 int i, r;
32 struct io_range io_range;
33 struct mem_range mem_range;
34 struct priv priv;
36 /* Check whether caller is allowed to make this call. Privileged proceses
37 * can only update the privileges of processes that are inhibited from
38 * running by the NO_PRIV flag. This flag is set when a privileged process
39 * forks.
41 caller_ptr = proc_addr(who_p);
42 if (! (priv(caller_ptr)->s_flags & SYS_PROC)) return(EPERM);
43 if(m_ptr->PR_ENDPT == SELF) proc_nr = who_p;
44 else if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return(EINVAL);
45 rp = proc_addr(proc_nr);
47 switch(m_ptr->CTL_REQUEST)
49 case SYS_PRIV_INIT:
50 if (! RTS_ISSET(rp, NO_PRIV)) return(EPERM);
52 /* Make sure this process has its own privileges structure. This may
53 * fail, since there are only a limited number of system processes.
54 * Then copy the privileges from the caller and restore some defaults.
56 if ((i=get_priv(rp, SYS_PROC)) != OK)
58 kprintf("do_privctl: out of priv structures\n");
59 return(i);
61 priv_id = priv(rp)->s_id; /* backup privilege id */
62 *priv(rp) = *priv(caller_ptr); /* copy from caller */
63 priv(rp)->s_id = priv_id; /* restore privilege id */
64 priv(rp)->s_proc_nr = proc_nr; /* reassociate process nr */
66 for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
67 priv(rp)->s_notify_pending.chunk[i] = 0; /* - notifications */
68 priv(rp)->s_int_pending = 0; /* - interrupts */
69 sigemptyset(&priv(rp)->s_sig_pending); /* - signals */
71 /* Now update the process' privileges as requested. */
72 rp->p_priv->s_trap_mask = FILLED_MASK;
73 for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
74 rp->p_priv->s_ipc_to.chunk[i] = FILLED_MASK;
76 unset_sys_bit(rp->p_priv->s_ipc_to, USER_PRIV_ID);
78 /* All process that this process can send to must be able to reply.
79 * Therefore, their send masks should be updated as well.
81 for (i=0; i<NR_SYS_PROCS; i++) {
82 if (get_sys_bit(rp->p_priv->s_ipc_to, i)) {
83 set_sys_bit(priv_addr(i)->s_ipc_to, priv_id(rp));
87 for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
88 rp->p_priv->s_ipc_sendrec.chunk[i] = FILLED_MASK;
90 unset_sys_bit(rp->p_priv->s_ipc_sendrec, USER_PRIV_ID);
92 /* No I/O resources, no memory resources, no IRQs, no grant table */
93 priv(rp)->s_nr_io_range= 0;
94 priv(rp)->s_nr_mem_range= 0;
95 priv(rp)->s_nr_irq= 0;
96 priv(rp)->s_grant_table= 0;
97 priv(rp)->s_grant_entries= 0;
99 if (m_ptr->CTL_ARG_PTR)
101 /* Copy privilege structure from caller */
102 if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
103 SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
104 return r;
106 /* Copy the call mask */
107 for (i= 0; i<CALL_MASK_SIZE; i++)
108 priv(rp)->s_k_call_mask[i]= priv.s_k_call_mask[i];
110 /* Copy IRQs */
111 if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
112 return EINVAL;
113 priv(rp)->s_nr_irq= priv.s_nr_irq;
114 for (i= 0; i<priv.s_nr_irq; i++)
116 priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
117 #if 0
118 kprintf("do_privctl: adding IRQ %d for %d\n",
119 priv(rp)->s_irq_tab[i], rp->p_endpoint);
120 #endif
123 priv(rp)->s_flags |= CHECK_IRQ; /* Check requests for IRQs */
125 /* Copy I/O ranges */
126 if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
127 return EINVAL;
128 priv(rp)->s_nr_io_range= priv.s_nr_io_range;
129 for (i= 0; i<priv.s_nr_io_range; i++)
131 priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
132 #if 0
133 kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
134 priv(rp)->s_io_tab[i].ior_base,
135 priv(rp)->s_io_tab[i].ior_limit,
136 rp->p_endpoint);
137 #endif
140 /* Check requests for IRQs */
141 priv(rp)->s_flags |= CHECK_IO_PORT;
143 memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
144 sizeof(priv(rp)->s_k_call_mask));
145 memcpy(&priv(rp)->s_ipc_to, &priv.s_ipc_to,
146 sizeof(priv(rp)->s_ipc_to));
147 memcpy(&priv(rp)->s_ipc_sendrec, &priv.s_ipc_sendrec,
148 sizeof(priv(rp)->s_ipc_sendrec));
151 /* Done. Privileges have been set. Allow process to run again. */
152 RTS_LOCK_UNSET(rp, NO_PRIV);
153 return(OK);
154 case SYS_PRIV_USER:
155 /* Make this process an ordinary user process. */
156 if (!RTS_ISSET(rp, NO_PRIV)) return(EPERM);
157 if ((i=get_priv(rp, 0)) != OK) return(i);
158 RTS_LOCK_UNSET(rp, NO_PRIV);
159 return(OK);
161 case SYS_PRIV_ADD_IO:
162 if (RTS_ISSET(rp, NO_PRIV))
163 return(EPERM);
165 /* Only system processes get I/O resources? */
166 if (!(priv(rp)->s_flags & SYS_PROC))
167 return EPERM;
169 #if 0 /* XXX -- do we need a call for this? */
170 if (strcmp(rp->p_name, "fxp") == 0 ||
171 strcmp(rp->p_name, "rtl8139") == 0)
173 kprintf("setting ipc_stats_target to %d\n", rp->p_endpoint);
174 ipc_stats_target= rp->p_endpoint;
176 #endif
178 /* Get the I/O range */
179 data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
180 SYSTEM, (vir_bytes) &io_range, sizeof(io_range));
181 priv(rp)->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */
182 i= priv(rp)->s_nr_io_range;
183 if (i >= NR_IO_RANGE)
184 return ENOMEM;
186 priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
187 priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
188 priv(rp)->s_nr_io_range++;
190 return OK;
192 case SYS_PRIV_ADD_MEM:
193 if (RTS_ISSET(rp, NO_PRIV))
194 return(EPERM);
196 /* Only system processes get memory resources? */
197 if (!(priv(rp)->s_flags & SYS_PROC))
198 return EPERM;
200 /* Get the memory range */
201 if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
202 SYSTEM, (vir_bytes) &mem_range, sizeof(mem_range))) != OK)
203 return r;
204 priv(rp)->s_flags |= CHECK_MEM; /* Check I/O accesses */
205 i= priv(rp)->s_nr_mem_range;
206 if (i >= NR_MEM_RANGE)
207 return ENOMEM;
209 #if 0
210 priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
211 priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
212 priv(rp)->s_nr_mem_range++;
213 #endif
215 return OK;
217 case SYS_PRIV_ADD_IRQ:
218 if (RTS_ISSET(rp, NO_PRIV))
219 return(EPERM);
221 /* Only system processes get IRQs? */
222 if (!(priv(rp)->s_flags & SYS_PROC))
223 return EPERM;
225 priv(rp)->s_flags |= CHECK_IRQ; /* Check IRQs */
227 i= priv(rp)->s_nr_irq;
228 if (i >= NR_IRQ)
229 return ENOMEM;
230 priv(rp)->s_irq_tab[i]= m_ptr->CTL_MM_PRIV;
231 priv(rp)->s_nr_irq++;
233 return OK;
234 default:
235 kprintf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
236 return EINVAL;
240 #endif /* USE_PRIVCTL */