FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_prot.c
1 /*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
39 * $FreeBSD: src/sys/kern/kern_prot.c,v 1.19.2.3 1999/09/05 08:15:01 peter Exp $
40 */
41
42 /*
43 * System calls related to processes and protection
44 */
45
46 #include <sys/param.h>
47 #include <sys/acct.h>
48 #include <sys/systm.h>
49 #include <sys/sysproto.h>
50 #include <sys/ucred.h>
51 #include <sys/proc.h>
52 #include <sys/timeb.h>
53 #include <sys/times.h>
54 #include <sys/malloc.h>
55 #include <sys/unistd.h>
56
57 #ifndef _SYS_SYSPROTO_H_
58 struct getpid_args {
59 int dummy;
60 };
61 #endif
62
63 /* ARGSUSED */
64 int
65 getpid(p, uap, retval)
66 struct proc *p;
67 struct getpid_args *uap;
68 int *retval;
69 {
70
71 *retval = p->p_pid;
72 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
73 retval[1] = p->p_pptr->p_pid;
74 #endif
75 return (0);
76 }
77
78 #ifndef _SYS_SYSPROTO_H_
79 struct getppid_args {
80 int dummy;
81 };
82 #endif
83 /* ARGSUSED */
84 int
85 getppid(p, uap, retval)
86 struct proc *p;
87 struct getppid_args *uap;
88 int *retval;
89 {
90
91 *retval = p->p_pptr->p_pid;
92 return (0);
93 }
94
95 /* Get process group ID; note that POSIX getpgrp takes no parameter */
96 #ifndef _SYS_SYSPROTO_H_
97 struct getpgrp_args {
98 int dummy;
99 };
100 #endif
101
102 int
103 getpgrp(p, uap, retval)
104 struct proc *p;
105 struct getpgrp_args *uap;
106 int *retval;
107 {
108
109 *retval = p->p_pgrp->pg_id;
110 return (0);
111 }
112
113 #ifndef _SYS_SYSPROTO_H_
114 struct getuid_args {
115 int dummy;
116 };
117 #endif
118
119 /* ARGSUSED */
120 int
121 getuid(p, uap, retval)
122 struct proc *p;
123 struct getuid_args *uap;
124 int *retval;
125 {
126
127 *retval = p->p_cred->p_ruid;
128 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
129 retval[1] = p->p_ucred->cr_uid;
130 #endif
131 return (0);
132 }
133
134 #ifndef _SYS_SYSPROTO_H_
135 struct geteuid_args {
136 int dummy;
137 };
138 #endif
139
140 /* ARGSUSED */
141 int
142 geteuid(p, uap, retval)
143 struct proc *p;
144 struct geteuid_args *uap;
145 int *retval;
146 {
147
148 *retval = p->p_ucred->cr_uid;
149 return (0);
150 }
151
152 #ifndef _SYS_SYSPROTO_H_
153 struct getgid_args {
154 int dummy;
155 };
156 #endif
157
158 /* ARGSUSED */
159 int
160 getgid(p, uap, retval)
161 struct proc *p;
162 struct getgid_args *uap;
163 int *retval;
164 {
165
166 *retval = p->p_cred->p_rgid;
167 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
168 retval[1] = p->p_ucred->cr_groups[0];
169 #endif
170 return (0);
171 }
172
173 /*
174 * Get effective group ID. The "egid" is groups[0], and could be obtained
175 * via getgroups. This syscall exists because it is somewhat painful to do
176 * correctly in a library function.
177 */
178 #ifndef _SYS_SYSPROTO_H_
179 struct getegid_args {
180 int dummy;
181 };
182 #endif
183
184 /* ARGSUSED */
185 int
186 getegid(p, uap, retval)
187 struct proc *p;
188 struct getegid_args *uap;
189 int *retval;
190 {
191
192 *retval = p->p_ucred->cr_groups[0];
193 return (0);
194 }
195
196 #ifndef _SYS_SYSPROTO_H_
197 struct getgroups_args {
198 u_int gidsetsize;
199 gid_t *gidset;
200 };
201 #endif
202 int
203 getgroups(p, uap, retval)
204 struct proc *p;
205 register struct getgroups_args *uap;
206 int *retval;
207 {
208 register struct pcred *pc = p->p_cred;
209 register u_int ngrp;
210 int error;
211
212 if ((ngrp = uap->gidsetsize) == 0) {
213 *retval = pc->pc_ucred->cr_ngroups;
214 return (0);
215 }
216 if (ngrp < pc->pc_ucred->cr_ngroups)
217 return (EINVAL);
218 ngrp = pc->pc_ucred->cr_ngroups;
219 if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
220 (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
221 return (error);
222 *retval = ngrp;
223 return (0);
224 }
225
226 #ifndef _SYS_SYSPROTO_H_
227 struct setsid_args {
228 int dummy;
229 };
230 #endif
231
232 /* ARGSUSED */
233 int
234 setsid(p, uap, retval)
235 register struct proc *p;
236 struct setsid_args *uap;
237 int *retval;
238 {
239
240 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
241 return (EPERM);
242 } else {
243 (void)enterpgrp(p, p->p_pid, 1);
244 *retval = p->p_pid;
245 return (0);
246 }
247 }
248
249 /*
250 * set process group (setpgid/old setpgrp)
251 *
252 * caller does setpgid(targpid, targpgid)
253 *
254 * pid must be caller or child of caller (ESRCH)
255 * if a child
256 * pid must be in same session (EPERM)
257 * pid can't have done an exec (EACCES)
258 * if pgid != pid
259 * there must exist some pid in same session having pgid (EPERM)
260 * pid must not be session leader (EPERM)
261 */
262 #ifndef _SYS_SYSPROTO_H_
263 struct setpgid_args {
264 int pid; /* target process id */
265 int pgid; /* target pgrp id */
266 };
267 #endif
268 /* ARGSUSED */
269 int
270 setpgid(curp, uap, retval)
271 struct proc *curp;
272 register struct setpgid_args *uap;
273 int *retval;
274 {
275 register struct proc *targp; /* target process */
276 register struct pgrp *pgrp; /* target pgrp */
277
278 if (uap->pgid < 0)
279 return (EINVAL);
280 if (uap->pid != 0 && uap->pid != curp->p_pid) {
281 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
282 return (ESRCH);
283 if (targp->p_pgrp == NULL || targp->p_session != curp->p_session)
284 return (EPERM);
285 if (targp->p_flag & P_EXEC)
286 return (EACCES);
287 } else
288 targp = curp;
289 if (SESS_LEADER(targp))
290 return (EPERM);
291 if (uap->pgid == 0)
292 uap->pgid = targp->p_pid;
293 else if (uap->pgid != targp->p_pid)
294 if ((pgrp = pgfind(uap->pgid)) == 0 ||
295 pgrp->pg_session != curp->p_session)
296 return (EPERM);
297 return (enterpgrp(targp, uap->pgid, 0));
298 }
299
300 /*
301 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
302 * compatable. It says that setting the uid/gid to euid/egid is a special
303 * case of "appropriate privilege". Once the rules are expanded out, this
304 * basically means that setuid(nnn) sets all three id's, in all permitted
305 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid())
306 * does not set the saved id - this is dangerous for traditional BSD
307 * programs. For this reason, we *really* do not want to set
308 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
309 */
310 #define POSIX_APPENDIX_B_4_2_2
311
312 #ifndef _SYS_SYSPROTO_H_
313 struct setuid_args {
314 uid_t uid;
315 };
316 #endif
317 /* ARGSUSED */
318 int
319 setuid(p, uap, retval)
320 struct proc *p;
321 struct setuid_args *uap;
322 int *retval;
323 {
324 register struct pcred *pc = p->p_cred;
325 register uid_t uid;
326 int error;
327
328 /*
329 * See if we have "permission" by POSIX 1003.1 rules.
330 *
331 * Note that setuid(geteuid()) is a special case of
332 * "appropriate privileges" in appendix B.4.2.2. We need
333 * to use this clause to be compatable with traditional BSD
334 * semantics. Basically, it means that "setuid(xx)" sets all
335 * three id's (assuming you have privs).
336 *
337 * Notes on the logic. We do things in three steps.
338 * 1: We determine if the euid is going to change, and do EPERM
339 * right away. We unconditionally change the euid later if this
340 * test is satisfied, simplifying that part of the logic.
341 * 2: We determine if the real and/or saved uid's are going to
342 * change. Determined by compile options.
343 * 3: Change euid last. (after tests in #2 for "appropriate privs")
344 */
345 uid = uap->uid;
346 if (uid != pc->p_ruid && /* allow setuid(getuid()) */
347 #ifdef _POSIX_SAVED_IDS
348 uid != pc->p_svuid && /* allow setuid(saved gid) */
349 #endif
350 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
351 uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */
352 #endif
353 (error = suser(pc->pc_ucred, &p->p_acflag)))
354 return (error);
355
356 #ifdef _POSIX_SAVED_IDS
357 /*
358 * Do we have "appropriate privileges" (are we root or uid == euid)
359 * If so, we are changing the real uid and/or saved uid.
360 */
361 if (
362 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */
363 uid == pc->pc_ucred->cr_uid ||
364 #endif
365 suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */
366 #endif
367 {
368 /*
369 * Transfer proc count to new user.
370 */
371 if (uid != pc->p_ruid) {
372 (void)chgproccnt(pc->p_ruid, -1);
373 (void)chgproccnt(uid, 1);
374 }
375 /*
376 * Set real uid
377 */
378 if (uid != pc->p_ruid) {
379 p->p_flag |= P_SUGID;
380 pc->p_ruid = uid;
381 }
382 /*
383 * Set saved uid
384 *
385 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
386 * the security of seteuid() depends on it. B.4.2.2 says it
387 * is important that we should do this.
388 */
389 if (pc->p_svuid != uid) {
390 p->p_flag |= P_SUGID;
391 pc->p_svuid = uid;
392 }
393 }
394
395 /*
396 * In all permitted cases, we are changing the euid.
397 * Copy credentials so other references do not see our changes.
398 */
399 if (pc->pc_ucred->cr_uid != uid) {
400 pc->pc_ucred = crcopy(pc->pc_ucred);
401 pc->pc_ucred->cr_uid = uid;
402 p->p_flag |= P_SUGID;
403 }
404 return (0);
405 }
406
407 #ifndef _SYS_SYSPROTO_H_
408 struct seteuid_args {
409 uid_t euid;
410 };
411 #endif
412 /* ARGSUSED */
413 int
414 seteuid(p, uap, retval)
415 struct proc *p;
416 struct seteuid_args *uap;
417 int *retval;
418 {
419 register struct pcred *pc = p->p_cred;
420 register uid_t euid;
421 int error;
422
423 euid = uap->euid;
424 if (euid != pc->p_ruid && /* allow seteuid(getuid()) */
425 euid != pc->p_svuid && /* allow seteuid(saved uid) */
426 (error = suser(pc->pc_ucred, &p->p_acflag)))
427 return (error);
428 /*
429 * Everything's okay, do it. Copy credentials so other references do
430 * not see our changes.
431 */
432 if (pc->pc_ucred->cr_uid != euid) {
433 pc->pc_ucred = crcopy(pc->pc_ucred);
434 pc->pc_ucred->cr_uid = euid;
435 p->p_flag |= P_SUGID;
436 }
437 return (0);
438 }
439
440 #ifndef _SYS_SYSPROTO_H_
441 struct setgid_args {
442 gid_t gid;
443 };
444 #endif
445 /* ARGSUSED */
446 int
447 setgid(p, uap, retval)
448 struct proc *p;
449 struct setgid_args *uap;
450 int *retval;
451 {
452 register struct pcred *pc = p->p_cred;
453 register gid_t gid;
454 int error;
455
456 /*
457 * See if we have "permission" by POSIX 1003.1 rules.
458 *
459 * Note that setgid(getegid()) is a special case of
460 * "appropriate privileges" in appendix B.4.2.2. We need
461 * to use this clause to be compatable with traditional BSD
462 * semantics. Basically, it means that "setgid(xx)" sets all
463 * three id's (assuming you have privs).
464 *
465 * For notes on the logic here, see setuid() above.
466 */
467 gid = uap->gid;
468 if (gid != pc->p_rgid && /* allow setgid(getgid()) */
469 #ifdef _POSIX_SAVED_IDS
470 gid != pc->p_svgid && /* allow setgid(saved gid) */
471 #endif
472 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
473 gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
474 #endif
475 (error = suser(pc->pc_ucred, &p->p_acflag)))
476 return (error);
477
478 #ifdef _POSIX_SAVED_IDS
479 /*
480 * Do we have "appropriate privileges" (are we root or gid == egid)
481 * If so, we are changing the real uid and saved gid.
482 */
483 if (
484 #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */
485 gid == pc->pc_ucred->cr_groups[0] ||
486 #endif
487 suser(pc->pc_ucred, &p->p_acflag) == 0) /* we are using privs */
488 #endif
489 {
490 /*
491 * Set real gid
492 */
493 if (pc->p_rgid != gid) {
494 p->p_flag |= P_SUGID;
495 pc->p_rgid = gid;
496 }
497 /*
498 * Set saved gid
499 *
500 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
501 * the security of setegid() depends on it. B.4.2.2 says it
502 * is important that we should do this.
503 */
504 if (pc->p_svgid != gid) {
505 p->p_flag |= P_SUGID;
506 pc->p_svgid = gid;
507 }
508 }
509 /*
510 * In all cases permitted cases, we are changing the egid.
511 * Copy credentials so other references do not see our changes.
512 */
513 if (pc->pc_ucred->cr_groups[0] != gid) {
514 pc->pc_ucred = crcopy(pc->pc_ucred);
515 pc->pc_ucred->cr_groups[0] = gid;
516 p->p_flag |= P_SUGID;
517 }
518 return (0);
519 }
520
521 #ifndef _SYS_SYSPROTO_H_
522 struct setegid_args {
523 gid_t egid;
524 };
525 #endif
526 /* ARGSUSED */
527 int
528 setegid(p, uap, retval)
529 struct proc *p;
530 struct setegid_args *uap;
531 int *retval;
532 {
533 register struct pcred *pc = p->p_cred;
534 register gid_t egid;
535 int error;
536
537 egid = uap->egid;
538 if (egid != pc->p_rgid && /* allow setegid(getgid()) */
539 egid != pc->p_svgid && /* allow setegid(saved gid) */
540 (error = suser(pc->pc_ucred, &p->p_acflag)))
541 return (error);
542 if (pc->pc_ucred->cr_groups[0] != egid) {
543 pc->pc_ucred = crcopy(pc->pc_ucred);
544 pc->pc_ucred->cr_groups[0] = egid;
545 p->p_flag |= P_SUGID;
546 }
547 return (0);
548 }
549
550 #ifndef _SYS_SYSPROTO_H_
551 struct setgroups_args {
552 u_int gidsetsize;
553 gid_t *gidset;
554 };
555 #endif
556 /* ARGSUSED */
557 int
558 setgroups(p, uap, retval)
559 struct proc *p;
560 struct setgroups_args *uap;
561 int *retval;
562 {
563 register struct pcred *pc = p->p_cred;
564 register u_int ngrp;
565 int error;
566
567 if ((error = suser(pc->pc_ucred, &p->p_acflag)))
568 return (error);
569 ngrp = uap->gidsetsize;
570 if (ngrp > NGROUPS)
571 return (EINVAL);
572 /*
573 * XXX A little bit lazy here. We could test if anything has
574 * changed before crcopy() and setting P_SUGID.
575 */
576 pc->pc_ucred = crcopy(pc->pc_ucred);
577 if (ngrp < 1) {
578 /*
579 * setgroups(0, NULL) is a legitimate way of clearing the
580 * groups vector on non-BSD systems (which generally do not
581 * have the egid in the groups[0]). We risk security holes
582 * when running non-BSD software if we do not do the same.
583 */
584 pc->pc_ucred->cr_ngroups = 1;
585 } else {
586 if ((error = copyin((caddr_t)uap->gidset,
587 (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
588 return (error);
589 pc->pc_ucred->cr_ngroups = ngrp;
590 }
591 p->p_flag |= P_SUGID;
592 return (0);
593 }
594
595 #ifndef _SYS_SYSPROTO_H_
596 struct setreuid_args {
597 uid_t ruid;
598 uid_t euid;
599 };
600 #endif
601 /* ARGSUSED */
602 int
603 setreuid(p, uap, retval)
604 register struct proc *p;
605 struct setreuid_args *uap;
606 int *retval;
607 {
608 register struct pcred *pc = p->p_cred;
609 register uid_t ruid, euid;
610 int error;
611
612 ruid = uap->ruid;
613 euid = uap->euid;
614 if ((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid ||
615 euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
616 euid != pc->p_ruid && euid != pc->p_svuid) &&
617 (error = suser(pc->pc_ucred, &p->p_acflag)))
618 return (error);
619
620 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
621 pc->pc_ucred = crcopy(pc->pc_ucred);
622 pc->pc_ucred->cr_uid = euid;
623 p->p_flag |= P_SUGID;
624 }
625 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
626 (void)chgproccnt(pc->p_ruid, -1);
627 (void)chgproccnt(ruid, 1);
628 pc->p_ruid = ruid;
629 p->p_flag |= P_SUGID;
630 }
631 if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
632 pc->p_svuid != pc->pc_ucred->cr_uid) {
633 pc->p_svuid = pc->pc_ucred->cr_uid;
634 p->p_flag |= P_SUGID;
635 }
636 return (0);
637 }
638
639 #ifndef _SYS_SYSPROTO_H_
640 struct setregid_args {
641 gid_t rgid;
642 gid_t egid;
643 };
644 #endif
645 /* ARGSUSED */
646 int
647 setregid(p, uap, retval)
648 register struct proc *p;
649 struct setregid_args *uap;
650 int *retval;
651 {
652 register struct pcred *pc = p->p_cred;
653 register gid_t rgid, egid;
654 int error;
655
656 rgid = uap->rgid;
657 egid = uap->egid;
658 if ((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid ||
659 egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
660 egid != pc->p_rgid && egid != pc->p_svgid) &&
661 (error = suser(pc->pc_ucred, &p->p_acflag)))
662 return (error);
663
664 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
665 pc->pc_ucred = crcopy(pc->pc_ucred);
666 pc->pc_ucred->cr_groups[0] = egid;
667 p->p_flag |= P_SUGID;
668 }
669 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
670 pc->p_rgid = rgid;
671 p->p_flag |= P_SUGID;
672 }
673 if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
674 pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
675 pc->p_svgid = pc->pc_ucred->cr_groups[0];
676 p->p_flag |= P_SUGID;
677 }
678 return (0);
679 }
680
681 #ifndef _SYS_SYSPROTO_H_
682 struct issetugid_args {
683 int dummy;
684 };
685 #endif
686 /* ARGSUSED */
687 int
688 issetugid(p, uap, retval)
689 register struct proc *p;
690 struct issetugid_args *uap;
691 int *retval;
692 {
693 /*
694 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
695 * we use P_SUGID because we consider changing the owners as
696 * "tainting" as well.
697 * This is significant for procs that start as root and "become"
698 * a user without an exec - programs cannot know *everything*
699 * that libc *might* have put in their data segment.
700 */
701 if (p->p_flag & P_SUGID)
702 return (1);
703 return (0);
704 }
705
706 /*
707 * Check if gid is a member of the group set.
708 */
709 int
710 groupmember(gid, cred)
711 gid_t gid;
712 register struct ucred *cred;
713 {
714 register gid_t *gp;
715 gid_t *egp;
716
717 egp = &(cred->cr_groups[cred->cr_ngroups]);
718 for (gp = cred->cr_groups; gp < egp; gp++)
719 if (*gp == gid)
720 return (1);
721 return (0);
722 }
723
724 /*
725 * Test whether the specified credentials imply "super-user"
726 * privilege; if so, and we have accounting info, set the flag
727 * indicating use of super-powers.
728 * Returns 0 or error.
729 */
730 int
731 suser(cred, acflag)
732 struct ucred *cred;
733 u_short *acflag;
734 {
735 if (cred->cr_uid == 0) {
736 if (acflag)
737 *acflag |= ASU;
738 return (0);
739 }
740 return (EPERM);
741 }
742
743 /*
744 * Allocate a zeroed cred structure.
745 */
746 struct ucred *
747 crget()
748 {
749 register struct ucred *cr;
750
751 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
752 bzero((caddr_t)cr, sizeof(*cr));
753 cr->cr_ref = 1;
754 return (cr);
755 }
756
757 /*
758 * Free a cred structure.
759 * Throws away space when ref count gets to 0.
760 */
761 void
762 crfree(cr)
763 struct ucred *cr;
764 {
765 int s;
766
767 s = splimp(); /* ??? */
768 if (--cr->cr_ref == 0)
769 FREE((caddr_t)cr, M_CRED);
770 (void) splx(s);
771 }
772
773 /*
774 * Copy cred structure to a new one and free the old one.
775 */
776 struct ucred *
777 crcopy(cr)
778 struct ucred *cr;
779 {
780 struct ucred *newcr;
781
782 if (cr->cr_ref == 1)
783 return (cr);
784 newcr = crget();
785 *newcr = *cr;
786 crfree(cr);
787 newcr->cr_ref = 1;
788 return (newcr);
789 }
790
791 /*
792 * Dup cred struct to a new held one.
793 */
794 struct ucred *
795 crdup(cr)
796 struct ucred *cr;
797 {
798 struct ucred *newcr;
799
800 newcr = crget();
801 *newcr = *cr;
802 newcr->cr_ref = 1;
803 return (newcr);
804 }
805
806 /*
807 * Get login name, if available.
808 */
809 #ifndef _SYS_SYSPROTO_H_
810 struct getlogin_args {
811 char *namebuf;
812 u_int namelen;
813 };
814 #endif
815 /* ARGSUSED */
816 int
817 getlogin(p, uap, retval)
818 struct proc *p;
819 struct getlogin_args *uap;
820 int *retval;
821 {
822
823 if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
824 uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
825 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
826 (caddr_t) uap->namebuf, uap->namelen));
827 }
828
829 /*
830 * Set login name.
831 */
832 #ifndef _SYS_SYSPROTO_H_
833 struct setlogin_args {
834 char *namebuf;
835 };
836 #endif
837 /* ARGSUSED */
838 int
839 setlogin(p, uap, retval)
840 struct proc *p;
841 struct setlogin_args *uap;
842 int *retval;
843 {
844 int error;
845
846 if ((error = suser(p->p_ucred, &p->p_acflag)))
847 return (error);
848 error = copyinstr((caddr_t) uap->namebuf,
849 (caddr_t) p->p_pgrp->pg_session->s_login,
850 sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
851 if (error == ENAMETOOLONG)
852 error = EINVAL;
853 return (error);
854 }
Cache object: d3815b613b91f761e2b77babdc878d73
|