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