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