1 /* The kernel call implemented in this file:
4 * The parameters for this kernel call are:
5 * m1_i1: PR_ENDPT (process number of caller)
15 #define FILLED_MASK (~0)
17 /*===========================================================================*
19 *===========================================================================*/
20 PUBLIC
int do_privctl(m_ptr
)
21 message
*m_ptr
; /* pointer to request message */
23 /* Handle sys_privctl(). Update a process' privileges. If the process is not
24 * yet a system process, make sure it gets its own privilege structure.
26 register struct proc
*caller_ptr
;
27 register struct proc
*rp
;
28 register struct priv
*sp
;
32 struct io_range io_range
;
33 struct mem_range mem_range
;
36 /* Check whether caller is allowed to make this call. Privileged proceses
37 * can only update the privileges of processes that are inhibited from
38 * running by the NO_PRIV flag. This flag is set when a privileged process
41 caller_ptr
= proc_addr(who_p
);
42 if (! (priv(caller_ptr
)->s_flags
& SYS_PROC
)) return(EPERM
);
43 if(m_ptr
->PR_ENDPT
== SELF
) proc_nr
= who_p
;
44 else if(!isokendpt(m_ptr
->PR_ENDPT
, &proc_nr
)) return(EINVAL
);
45 rp
= proc_addr(proc_nr
);
47 switch(m_ptr
->CTL_REQUEST
)
50 if (! RTS_ISSET(rp
, NO_PRIV
)) return(EPERM
);
52 /* Make sure this process has its own privileges structure. This may
53 * fail, since there are only a limited number of system processes.
54 * Then copy the privileges from the caller and restore some defaults.
56 if ((i
=get_priv(rp
, SYS_PROC
)) != OK
)
58 kprintf("do_privctl: out of priv structures\n");
61 priv_id
= priv(rp
)->s_id
; /* backup privilege id */
62 *priv(rp
) = *priv(caller_ptr
); /* copy from caller */
63 priv(rp
)->s_id
= priv_id
; /* restore privilege id */
64 priv(rp
)->s_proc_nr
= proc_nr
; /* reassociate process nr */
66 for (i
=0; i
< BITMAP_CHUNKS(NR_SYS_PROCS
); i
++) /* remove pending: */
67 priv(rp
)->s_notify_pending
.chunk
[i
] = 0; /* - notifications */
68 priv(rp
)->s_int_pending
= 0; /* - interrupts */
69 sigemptyset(&priv(rp
)->s_sig_pending
); /* - signals */
71 /* Now update the process' privileges as requested. */
72 rp
->p_priv
->s_trap_mask
= FILLED_MASK
;
73 for (i
=0; i
<BITMAP_CHUNKS(NR_SYS_PROCS
); i
++) {
74 rp
->p_priv
->s_ipc_to
.chunk
[i
] = FILLED_MASK
;
76 unset_sys_bit(rp
->p_priv
->s_ipc_to
, USER_PRIV_ID
);
78 /* All process that this process can send to must be able to reply.
79 * Therefore, their send masks should be updated as well.
81 for (i
=0; i
<NR_SYS_PROCS
; i
++) {
82 if (get_sys_bit(rp
->p_priv
->s_ipc_to
, i
)) {
83 set_sys_bit(priv_addr(i
)->s_ipc_to
, priv_id(rp
));
87 for (i
=0; i
<BITMAP_CHUNKS(NR_SYS_PROCS
); i
++) {
88 rp
->p_priv
->s_ipc_sendrec
.chunk
[i
] = FILLED_MASK
;
90 unset_sys_bit(rp
->p_priv
->s_ipc_sendrec
, USER_PRIV_ID
);
92 /* No I/O resources, no memory resources, no IRQs, no grant table */
93 priv(rp
)->s_nr_io_range
= 0;
94 priv(rp
)->s_nr_mem_range
= 0;
95 priv(rp
)->s_nr_irq
= 0;
96 priv(rp
)->s_grant_table
= 0;
97 priv(rp
)->s_grant_entries
= 0;
99 if (m_ptr
->CTL_ARG_PTR
)
101 /* Copy privilege structure from caller */
102 if((r
=data_copy(who_e
, (vir_bytes
) m_ptr
->CTL_ARG_PTR
,
103 SYSTEM
, (vir_bytes
) &priv
, sizeof(priv
))) != OK
)
106 /* Copy the call mask */
107 for (i
= 0; i
<CALL_MASK_SIZE
; i
++)
108 priv(rp
)->s_k_call_mask
[i
]= priv
.s_k_call_mask
[i
];
111 if (priv
.s_nr_irq
< 0 || priv
.s_nr_irq
> NR_IRQ
)
113 priv(rp
)->s_nr_irq
= priv
.s_nr_irq
;
114 for (i
= 0; i
<priv
.s_nr_irq
; i
++)
116 priv(rp
)->s_irq_tab
[i
]= priv
.s_irq_tab
[i
];
118 kprintf("do_privctl: adding IRQ %d for %d\n",
119 priv(rp
)->s_irq_tab
[i
], rp
->p_endpoint
);
123 priv(rp
)->s_flags
|= CHECK_IRQ
; /* Check requests for IRQs */
125 /* Copy I/O ranges */
126 if (priv
.s_nr_io_range
< 0 || priv
.s_nr_io_range
> NR_IO_RANGE
)
128 priv(rp
)->s_nr_io_range
= priv
.s_nr_io_range
;
129 for (i
= 0; i
<priv
.s_nr_io_range
; i
++)
131 priv(rp
)->s_io_tab
[i
]= priv
.s_io_tab
[i
];
133 kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
134 priv(rp
)->s_io_tab
[i
].ior_base
,
135 priv(rp
)->s_io_tab
[i
].ior_limit
,
140 /* Check requests for IRQs */
141 priv(rp
)->s_flags
|= CHECK_IO_PORT
;
143 memcpy(priv(rp
)->s_k_call_mask
, priv
.s_k_call_mask
,
144 sizeof(priv(rp
)->s_k_call_mask
));
145 memcpy(&priv(rp
)->s_ipc_to
, &priv
.s_ipc_to
,
146 sizeof(priv(rp
)->s_ipc_to
));
147 memcpy(&priv(rp
)->s_ipc_sendrec
, &priv
.s_ipc_sendrec
,
148 sizeof(priv(rp
)->s_ipc_sendrec
));
151 /* Done. Privileges have been set. Allow process to run again. */
152 RTS_LOCK_UNSET(rp
, NO_PRIV
);
155 /* Make this process an ordinary user process. */
156 if (!RTS_ISSET(rp
, NO_PRIV
)) return(EPERM
);
157 if ((i
=get_priv(rp
, 0)) != OK
) return(i
);
158 RTS_LOCK_UNSET(rp
, NO_PRIV
);
161 case SYS_PRIV_ADD_IO
:
162 if (RTS_ISSET(rp
, NO_PRIV
))
165 /* Only system processes get I/O resources? */
166 if (!(priv(rp
)->s_flags
& SYS_PROC
))
169 #if 0 /* XXX -- do we need a call for this? */
170 if (strcmp(rp
->p_name
, "fxp") == 0 ||
171 strcmp(rp
->p_name
, "rtl8139") == 0)
173 kprintf("setting ipc_stats_target to %d\n", rp
->p_endpoint
);
174 ipc_stats_target
= rp
->p_endpoint
;
178 /* Get the I/O range */
179 data_copy(who_e
, (vir_bytes
) m_ptr
->CTL_ARG_PTR
,
180 SYSTEM
, (vir_bytes
) &io_range
, sizeof(io_range
));
181 priv(rp
)->s_flags
|= CHECK_IO_PORT
; /* Check I/O accesses */
182 i
= priv(rp
)->s_nr_io_range
;
183 if (i
>= NR_IO_RANGE
)
186 priv(rp
)->s_io_tab
[i
].ior_base
= io_range
.ior_base
;
187 priv(rp
)->s_io_tab
[i
].ior_limit
= io_range
.ior_limit
;
188 priv(rp
)->s_nr_io_range
++;
192 case SYS_PRIV_ADD_MEM
:
193 if (RTS_ISSET(rp
, NO_PRIV
))
196 /* Only system processes get memory resources? */
197 if (!(priv(rp
)->s_flags
& SYS_PROC
))
200 /* Get the memory range */
201 if((r
=data_copy(who_e
, (vir_bytes
) m_ptr
->CTL_ARG_PTR
,
202 SYSTEM
, (vir_bytes
) &mem_range
, sizeof(mem_range
))) != OK
)
204 priv(rp
)->s_flags
|= CHECK_MEM
; /* Check I/O accesses */
205 i
= priv(rp
)->s_nr_mem_range
;
206 if (i
>= NR_MEM_RANGE
)
210 priv(rp
)->s_mem_tab
[i
].mr_base
= mem_range
.mr_base
;
211 priv(rp
)->s_mem_tab
[i
].mr_limit
= mem_range
.mr_limit
;
212 priv(rp
)->s_nr_mem_range
++;
217 case SYS_PRIV_ADD_IRQ
:
218 if (RTS_ISSET(rp
, NO_PRIV
))
221 /* Only system processes get IRQs? */
222 if (!(priv(rp
)->s_flags
& SYS_PROC
))
225 priv(rp
)->s_flags
|= CHECK_IRQ
; /* Check IRQs */
227 i
= priv(rp
)->s_nr_irq
;
230 priv(rp
)->s_irq_tab
[i
]= m_ptr
->CTL_MM_PRIV
;
231 priv(rp
)->s_nr_irq
++;
235 kprintf("do_privctl: bad request %d\n", m_ptr
->CTL_REQUEST
);
240 #endif /* USE_PRIVCTL */