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