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