kernel: kill proc with bogus ipc address
[minix.git] / kernel / system / do_privctl.c
blob9bc2366de290f0859a931164531dff32b2177217
1 /* The kernel call implemented in this file:
2 * m_type: SYS_PRIVCTL
4 * The parameters for this kernel call are:
5 * m2_i1: CTL_ENDPT (process endpoint of target)
6 * m2_i2: CTL_REQUEST (privilege control request)
7 * m2_p1: CTL_ARG_PTR (pointer to request data)
8 */
10 #include "kernel/system.h"
11 #include "kernel/ipc.h"
12 #include <signal.h>
13 #include <string.h>
14 #include <minix/endpoint.h>
16 #if USE_PRIVCTL
18 #define PRIV_DEBUG 0
20 static int update_priv(struct proc *rp, struct priv *priv);
22 /*===========================================================================*
23 * do_privctl *
24 *===========================================================================*/
25 int do_privctl(struct proc * caller, message * m_ptr)
27 /* Handle sys_privctl(). Update a process' privileges. If the process is not
28 * yet a system process, make sure it gets its own privilege structure.
30 struct proc *rp;
31 proc_nr_t proc_nr;
32 sys_id_t priv_id;
33 sys_map_t map;
34 int ipc_to_m, kcalls;
35 int i, r;
36 struct io_range io_range;
37 struct minix_mem_range mem_range;
38 struct priv priv;
39 int irq;
41 /* Check whether caller is allowed to make this call. Privileged proceses
42 * can only update the privileges of processes that are inhibited from
43 * running by the RTS_NO_PRIV flag. This flag is set when a privileged process
44 * forks.
46 if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
47 if(m_ptr->CTL_ENDPT == SELF) okendpt(caller->p_endpoint, &proc_nr);
48 else if(!isokendpt(m_ptr->CTL_ENDPT, &proc_nr)) return(EINVAL);
49 rp = proc_addr(proc_nr);
51 switch(m_ptr->CTL_REQUEST)
53 case SYS_PRIV_ALLOW:
54 /* Allow process to run. Make sure its privilege structure has already
55 * been set.
57 if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
58 return(EPERM);
60 RTS_UNSET(rp, RTS_NO_PRIV);
61 return(OK);
63 case SYS_PRIV_YIELD:
64 /* Allow process to run and suspend the caller. */
65 if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
66 return(EPERM);
68 RTS_SET(caller, RTS_NO_PRIV);
69 RTS_UNSET(rp, RTS_NO_PRIV);
70 return(OK);
72 case SYS_PRIV_DISALLOW:
73 /* Disallow process from running. */
74 if (RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
75 RTS_SET(rp, RTS_NO_PRIV);
76 return(OK);
78 case SYS_PRIV_SET_SYS:
79 /* Set a privilege structure of a blocked system process. */
80 if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
82 /* Check whether a static or dynamic privilege id must be allocated. */
83 priv_id = NULL_PRIV_ID;
84 if (m_ptr->CTL_ARG_PTR)
86 /* Copy privilege structure from caller */
87 if((r=data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
88 KERNEL, (vir_bytes) &priv, sizeof(priv))) != OK)
89 return r;
91 /* See if the caller wants to assign a static privilege id. */
92 if(!(priv.s_flags & DYN_PRIV_ID)) {
93 priv_id = priv.s_id;
97 /* Make sure this process has its own privileges structure. This may
98 * fail, since there are only a limited number of system processes.
99 * Then copy privileges from the caller and restore some defaults.
101 if ((i=get_priv(rp, priv_id)) != OK)
103 printf("do_privctl: unable to allocate priv_id %d: %d\n",
104 priv_id, i);
105 return(i);
107 priv_id = priv(rp)->s_id; /* backup privilege id */
108 *priv(rp) = *priv(caller); /* copy from caller */
109 priv(rp)->s_id = priv_id; /* restore privilege id */
110 priv(rp)->s_proc_nr = proc_nr; /* reassociate process nr */
112 for (i=0; i< NR_SYS_CHUNKS; i++) /* remove pending: */
113 priv(rp)->s_notify_pending.chunk[i] = 0; /* - notifications */
114 priv(rp)->s_int_pending = 0; /* - interrupts */
115 (void) sigemptyset(&priv(rp)->s_sig_pending); /* - signals */
116 reset_timer(&priv(rp)->s_alarm_timer); /* - alarm */
117 priv(rp)->s_asyntab= -1; /* - asynsends */
118 priv(rp)->s_asynsize= 0;
120 /* Set defaults for privilege bitmaps. */
121 priv(rp)->s_flags= DSRV_F; /* privilege flags */
122 priv(rp)->s_trap_mask= DSRV_T; /* allowed traps */
123 memset(&map, 0, sizeof(map));
124 ipc_to_m = DSRV_M; /* allowed targets */
125 if (ipc_to_m == ALL_M) {
126 for (i = 0; i < NR_SYS_PROCS; i++)
127 set_sys_bit(map, i);
129 fill_sendto_mask(rp, &map);
130 kcalls = DSRV_KC; /* allowed kernel calls */
131 for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
132 priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
135 /* Set the default signal managers. */
136 priv(rp)->s_sig_mgr = DSRV_SM;
137 priv(rp)->s_bak_sig_mgr = NONE;
139 /* Set defaults for resources: no I/O resources, no memory resources,
140 * no IRQs, no grant table
142 priv(rp)->s_nr_io_range= 0;
143 priv(rp)->s_nr_mem_range= 0;
144 priv(rp)->s_nr_irq= 0;
145 priv(rp)->s_grant_table= 0;
146 priv(rp)->s_grant_entries= 0;
148 /* Override defaults if the caller has supplied a privilege structure. */
149 if (m_ptr->CTL_ARG_PTR)
151 if((r = update_priv(rp, &priv)) != OK) {
152 return r;
156 return(OK);
158 case SYS_PRIV_SET_USER:
159 /* Set a privilege structure of a blocked user process. */
160 if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
162 /* Link the process to the privilege structure of the root user
163 * process all the user processes share.
165 priv(rp) = priv_addr(USER_PRIV_ID);
167 return(OK);
169 case SYS_PRIV_ADD_IO:
170 if (RTS_ISSET(rp, RTS_NO_PRIV))
171 return(EPERM);
173 /* Only system processes get I/O resources? */
174 if (!(priv(rp)->s_flags & SYS_PROC))
175 return EPERM;
177 #if 0 /* XXX -- do we need a call for this? */
178 if (strcmp(rp->p_name, "fxp") == 0 ||
179 strcmp(rp->p_name, "rtl8139") == 0)
181 printf("setting ipc_stats_target to %d\n", rp->p_endpoint);
182 ipc_stats_target= rp->p_endpoint;
184 #endif
186 /* Get the I/O range */
187 data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
188 KERNEL, (vir_bytes) &io_range, sizeof(io_range));
189 priv(rp)->s_flags |= CHECK_IO_PORT; /* Check I/O accesses */
191 for (i = 0; i < priv(rp)->s_nr_io_range; i++) {
192 if (priv(rp)->s_io_tab[i].ior_base == io_range.ior_base &&
193 priv(rp)->s_io_tab[i].ior_limit == io_range.ior_limit)
194 return OK;
197 i= priv(rp)->s_nr_io_range;
198 if (i >= NR_IO_RANGE) {
199 printf("do_privctl: %d already has %d i/o ranges.\n",
200 rp->p_endpoint, i);
201 return ENOMEM;
204 priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
205 priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
206 priv(rp)->s_nr_io_range++;
208 return OK;
210 case SYS_PRIV_ADD_MEM:
211 if (RTS_ISSET(rp, RTS_NO_PRIV))
212 return(EPERM);
214 /* Only system processes get memory resources? */
215 if (!(priv(rp)->s_flags & SYS_PROC))
216 return EPERM;
218 /* Get the memory range */
219 if((r=data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
220 KERNEL, (vir_bytes) &mem_range, sizeof(mem_range))) != OK)
221 return r;
222 priv(rp)->s_flags |= CHECK_MEM; /* Check memory mappings */
224 /* When restarting a driver, check if it already has the premission */
225 for (i = 0; i < priv(rp)->s_nr_mem_range; i++) {
226 if (priv(rp)->s_mem_tab[i].mr_base == mem_range.mr_base &&
227 priv(rp)->s_mem_tab[i].mr_limit == mem_range.mr_limit)
228 return OK;
231 i= priv(rp)->s_nr_mem_range;
232 if (i >= NR_MEM_RANGE) {
233 printf("do_privctl: %d already has %d mem ranges.\n",
234 rp->p_endpoint, i);
235 return ENOMEM;
238 priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
239 priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
240 priv(rp)->s_nr_mem_range++;
242 return OK;
244 case SYS_PRIV_ADD_IRQ:
245 if (RTS_ISSET(rp, RTS_NO_PRIV))
246 return(EPERM);
248 /* Only system processes get IRQs? */
249 if (!(priv(rp)->s_flags & SYS_PROC))
250 return EPERM;
252 data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
253 KERNEL, (vir_bytes) &irq, sizeof(irq));
254 priv(rp)->s_flags |= CHECK_IRQ; /* Check IRQs */
256 /* When restarting a driver, check if it already has the premission */
257 for (i = 0; i < priv(rp)->s_nr_irq; i++) {
258 if (priv(rp)->s_irq_tab[i] == irq)
259 return OK;
262 i= priv(rp)->s_nr_irq;
263 if (i >= NR_IRQ) {
264 printf("do_privctl: %d already has %d irq's.\n",
265 rp->p_endpoint, i);
266 return ENOMEM;
268 priv(rp)->s_irq_tab[i]= irq;
269 priv(rp)->s_nr_irq++;
271 return OK;
272 case SYS_PRIV_QUERY_MEM:
274 phys_bytes addr, limit;
275 struct priv *sp;
276 /* See if a certain process is allowed to map in certain physical
277 * memory.
279 addr = (phys_bytes) m_ptr->CTL_PHYSSTART;
280 limit = addr + (phys_bytes) m_ptr->CTL_PHYSLEN - 1;
281 if(limit < addr)
282 return EPERM;
283 if(!(sp = priv(rp)))
284 return EPERM;
285 if (!(sp->s_flags & SYS_PROC))
286 return EPERM;
287 for(i = 0; i < sp->s_nr_mem_range; i++) {
288 if(addr >= sp->s_mem_tab[i].mr_base &&
289 limit <= sp->s_mem_tab[i].mr_limit)
290 return OK;
292 return EPERM;
295 case SYS_PRIV_UPDATE_SYS:
296 /* Update the privilege structure of a system process. */
297 if(!m_ptr->CTL_ARG_PTR) return EINVAL;
299 /* Copy privilege structure from caller */
300 if((r=data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
301 KERNEL, (vir_bytes) &priv, sizeof(priv))) != OK)
302 return r;
304 /* Override settings in existing privilege structure. */
305 if((r = update_priv(rp, &priv)) != OK) {
306 return r;
309 return(OK);
311 default:
312 printf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
313 return EINVAL;
317 /*===========================================================================*
318 * update_priv *
319 *===========================================================================*/
320 static int update_priv(struct proc *rp, struct priv *priv)
322 /* Update the privilege structure of a given process. */
324 int i;
326 /* Copy s_flags and signal managers. */
327 priv(rp)->s_flags = priv->s_flags;
328 priv(rp)->s_sig_mgr = priv->s_sig_mgr;
329 priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
331 /* Copy IRQs. */
332 if(priv->s_flags & CHECK_IRQ) {
333 if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
334 return EINVAL;
335 priv(rp)->s_nr_irq= priv->s_nr_irq;
336 for (i= 0; i<priv->s_nr_irq; i++)
338 priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
339 #if PRIV_DEBUG
340 printf("do_privctl: adding IRQ %d for %d\n",
341 priv(rp)->s_irq_tab[i], rp->p_endpoint);
342 #endif
346 /* Copy I/O ranges. */
347 if(priv->s_flags & CHECK_IO_PORT) {
348 if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
349 return EINVAL;
350 priv(rp)->s_nr_io_range= priv->s_nr_io_range;
351 for (i= 0; i<priv->s_nr_io_range; i++)
353 priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
354 #if PRIV_DEBUG
355 printf("do_privctl: adding I/O range [%x..%x] for %d\n",
356 priv(rp)->s_io_tab[i].ior_base,
357 priv(rp)->s_io_tab[i].ior_limit,
358 rp->p_endpoint);
359 #endif
363 /* Copy memory ranges. */
364 if(priv->s_flags & CHECK_MEM) {
365 if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
366 return EINVAL;
367 priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
368 for (i= 0; i<priv->s_nr_mem_range; i++)
370 priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
371 #if PRIV_DEBUG
372 printf("do_privctl: adding mem range [%x..%x] for %d\n",
373 priv(rp)->s_mem_tab[i].mr_base,
374 priv(rp)->s_mem_tab[i].mr_limit,
375 rp->p_endpoint);
376 #endif
380 /* Copy trap mask. */
381 priv(rp)->s_trap_mask = priv->s_trap_mask;
383 /* Copy target mask. */
384 #if PRIV_DEBUG
385 printf("do_privctl: Setting ipc target mask for %d:");
386 for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
387 printf(" %08x", get_sys_bits(priv->s_ipc_to, i));
389 printf("\n");
390 #endif
392 fill_sendto_mask(rp, &priv->s_ipc_to);
394 #if PRIV_DEBUG
395 printf("do_privctl: Set ipc target mask for %d:");
396 for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
397 printf(" %08x", get_sys_bits(priv(rp)->s_ipc_to, i));
399 printf("\n");
400 #endif
402 /* Copy kernel call mask. */
403 memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
404 sizeof(priv(rp)->s_k_call_mask));
406 return OK;
409 #endif /* USE_PRIVCTL */