xref: /minix3/minix/kernel/system/do_privctl.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /* The kernel call implemented in this file:
2  *   m_type:	SYS_PRIVCTL
3  *
4  * The parameters for this kernel call are:
5  *   m_lsys_krn_sys_privctl.endpt		(process endpoint of target)
6  *   m_lsys_krn_sys_privctl.request		(privilege control request)
7  *   m_lsys_krn_sys_privctl.arg_ptr		(pointer to request data)
8  *   m.m_lsys_krn_sys_privctl.phys_start
9  *   m.m_lsys_krn_sys_privctl.phys_len
10  */
11 
12 #include "kernel/system.h"
13 #include "kernel/ipc.h"
14 #include <signal.h>
15 #include <string.h>
16 #include <minix/endpoint.h>
17 
18 #if USE_PRIVCTL
19 
20 #define PRIV_DEBUG 0
21 
22 static int update_priv(struct proc *rp, struct priv *priv);
23 
24 /*===========================================================================*
25  *				do_privctl				     *
26  *===========================================================================*/
27 int do_privctl(struct proc * caller, message * m_ptr)
28 {
29 /* Handle sys_privctl(). Update a process' privileges. If the process is not
30  * yet a system process, make sure it gets its own privilege structure.
31  */
32   struct proc *rp;
33   proc_nr_t proc_nr;
34   sys_id_t priv_id;
35   sys_map_t map;
36   int ipc_to_m, kcalls;
37   int i, r;
38   struct io_range io_range;
39   struct minix_mem_range mem_range;
40   struct priv priv;
41   int irq;
42 
43   /* Check whether caller is allowed to make this call. Privileged processes
44    * can only update the privileges of processes that are inhibited from
45    * running by the RTS_NO_PRIV flag. This flag is set when a privileged process
46    * forks.
47    */
48   if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
49   if(m_ptr->m_lsys_krn_sys_privctl.endpt == SELF) okendpt(caller->p_endpoint,
50 	&proc_nr);
51   else if(!isokendpt(m_ptr->m_lsys_krn_sys_privctl.endpt, &proc_nr))
52 	return(EINVAL);
53   rp = proc_addr(proc_nr);
54 
55   switch(m_ptr->m_lsys_krn_sys_privctl.request)
56   {
57   case SYS_PRIV_ALLOW:
58 	/* Allow process to run. Make sure its privilege structure has already
59 	 * been set.
60 	 */
61 	if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
62 		return(EPERM);
63 	}
64 	RTS_UNSET(rp, RTS_NO_PRIV);
65 	return(OK);
66 
67   case SYS_PRIV_YIELD:
68 	/* Allow process to run and suspend the caller. */
69 	if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
70 		return(EPERM);
71 	}
72 	RTS_SET(caller, RTS_NO_PRIV);
73 	RTS_UNSET(rp, RTS_NO_PRIV);
74 	return(OK);
75 
76   case SYS_PRIV_DISALLOW:
77 	/* Disallow process from running. */
78 	if (RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
79 	RTS_SET(rp, RTS_NO_PRIV);
80 	return(OK);
81 
82   case SYS_PRIV_SET_SYS:
83 	/* Set a privilege structure of a blocked system process. */
84 	if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
85 
86 	/* Check whether a static or dynamic privilege id must be allocated. */
87 	priv_id = NULL_PRIV_ID;
88 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
89 	{
90 		/* Copy privilege structure from caller */
91 		if((r=data_copy(caller->p_endpoint,
92 			m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
93 			(vir_bytes) &priv, sizeof(priv))) != OK)
94 			return r;
95 
96 		/* See if the caller wants to assign a static privilege id. */
97 		if(!(priv.s_flags & DYN_PRIV_ID)) {
98 			priv_id = priv.s_id;
99 		}
100 	}
101 
102 	/* Make sure this process has its own privileges structure. This may
103 	 * fail, since there are only a limited number of system processes.
104 	 * Then copy privileges from the caller and restore some defaults.
105 	 */
106 	if ((i=get_priv(rp, priv_id)) != OK)
107 	{
108 		printf("do_privctl: unable to allocate priv_id %d: %d\n",
109 			priv_id, i);
110 		return(i);
111 	}
112 	priv_id = priv(rp)->s_id;		/* backup privilege id */
113 	*priv(rp) = *priv(caller);		/* copy from caller */
114 	priv(rp)->s_id = priv_id;		/* restore privilege id */
115 	priv(rp)->s_proc_nr = proc_nr;		/* reassociate process nr */
116 
117 	for (i=0; i< NR_SYS_CHUNKS; i++)		/* remove pending: */
118 	      priv(rp)->s_notify_pending.chunk[i] = 0;	/* - notifications */
119 	priv(rp)->s_int_pending = 0;			/* - interrupts */
120 	(void) sigemptyset(&priv(rp)->s_sig_pending);	/* - signals */
121 	reset_kernel_timer(&priv(rp)->s_alarm_timer);	/* - alarm */
122 	priv(rp)->s_asyntab= -1;			/* - asynsends */
123 	priv(rp)->s_asynsize= 0;
124 	priv(rp)->s_diag_sig = FALSE;		/* no request for diag sigs */
125 
126 	/* Set defaults for privilege bitmaps. */
127 	priv(rp)->s_flags= DSRV_F;           /* privilege flags */
128 	priv(rp)->s_trap_mask= DSRV_T;       /* allowed traps */
129 	memset(&map, 0, sizeof(map));
130 	ipc_to_m = DSRV_M;                   /* allowed targets */
131 	if (ipc_to_m == ALL_M) {
132 		for (i = 0; i < NR_SYS_PROCS; i++)
133 			set_sys_bit(map, i);
134 	}
135 	fill_sendto_mask(rp, &map);
136 	kcalls = DSRV_KC;                    /* allowed kernel calls */
137 	for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
138 		priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
139 	}
140 
141 	/* Set the default signal managers. */
142 	priv(rp)->s_sig_mgr = DSRV_SM;
143 	priv(rp)->s_bak_sig_mgr = NONE;
144 
145 	/* Set defaults for resources: no I/O resources, no memory resources,
146 	 * no IRQs, no grant table
147 	 */
148 	priv(rp)->s_nr_io_range= 0;
149 	priv(rp)->s_nr_mem_range= 0;
150 	priv(rp)->s_nr_irq= 0;
151 	priv(rp)->s_grant_table= 0;
152 	priv(rp)->s_grant_entries= 0;
153 
154 	/* Override defaults if the caller has supplied a privilege structure. */
155 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
156 	{
157 		if((r = update_priv(rp, &priv)) != OK) {
158 			return r;
159 		}
160 	}
161 
162 	return(OK);
163 
164   case SYS_PRIV_SET_USER:
165 	/* Set a privilege structure of a blocked user process. */
166 	if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
167 
168 	/* Link the process to the privilege structure of the root user
169 	 * process all the user processes share.
170 	 */
171 	priv(rp) = priv_addr(USER_PRIV_ID);
172 
173 	return(OK);
174 
175   case SYS_PRIV_ADD_IO:
176 	if (RTS_ISSET(rp, RTS_NO_PRIV))
177 		return(EPERM);
178 
179 	/* Only system processes get I/O resources? */
180 	if (!(priv(rp)->s_flags & SYS_PROC))
181 		return EPERM;
182 
183 #if 0 /* XXX -- do we need a call for this? */
184 	if (strcmp(rp->p_name, "fxp") == 0 ||
185 		strcmp(rp->p_name, "rtl8139") == 0)
186 	{
187 		printf("setting ipc_stats_target to %d\n", rp->p_endpoint);
188 		ipc_stats_target= rp->p_endpoint;
189 	}
190 #endif
191 
192 	/* Get the I/O range */
193 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
194 		KERNEL, (vir_bytes) &io_range, sizeof(io_range));
195 	priv(rp)->s_flags |= CHECK_IO_PORT;	/* Check I/O accesses */
196 
197 	for (i = 0; i < priv(rp)->s_nr_io_range; i++) {
198 		if (priv(rp)->s_io_tab[i].ior_base == io_range.ior_base &&
199 			priv(rp)->s_io_tab[i].ior_limit == io_range.ior_limit)
200 			return OK;
201 	}
202 
203 	i= priv(rp)->s_nr_io_range;
204 	if (i >= NR_IO_RANGE) {
205 		printf("do_privctl: %d already has %d i/o ranges.\n",
206 			rp->p_endpoint, i);
207 		return ENOMEM;
208 	}
209 
210 	priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
211 	priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
212 	priv(rp)->s_nr_io_range++;
213 
214 	return OK;
215 
216   case SYS_PRIV_ADD_MEM:
217 	if (RTS_ISSET(rp, RTS_NO_PRIV))
218 		return(EPERM);
219 
220 	/* Only system processes get memory resources? */
221 	if (!(priv(rp)->s_flags & SYS_PROC))
222 		return EPERM;
223 
224 	/* Get the memory range */
225 	if((r=data_copy(caller->p_endpoint,
226 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
227 		(vir_bytes) &mem_range, sizeof(mem_range))) != OK)
228 		return r;
229 	priv(rp)->s_flags |= CHECK_MEM;	/* Check memory mappings */
230 
231 	/* When restarting a driver, check if it already has the permission */
232 	for (i = 0; i < priv(rp)->s_nr_mem_range; i++) {
233 		if (priv(rp)->s_mem_tab[i].mr_base == mem_range.mr_base &&
234 			priv(rp)->s_mem_tab[i].mr_limit == mem_range.mr_limit)
235 			return OK;
236 	}
237 
238 	i= priv(rp)->s_nr_mem_range;
239 	if (i >= NR_MEM_RANGE) {
240 		printf("do_privctl: %d already has %d mem ranges.\n",
241 			rp->p_endpoint, i);
242 		return ENOMEM;
243 	}
244 
245 	priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
246 	priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
247 	priv(rp)->s_nr_mem_range++;
248 
249 	return OK;
250 
251   case SYS_PRIV_ADD_IRQ:
252 	if (RTS_ISSET(rp, RTS_NO_PRIV))
253 		return(EPERM);
254 
255 	/* Only system processes get IRQs? */
256 	if (!(priv(rp)->s_flags & SYS_PROC))
257 		return EPERM;
258 
259 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
260 		KERNEL, (vir_bytes) &irq, sizeof(irq));
261 	priv(rp)->s_flags |= CHECK_IRQ;	/* Check IRQs */
262 
263 	/* When restarting a driver, check if it already has the permission */
264 	for (i = 0; i < priv(rp)->s_nr_irq; i++) {
265 		if (priv(rp)->s_irq_tab[i] == irq)
266 			return OK;
267 	}
268 
269 	i= priv(rp)->s_nr_irq;
270 	if (i >= NR_IRQ) {
271 		printf("do_privctl: %d already has %d irq's.\n",
272 			rp->p_endpoint, i);
273 		return ENOMEM;
274 	}
275 	priv(rp)->s_irq_tab[i]= irq;
276 	priv(rp)->s_nr_irq++;
277 
278 	return OK;
279   case SYS_PRIV_QUERY_MEM:
280   {
281 	phys_bytes addr, limit;
282   	struct priv *sp;
283 	/* See if a certain process is allowed to map in certain physical
284 	 * memory.
285 	 */
286 	addr = (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_start;
287 	limit = addr + (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_len - 1;
288 	if(limit < addr)
289 		return EPERM;
290 	if(!(sp = priv(rp)))
291 		return EPERM;
292 	if (!(sp->s_flags & SYS_PROC))
293 		return EPERM;
294 	for(i = 0; i < sp->s_nr_mem_range; i++) {
295 		if(addr >= sp->s_mem_tab[i].mr_base &&
296 		   limit <= sp->s_mem_tab[i].mr_limit)
297 			return OK;
298 	}
299 	return EPERM;
300   }
301 
302   case SYS_PRIV_UPDATE_SYS:
303 	/* Update the privilege structure of a system process. */
304 	if(!m_ptr->m_lsys_krn_sys_privctl.arg_ptr) return EINVAL;
305 
306 	/* Copy privilege structure from caller */
307 	if((r=data_copy(caller->p_endpoint,
308 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
309 		(vir_bytes) &priv, sizeof(priv))) != OK)
310 		return r;
311 
312 	/* Override settings in existing privilege structure. */
313 	if((r = update_priv(rp, &priv)) != OK) {
314 		return r;
315 	}
316 
317 	return(OK);
318 
319   default:
320 	printf("do_privctl: bad request %d\n",
321 		m_ptr->m_lsys_krn_sys_privctl.request);
322 	return EINVAL;
323   }
324 }
325 
326 /*===========================================================================*
327  *				update_priv				     *
328  *===========================================================================*/
329 static int update_priv(struct proc *rp, struct priv *priv)
330 {
331 /* Update the privilege structure of a given process. */
332 
333   int i;
334 
335   /* Copy s_flags and signal managers. */
336   priv(rp)->s_flags = priv->s_flags;
337   priv(rp)->s_sig_mgr = priv->s_sig_mgr;
338   priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
339 
340   /* Copy IRQs. */
341   if(priv->s_flags & CHECK_IRQ) {
342   	if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
343   		return EINVAL;
344   	priv(rp)->s_nr_irq= priv->s_nr_irq;
345   	for (i= 0; i<priv->s_nr_irq; i++)
346   	{
347   		priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
348 #if PRIV_DEBUG
349   		printf("do_privctl: adding IRQ %d for %d\n",
350   			priv(rp)->s_irq_tab[i], rp->p_endpoint);
351 #endif
352   	}
353   }
354 
355   /* Copy I/O ranges. */
356   if(priv->s_flags & CHECK_IO_PORT) {
357   	if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
358   		return EINVAL;
359   	priv(rp)->s_nr_io_range= priv->s_nr_io_range;
360   	for (i= 0; i<priv->s_nr_io_range; i++)
361   	{
362   		priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
363 #if PRIV_DEBUG
364   		printf("do_privctl: adding I/O range [%x..%x] for %d\n",
365   			priv(rp)->s_io_tab[i].ior_base,
366   			priv(rp)->s_io_tab[i].ior_limit,
367   			rp->p_endpoint);
368 #endif
369   	}
370   }
371 
372   /* Copy memory ranges. */
373   if(priv->s_flags & CHECK_MEM) {
374   	if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
375   		return EINVAL;
376   	priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
377   	for (i= 0; i<priv->s_nr_mem_range; i++)
378   	{
379   		priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
380 #if PRIV_DEBUG
381   		printf("do_privctl: adding mem range [%x..%x] for %d\n",
382   			priv(rp)->s_mem_tab[i].mr_base,
383   			priv(rp)->s_mem_tab[i].mr_limit,
384   			rp->p_endpoint);
385 #endif
386   	}
387   }
388 
389   /* Copy trap mask. */
390   priv(rp)->s_trap_mask = priv->s_trap_mask;
391 
392   /* Copy target mask. */
393 #if PRIV_DEBUG
394   printf("do_privctl: Setting ipc target mask for %d:");
395   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
396   	printf(" %08x", get_sys_bits(priv->s_ipc_to, i));
397   }
398   printf("\n");
399 #endif
400 
401   fill_sendto_mask(rp, &priv->s_ipc_to);
402 
403 #if PRIV_DEBUG
404   printf("do_privctl: Set ipc target mask for %d:");
405   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
406   	printf(" %08x", get_sys_bits(priv(rp)->s_ipc_to, i));
407   }
408   printf("\n");
409 #endif
410 
411   /* Copy kernel call mask. */
412   memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
413   	sizeof(priv(rp)->s_k_call_mask));
414 
415   return OK;
416 }
417 
418 #endif /* USE_PRIVCTL */
419 
420