xref: /minix3/minix/kernel/system/do_privctl.c (revision c8a9900b0c9747f0204da0b3ece358573974b606)
1433d6423SLionel Sambuc /* The kernel call implemented in this file:
2433d6423SLionel Sambuc  *   m_type:	SYS_PRIVCTL
3433d6423SLionel Sambuc  *
4433d6423SLionel Sambuc  * The parameters for this kernel call are:
5433d6423SLionel Sambuc  *   m_lsys_krn_sys_privctl.endpt		(process endpoint of target)
6433d6423SLionel Sambuc  *   m_lsys_krn_sys_privctl.request		(privilege control request)
7433d6423SLionel Sambuc  *   m_lsys_krn_sys_privctl.arg_ptr		(pointer to request data)
8433d6423SLionel Sambuc  *   m.m_lsys_krn_sys_privctl.phys_start
9433d6423SLionel Sambuc  *   m.m_lsys_krn_sys_privctl.phys_len
10433d6423SLionel Sambuc  */
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc #include "kernel/system.h"
13433d6423SLionel Sambuc #include "kernel/ipc.h"
14433d6423SLionel Sambuc #include <signal.h>
15433d6423SLionel Sambuc #include <string.h>
16433d6423SLionel Sambuc #include <minix/endpoint.h>
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc #if USE_PRIVCTL
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc #define PRIV_DEBUG 0
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc static int update_priv(struct proc *rp, struct priv *priv);
23433d6423SLionel Sambuc 
24433d6423SLionel Sambuc /*===========================================================================*
25433d6423SLionel Sambuc  *				do_privctl				     *
26433d6423SLionel Sambuc  *===========================================================================*/
27433d6423SLionel Sambuc int do_privctl(struct proc * caller, message * m_ptr)
28433d6423SLionel Sambuc {
29433d6423SLionel Sambuc /* Handle sys_privctl(). Update a process' privileges. If the process is not
30433d6423SLionel Sambuc  * yet a system process, make sure it gets its own privilege structure.
31433d6423SLionel Sambuc  */
32433d6423SLionel Sambuc   struct proc *rp;
33433d6423SLionel Sambuc   proc_nr_t proc_nr;
34433d6423SLionel Sambuc   sys_id_t priv_id;
35433d6423SLionel Sambuc   sys_map_t map;
36433d6423SLionel Sambuc   int ipc_to_m, kcalls;
37433d6423SLionel Sambuc   int i, r;
38433d6423SLionel Sambuc   struct io_range io_range;
39433d6423SLionel Sambuc   struct minix_mem_range mem_range;
40433d6423SLionel Sambuc   struct priv priv;
41433d6423SLionel Sambuc   int irq;
42433d6423SLionel Sambuc 
43433d6423SLionel Sambuc   /* Check whether caller is allowed to make this call. Privileged processes
44433d6423SLionel Sambuc    * can only update the privileges of processes that are inhibited from
45433d6423SLionel Sambuc    * running by the RTS_NO_PRIV flag. This flag is set when a privileged process
46433d6423SLionel Sambuc    * forks.
47433d6423SLionel Sambuc    */
48433d6423SLionel Sambuc   if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
49433d6423SLionel Sambuc   if(m_ptr->m_lsys_krn_sys_privctl.endpt == SELF) okendpt(caller->p_endpoint,
50433d6423SLionel Sambuc 	&proc_nr);
51433d6423SLionel Sambuc   else if(!isokendpt(m_ptr->m_lsys_krn_sys_privctl.endpt, &proc_nr))
52433d6423SLionel Sambuc 	return(EINVAL);
53433d6423SLionel Sambuc   rp = proc_addr(proc_nr);
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc   switch(m_ptr->m_lsys_krn_sys_privctl.request)
56433d6423SLionel Sambuc   {
57433d6423SLionel Sambuc   case SYS_PRIV_ALLOW:
58433d6423SLionel Sambuc 	/* Allow process to run. Make sure its privilege structure has already
59433d6423SLionel Sambuc 	 * been set.
60433d6423SLionel Sambuc 	 */
61433d6423SLionel Sambuc 	if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
62433d6423SLionel Sambuc 		return(EPERM);
63433d6423SLionel Sambuc 	}
64433d6423SLionel Sambuc 	RTS_UNSET(rp, RTS_NO_PRIV);
65433d6423SLionel Sambuc 	return(OK);
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc   case SYS_PRIV_YIELD:
68433d6423SLionel Sambuc 	/* Allow process to run and suspend the caller. */
69433d6423SLionel Sambuc 	if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
70433d6423SLionel Sambuc 		return(EPERM);
71433d6423SLionel Sambuc 	}
72433d6423SLionel Sambuc 	RTS_SET(caller, RTS_NO_PRIV);
73433d6423SLionel Sambuc 	RTS_UNSET(rp, RTS_NO_PRIV);
74433d6423SLionel Sambuc 	return(OK);
75433d6423SLionel Sambuc 
76433d6423SLionel Sambuc   case SYS_PRIV_DISALLOW:
77433d6423SLionel Sambuc 	/* Disallow process from running. */
78433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
79433d6423SLionel Sambuc 	RTS_SET(rp, RTS_NO_PRIV);
80433d6423SLionel Sambuc 	return(OK);
81433d6423SLionel Sambuc 
826fc50062SCristiano Giuffrida   case SYS_PRIV_CLEAR_IPC_REFS:
836fc50062SCristiano Giuffrida 	/* Clear pending IPC for the process. */
846fc50062SCristiano Giuffrida 	clear_ipc_refs(rp, EDEADSRCDST);
856fc50062SCristiano Giuffrida 	return(OK);
866fc50062SCristiano Giuffrida 
87433d6423SLionel Sambuc   case SYS_PRIV_SET_SYS:
88433d6423SLionel Sambuc 	/* Set a privilege structure of a blocked system process. */
89433d6423SLionel Sambuc 	if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc 	/* Check whether a static or dynamic privilege id must be allocated. */
92433d6423SLionel Sambuc 	priv_id = NULL_PRIV_ID;
93433d6423SLionel Sambuc 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
94433d6423SLionel Sambuc 	{
95433d6423SLionel Sambuc 		/* Copy privilege structure from caller */
96433d6423SLionel Sambuc 		if((r=data_copy(caller->p_endpoint,
97433d6423SLionel Sambuc 			m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
98433d6423SLionel Sambuc 			(vir_bytes) &priv, sizeof(priv))) != OK)
99433d6423SLionel Sambuc 			return r;
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc 		/* See if the caller wants to assign a static privilege id. */
102433d6423SLionel Sambuc 		if(!(priv.s_flags & DYN_PRIV_ID)) {
103433d6423SLionel Sambuc 			priv_id = priv.s_id;
104433d6423SLionel Sambuc 		}
105433d6423SLionel Sambuc 	}
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc 	/* Make sure this process has its own privileges structure. This may
108433d6423SLionel Sambuc 	 * fail, since there are only a limited number of system processes.
109433d6423SLionel Sambuc 	 * Then copy privileges from the caller and restore some defaults.
110433d6423SLionel Sambuc 	 */
111433d6423SLionel Sambuc 	if ((i=get_priv(rp, priv_id)) != OK)
112433d6423SLionel Sambuc 	{
113433d6423SLionel Sambuc 		printf("do_privctl: unable to allocate priv_id %d: %d\n",
114433d6423SLionel Sambuc 			priv_id, i);
115433d6423SLionel Sambuc 		return(i);
116433d6423SLionel Sambuc 	}
117433d6423SLionel Sambuc 	priv_id = priv(rp)->s_id;		/* backup privilege id */
118433d6423SLionel Sambuc 	*priv(rp) = *priv(caller);		/* copy from caller */
119433d6423SLionel Sambuc 	priv(rp)->s_id = priv_id;		/* restore privilege id */
120433d6423SLionel Sambuc 	priv(rp)->s_proc_nr = proc_nr;		/* reassociate process nr */
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc 	for (i=0; i< NR_SYS_CHUNKS; i++)		/* remove pending: */
123433d6423SLionel Sambuc 	      priv(rp)->s_notify_pending.chunk[i] = 0;	/* - notifications */
124433d6423SLionel Sambuc 	priv(rp)->s_int_pending = 0;			/* - interrupts */
125433d6423SLionel Sambuc 	(void) sigemptyset(&priv(rp)->s_sig_pending);	/* - signals */
126433d6423SLionel Sambuc 	reset_kernel_timer(&priv(rp)->s_alarm_timer);	/* - alarm */
127433d6423SLionel Sambuc 	priv(rp)->s_asyntab= -1;			/* - asynsends */
128433d6423SLionel Sambuc 	priv(rp)->s_asynsize= 0;
129433d6423SLionel Sambuc 	priv(rp)->s_diag_sig = FALSE;		/* no request for diag sigs */
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc 	/* Set defaults for privilege bitmaps. */
132433d6423SLionel Sambuc 	priv(rp)->s_flags= DSRV_F;           /* privilege flags */
13376bf77a2SCristiano Giuffrida 	priv(rp)->s_init_flags= DSRV_I;      /* initialization flags */
134433d6423SLionel Sambuc 	priv(rp)->s_trap_mask= DSRV_T;       /* allowed traps */
135433d6423SLionel Sambuc 	memset(&map, 0, sizeof(map));
136433d6423SLionel Sambuc 	ipc_to_m = DSRV_M;                   /* allowed targets */
137433d6423SLionel Sambuc 	if (ipc_to_m == ALL_M) {
138433d6423SLionel Sambuc 		for (i = 0; i < NR_SYS_PROCS; i++)
139433d6423SLionel Sambuc 			set_sys_bit(map, i);
140433d6423SLionel Sambuc 	}
141433d6423SLionel Sambuc 	fill_sendto_mask(rp, &map);
142433d6423SLionel Sambuc 	kcalls = DSRV_KC;                    /* allowed kernel calls */
143433d6423SLionel Sambuc 	for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
144433d6423SLionel Sambuc 		priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
145433d6423SLionel Sambuc 	}
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc 	/* Set the default signal managers. */
148433d6423SLionel Sambuc 	priv(rp)->s_sig_mgr = DSRV_SM;
149433d6423SLionel Sambuc 	priv(rp)->s_bak_sig_mgr = NONE;
150433d6423SLionel Sambuc 
151433d6423SLionel Sambuc 	/* Set defaults for resources: no I/O resources, no memory resources,
152*c8a9900bSCristiano Giuffrida 	 * no IRQs, no grant table, no ipc filter
153433d6423SLionel Sambuc 	 */
154433d6423SLionel Sambuc 	priv(rp)->s_nr_io_range= 0;
155433d6423SLionel Sambuc 	priv(rp)->s_nr_mem_range= 0;
156433d6423SLionel Sambuc 	priv(rp)->s_nr_irq= 0;
157433d6423SLionel Sambuc 	priv(rp)->s_grant_table= 0;
158433d6423SLionel Sambuc 	priv(rp)->s_grant_entries= 0;
15941022be1SCristiano Giuffrida 	priv(rp)->s_state_table= 0;
16041022be1SCristiano Giuffrida 	priv(rp)->s_state_entries= 0;
161*c8a9900bSCristiano Giuffrida 	priv(rp)->s_ipcf= 0;
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc 	/* Override defaults if the caller has supplied a privilege structure. */
164433d6423SLionel Sambuc 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
165433d6423SLionel Sambuc 	{
166433d6423SLionel Sambuc 		if((r = update_priv(rp, &priv)) != OK) {
167433d6423SLionel Sambuc 			return r;
168433d6423SLionel Sambuc 		}
169433d6423SLionel Sambuc 	}
170433d6423SLionel Sambuc 
171433d6423SLionel Sambuc 	return(OK);
172433d6423SLionel Sambuc 
173433d6423SLionel Sambuc   case SYS_PRIV_SET_USER:
174433d6423SLionel Sambuc 	/* Set a privilege structure of a blocked user process. */
175433d6423SLionel Sambuc 	if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
176433d6423SLionel Sambuc 
177433d6423SLionel Sambuc 	/* Link the process to the privilege structure of the root user
178433d6423SLionel Sambuc 	 * process all the user processes share.
179433d6423SLionel Sambuc 	 */
180433d6423SLionel Sambuc 	priv(rp) = priv_addr(USER_PRIV_ID);
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc 	return(OK);
183433d6423SLionel Sambuc 
184433d6423SLionel Sambuc   case SYS_PRIV_ADD_IO:
185433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
186433d6423SLionel Sambuc 		return(EPERM);
187433d6423SLionel Sambuc 
188433d6423SLionel Sambuc #if 0 /* XXX -- do we need a call for this? */
189433d6423SLionel Sambuc 	if (strcmp(rp->p_name, "fxp") == 0 ||
190433d6423SLionel Sambuc 		strcmp(rp->p_name, "rtl8139") == 0)
191433d6423SLionel Sambuc 	{
192433d6423SLionel Sambuc 		printf("setting ipc_stats_target to %d\n", rp->p_endpoint);
193433d6423SLionel Sambuc 		ipc_stats_target= rp->p_endpoint;
194433d6423SLionel Sambuc 	}
195433d6423SLionel Sambuc #endif
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc 	/* Get the I/O range */
198433d6423SLionel Sambuc 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
199433d6423SLionel Sambuc 		KERNEL, (vir_bytes) &io_range, sizeof(io_range));
200433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_IO_PORT;	/* Check I/O accesses */
201433d6423SLionel Sambuc 
202433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_io_range; i++) {
203433d6423SLionel Sambuc 		if (priv(rp)->s_io_tab[i].ior_base == io_range.ior_base &&
204433d6423SLionel Sambuc 			priv(rp)->s_io_tab[i].ior_limit == io_range.ior_limit)
205433d6423SLionel Sambuc 			return OK;
206433d6423SLionel Sambuc 	}
207433d6423SLionel Sambuc 
208433d6423SLionel Sambuc 	i= priv(rp)->s_nr_io_range;
209433d6423SLionel Sambuc 	if (i >= NR_IO_RANGE) {
210433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d i/o ranges.\n",
211433d6423SLionel Sambuc 			rp->p_endpoint, i);
212433d6423SLionel Sambuc 		return ENOMEM;
213433d6423SLionel Sambuc 	}
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc 	priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
216433d6423SLionel Sambuc 	priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
217433d6423SLionel Sambuc 	priv(rp)->s_nr_io_range++;
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc 	return OK;
220433d6423SLionel Sambuc 
221433d6423SLionel Sambuc   case SYS_PRIV_ADD_MEM:
222433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
223433d6423SLionel Sambuc 		return(EPERM);
224433d6423SLionel Sambuc 
225433d6423SLionel Sambuc 	/* Get the memory range */
226433d6423SLionel Sambuc 	if((r=data_copy(caller->p_endpoint,
227433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
228433d6423SLionel Sambuc 		(vir_bytes) &mem_range, sizeof(mem_range))) != OK)
229433d6423SLionel Sambuc 		return r;
230433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_MEM;	/* Check memory mappings */
231433d6423SLionel Sambuc 
232433d6423SLionel Sambuc 	/* When restarting a driver, check if it already has the permission */
233433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_mem_range; i++) {
234433d6423SLionel Sambuc 		if (priv(rp)->s_mem_tab[i].mr_base == mem_range.mr_base &&
235433d6423SLionel Sambuc 			priv(rp)->s_mem_tab[i].mr_limit == mem_range.mr_limit)
236433d6423SLionel Sambuc 			return OK;
237433d6423SLionel Sambuc 	}
238433d6423SLionel Sambuc 
239433d6423SLionel Sambuc 	i= priv(rp)->s_nr_mem_range;
240433d6423SLionel Sambuc 	if (i >= NR_MEM_RANGE) {
241433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d mem ranges.\n",
242433d6423SLionel Sambuc 			rp->p_endpoint, i);
243433d6423SLionel Sambuc 		return ENOMEM;
244433d6423SLionel Sambuc 	}
245433d6423SLionel Sambuc 
246433d6423SLionel Sambuc 	priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
247433d6423SLionel Sambuc 	priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
248433d6423SLionel Sambuc 	priv(rp)->s_nr_mem_range++;
249433d6423SLionel Sambuc 
250433d6423SLionel Sambuc 	return OK;
251433d6423SLionel Sambuc 
252433d6423SLionel Sambuc   case SYS_PRIV_ADD_IRQ:
253433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
254433d6423SLionel Sambuc 		return(EPERM);
255433d6423SLionel Sambuc 
2565d831176SLionel Sambuc #if 0
257433d6423SLionel Sambuc 	/* Only system processes get IRQs? */
258433d6423SLionel Sambuc 	if (!(priv(rp)->s_flags & SYS_PROC))
259433d6423SLionel Sambuc 		return EPERM;
2605d831176SLionel Sambuc #endif
261433d6423SLionel Sambuc 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
262433d6423SLionel Sambuc 		KERNEL, (vir_bytes) &irq, sizeof(irq));
263433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_IRQ;	/* Check IRQs */
264433d6423SLionel Sambuc 
265433d6423SLionel Sambuc 	/* When restarting a driver, check if it already has the permission */
266433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_irq; i++) {
267433d6423SLionel Sambuc 		if (priv(rp)->s_irq_tab[i] == irq)
268433d6423SLionel Sambuc 			return OK;
269433d6423SLionel Sambuc 	}
270433d6423SLionel Sambuc 
271433d6423SLionel Sambuc 	i= priv(rp)->s_nr_irq;
272433d6423SLionel Sambuc 	if (i >= NR_IRQ) {
273433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d irq's.\n",
274433d6423SLionel Sambuc 			rp->p_endpoint, i);
275433d6423SLionel Sambuc 		return ENOMEM;
276433d6423SLionel Sambuc 	}
277433d6423SLionel Sambuc 	priv(rp)->s_irq_tab[i]= irq;
278433d6423SLionel Sambuc 	priv(rp)->s_nr_irq++;
279433d6423SLionel Sambuc 
280433d6423SLionel Sambuc 	return OK;
281433d6423SLionel Sambuc   case SYS_PRIV_QUERY_MEM:
282433d6423SLionel Sambuc   {
283433d6423SLionel Sambuc 	phys_bytes addr, limit;
284433d6423SLionel Sambuc   	struct priv *sp;
285433d6423SLionel Sambuc 	/* See if a certain process is allowed to map in certain physical
286433d6423SLionel Sambuc 	 * memory.
287433d6423SLionel Sambuc 	 */
288433d6423SLionel Sambuc 	addr = (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_start;
289433d6423SLionel Sambuc 	limit = addr + (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_len - 1;
290433d6423SLionel Sambuc 	if(limit < addr)
291433d6423SLionel Sambuc 		return EPERM;
292433d6423SLionel Sambuc 	if(!(sp = priv(rp)))
293433d6423SLionel Sambuc 		return EPERM;
294433d6423SLionel Sambuc 	for(i = 0; i < sp->s_nr_mem_range; i++) {
295433d6423SLionel Sambuc 		if(addr >= sp->s_mem_tab[i].mr_base &&
296433d6423SLionel Sambuc 		   limit <= sp->s_mem_tab[i].mr_limit)
297433d6423SLionel Sambuc 			return OK;
298433d6423SLionel Sambuc 	}
299433d6423SLionel Sambuc 	return EPERM;
300433d6423SLionel Sambuc   }
301433d6423SLionel Sambuc 
302433d6423SLionel Sambuc   case SYS_PRIV_UPDATE_SYS:
303433d6423SLionel Sambuc 	/* Update the privilege structure of a system process. */
304433d6423SLionel Sambuc 	if(!m_ptr->m_lsys_krn_sys_privctl.arg_ptr) return EINVAL;
305433d6423SLionel Sambuc 
306433d6423SLionel Sambuc 	/* Copy privilege structure from caller */
307433d6423SLionel Sambuc 	if((r=data_copy(caller->p_endpoint,
308433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
309433d6423SLionel Sambuc 		(vir_bytes) &priv, sizeof(priv))) != OK)
310433d6423SLionel Sambuc 		return r;
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc 	/* Override settings in existing privilege structure. */
313433d6423SLionel Sambuc 	if((r = update_priv(rp, &priv)) != OK) {
314433d6423SLionel Sambuc 		return r;
315433d6423SLionel Sambuc 	}
316433d6423SLionel Sambuc 
317433d6423SLionel Sambuc 	return(OK);
318433d6423SLionel Sambuc 
319433d6423SLionel Sambuc   default:
320433d6423SLionel Sambuc 	printf("do_privctl: bad request %d\n",
321433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.request);
322433d6423SLionel Sambuc 	return EINVAL;
323433d6423SLionel Sambuc   }
324433d6423SLionel Sambuc }
325433d6423SLionel Sambuc 
326433d6423SLionel Sambuc /*===========================================================================*
327433d6423SLionel Sambuc  *				update_priv				     *
328433d6423SLionel Sambuc  *===========================================================================*/
329433d6423SLionel Sambuc static int update_priv(struct proc *rp, struct priv *priv)
330433d6423SLionel Sambuc {
331433d6423SLionel Sambuc /* Update the privilege structure of a given process. */
332433d6423SLionel Sambuc 
333433d6423SLionel Sambuc   int i;
334433d6423SLionel Sambuc 
33576bf77a2SCristiano Giuffrida   /* Copy flags and signal managers. */
336433d6423SLionel Sambuc   priv(rp)->s_flags = priv->s_flags;
33776bf77a2SCristiano Giuffrida   priv(rp)->s_init_flags = priv->s_init_flags;
338433d6423SLionel Sambuc   priv(rp)->s_sig_mgr = priv->s_sig_mgr;
339433d6423SLionel Sambuc   priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
340433d6423SLionel Sambuc 
341433d6423SLionel Sambuc   /* Copy IRQs. */
342433d6423SLionel Sambuc   if(priv->s_flags & CHECK_IRQ) {
343433d6423SLionel Sambuc   	if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
344433d6423SLionel Sambuc   		return EINVAL;
345433d6423SLionel Sambuc   	priv(rp)->s_nr_irq= priv->s_nr_irq;
346433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_irq; i++)
347433d6423SLionel Sambuc   	{
348433d6423SLionel Sambuc   		priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
349433d6423SLionel Sambuc #if PRIV_DEBUG
350433d6423SLionel Sambuc   		printf("do_privctl: adding IRQ %d for %d\n",
351433d6423SLionel Sambuc   			priv(rp)->s_irq_tab[i], rp->p_endpoint);
352433d6423SLionel Sambuc #endif
353433d6423SLionel Sambuc   	}
354433d6423SLionel Sambuc   }
355433d6423SLionel Sambuc 
356433d6423SLionel Sambuc   /* Copy I/O ranges. */
357433d6423SLionel Sambuc   if(priv->s_flags & CHECK_IO_PORT) {
358433d6423SLionel Sambuc   	if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
359433d6423SLionel Sambuc   		return EINVAL;
360433d6423SLionel Sambuc   	priv(rp)->s_nr_io_range= priv->s_nr_io_range;
361433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_io_range; i++)
362433d6423SLionel Sambuc   	{
363433d6423SLionel Sambuc   		priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
364433d6423SLionel Sambuc #if PRIV_DEBUG
365433d6423SLionel Sambuc   		printf("do_privctl: adding I/O range [%x..%x] for %d\n",
366433d6423SLionel Sambuc   			priv(rp)->s_io_tab[i].ior_base,
367433d6423SLionel Sambuc   			priv(rp)->s_io_tab[i].ior_limit,
368433d6423SLionel Sambuc   			rp->p_endpoint);
369433d6423SLionel Sambuc #endif
370433d6423SLionel Sambuc   	}
371433d6423SLionel Sambuc   }
372433d6423SLionel Sambuc 
373433d6423SLionel Sambuc   /* Copy memory ranges. */
374433d6423SLionel Sambuc   if(priv->s_flags & CHECK_MEM) {
375433d6423SLionel Sambuc   	if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
376433d6423SLionel Sambuc   		return EINVAL;
377433d6423SLionel Sambuc   	priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
378433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_mem_range; i++)
379433d6423SLionel Sambuc   	{
380433d6423SLionel Sambuc   		priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
381433d6423SLionel Sambuc #if PRIV_DEBUG
382433d6423SLionel Sambuc   		printf("do_privctl: adding mem range [%x..%x] for %d\n",
383433d6423SLionel Sambuc   			priv(rp)->s_mem_tab[i].mr_base,
384433d6423SLionel Sambuc   			priv(rp)->s_mem_tab[i].mr_limit,
385433d6423SLionel Sambuc   			rp->p_endpoint);
386433d6423SLionel Sambuc #endif
387433d6423SLionel Sambuc   	}
388433d6423SLionel Sambuc   }
389433d6423SLionel Sambuc 
390433d6423SLionel Sambuc   /* Copy trap mask. */
391433d6423SLionel Sambuc   priv(rp)->s_trap_mask = priv->s_trap_mask;
392433d6423SLionel Sambuc 
393433d6423SLionel Sambuc   /* Copy target mask. */
394433d6423SLionel Sambuc #if PRIV_DEBUG
395433d6423SLionel Sambuc   printf("do_privctl: Setting ipc target mask for %d:");
396433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
397433d6423SLionel Sambuc   	printf(" %08x", get_sys_bits(priv->s_ipc_to, i));
398433d6423SLionel Sambuc   }
399433d6423SLionel Sambuc   printf("\n");
400433d6423SLionel Sambuc #endif
401433d6423SLionel Sambuc 
402433d6423SLionel Sambuc   fill_sendto_mask(rp, &priv->s_ipc_to);
403433d6423SLionel Sambuc 
404433d6423SLionel Sambuc #if PRIV_DEBUG
405433d6423SLionel Sambuc   printf("do_privctl: Set ipc target mask for %d:");
406433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
407433d6423SLionel Sambuc   	printf(" %08x", get_sys_bits(priv(rp)->s_ipc_to, i));
408433d6423SLionel Sambuc   }
409433d6423SLionel Sambuc   printf("\n");
410433d6423SLionel Sambuc #endif
411433d6423SLionel Sambuc 
412433d6423SLionel Sambuc   /* Copy kernel call mask. */
413433d6423SLionel Sambuc   memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
414433d6423SLionel Sambuc   	sizeof(priv(rp)->s_k_call_mask));
415433d6423SLionel Sambuc 
416433d6423SLionel Sambuc   return OK;
417433d6423SLionel Sambuc }
418433d6423SLionel Sambuc 
419433d6423SLionel Sambuc #endif /* USE_PRIVCTL */
420433d6423SLionel Sambuc 
421