xref: /minix3/minix/kernel/system/do_privctl.c (revision 76bf77a21f01f3eb5a218cc711a04895ded2676d)
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 
82433d6423SLionel Sambuc   case SYS_PRIV_SET_SYS:
83433d6423SLionel Sambuc 	/* Set a privilege structure of a blocked system process. */
84433d6423SLionel Sambuc 	if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
85433d6423SLionel Sambuc 
86433d6423SLionel Sambuc 	/* Check whether a static or dynamic privilege id must be allocated. */
87433d6423SLionel Sambuc 	priv_id = NULL_PRIV_ID;
88433d6423SLionel Sambuc 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
89433d6423SLionel Sambuc 	{
90433d6423SLionel Sambuc 		/* Copy privilege structure from caller */
91433d6423SLionel Sambuc 		if((r=data_copy(caller->p_endpoint,
92433d6423SLionel Sambuc 			m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
93433d6423SLionel Sambuc 			(vir_bytes) &priv, sizeof(priv))) != OK)
94433d6423SLionel Sambuc 			return r;
95433d6423SLionel Sambuc 
96433d6423SLionel Sambuc 		/* See if the caller wants to assign a static privilege id. */
97433d6423SLionel Sambuc 		if(!(priv.s_flags & DYN_PRIV_ID)) {
98433d6423SLionel Sambuc 			priv_id = priv.s_id;
99433d6423SLionel Sambuc 		}
100433d6423SLionel Sambuc 	}
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc 	/* Make sure this process has its own privileges structure. This may
103433d6423SLionel Sambuc 	 * fail, since there are only a limited number of system processes.
104433d6423SLionel Sambuc 	 * Then copy privileges from the caller and restore some defaults.
105433d6423SLionel Sambuc 	 */
106433d6423SLionel Sambuc 	if ((i=get_priv(rp, priv_id)) != OK)
107433d6423SLionel Sambuc 	{
108433d6423SLionel Sambuc 		printf("do_privctl: unable to allocate priv_id %d: %d\n",
109433d6423SLionel Sambuc 			priv_id, i);
110433d6423SLionel Sambuc 		return(i);
111433d6423SLionel Sambuc 	}
112433d6423SLionel Sambuc 	priv_id = priv(rp)->s_id;		/* backup privilege id */
113433d6423SLionel Sambuc 	*priv(rp) = *priv(caller);		/* copy from caller */
114433d6423SLionel Sambuc 	priv(rp)->s_id = priv_id;		/* restore privilege id */
115433d6423SLionel Sambuc 	priv(rp)->s_proc_nr = proc_nr;		/* reassociate process nr */
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc 	for (i=0; i< NR_SYS_CHUNKS; i++)		/* remove pending: */
118433d6423SLionel Sambuc 	      priv(rp)->s_notify_pending.chunk[i] = 0;	/* - notifications */
119433d6423SLionel Sambuc 	priv(rp)->s_int_pending = 0;			/* - interrupts */
120433d6423SLionel Sambuc 	(void) sigemptyset(&priv(rp)->s_sig_pending);	/* - signals */
121433d6423SLionel Sambuc 	reset_kernel_timer(&priv(rp)->s_alarm_timer);	/* - alarm */
122433d6423SLionel Sambuc 	priv(rp)->s_asyntab= -1;			/* - asynsends */
123433d6423SLionel Sambuc 	priv(rp)->s_asynsize= 0;
124433d6423SLionel Sambuc 	priv(rp)->s_diag_sig = FALSE;		/* no request for diag sigs */
125433d6423SLionel Sambuc 
126433d6423SLionel Sambuc 	/* Set defaults for privilege bitmaps. */
127433d6423SLionel Sambuc 	priv(rp)->s_flags= DSRV_F;           /* privilege flags */
128*76bf77a2SCristiano Giuffrida 	priv(rp)->s_init_flags= DSRV_I;      /* initialization flags */
129433d6423SLionel Sambuc 	priv(rp)->s_trap_mask= DSRV_T;       /* allowed traps */
130433d6423SLionel Sambuc 	memset(&map, 0, sizeof(map));
131433d6423SLionel Sambuc 	ipc_to_m = DSRV_M;                   /* allowed targets */
132433d6423SLionel Sambuc 	if (ipc_to_m == ALL_M) {
133433d6423SLionel Sambuc 		for (i = 0; i < NR_SYS_PROCS; i++)
134433d6423SLionel Sambuc 			set_sys_bit(map, i);
135433d6423SLionel Sambuc 	}
136433d6423SLionel Sambuc 	fill_sendto_mask(rp, &map);
137433d6423SLionel Sambuc 	kcalls = DSRV_KC;                    /* allowed kernel calls */
138433d6423SLionel Sambuc 	for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
139433d6423SLionel Sambuc 		priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
140433d6423SLionel Sambuc 	}
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc 	/* Set the default signal managers. */
143433d6423SLionel Sambuc 	priv(rp)->s_sig_mgr = DSRV_SM;
144433d6423SLionel Sambuc 	priv(rp)->s_bak_sig_mgr = NONE;
145433d6423SLionel Sambuc 
146433d6423SLionel Sambuc 	/* Set defaults for resources: no I/O resources, no memory resources,
147433d6423SLionel Sambuc 	 * no IRQs, no grant table
148433d6423SLionel Sambuc 	 */
149433d6423SLionel Sambuc 	priv(rp)->s_nr_io_range= 0;
150433d6423SLionel Sambuc 	priv(rp)->s_nr_mem_range= 0;
151433d6423SLionel Sambuc 	priv(rp)->s_nr_irq= 0;
152433d6423SLionel Sambuc 	priv(rp)->s_grant_table= 0;
153433d6423SLionel Sambuc 	priv(rp)->s_grant_entries= 0;
15441022be1SCristiano Giuffrida 	priv(rp)->s_state_table= 0;
15541022be1SCristiano Giuffrida 	priv(rp)->s_state_entries= 0;
156433d6423SLionel Sambuc 
157433d6423SLionel Sambuc 	/* Override defaults if the caller has supplied a privilege structure. */
158433d6423SLionel Sambuc 	if (m_ptr->m_lsys_krn_sys_privctl.arg_ptr)
159433d6423SLionel Sambuc 	{
160433d6423SLionel Sambuc 		if((r = update_priv(rp, &priv)) != OK) {
161433d6423SLionel Sambuc 			return r;
162433d6423SLionel Sambuc 		}
163433d6423SLionel Sambuc 	}
164433d6423SLionel Sambuc 
165433d6423SLionel Sambuc 	return(OK);
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc   case SYS_PRIV_SET_USER:
168433d6423SLionel Sambuc 	/* Set a privilege structure of a blocked user process. */
169433d6423SLionel Sambuc 	if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
170433d6423SLionel Sambuc 
171433d6423SLionel Sambuc 	/* Link the process to the privilege structure of the root user
172433d6423SLionel Sambuc 	 * process all the user processes share.
173433d6423SLionel Sambuc 	 */
174433d6423SLionel Sambuc 	priv(rp) = priv_addr(USER_PRIV_ID);
175433d6423SLionel Sambuc 
176433d6423SLionel Sambuc 	return(OK);
177433d6423SLionel Sambuc 
178433d6423SLionel Sambuc   case SYS_PRIV_ADD_IO:
179433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
180433d6423SLionel Sambuc 		return(EPERM);
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc #if 0 /* XXX -- do we need a call for this? */
183433d6423SLionel Sambuc 	if (strcmp(rp->p_name, "fxp") == 0 ||
184433d6423SLionel Sambuc 		strcmp(rp->p_name, "rtl8139") == 0)
185433d6423SLionel Sambuc 	{
186433d6423SLionel Sambuc 		printf("setting ipc_stats_target to %d\n", rp->p_endpoint);
187433d6423SLionel Sambuc 		ipc_stats_target= rp->p_endpoint;
188433d6423SLionel Sambuc 	}
189433d6423SLionel Sambuc #endif
190433d6423SLionel Sambuc 
191433d6423SLionel Sambuc 	/* Get the I/O range */
192433d6423SLionel Sambuc 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
193433d6423SLionel Sambuc 		KERNEL, (vir_bytes) &io_range, sizeof(io_range));
194433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_IO_PORT;	/* Check I/O accesses */
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_io_range; i++) {
197433d6423SLionel Sambuc 		if (priv(rp)->s_io_tab[i].ior_base == io_range.ior_base &&
198433d6423SLionel Sambuc 			priv(rp)->s_io_tab[i].ior_limit == io_range.ior_limit)
199433d6423SLionel Sambuc 			return OK;
200433d6423SLionel Sambuc 	}
201433d6423SLionel Sambuc 
202433d6423SLionel Sambuc 	i= priv(rp)->s_nr_io_range;
203433d6423SLionel Sambuc 	if (i >= NR_IO_RANGE) {
204433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d i/o ranges.\n",
205433d6423SLionel Sambuc 			rp->p_endpoint, i);
206433d6423SLionel Sambuc 		return ENOMEM;
207433d6423SLionel Sambuc 	}
208433d6423SLionel Sambuc 
209433d6423SLionel Sambuc 	priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
210433d6423SLionel Sambuc 	priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
211433d6423SLionel Sambuc 	priv(rp)->s_nr_io_range++;
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc 	return OK;
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc   case SYS_PRIV_ADD_MEM:
216433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
217433d6423SLionel Sambuc 		return(EPERM);
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc 	/* Get the memory range */
220433d6423SLionel Sambuc 	if((r=data_copy(caller->p_endpoint,
221433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
222433d6423SLionel Sambuc 		(vir_bytes) &mem_range, sizeof(mem_range))) != OK)
223433d6423SLionel Sambuc 		return r;
224433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_MEM;	/* Check memory mappings */
225433d6423SLionel Sambuc 
226433d6423SLionel Sambuc 	/* When restarting a driver, check if it already has the permission */
227433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_mem_range; i++) {
228433d6423SLionel Sambuc 		if (priv(rp)->s_mem_tab[i].mr_base == mem_range.mr_base &&
229433d6423SLionel Sambuc 			priv(rp)->s_mem_tab[i].mr_limit == mem_range.mr_limit)
230433d6423SLionel Sambuc 			return OK;
231433d6423SLionel Sambuc 	}
232433d6423SLionel Sambuc 
233433d6423SLionel Sambuc 	i= priv(rp)->s_nr_mem_range;
234433d6423SLionel Sambuc 	if (i >= NR_MEM_RANGE) {
235433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d mem ranges.\n",
236433d6423SLionel Sambuc 			rp->p_endpoint, i);
237433d6423SLionel Sambuc 		return ENOMEM;
238433d6423SLionel Sambuc 	}
239433d6423SLionel Sambuc 
240433d6423SLionel Sambuc 	priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
241433d6423SLionel Sambuc 	priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
242433d6423SLionel Sambuc 	priv(rp)->s_nr_mem_range++;
243433d6423SLionel Sambuc 
244433d6423SLionel Sambuc 	return OK;
245433d6423SLionel Sambuc 
246433d6423SLionel Sambuc   case SYS_PRIV_ADD_IRQ:
247433d6423SLionel Sambuc 	if (RTS_ISSET(rp, RTS_NO_PRIV))
248433d6423SLionel Sambuc 		return(EPERM);
249433d6423SLionel Sambuc 
2505d831176SLionel Sambuc #if 0
251433d6423SLionel Sambuc 	/* Only system processes get IRQs? */
252433d6423SLionel Sambuc 	if (!(priv(rp)->s_flags & SYS_PROC))
253433d6423SLionel Sambuc 		return EPERM;
2545d831176SLionel Sambuc #endif
255433d6423SLionel Sambuc 	data_copy(caller->p_endpoint, m_ptr->m_lsys_krn_sys_privctl.arg_ptr,
256433d6423SLionel Sambuc 		KERNEL, (vir_bytes) &irq, sizeof(irq));
257433d6423SLionel Sambuc 	priv(rp)->s_flags |= CHECK_IRQ;	/* Check IRQs */
258433d6423SLionel Sambuc 
259433d6423SLionel Sambuc 	/* When restarting a driver, check if it already has the permission */
260433d6423SLionel Sambuc 	for (i = 0; i < priv(rp)->s_nr_irq; i++) {
261433d6423SLionel Sambuc 		if (priv(rp)->s_irq_tab[i] == irq)
262433d6423SLionel Sambuc 			return OK;
263433d6423SLionel Sambuc 	}
264433d6423SLionel Sambuc 
265433d6423SLionel Sambuc 	i= priv(rp)->s_nr_irq;
266433d6423SLionel Sambuc 	if (i >= NR_IRQ) {
267433d6423SLionel Sambuc 		printf("do_privctl: %d already has %d irq's.\n",
268433d6423SLionel Sambuc 			rp->p_endpoint, i);
269433d6423SLionel Sambuc 		return ENOMEM;
270433d6423SLionel Sambuc 	}
271433d6423SLionel Sambuc 	priv(rp)->s_irq_tab[i]= irq;
272433d6423SLionel Sambuc 	priv(rp)->s_nr_irq++;
273433d6423SLionel Sambuc 
274433d6423SLionel Sambuc 	return OK;
275433d6423SLionel Sambuc   case SYS_PRIV_QUERY_MEM:
276433d6423SLionel Sambuc   {
277433d6423SLionel Sambuc 	phys_bytes addr, limit;
278433d6423SLionel Sambuc   	struct priv *sp;
279433d6423SLionel Sambuc 	/* See if a certain process is allowed to map in certain physical
280433d6423SLionel Sambuc 	 * memory.
281433d6423SLionel Sambuc 	 */
282433d6423SLionel Sambuc 	addr = (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_start;
283433d6423SLionel Sambuc 	limit = addr + (phys_bytes) m_ptr->m_lsys_krn_sys_privctl.phys_len - 1;
284433d6423SLionel Sambuc 	if(limit < addr)
285433d6423SLionel Sambuc 		return EPERM;
286433d6423SLionel Sambuc 	if(!(sp = priv(rp)))
287433d6423SLionel Sambuc 		return EPERM;
288433d6423SLionel Sambuc 	for(i = 0; i < sp->s_nr_mem_range; i++) {
289433d6423SLionel Sambuc 		if(addr >= sp->s_mem_tab[i].mr_base &&
290433d6423SLionel Sambuc 		   limit <= sp->s_mem_tab[i].mr_limit)
291433d6423SLionel Sambuc 			return OK;
292433d6423SLionel Sambuc 	}
293433d6423SLionel Sambuc 	return EPERM;
294433d6423SLionel Sambuc   }
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc   case SYS_PRIV_UPDATE_SYS:
297433d6423SLionel Sambuc 	/* Update the privilege structure of a system process. */
298433d6423SLionel Sambuc 	if(!m_ptr->m_lsys_krn_sys_privctl.arg_ptr) return EINVAL;
299433d6423SLionel Sambuc 
300433d6423SLionel Sambuc 	/* Copy privilege structure from caller */
301433d6423SLionel Sambuc 	if((r=data_copy(caller->p_endpoint,
302433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.arg_ptr, KERNEL,
303433d6423SLionel Sambuc 		(vir_bytes) &priv, sizeof(priv))) != OK)
304433d6423SLionel Sambuc 		return r;
305433d6423SLionel Sambuc 
306433d6423SLionel Sambuc 	/* Override settings in existing privilege structure. */
307433d6423SLionel Sambuc 	if((r = update_priv(rp, &priv)) != OK) {
308433d6423SLionel Sambuc 		return r;
309433d6423SLionel Sambuc 	}
310433d6423SLionel Sambuc 
311433d6423SLionel Sambuc 	return(OK);
312433d6423SLionel Sambuc 
313433d6423SLionel Sambuc   default:
314433d6423SLionel Sambuc 	printf("do_privctl: bad request %d\n",
315433d6423SLionel Sambuc 		m_ptr->m_lsys_krn_sys_privctl.request);
316433d6423SLionel Sambuc 	return EINVAL;
317433d6423SLionel Sambuc   }
318433d6423SLionel Sambuc }
319433d6423SLionel Sambuc 
320433d6423SLionel Sambuc /*===========================================================================*
321433d6423SLionel Sambuc  *				update_priv				     *
322433d6423SLionel Sambuc  *===========================================================================*/
323433d6423SLionel Sambuc static int update_priv(struct proc *rp, struct priv *priv)
324433d6423SLionel Sambuc {
325433d6423SLionel Sambuc /* Update the privilege structure of a given process. */
326433d6423SLionel Sambuc 
327433d6423SLionel Sambuc   int i;
328433d6423SLionel Sambuc 
329*76bf77a2SCristiano Giuffrida   /* Copy flags and signal managers. */
330433d6423SLionel Sambuc   priv(rp)->s_flags = priv->s_flags;
331*76bf77a2SCristiano Giuffrida   priv(rp)->s_init_flags = priv->s_init_flags;
332433d6423SLionel Sambuc   priv(rp)->s_sig_mgr = priv->s_sig_mgr;
333433d6423SLionel Sambuc   priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
334433d6423SLionel Sambuc 
335433d6423SLionel Sambuc   /* Copy IRQs. */
336433d6423SLionel Sambuc   if(priv->s_flags & CHECK_IRQ) {
337433d6423SLionel Sambuc   	if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
338433d6423SLionel Sambuc   		return EINVAL;
339433d6423SLionel Sambuc   	priv(rp)->s_nr_irq= priv->s_nr_irq;
340433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_irq; i++)
341433d6423SLionel Sambuc   	{
342433d6423SLionel Sambuc   		priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
343433d6423SLionel Sambuc #if PRIV_DEBUG
344433d6423SLionel Sambuc   		printf("do_privctl: adding IRQ %d for %d\n",
345433d6423SLionel Sambuc   			priv(rp)->s_irq_tab[i], rp->p_endpoint);
346433d6423SLionel Sambuc #endif
347433d6423SLionel Sambuc   	}
348433d6423SLionel Sambuc   }
349433d6423SLionel Sambuc 
350433d6423SLionel Sambuc   /* Copy I/O ranges. */
351433d6423SLionel Sambuc   if(priv->s_flags & CHECK_IO_PORT) {
352433d6423SLionel Sambuc   	if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
353433d6423SLionel Sambuc   		return EINVAL;
354433d6423SLionel Sambuc   	priv(rp)->s_nr_io_range= priv->s_nr_io_range;
355433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_io_range; i++)
356433d6423SLionel Sambuc   	{
357433d6423SLionel Sambuc   		priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
358433d6423SLionel Sambuc #if PRIV_DEBUG
359433d6423SLionel Sambuc   		printf("do_privctl: adding I/O range [%x..%x] for %d\n",
360433d6423SLionel Sambuc   			priv(rp)->s_io_tab[i].ior_base,
361433d6423SLionel Sambuc   			priv(rp)->s_io_tab[i].ior_limit,
362433d6423SLionel Sambuc   			rp->p_endpoint);
363433d6423SLionel Sambuc #endif
364433d6423SLionel Sambuc   	}
365433d6423SLionel Sambuc   }
366433d6423SLionel Sambuc 
367433d6423SLionel Sambuc   /* Copy memory ranges. */
368433d6423SLionel Sambuc   if(priv->s_flags & CHECK_MEM) {
369433d6423SLionel Sambuc   	if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
370433d6423SLionel Sambuc   		return EINVAL;
371433d6423SLionel Sambuc   	priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
372433d6423SLionel Sambuc   	for (i= 0; i<priv->s_nr_mem_range; i++)
373433d6423SLionel Sambuc   	{
374433d6423SLionel Sambuc   		priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
375433d6423SLionel Sambuc #if PRIV_DEBUG
376433d6423SLionel Sambuc   		printf("do_privctl: adding mem range [%x..%x] for %d\n",
377433d6423SLionel Sambuc   			priv(rp)->s_mem_tab[i].mr_base,
378433d6423SLionel Sambuc   			priv(rp)->s_mem_tab[i].mr_limit,
379433d6423SLionel Sambuc   			rp->p_endpoint);
380433d6423SLionel Sambuc #endif
381433d6423SLionel Sambuc   	}
382433d6423SLionel Sambuc   }
383433d6423SLionel Sambuc 
384433d6423SLionel Sambuc   /* Copy trap mask. */
385433d6423SLionel Sambuc   priv(rp)->s_trap_mask = priv->s_trap_mask;
386433d6423SLionel Sambuc 
387433d6423SLionel Sambuc   /* Copy target mask. */
388433d6423SLionel Sambuc #if PRIV_DEBUG
389433d6423SLionel Sambuc   printf("do_privctl: Setting ipc target mask for %d:");
390433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
391433d6423SLionel Sambuc   	printf(" %08x", get_sys_bits(priv->s_ipc_to, i));
392433d6423SLionel Sambuc   }
393433d6423SLionel Sambuc   printf("\n");
394433d6423SLionel Sambuc #endif
395433d6423SLionel Sambuc 
396433d6423SLionel Sambuc   fill_sendto_mask(rp, &priv->s_ipc_to);
397433d6423SLionel Sambuc 
398433d6423SLionel Sambuc #if PRIV_DEBUG
399433d6423SLionel Sambuc   printf("do_privctl: Set ipc target mask for %d:");
400433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
401433d6423SLionel Sambuc   	printf(" %08x", get_sys_bits(priv(rp)->s_ipc_to, i));
402433d6423SLionel Sambuc   }
403433d6423SLionel Sambuc   printf("\n");
404433d6423SLionel Sambuc #endif
405433d6423SLionel Sambuc 
406433d6423SLionel Sambuc   /* Copy kernel call mask. */
407433d6423SLionel Sambuc   memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
408433d6423SLionel Sambuc   	sizeof(priv(rp)->s_k_call_mask));
409433d6423SLionel Sambuc 
410433d6423SLionel Sambuc   return OK;
411433d6423SLionel Sambuc }
412433d6423SLionel Sambuc 
413433d6423SLionel Sambuc #endif /* USE_PRIVCTL */
414433d6423SLionel Sambuc 
415