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.1.1.1 (Berkeley) 05/01/89 18 */ 19 20 /* 21 * System calls related to processes and protection 22 */ 23 24 #include "machine/reg.h" 25 26 #include "param.h" 27 #include "acct.h" 28 #include "systm.h" 29 #include "user.h" 30 #include "proc.h" 31 #include "timeb.h" 32 #include "times.h" 33 #include "reboot.h" 34 #include "mount.h" 35 #include "buf.h" 36 #include "../ufs/quota.h" 37 #include "malloc.h" 38 #define GRPSTART 0 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 uap->pid = u.u_procp->p_pid; 56 p = pfind(uap->pid); 57 if (p == 0) { 58 u.u_error = ESRCH; 59 return; 60 } 61 u.u_r.r_val1 = p->p_pgrp; 62 } 63 64 getuid() 65 { 66 67 u.u_r.r_val1 = u.u_ruid; 68 u.u_r.r_val2 = u.u_uid; 69 } 70 71 getgid() 72 { 73 74 u.u_r.r_val1 = u.u_rgid; 75 u.u_r.r_val2 = u.u_gid; 76 } 77 78 getgroups() 79 { 80 register struct a { 81 u_int gidsetsize; 82 int *gidset; 83 } *uap = (struct a *)u.u_ap; 84 register gid_t *gp; 85 register int *lp; 86 int groups[NGROUPS]; 87 88 if (uap->gidsetsize == 0) { 89 u.u_r.r_val1 = u.u_ngroups - GRPSTART; 90 return; 91 } 92 if (uap->gidsetsize < u.u_ngroups - GRPSTART) { 93 u.u_error = EINVAL; 94 return; 95 } 96 uap->gidsetsize = u.u_ngroups - GRPSTART; 97 gp = &u.u_groups[GRPSTART]; 98 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 99 *lp++ = *gp++; 100 u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 101 uap->gidsetsize * sizeof (groups[0])); 102 if (u.u_error) 103 return; 104 u.u_r.r_val1 = uap->gidsetsize; 105 } 106 107 setpgrp() 108 { 109 register struct proc *p; 110 register struct a { 111 int pid; 112 int pgrp; 113 } *uap = (struct a *)u.u_ap; 114 115 if (uap->pid == 0) 116 uap->pid = u.u_procp->p_pid; 117 p = pfind(uap->pid); 118 if (p == 0) { 119 u.u_error = ESRCH; 120 return; 121 } 122 /* need better control mechanisms for process groups */ 123 if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) { 124 u.u_error = EPERM; 125 return; 126 } 127 p->p_pgrp = uap->pgrp; 128 } 129 130 setreuid() 131 { 132 struct a { 133 int ruid; 134 int euid; 135 } *uap; 136 register int ruid, euid; 137 138 uap = (struct a *)u.u_ap; 139 ruid = uap->ruid; 140 if (ruid == -1) 141 ruid = u.u_ruid; 142 if (u.u_ruid != ruid && u.u_uid != ruid && 143 (u.u_error = suser(u.u_cred, &u.u_acflag))) 144 return; 145 euid = uap->euid; 146 if (euid == -1) 147 euid = u.u_uid; 148 if (u.u_ruid != euid && u.u_uid != euid && 149 (u.u_error = suser(u.u_cred, &u.u_acflag))) 150 return; 151 /* 152 * Everything's okay, do it. 153 * Copy credentials so other references do not 154 * see our changes. 155 */ 156 #ifdef QUOTA 157 if (u.u_quota->q_uid != ruid) { 158 qclean(); 159 qstart(getquota((uid_t)ruid, 0, 0)); 160 } 161 #endif 162 if (u.u_cred->cr_ref > 1) 163 u.u_cred = crcopy(u.u_cred); 164 u.u_procp->p_uid = euid; 165 u.u_ruid = ruid; 166 u.u_uid = euid; 167 } 168 169 setregid() 170 { 171 register struct a { 172 int rgid; 173 int egid; 174 } *uap; 175 register int rgid, egid; 176 177 uap = (struct a *)u.u_ap; 178 rgid = uap->rgid; 179 if (rgid == -1) 180 rgid = u.u_rgid; 181 if (u.u_rgid != rgid && u.u_gid != rgid && 182 (u.u_error = suser(u.u_cred, &u.u_acflag))) 183 return; 184 egid = uap->egid; 185 if (egid == -1) 186 egid = u.u_gid; 187 if (u.u_rgid != egid && u.u_gid != egid && 188 (u.u_error = suser(u.u_cred, &u.u_acflag))) 189 return; 190 if (u.u_cred->cr_ref > 1) 191 u.u_cred = crcopy(u.u_cred); 192 u.u_rgid = rgid; 193 u.u_gid = egid; 194 } 195 196 setgroups() 197 { 198 register struct a { 199 u_int gidsetsize; 200 int *gidset; 201 } *uap = (struct a *)u.u_ap; 202 register gid_t *gp; 203 register int *lp; 204 int ngrp, groups[NGROUPS]; 205 206 if (u.u_error = suser(u.u_cred, &u.u_acflag)) 207 return; 208 ngrp = uap->gidsetsize + GRPSTART; 209 if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 210 u.u_error = EINVAL; 211 return; 212 } 213 u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 214 uap->gidsetsize * sizeof (groups[0])); 215 if (u.u_error) 216 return; 217 gp = &u.u_groups[GRPSTART]; 218 for (lp = groups; lp < &groups[uap->gidsetsize]; ) 219 *gp++ = *lp++; 220 u.u_ngroups = ngrp; 221 } 222 223 /* 224 * Check if gid is a member of the group set. 225 */ 226 groupmember(gid, cred) 227 gid_t gid; 228 register struct ucred *cred; 229 { 230 register gid_t *gp; 231 gid_t *egp; 232 233 egp = &(cred->cr_groups[cred->cr_ngroups]); 234 for (gp = cred->cr_groups; gp < egp; gp++) 235 if (*gp == gid) 236 return (1); 237 return (0); 238 } 239 240 /* 241 * Test if the current user is the super user. 242 */ 243 suser(cred, acflag) 244 struct ucred *cred; 245 short *acflag; 246 { 247 248 if (cred->cr_uid == 0) { 249 if (acflag) 250 *acflag |= ASU; 251 return (0); 252 } 253 return (EPERM); 254 } 255 256 /* 257 * Allocate a zeroed cred structure. 258 */ 259 struct ucred * 260 crget() 261 { 262 register struct ucred *cr; 263 264 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 265 bzero((caddr_t)cr, sizeof(*cr)); 266 cr->cr_ref = 1; 267 return(cr); 268 } 269 270 /* 271 * Free a cred structure. 272 * Throws away space when ref count gets to 0. 273 */ 274 crfree(cr) 275 struct ucred *cr; 276 { 277 int s = splimp(); 278 279 if (--cr->cr_ref != 0) { 280 (void) splx(s); 281 return; 282 } 283 FREE((caddr_t)cr, M_CRED); 284 (void) splx(s); 285 } 286 287 /* 288 * Copy cred structure to a new one and free the old one. 289 */ 290 struct ucred * 291 crcopy(cr) 292 struct ucred *cr; 293 { 294 struct ucred *newcr; 295 296 newcr = crget(); 297 *newcr = *cr; 298 crfree(cr); 299 newcr->cr_ref = 1; 300 return(newcr); 301 } 302 303 /* 304 * Dup cred struct to a new held one. 305 */ 306 struct ucred * 307 crdup(cr) 308 struct ucred *cr; 309 { 310 struct ucred *newcr; 311 312 newcr = crget(); 313 *newcr = *cr; 314 newcr->cr_ref = 1; 315 return(newcr); 316 } 317