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.6 (Berkeley) 05/01/89 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 #define GRPSTART 0 37 38 #include "machine/reg.h" 39 40 getpid() 41 { 42 43 u.u_r.r_val1 = u.u_procp->p_pid; 44 u.u_r.r_val2 = u.u_procp->p_ppid; 45 } 46 47 getpgrp() 48 { 49 register struct a { 50 int pid; 51 } *uap = (struct a *)u.u_ap; 52 register struct proc *p; 53 54 if (uap->pid == 0) 55 p = u.u_procp; 56 else if ((p = pfind(uap->pid)) == 0) { 57 u.u_error = ESRCH; 58 return; 59 } 60 u.u_r.r_val1 = p->p_pgrp->pg_id; 61 } 62 63 getuid() 64 { 65 66 u.u_r.r_val1 = u.u_ruid; 67 u.u_r.r_val2 = u.u_uid; 68 } 69 70 getgid() 71 { 72 73 u.u_r.r_val1 = u.u_rgid; 74 u.u_r.r_val2 = u.u_gid; 75 } 76 77 getgroups() 78 { 79 register struct a { 80 u_int gidsetsize; 81 int *gidset; 82 } *uap = (struct a *)u.u_ap; 83 register gid_t *gp; 84 register int *lp; 85 int groups[NGROUPS]; 86 87 if (uap->gidsetsize == 0) { 88 u.u_r.r_val1 = u.u_ngroups - GRPSTART; 89 return; 90 } 91 if (uap->gidsetsize < u.u_ngroups - GRPSTART) { 92 u.u_error = EINVAL; 93 return; 94 } 95 uap->gidsetsize = u.u_ngroups - GRPSTART; 96 gp = &u.u_groups[GRPSTART]; 97 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 98 *lp++ = *gp++; 99 u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 100 uap->gidsetsize * sizeof (groups[0])); 101 if (u.u_error) 102 return; 103 u.u_r.r_val1 = uap->gidsetsize; 104 } 105 106 setsid() 107 { 108 register struct proc *p = u.u_procp; 109 110 if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid)) 111 u.u_error = EPERM; 112 else { 113 pgmv(p, p->p_pid, 1); 114 u.u_r.r_val1 = p->p_pid; 115 } 116 return; 117 } 118 119 /* 120 * set process group 121 * 122 * if target pid != caller's pid 123 * pid must be an inferior 124 * pid must be in same session 125 * pid can't have done an exec 126 * there must exist a pid with pgid in same session 127 * pid must not be session leader 128 */ 129 setpgrp() 130 { 131 register struct a { 132 int pid; 133 int pgid; 134 } *uap = (struct a *)u.u_ap; 135 register struct proc *p; 136 register struct pgrp *pgrp; 137 138 if (uap->pid == 0) 139 p = u.u_procp; 140 else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) { 141 u.u_error = ESRCH; 142 return; 143 } 144 else if (p != u.u_procp) { 145 if (p->p_session != u.u_procp->p_session) { 146 u.u_error = EPERM; 147 return; 148 } 149 if (p->p_flag&SEXEC) { 150 u.u_error = EACCES; 151 return; 152 } 153 } 154 if (SESS_LEADER(p)) { 155 u.u_error = EPERM; 156 return; 157 } 158 if (uap->pgid == 0) 159 uap->pgid = p->p_pid; 160 else if ((uap->pgid != p->p_pid) && 161 (((pgrp = pgfind(uap->pgid)) == 0) || 162 pgrp->pg_mem == NULL || 163 pgrp->pg_session != u.u_procp->p_session)) { 164 u.u_error = EPERM; 165 return; 166 } 167 /* 168 * done checking, now doit 169 */ 170 pgmv(p, uap->pgid, 0); 171 } 172 173 setreuid() 174 { 175 struct a { 176 int ruid; 177 int euid; 178 } *uap; 179 register int ruid, euid; 180 181 uap = (struct a *)u.u_ap; 182 ruid = uap->ruid; 183 if (ruid == -1) 184 ruid = u.u_ruid; 185 if (u.u_ruid != ruid && u.u_uid != ruid && 186 (u.u_error = suser(u.u_cred, &u.u_acflag))) 187 return; 188 euid = uap->euid; 189 if (euid == -1) 190 euid = u.u_uid; 191 if (u.u_ruid != euid && u.u_uid != euid && 192 (u.u_error = suser(u.u_cred, &u.u_acflag))) 193 return; 194 /* 195 * Everything's okay, do it. 196 * Copy credentials so other references do not 197 * see our changes. 198 */ 199 #ifdef QUOTA 200 if (u.u_quota->q_uid != ruid) { 201 qclean(); 202 qstart(getquota((uid_t)ruid, 0, 0)); 203 } 204 #endif 205 if (u.u_cred->cr_ref > 1) 206 u.u_cred = crcopy(u.u_cred); 207 u.u_procp->p_uid = euid; 208 u.u_ruid = ruid; 209 u.u_uid = euid; 210 } 211 212 setregid() 213 { 214 register struct a { 215 int rgid; 216 int egid; 217 } *uap; 218 register int rgid, egid; 219 220 uap = (struct a *)u.u_ap; 221 rgid = uap->rgid; 222 if (rgid == -1) 223 rgid = u.u_rgid; 224 if (u.u_rgid != rgid && u.u_gid != rgid && 225 (u.u_error = suser(u.u_cred, &u.u_acflag))) 226 return; 227 egid = uap->egid; 228 if (egid == -1) 229 egid = u.u_gid; 230 if (u.u_rgid != egid && u.u_gid != egid && 231 (u.u_error = suser(u.u_cred, &u.u_acflag))) 232 return; 233 if (u.u_cred->cr_ref > 1) 234 u.u_cred = crcopy(u.u_cred); 235 u.u_rgid = rgid; 236 u.u_gid = egid; 237 } 238 239 setgroups() 240 { 241 register struct a { 242 u_int gidsetsize; 243 int *gidset; 244 } *uap = (struct a *)u.u_ap; 245 register gid_t *gp; 246 register int *lp; 247 int ngrp, groups[NGROUPS]; 248 249 if (u.u_error = suser(u.u_cred, &u.u_acflag)) 250 return; 251 ngrp = uap->gidsetsize + GRPSTART; 252 if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 253 u.u_error = EINVAL; 254 return; 255 } 256 u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 257 uap->gidsetsize * sizeof (groups[0])); 258 if (u.u_error) 259 return; 260 gp = &u.u_groups[GRPSTART]; 261 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 262 *gp++ = *lp++; 263 u.u_ngroups = ngrp; 264 } 265 266 /* 267 * Check if gid is a member of the group set. 268 */ 269 groupmember(gid, cred) 270 gid_t gid; 271 register struct ucred *cred; 272 { 273 register gid_t *gp; 274 gid_t *egp; 275 276 egp = &(cred->cr_groups[cred->cr_ngroups]); 277 for (gp = cred->cr_groups; gp < egp; gp++) 278 if (*gp == gid) 279 return (1); 280 return (0); 281 } 282 283 /* 284 * Test if the current user is the super user. 285 */ 286 suser(cred, acflag) 287 struct ucred *cred; 288 short *acflag; 289 { 290 291 if (cred->cr_uid == 0) { 292 if (acflag) 293 *acflag |= ASU; 294 return (0); 295 } 296 return (EPERM); 297 } 298 299 /* 300 * Allocate a zeroed cred structure. 301 */ 302 struct ucred * 303 crget() 304 { 305 register struct ucred *cr; 306 307 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 308 bzero((caddr_t)cr, sizeof(*cr)); 309 cr->cr_ref = 1; 310 return(cr); 311 } 312 313 /* 314 * Free a cred structure. 315 * Throws away space when ref count gets to 0. 316 */ 317 crfree(cr) 318 struct ucred *cr; 319 { 320 int s = splimp(); 321 322 if (--cr->cr_ref != 0) { 323 (void) splx(s); 324 return; 325 } 326 FREE((caddr_t)cr, M_CRED); 327 (void) splx(s); 328 } 329 330 /* 331 * Copy cred structure to a new one and free the old one. 332 */ 333 struct ucred * 334 crcopy(cr) 335 struct ucred *cr; 336 { 337 struct ucred *newcr; 338 339 newcr = crget(); 340 *newcr = *cr; 341 crfree(cr); 342 newcr->cr_ref = 1; 343 return(newcr); 344 } 345 346 /* 347 * Dup cred struct to a new held one. 348 */ 349 struct ucred * 350 crdup(cr) 351 struct ucred *cr; 352 { 353 struct ucred *newcr; 354 355 newcr = crget(); 356 *newcr = *cr; 357 newcr->cr_ref = 1; 358 return(newcr); 359 } 360 361 /* 362 * Get login name of process owner, if available 363 */ 364 365 getlogname() 366 { 367 struct a { 368 char *namebuf; 369 u_int namelen; 370 } *uap = (struct a *)u.u_ap; 371 372 if (uap->namelen > sizeof (u.u_logname)) 373 uap->namelen = sizeof (u.u_logname); 374 u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf, 375 uap->namelen); 376 } 377 378 /* 379 * Set login name of process owner 380 */ 381 382 setlogname() 383 { 384 struct a { 385 char *namebuf; 386 u_int namelen; 387 } *uap = (struct a *)u.u_ap; 388 389 if (u.u_error = suser(u.u_cred, &u.u_acflag)) 390 return; 391 if (uap->namelen > sizeof (u.u_logname) - 1) 392 u.u_error = EINVAL; 393 else 394 u.u_error = copyin((caddr_t)uap->namebuf, 395 (caddr_t)u.u_logname, uap->namelen); 396 } 397