dynamically allocate the name cache and name cache hashing header
[unix-history] / usr / src / sys / kern / kern_prot.c
CommitLineData
da7c5cc6 1/*
88a39492
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
88a39492
KM
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 *
164c0f54 17 * @(#)kern_prot.c 7.8 (Berkeley) %G%
da7c5cc6 18 */
a05af100
BJ
19
20/*
4147b3f6 21 * System calls related to processes and protection
a05af100
BJ
22 */
23
94368568 24#include "param.h"
88a39492 25#include "acct.h"
94368568 26#include "systm.h"
94368568 27#include "user.h"
94368568
JB
28#include "proc.h"
29#include "timeb.h"
30#include "times.h"
31#include "reboot.h"
94368568 32#include "mount.h"
88a39492
KM
33#include "buf.h"
34#include "../ufs/quota.h"
35#include "malloc.h"
a05af100 36
d301d150
KM
37#include "machine/reg.h"
38
4147b3f6
BJ
39getpid()
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
46getpgrp()
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)
8fe87cbb
MT
54 p = u.u_procp;
55 else if ((p = pfind(uap->pid)) == 0) {
4147b3f6
BJ
56 u.u_error = ESRCH;
57 return;
58 }
8fe87cbb 59 u.u_r.r_val1 = p->p_pgrp->pg_id;
4147b3f6
BJ
60}
61
a05af100
BJ
62getuid()
63{
64
164c0f54
MK
65 u.u_r.r_val1 = u.u_procp->p_ruid;
66 u.u_r.r_val2 = u.u_cred->cr_uid;
a05af100
BJ
67}
68
4147b3f6
BJ
69getgid()
70{
71
164c0f54
MK
72 u.u_r.r_val1 = u.u_procp->p_rgid;
73 u.u_r.r_val2 = u.u_cred->cr_groups[0];
4147b3f6
BJ
74}
75
197da11b 76getgroups()
4147b3f6
BJ
77{
78 register struct a {
b32450f4 79 u_int gidsetsize;
4147b3f6
BJ
80 int *gidset;
81 } *uap = (struct a *)u.u_ap;
38b6104c
MK
82 register gid_t *gp;
83 register int *lp;
84 int groups[NGROUPS];
4147b3f6 85
88a39492 86 if (uap->gidsetsize == 0) {
164c0f54 87 u.u_r.r_val1 = u.u_cred->cr_ngroups;
88a39492
KM
88 return;
89 }
164c0f54 90 if (uap->gidsetsize < u.u_cred->cr_ngroups) {
197da11b
BJ
91 u.u_error = EINVAL;
92 return;
93 }
164c0f54
MK
94 uap->gidsetsize = u.u_cred->cr_ngroups;
95 gp = u.u_cred->cr_groups;
88a39492 96 for (lp = groups; lp < &groups[uap->gidsetsize]; )
38b6104c
MK
97 *lp++ = *gp++;
98 u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
99 uap->gidsetsize * sizeof (groups[0]));
127f7d76 100 if (u.u_error)
4147b3f6 101 return;
197da11b 102 u.u_r.r_val1 = uap->gidsetsize;
4147b3f6
BJ
103}
104
8fe87cbb
MT
105setsid()
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 *
164c0f54
MK
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)
8fe87cbb 130 */
4147b3f6
BJ
131setpgrp()
132{
4147b3f6
BJ
133 register struct a {
134 int pid;
8fe87cbb 135 int pgid;
4147b3f6 136 } *uap = (struct a *)u.u_ap;
8fe87cbb
MT
137 register struct proc *p;
138 register struct pgrp *pgrp;
4147b3f6
BJ
139
140 if (uap->pid == 0)
8fe87cbb
MT
141 p = u.u_procp;
142 else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) {
4147b3f6
BJ
143 u.u_error = ESRCH;
144 return;
145 }
8fe87cbb
MT
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)) {
4147b3f6
BJ
166 u.u_error = EPERM;
167 return;
168 }
8fe87cbb
MT
169 /*
170 * done checking, now doit
171 */
172 pgmv(p, uap->pgid, 0);
4147b3f6
BJ
173}
174
4f083fd7
SL
175setreuid()
176{
177 struct a {
178 int ruid;
179 int euid;
180 } *uap;
164c0f54 181 register struct proc *p = u.u_procp;
4f083fd7
SL
182 register int ruid, euid;
183
184 uap = (struct a *)u.u_ap;
185 ruid = uap->ruid;
186 if (ruid == -1)
4f083fd7
SL
187 return;
188 euid = uap->euid;
189 if (euid == -1)
4f083fd7
SL
190 return;
191 /*
192 * Everything's okay, do it.
88a39492
KM
193 * Copy credentials so other references do not
194 * see our changes.
4f083fd7 195 */
4f083fd7 196#ifdef QUOTA
709593b8
SL
197 if (u.u_quota->q_uid != ruid) {
198 qclean();
8011f5df 199 qstart(getquota((uid_t)ruid, 0, 0));
4f083fd7 200 }
709593b8 201#endif
88a39492
KM
202 if (u.u_cred->cr_ref > 1)
203 u.u_cred = crcopy(u.u_cred);
164c0f54
MK
204 u.u_cred->cr_uid = euid;
205 p->p_uid = euid;
206 p->p_ruid = ruid;
4f083fd7
SL
207}
208
4f083fd7
SL
209setregid()
210{
211 register struct a {
212 int rgid;
213 int egid;
214 } *uap;
215 register int rgid, egid;
164c0f54 216 register struct proc *p = u.u_procp;
4f083fd7
SL
217
218 uap = (struct a *)u.u_ap;
219 rgid = uap->rgid;
220 if (rgid == -1)
4f083fd7
SL
221 return;
222 egid = uap->egid;
223 if (egid == -1)
4f083fd7 224 return;
88a39492
KM
225 if (u.u_cred->cr_ref > 1)
226 u.u_cred = crcopy(u.u_cred);
164c0f54
MK
227 p->p_rgid = rgid;
228 u.u_cred->cr_groups[0] = egid;
4f083fd7 229}
a05af100 230
197da11b 231setgroups()
4147b3f6
BJ
232{
233 register struct a {
b32450f4 234 u_int gidsetsize;
4147b3f6
BJ
235 int *gidset;
236 } *uap = (struct a *)u.u_ap;
38b6104c
MK
237 register gid_t *gp;
238 register int *lp;
88a39492 239 int ngrp, groups[NGROUPS];
4147b3f6 240
849cbd39 241 if (u.u_error = suser(u.u_cred, &u.u_acflag))
4147b3f6 242 return;
164c0f54
MK
243 ngrp = uap->gidsetsize;
244 if (ngrp > NGROUPS) {
197da11b 245 u.u_error = EINVAL;
4147b3f6
BJ
246 return;
247 }
38b6104c
MK
248 u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
249 uap->gidsetsize * sizeof (groups[0]));
127f7d76 250 if (u.u_error)
4147b3f6 251 return;
164c0f54 252 gp = u.u_cred->cr_groups;
88a39492 253 for (lp = groups; lp < &groups[uap->gidsetsize]; )
38b6104c 254 *gp++ = *lp++;
164c0f54 255 u.u_cred->cr_ngroups = ngrp;
4147b3f6
BJ
256}
257
f926daf9 258/*
88a39492 259 * Check if gid is a member of the group set.
f926daf9 260 */
88a39492 261groupmember(gid, cred)
90731a34 262 gid_t gid;
88a39492 263 register struct ucred *cred;
197da11b 264{
38b6104c 265 register gid_t *gp;
88a39492 266 gid_t *egp;
197da11b 267
88a39492
KM
268 egp = &(cred->cr_groups[cred->cr_ngroups]);
269 for (gp = cred->cr_groups; gp < egp; gp++)
197da11b 270 if (*gp == gid)
88a39492
KM
271 return (1);
272 return (0);
197da11b
BJ
273}
274
f926daf9 275/*
88a39492 276 * Test if the current user is the super user.
f926daf9 277 */
88a39492
KM
278suser(cred, acflag)
279 struct ucred *cred;
280 short *acflag;
197da11b 281{
197da11b 282
88a39492
KM
283 if (cred->cr_uid == 0) {
284 if (acflag)
285 *acflag |= ASU;
286 return (0);
38b6104c 287 }
88a39492 288 return (EPERM);
197da11b 289}
f926daf9
SL
290
291/*
88a39492 292 * Allocate a zeroed cred structure.
f926daf9 293 */
88a39492
KM
294struct ucred *
295crget()
f926daf9 296{
88a39492 297 register struct ucred *cr;
f926daf9 298
88a39492
KM
299 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
300 bzero((caddr_t)cr, sizeof(*cr));
301 cr->cr_ref = 1;
302 return(cr);
303}
304
305/*
306 * Free a cred structure.
307 * Throws away space when ref count gets to 0.
308 */
309crfree(cr)
310 struct ucred *cr;
311{
312 int s = splimp();
313
314 if (--cr->cr_ref != 0) {
315 (void) splx(s);
316 return;
317 }
318 FREE((caddr_t)cr, M_CRED);
319 (void) splx(s);
320}
321
322/*
323 * Copy cred structure to a new one and free the old one.
324 */
325struct ucred *
326crcopy(cr)
327 struct ucred *cr;
328{
329 struct ucred *newcr;
330
331 newcr = crget();
332 *newcr = *cr;
333 crfree(cr);
334 newcr->cr_ref = 1;
335 return(newcr);
336}
337
338/*
339 * Dup cred struct to a new held one.
340 */
341struct ucred *
342crdup(cr)
343 struct ucred *cr;
344{
345 struct ucred *newcr;
346
347 newcr = crget();
348 *newcr = *cr;
349 newcr->cr_ref = 1;
350 return(newcr);
f926daf9 351}
5b6ee178
KF
352
353/*
164c0f54 354 * Get login name, if available.
5b6ee178 355 */
164c0f54 356getlogin()
5b6ee178
KF
357{
358 struct a {
359 char *namebuf;
360 u_int namelen;
361 } *uap = (struct a *)u.u_ap;
362
164c0f54
MK
363 if (uap->namelen > sizeof (u.u_procp->p_logname))
364 uap->namelen = sizeof (u.u_procp->p_logname);
365 u.u_error = copyout((caddr_t)u.u_procp->p_logname,
366 (caddr_t)uap->namebuf, uap->namelen);
5b6ee178
KF
367}
368
369/*
164c0f54 370 * Set login name.
5b6ee178 371 */
164c0f54 372setlogin()
5b6ee178
KF
373{
374 struct a {
375 char *namebuf;
5b6ee178 376 } *uap = (struct a *)u.u_ap;
164c0f54 377 int error;
5b6ee178 378
849cbd39
KM
379 if (u.u_error = suser(u.u_cred, &u.u_acflag))
380 return;
164c0f54
MK
381 error = copyinstr((caddr_t)uap->namebuf, (caddr_t)u.u_procp->p_logname,
382 sizeof (u.u_procp->p_logname) - 1, (int *) 0);
383 if (error == ENOENT) /* name too long */
384 error = EINVAL;
385 u.u_error = error;
5b6ee178 386}