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