1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)kern_prot.c 7.9 (Berkeley) 04/27/90 18 */ 19 20 /* 21 * System calls related to processes and protection 22 */ 23 24 #include "param.h" 25 #include "acct.h" 26 #include "systm.h" 27 #include "user.h" 28 #include "proc.h" 29 #include "timeb.h" 30 #include "times.h" 31 #include "reboot.h" 32 #include "mount.h" 33 #include "buf.h" 34 #include "../ufs/quota.h" 35 #include "malloc.h" 36 37 #include "machine/reg.h" 38 39 getpid() 40 { 41 42 u.u_r.r_val1 = u.u_procp->p_pid; 43 u.u_r.r_val2 = u.u_procp->p_ppid; 44 } 45 46 getpgrp() 47 { 48 register struct a { 49 int pid; 50 } *uap = (struct a *)u.u_ap; 51 register struct proc *p; 52 53 if (uap->pid == 0) 54 p = u.u_procp; 55 else if ((p = pfind(uap->pid)) == 0) { 56 u.u_error = ESRCH; 57 return; 58 } 59 u.u_r.r_val1 = p->p_pgrp->pg_id; 60 } 61 62 getuid() 63 { 64 65 u.u_r.r_val1 = u.u_procp->p_ruid; 66 u.u_r.r_val2 = u.u_cred->cr_uid; 67 } 68 69 getgid() 70 { 71 72 u.u_r.r_val1 = u.u_procp->p_rgid; 73 u.u_r.r_val2 = u.u_cred->cr_groups[0]; 74 } 75 76 getgroups() 77 { 78 register struct a { 79 u_int gidsetsize; 80 int *gidset; 81 } *uap = (struct a *)u.u_ap; 82 register gid_t *gp; 83 register int *lp; 84 int groups[NGROUPS]; 85 86 if (uap->gidsetsize == 0) { 87 u.u_r.r_val1 = u.u_cred->cr_ngroups; 88 return; 89 } 90 if (uap->gidsetsize < u.u_cred->cr_ngroups) { 91 u.u_error = EINVAL; 92 return; 93 } 94 uap->gidsetsize = u.u_cred->cr_ngroups; 95 gp = u.u_cred->cr_groups; 96 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 97 *lp++ = *gp++; 98 u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 99 uap->gidsetsize * sizeof (groups[0])); 100 if (u.u_error) 101 return; 102 u.u_r.r_val1 = uap->gidsetsize; 103 } 104 105 setsid() 106 { 107 register struct proc *p = u.u_procp; 108 109 if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid)) 110 u.u_error = EPERM; 111 else { 112 pgmv(p, p->p_pid, 1); 113 u.u_r.r_val1 = p->p_pid; 114 } 115 return; 116 } 117 118 /* 119 * set process group 120 * 121 * caller does setpgrp(pid, pgid) 122 * 123 * pid must be caller or child of caller (ESRCH) 124 * if a child 125 * pid must be in same session (EPERM) 126 * pid can't have done an exec (EACCES) 127 * if pgid != pid 128 * there must exist some pid in same session having pgid (EPERM) 129 * pid must not be session leader (EPERM) 130 */ 131 setpgrp() 132 { 133 register struct a { 134 int pid; 135 int pgid; 136 } *uap = (struct a *)u.u_ap; 137 register struct proc *p; 138 register struct pgrp *pgrp; 139 140 if (uap->pid == 0) 141 p = u.u_procp; 142 else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) { 143 u.u_error = ESRCH; 144 return; 145 } 146 else if (p != u.u_procp) { 147 if (p->p_session != u.u_procp->p_session) { 148 u.u_error = EPERM; 149 return; 150 } 151 if (p->p_flag&SEXEC) { 152 u.u_error = EACCES; 153 return; 154 } 155 } 156 if (SESS_LEADER(p)) { 157 u.u_error = EPERM; 158 return; 159 } 160 if (uap->pgid == 0) 161 uap->pgid = p->p_pid; 162 else if ((uap->pgid != p->p_pid) && 163 (((pgrp = pgfind(uap->pgid)) == 0) || 164 pgrp->pg_mem == NULL || 165 pgrp->pg_session != u.u_procp->p_session)) { 166 u.u_error = EPERM; 167 return; 168 } 169 /* 170 * done checking, now doit 171 */ 172 pgmv(p, uap->pgid, 0); 173 } 174 175 setreuid() 176 { 177 struct a { 178 int ruid; 179 int euid; 180 } *uap; 181 register struct proc *p = u.u_procp; 182 register int ruid, euid; 183 184 uap = (struct a *)u.u_ap; 185 ruid = uap->ruid; 186 if (ruid == -1) 187 ruid = p->p_ruid; 188 #ifdef COMPAT_43 189 if (ruid != p->p_ruid && ruid != u.u_cred->cr_uid /* XXX */ && 190 (u.u_error = suser(u.u_cred, &u.u_acflag))) 191 #else 192 if (ruid != p->p_ruid && (u.u_error = suser(u.u_cred, &u.u_acflag))) 193 #endif 194 return; 195 euid = uap->euid; 196 if (euid == -1) 197 euid = u.u_cred->cr_uid; 198 if (euid != u.u_cred->cr_uid && euid != p->p_ruid && 199 euid != p->p_svuid && (u.u_error = suser(u.u_cred, &u.u_acflag))) 200 return; 201 /* 202 * Everything's okay, do it. 203 * Copy credentials so other references do not 204 * see our changes. 205 */ 206 if (u.u_cred->cr_ref > 1) 207 u.u_cred = crcopy(u.u_cred); 208 u.u_cred->cr_uid = euid; 209 p->p_uid = euid; 210 p->p_ruid = ruid; 211 } 212 213 setregid() 214 { 215 register struct a { 216 int rgid; 217 int egid; 218 } *uap; 219 register int rgid, egid; 220 register struct proc *p = u.u_procp; 221 222 uap = (struct a *)u.u_ap; 223 rgid = uap->rgid; 224 if (rgid == -1) 225 rgid = p->p_rgid; 226 #ifdef COMPAT_43_XXX 227 if (rgid != p->p_rgid && rgid != u.u_cred->cr_groups[0] /* XXX */ && 228 (u.u_error = suser(u.u_cred, &u.u_acflag))) 229 #else 230 if (rgid != p->p_rgid && (u.u_error = suser(u.u_cred, &u.u_acflag))) 231 #endif 232 return; 233 egid = uap->egid; 234 if (egid == -1) 235 egid = u.u_cred->cr_groups[0]; 236 if (egid != u.u_cred->cr_groups[0] && egid != p->p_rgid && 237 egid != p->p_svgid && (u.u_error = suser(u.u_cred, &u.u_acflag))) 238 return; 239 if (u.u_cred->cr_ref > 1) 240 u.u_cred = crcopy(u.u_cred); 241 p->p_rgid = rgid; 242 u.u_cred->cr_groups[0] = egid; 243 } 244 245 setgroups() 246 { 247 register struct a { 248 u_int gidsetsize; 249 int *gidset; 250 } *uap = (struct a *)u.u_ap; 251 register gid_t *gp; 252 register int *lp; 253 int ngrp, groups[NGROUPS]; 254 255 if (u.u_error = suser(u.u_cred, &u.u_acflag)) 256 return; 257 ngrp = uap->gidsetsize; 258 if (ngrp > NGROUPS) { 259 u.u_error = EINVAL; 260 return; 261 } 262 u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 263 uap->gidsetsize * sizeof (groups[0])); 264 if (u.u_error) 265 return; 266 gp = u.u_cred->cr_groups; 267 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 268 *gp++ = *lp++; 269 u.u_cred->cr_ngroups = ngrp; 270 } 271 272 /* 273 * Check if gid is a member of the group set. 274 */ 275 groupmember(gid, cred) 276 gid_t gid; 277 register struct ucred *cred; 278 { 279 register gid_t *gp; 280 gid_t *egp; 281 282 egp = &(cred->cr_groups[cred->cr_ngroups]); 283 for (gp = cred->cr_groups; gp < egp; gp++) 284 if (*gp == gid) 285 return (1); 286 return (0); 287 } 288 289 /* 290 * Test if the current user is the super user. 291 */ 292 suser(cred, acflag) 293 struct ucred *cred; 294 short *acflag; 295 { 296 297 if (cred->cr_uid == 0) { 298 if (acflag) 299 *acflag |= ASU; 300 return (0); 301 } 302 return (EPERM); 303 } 304 305 /* 306 * Allocate a zeroed cred structure. 307 */ 308 struct ucred * 309 crget() 310 { 311 register struct ucred *cr; 312 313 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 314 bzero((caddr_t)cr, sizeof(*cr)); 315 cr->cr_ref = 1; 316 return(cr); 317 } 318 319 /* 320 * Free a cred structure. 321 * Throws away space when ref count gets to 0. 322 */ 323 crfree(cr) 324 struct ucred *cr; 325 { 326 int s = splimp(); 327 328 if (--cr->cr_ref != 0) { 329 (void) splx(s); 330 return; 331 } 332 FREE((caddr_t)cr, M_CRED); 333 (void) splx(s); 334 } 335 336 /* 337 * Copy cred structure to a new one and free the old one. 338 */ 339 struct ucred * 340 crcopy(cr) 341 struct ucred *cr; 342 { 343 struct ucred *newcr; 344 345 newcr = crget(); 346 *newcr = *cr; 347 crfree(cr); 348 newcr->cr_ref = 1; 349 return(newcr); 350 } 351 352 /* 353 * Dup cred struct to a new held one. 354 */ 355 struct ucred * 356 crdup(cr) 357 struct ucred *cr; 358 { 359 struct ucred *newcr; 360 361 newcr = crget(); 362 *newcr = *cr; 363 newcr->cr_ref = 1; 364 return(newcr); 365 } 366 367 /* 368 * Get login name, if available. 369 */ 370 getlogin() 371 { 372 struct a { 373 char *namebuf; 374 u_int namelen; 375 } *uap = (struct a *)u.u_ap; 376 377 if (uap->namelen > sizeof (u.u_procp->p_logname)) 378 uap->namelen = sizeof (u.u_procp->p_logname); 379 u.u_error = copyout((caddr_t)u.u_procp->p_logname, 380 (caddr_t)uap->namebuf, uap->namelen); 381 } 382 383 /* 384 * Set login name. 385 */ 386 setlogin() 387 { 388 struct a { 389 char *namebuf; 390 } *uap = (struct a *)u.u_ap; 391 int error; 392 393 if (u.u_error = suser(u.u_cred, &u.u_acflag)) 394 return; 395 error = copyinstr((caddr_t)uap->namebuf, (caddr_t)u.u_procp->p_logname, 396 sizeof (u.u_procp->p_logname) - 1, (int *) 0); 397 if (error == ENOENT) /* name too long */ 398 error = EINVAL; 399 u.u_error = error; 400 } 401