kern_prot.c revision 1.15 1 1.14 cgd /*
2 1.15 cgd * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3 1.15 cgd * The Regents of the University of California. All rights reserved.
4 1.14 cgd * (c) UNIX System Laboratories, Inc.
5 1.14 cgd * All or some portions of this file are derived from material licensed
6 1.14 cgd * to the University of California by American Telephone and Telegraph
7 1.14 cgd * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 1.14 cgd * the permission of UNIX System Laboratories, Inc.
9 1.14 cgd *
10 1.14 cgd * Redistribution and use in source and binary forms, with or without
11 1.14 cgd * modification, are permitted provided that the following conditions
12 1.14 cgd * are met:
13 1.14 cgd * 1. Redistributions of source code must retain the above copyright
14 1.14 cgd * notice, this list of conditions and the following disclaimer.
15 1.14 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.14 cgd * notice, this list of conditions and the following disclaimer in the
17 1.14 cgd * documentation and/or other materials provided with the distribution.
18 1.14 cgd * 3. All advertising materials mentioning features or use of this software
19 1.14 cgd * must display the following acknowledgement:
20 1.14 cgd * This product includes software developed by the University of
21 1.14 cgd * California, Berkeley and its contributors.
22 1.14 cgd * 4. Neither the name of the University nor the names of its contributors
23 1.14 cgd * may be used to endorse or promote products derived from this software
24 1.14 cgd * without specific prior written permission.
25 1.14 cgd *
26 1.14 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.14 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.14 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.14 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.14 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.14 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.14 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.14 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.14 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.14 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.14 cgd * SUCH DAMAGE.
37 1.14 cgd *
38 1.15 cgd * from: @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
39 1.15 cgd * $Id: kern_prot.c,v 1.15 1994/05/19 05:57:55 cgd Exp $
40 1.14 cgd */
41 1.14 cgd
42 1.14 cgd /*
43 1.14 cgd * System calls related to processes and protection
44 1.14 cgd */
45 1.14 cgd
46 1.14 cgd #include <sys/param.h>
47 1.14 cgd #include <sys/acct.h>
48 1.14 cgd #include <sys/systm.h>
49 1.14 cgd #include <sys/ucred.h>
50 1.14 cgd #include <sys/proc.h>
51 1.14 cgd #include <sys/timeb.h>
52 1.14 cgd #include <sys/times.h>
53 1.14 cgd #include <sys/malloc.h>
54 1.14 cgd
55 1.14 cgd /* ARGSUSED */
56 1.14 cgd getpid(p, uap, retval)
57 1.14 cgd struct proc *p;
58 1.14 cgd void *uap;
59 1.14 cgd int *retval;
60 1.14 cgd {
61 1.14 cgd
62 1.14 cgd *retval = p->p_pid;
63 1.14 cgd #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
64 1.14 cgd retval[1] = p->p_pptr->p_pid;
65 1.14 cgd #endif
66 1.14 cgd return (0);
67 1.14 cgd }
68 1.14 cgd
69 1.14 cgd /* ARGSUSED */
70 1.14 cgd getppid(p, uap, retval)
71 1.14 cgd struct proc *p;
72 1.14 cgd void *uap;
73 1.14 cgd int *retval;
74 1.14 cgd {
75 1.14 cgd
76 1.14 cgd *retval = p->p_pptr->p_pid;
77 1.14 cgd return (0);
78 1.14 cgd }
79 1.14 cgd
80 1.14 cgd /* Get process group ID; note that POSIX getpgrp takes no parameter */
81 1.14 cgd getpgrp(p, uap, retval)
82 1.14 cgd struct proc *p;
83 1.14 cgd void *uap;
84 1.14 cgd int *retval;
85 1.14 cgd {
86 1.14 cgd
87 1.14 cgd *retval = p->p_pgrp->pg_id;
88 1.14 cgd return (0);
89 1.14 cgd }
90 1.14 cgd
91 1.14 cgd /* ARGSUSED */
92 1.14 cgd getuid(p, uap, retval)
93 1.14 cgd struct proc *p;
94 1.14 cgd void *uap;
95 1.14 cgd int *retval;
96 1.14 cgd {
97 1.14 cgd
98 1.14 cgd *retval = p->p_cred->p_ruid;
99 1.14 cgd #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
100 1.14 cgd retval[1] = p->p_ucred->cr_uid;
101 1.14 cgd #endif
102 1.14 cgd return (0);
103 1.14 cgd }
104 1.14 cgd
105 1.14 cgd /* ARGSUSED */
106 1.14 cgd geteuid(p, uap, retval)
107 1.14 cgd struct proc *p;
108 1.14 cgd void *uap;
109 1.14 cgd int *retval;
110 1.14 cgd {
111 1.14 cgd
112 1.14 cgd *retval = p->p_ucred->cr_uid;
113 1.14 cgd return (0);
114 1.14 cgd }
115 1.14 cgd
116 1.14 cgd /* ARGSUSED */
117 1.14 cgd getgid(p, uap, retval)
118 1.14 cgd struct proc *p;
119 1.14 cgd void *uap;
120 1.14 cgd int *retval;
121 1.14 cgd {
122 1.14 cgd
123 1.14 cgd *retval = p->p_cred->p_rgid;
124 1.14 cgd #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
125 1.14 cgd retval[1] = p->p_ucred->cr_groups[0];
126 1.14 cgd #endif
127 1.14 cgd return (0);
128 1.14 cgd }
129 1.14 cgd
130 1.14 cgd /*
131 1.14 cgd * Get effective group ID. The "egid" is groups[0], and could be obtained
132 1.14 cgd * via getgroups. This syscall exists because it is somewhat painful to do
133 1.14 cgd * correctly in a library function.
134 1.14 cgd */
135 1.14 cgd /* ARGSUSED */
136 1.14 cgd getegid(p, uap, retval)
137 1.14 cgd struct proc *p;
138 1.14 cgd void *uap;
139 1.14 cgd int *retval;
140 1.14 cgd {
141 1.14 cgd
142 1.14 cgd *retval = p->p_ucred->cr_groups[0];
143 1.14 cgd return (0);
144 1.14 cgd }
145 1.14 cgd
146 1.14 cgd struct getgroups_args {
147 1.14 cgd u_int gidsetsize;
148 1.14 cgd gid_t *gidset;
149 1.14 cgd };
150 1.14 cgd getgroups(p, uap, retval)
151 1.14 cgd struct proc *p;
152 1.14 cgd register struct getgroups_args *uap;
153 1.14 cgd int *retval;
154 1.14 cgd {
155 1.14 cgd register struct pcred *pc = p->p_cred;
156 1.14 cgd register u_int ngrp;
157 1.14 cgd int error;
158 1.14 cgd
159 1.14 cgd if ((ngrp = uap->gidsetsize) == 0) {
160 1.14 cgd *retval = pc->pc_ucred->cr_ngroups;
161 1.14 cgd return (0);
162 1.14 cgd }
163 1.14 cgd if (ngrp < pc->pc_ucred->cr_ngroups)
164 1.14 cgd return (EINVAL);
165 1.14 cgd ngrp = pc->pc_ucred->cr_ngroups;
166 1.14 cgd if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
167 1.14 cgd (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))
168 1.14 cgd return (error);
169 1.14 cgd *retval = ngrp;
170 1.14 cgd return (0);
171 1.14 cgd }
172 1.14 cgd
173 1.14 cgd /* ARGSUSED */
174 1.14 cgd setsid(p, uap, retval)
175 1.14 cgd register struct proc *p;
176 1.14 cgd void *uap;
177 1.14 cgd int *retval;
178 1.14 cgd {
179 1.14 cgd
180 1.14 cgd if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
181 1.14 cgd return (EPERM);
182 1.14 cgd } else {
183 1.15 cgd (void)enterpgrp(p, p->p_pid, 1);
184 1.14 cgd *retval = p->p_pid;
185 1.14 cgd return (0);
186 1.14 cgd }
187 1.14 cgd }
188 1.14 cgd
189 1.14 cgd /*
190 1.14 cgd * set process group (setpgid/old setpgrp)
191 1.14 cgd *
192 1.14 cgd * caller does setpgid(targpid, targpgid)
193 1.14 cgd *
194 1.14 cgd * pid must be caller or child of caller (ESRCH)
195 1.14 cgd * if a child
196 1.14 cgd * pid must be in same session (EPERM)
197 1.14 cgd * pid can't have done an exec (EACCES)
198 1.14 cgd * if pgid != pid
199 1.14 cgd * there must exist some pid in same session having pgid (EPERM)
200 1.14 cgd * pid must not be session leader (EPERM)
201 1.14 cgd */
202 1.14 cgd struct setpgid_args {
203 1.14 cgd int pid; /* target process id */
204 1.14 cgd int pgid; /* target pgrp id */
205 1.14 cgd };
206 1.14 cgd /* ARGSUSED */
207 1.14 cgd setpgid(curp, uap, retval)
208 1.14 cgd struct proc *curp;
209 1.14 cgd register struct setpgid_args *uap;
210 1.14 cgd int *retval;
211 1.14 cgd {
212 1.14 cgd register struct proc *targp; /* target process */
213 1.14 cgd register struct pgrp *pgrp; /* target pgrp */
214 1.14 cgd
215 1.14 cgd #ifdef COMPAT_09
216 1.14 cgd uap->pid = (short) uap->pid; /* XXX */
217 1.14 cgd uap->pgid = (short) uap->pgid; /* XXX */
218 1.14 cgd #endif
219 1.14 cgd
220 1.14 cgd if (uap->pid != 0 && uap->pid != curp->p_pid) {
221 1.14 cgd if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
222 1.14 cgd return (ESRCH);
223 1.14 cgd if (targp->p_session != curp->p_session)
224 1.14 cgd return (EPERM);
225 1.15 cgd if (targp->p_flag & P_EXEC)
226 1.14 cgd return (EACCES);
227 1.14 cgd } else
228 1.14 cgd targp = curp;
229 1.14 cgd if (SESS_LEADER(targp))
230 1.14 cgd return (EPERM);
231 1.14 cgd if (uap->pgid == 0)
232 1.14 cgd uap->pgid = targp->p_pid;
233 1.14 cgd else if (uap->pgid != targp->p_pid)
234 1.14 cgd if ((pgrp = pgfind(uap->pgid)) == 0 ||
235 1.14 cgd pgrp->pg_session != curp->p_session)
236 1.14 cgd return (EPERM);
237 1.15 cgd return (enterpgrp(targp, uap->pgid, 0));
238 1.14 cgd }
239 1.14 cgd
240 1.14 cgd struct setuid_args {
241 1.14 cgd uid_t uid;
242 1.14 cgd };
243 1.14 cgd /* ARGSUSED */
244 1.14 cgd setuid(p, uap, retval)
245 1.14 cgd struct proc *p;
246 1.14 cgd struct setuid_args *uap;
247 1.14 cgd int *retval;
248 1.14 cgd {
249 1.14 cgd register struct pcred *pc = p->p_cred;
250 1.14 cgd register uid_t uid;
251 1.14 cgd int error;
252 1.14 cgd
253 1.14 cgd #ifdef COMPAT_09 /* XXX */
254 1.14 cgd uid = (u_short)uap->uid;
255 1.14 cgd #else
256 1.14 cgd uid = uap->uid;
257 1.14 cgd #endif
258 1.14 cgd if (uid != pc->p_ruid &&
259 1.14 cgd (error = suser(pc->pc_ucred, &p->p_acflag)))
260 1.14 cgd return (error);
261 1.14 cgd /*
262 1.15 cgd * Everything's okay, do it.
263 1.15 cgd * Transfer proc count to new user.
264 1.15 cgd * Copy credentials so other references do not see our changes.
265 1.14 cgd */
266 1.15 cgd (void)chgproccnt(pc->p_ruid, -1);
267 1.15 cgd (void)chgproccnt(uid, 1);
268 1.14 cgd pc->pc_ucred = crcopy(pc->pc_ucred);
269 1.14 cgd pc->pc_ucred->cr_uid = uid;
270 1.14 cgd pc->p_ruid = uid;
271 1.14 cgd pc->p_svuid = uid;
272 1.14 cgd p->p_flag |= P_SUGID;
273 1.14 cgd return (0);
274 1.14 cgd }
275 1.14 cgd
276 1.14 cgd struct seteuid_args {
277 1.14 cgd uid_t euid;
278 1.14 cgd };
279 1.14 cgd /* ARGSUSED */
280 1.14 cgd seteuid(p, uap, retval)
281 1.14 cgd struct proc *p;
282 1.14 cgd struct seteuid_args *uap;
283 1.14 cgd int *retval;
284 1.14 cgd {
285 1.14 cgd register struct pcred *pc = p->p_cred;
286 1.14 cgd register uid_t euid;
287 1.14 cgd int error;
288 1.14 cgd
289 1.14 cgd #ifdef COMPAT_09 /* XXX */
290 1.14 cgd euid = (u_short)uap->euid;
291 1.14 cgd #else
292 1.14 cgd euid = uap->euid;
293 1.14 cgd #endif
294 1.14 cgd if (euid != pc->p_ruid && euid != pc->p_svuid &&
295 1.14 cgd (error = suser(pc->pc_ucred, &p->p_acflag)))
296 1.14 cgd return (error);
297 1.14 cgd /*
298 1.14 cgd * Everything's okay, do it. Copy credentials so other references do
299 1.14 cgd * not see our changes.
300 1.14 cgd */
301 1.14 cgd pc->pc_ucred = crcopy(pc->pc_ucred);
302 1.14 cgd pc->pc_ucred->cr_uid = euid;
303 1.14 cgd p->p_flag |= P_SUGID;
304 1.14 cgd return (0);
305 1.14 cgd }
306 1.14 cgd
307 1.14 cgd struct setgid_args {
308 1.14 cgd gid_t gid;
309 1.14 cgd };
310 1.14 cgd /* ARGSUSED */
311 1.14 cgd setgid(p, uap, retval)
312 1.14 cgd struct proc *p;
313 1.14 cgd struct setgid_args *uap;
314 1.14 cgd int *retval;
315 1.14 cgd {
316 1.14 cgd register struct pcred *pc = p->p_cred;
317 1.14 cgd register gid_t gid;
318 1.14 cgd int error;
319 1.14 cgd
320 1.14 cgd #ifdef COMPAT_09 /* XXX */
321 1.14 cgd gid = (u_short)uap->gid;
322 1.14 cgd #else
323 1.14 cgd gid = uap->gid;
324 1.14 cgd #endif
325 1.14 cgd if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
326 1.14 cgd return (error);
327 1.14 cgd pc->pc_ucred = crcopy(pc->pc_ucred);
328 1.14 cgd pc->pc_ucred->cr_groups[0] = gid;
329 1.14 cgd pc->p_rgid = gid;
330 1.14 cgd pc->p_svgid = gid; /* ??? */
331 1.14 cgd p->p_flag |= P_SUGID;
332 1.14 cgd return (0);
333 1.14 cgd }
334 1.14 cgd
335 1.14 cgd struct setegid_args {
336 1.14 cgd gid_t egid;
337 1.14 cgd };
338 1.14 cgd /* ARGSUSED */
339 1.14 cgd setegid(p, uap, retval)
340 1.14 cgd struct proc *p;
341 1.14 cgd struct setegid_args *uap;
342 1.14 cgd int *retval;
343 1.14 cgd {
344 1.14 cgd register struct pcred *pc = p->p_cred;
345 1.14 cgd register gid_t egid;
346 1.14 cgd int error;
347 1.14 cgd
348 1.14 cgd #ifdef COMPAT_09 /* XXX */
349 1.14 cgd egid = (u_short)uap->egid;
350 1.14 cgd #else
351 1.14 cgd egid = uap->egid;
352 1.14 cgd #endif
353 1.14 cgd if (egid != pc->p_rgid && egid != pc->p_svgid &&
354 1.14 cgd (error = suser(pc->pc_ucred, &p->p_acflag)))
355 1.14 cgd return (error);
356 1.14 cgd pc->pc_ucred = crcopy(pc->pc_ucred);
357 1.14 cgd pc->pc_ucred->cr_groups[0] = egid;
358 1.14 cgd p->p_flag |= P_SUGID;
359 1.14 cgd return (0);
360 1.14 cgd }
361 1.14 cgd
362 1.15 cgd struct setgroups_args {
363 1.15 cgd u_int gidsetsize;
364 1.15 cgd gid_t *gidset;
365 1.15 cgd };
366 1.15 cgd /* ARGSUSED */
367 1.15 cgd setgroups(p, uap, retval)
368 1.15 cgd struct proc *p;
369 1.15 cgd struct setgroups_args *uap;
370 1.15 cgd int *retval;
371 1.15 cgd {
372 1.15 cgd register struct pcred *pc = p->p_cred;
373 1.15 cgd register u_int ngrp;
374 1.15 cgd int error;
375 1.15 cgd
376 1.15 cgd if (error = suser(pc->pc_ucred, &p->p_acflag))
377 1.15 cgd return (error);
378 1.15 cgd if ((ngrp = uap->gidsetsize) > NGROUPS)
379 1.15 cgd return (EINVAL);
380 1.15 cgd pc->pc_ucred = crcopy(pc->pc_ucred);
381 1.15 cgd if (error = copyin((caddr_t)uap->gidset,
382 1.15 cgd (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
383 1.15 cgd return (error);
384 1.15 cgd pc->pc_ucred->cr_ngroups = ngrp;
385 1.15 cgd p->p_flag |= P_SUGID;
386 1.15 cgd return (0);
387 1.15 cgd }
388 1.14 cgd
389 1.15 cgd #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
390 1.15 cgd struct setreuid_args {
391 1.15 cgd int ruid;
392 1.15 cgd int euid;
393 1.14 cgd };
394 1.14 cgd /* ARGSUSED */
395 1.14 cgd osetreuid(p, uap, retval)
396 1.14 cgd register struct proc *p;
397 1.15 cgd struct setreuid_args *uap;
398 1.14 cgd int *retval;
399 1.14 cgd {
400 1.14 cgd register struct pcred *pc = p->p_cred;
401 1.15 cgd struct seteuid_args args;
402 1.14 cgd
403 1.14 cgd /*
404 1.14 cgd * we assume that the intent of setting ruid is to be able to get
405 1.14 cgd * back ruid priviledge. So we make sure that we will be able to
406 1.14 cgd * do so, but do not actually set the ruid.
407 1.14 cgd */
408 1.14 cgd if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid &&
409 1.14 cgd uap->ruid != pc->p_svuid)
410 1.14 cgd return (EPERM);
411 1.14 cgd if (uap->euid == (uid_t)-1)
412 1.14 cgd return (0);
413 1.14 cgd args.euid = uap->euid;
414 1.14 cgd return (seteuid(p, &args, retval));
415 1.14 cgd }
416 1.14 cgd
417 1.15 cgd struct setregid_args {
418 1.15 cgd int rgid;
419 1.15 cgd int egid;
420 1.14 cgd };
421 1.14 cgd /* ARGSUSED */
422 1.14 cgd osetregid(p, uap, retval)
423 1.14 cgd register struct proc *p;
424 1.15 cgd struct setregid_args *uap;
425 1.14 cgd int *retval;
426 1.14 cgd {
427 1.14 cgd register struct pcred *pc = p->p_cred;
428 1.14 cgd struct setegid_args args;
429 1.14 cgd
430 1.14 cgd /*
431 1.14 cgd * we assume that the intent of setting rgid is to be able to get
432 1.14 cgd * back rgid priviledge. So we make sure that we will be able to
433 1.14 cgd * do so, but do not actually set the rgid.
434 1.14 cgd */
435 1.14 cgd if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid &&
436 1.14 cgd uap->rgid != pc->p_svgid)
437 1.14 cgd return (EPERM);
438 1.14 cgd if (uap->egid == (gid_t)-1)
439 1.14 cgd return (0);
440 1.14 cgd args.egid = uap->egid;
441 1.14 cgd return (setegid(p, &args, retval));
442 1.14 cgd }
443 1.15 cgd #endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
444 1.14 cgd
445 1.14 cgd /*
446 1.14 cgd * Check if gid is a member of the group set.
447 1.14 cgd */
448 1.14 cgd groupmember(gid, cred)
449 1.14 cgd gid_t gid;
450 1.14 cgd register struct ucred *cred;
451 1.14 cgd {
452 1.14 cgd register gid_t *gp;
453 1.14 cgd gid_t *egp;
454 1.14 cgd
455 1.14 cgd egp = &(cred->cr_groups[cred->cr_ngroups]);
456 1.14 cgd for (gp = cred->cr_groups; gp < egp; gp++)
457 1.14 cgd if (*gp == gid)
458 1.14 cgd return (1);
459 1.14 cgd return (0);
460 1.14 cgd }
461 1.14 cgd
462 1.14 cgd /*
463 1.14 cgd * Test whether the specified credentials imply "super-user"
464 1.14 cgd * privilege; if so, and we have accounting info, set the flag
465 1.14 cgd * indicating use of super-powers.
466 1.14 cgd * Returns 0 or error.
467 1.14 cgd */
468 1.14 cgd suser(cred, acflag)
469 1.14 cgd struct ucred *cred;
470 1.14 cgd u_short *acflag;
471 1.14 cgd {
472 1.14 cgd if (cred->cr_uid == 0) {
473 1.14 cgd if (acflag)
474 1.14 cgd *acflag |= ASU;
475 1.14 cgd return (0);
476 1.14 cgd }
477 1.14 cgd return (EPERM);
478 1.14 cgd }
479 1.14 cgd
480 1.14 cgd /*
481 1.14 cgd * Allocate a zeroed cred structure.
482 1.14 cgd */
483 1.14 cgd struct ucred *
484 1.14 cgd crget()
485 1.14 cgd {
486 1.14 cgd register struct ucred *cr;
487 1.14 cgd
488 1.14 cgd MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
489 1.14 cgd bzero((caddr_t)cr, sizeof(*cr));
490 1.14 cgd cr->cr_ref = 1;
491 1.14 cgd return (cr);
492 1.14 cgd }
493 1.14 cgd
494 1.14 cgd /*
495 1.14 cgd * Free a cred structure.
496 1.14 cgd * Throws away space when ref count gets to 0.
497 1.14 cgd */
498 1.14 cgd crfree(cr)
499 1.14 cgd struct ucred *cr;
500 1.14 cgd {
501 1.15 cgd int s;
502 1.14 cgd
503 1.15 cgd s = splimp(); /* ??? */
504 1.15 cgd if (--cr->cr_ref == 0)
505 1.15 cgd FREE((caddr_t)cr, M_CRED);
506 1.14 cgd (void) splx(s);
507 1.14 cgd }
508 1.14 cgd
509 1.14 cgd /*
510 1.14 cgd * Copy cred structure to a new one and free the old one.
511 1.14 cgd */
512 1.14 cgd struct ucred *
513 1.14 cgd crcopy(cr)
514 1.14 cgd struct ucred *cr;
515 1.14 cgd {
516 1.14 cgd struct ucred *newcr;
517 1.14 cgd
518 1.14 cgd if (cr->cr_ref == 1)
519 1.14 cgd return (cr);
520 1.14 cgd newcr = crget();
521 1.14 cgd *newcr = *cr;
522 1.14 cgd crfree(cr);
523 1.14 cgd newcr->cr_ref = 1;
524 1.14 cgd return (newcr);
525 1.14 cgd }
526 1.14 cgd
527 1.14 cgd /*
528 1.14 cgd * Dup cred struct to a new held one.
529 1.14 cgd */
530 1.14 cgd struct ucred *
531 1.14 cgd crdup(cr)
532 1.14 cgd struct ucred *cr;
533 1.14 cgd {
534 1.14 cgd struct ucred *newcr;
535 1.14 cgd
536 1.14 cgd newcr = crget();
537 1.14 cgd *newcr = *cr;
538 1.14 cgd newcr->cr_ref = 1;
539 1.14 cgd return (newcr);
540 1.14 cgd }
541 1.14 cgd
542 1.14 cgd /*
543 1.14 cgd * Get login name, if available.
544 1.14 cgd */
545 1.14 cgd struct getlogin_args {
546 1.14 cgd char *namebuf;
547 1.14 cgd u_int namelen;
548 1.14 cgd };
549 1.14 cgd /* ARGSUSED */
550 1.14 cgd getlogin(p, uap, retval)
551 1.14 cgd struct proc *p;
552 1.14 cgd struct getlogin_args *uap;
553 1.14 cgd int *retval;
554 1.14 cgd {
555 1.14 cgd
556 1.14 cgd if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
557 1.14 cgd uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
558 1.14 cgd return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
559 1.14 cgd (caddr_t) uap->namebuf, uap->namelen));
560 1.14 cgd }
561 1.14 cgd
562 1.14 cgd /*
563 1.14 cgd * Set login name.
564 1.14 cgd */
565 1.14 cgd struct setlogin_args {
566 1.14 cgd char *namebuf;
567 1.14 cgd };
568 1.14 cgd /* ARGSUSED */
569 1.14 cgd setlogin(p, uap, retval)
570 1.14 cgd struct proc *p;
571 1.14 cgd struct setlogin_args *uap;
572 1.14 cgd int *retval;
573 1.14 cgd {
574 1.14 cgd int error;
575 1.14 cgd
576 1.14 cgd if (error = suser(p->p_ucred, &p->p_acflag))
577 1.14 cgd return (error);
578 1.14 cgd error = copyinstr((caddr_t) uap->namebuf,
579 1.14 cgd (caddr_t) p->p_pgrp->pg_session->s_login,
580 1.14 cgd sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
581 1.14 cgd if (error == ENAMETOOLONG)
582 1.14 cgd error = EINVAL;
583 1.14 cgd return (error);
584 1.14 cgd }
585