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