]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_prot.c
xnu-517.9.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_prot.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
61 */
62
63 /*
64 * System calls related to processes and protection
65 */
66
67 #include <sys/param.h>
68 #include <sys/acct.h>
69 #include <sys/systm.h>
70 #include <sys/ucred.h>
71 #include <sys/proc.h>
72 #include <sys/timeb.h>
73 #include <sys/times.h>
74 #include <sys/malloc.h>
75
76 #include <bsm/audit_kernel.h>
77
78 #include <sys/mount.h>
79 #include <mach/message.h>
80 #include <mach/host_security.h>
81
82 #include <kern/host.h>
83
84 /*
85 * setprivexec: (dis)allow this process to hold
86 * task, thread, or execption ports of processes about to exec.
87 */
88 struct setprivexec_args {
89 int flag;
90 };
91 int
92 setprivexec(p, uap, retval)
93 struct proc *p;
94 register struct setprivexec_args *uap;
95 register_t *retval;
96 {
97 AUDIT_ARG(value, uap->flag);
98 *retval = p->p_debugger;
99 p->p_debugger = (uap->flag != 0);
100 return(0);
101 }
102
103 /* ARGSUSED */
104 getpid(p, uap, retval)
105 struct proc *p;
106 void *uap;
107 register_t *retval;
108 {
109
110 *retval = p->p_pid;
111 #if COMPAT_43
112 retval[1] = p->p_pptr->p_pid;
113 #endif
114 return (0);
115 }
116
117 /* ARGSUSED */
118 getppid(p, uap, retval)
119 struct proc *p;
120 void *uap;
121 register_t *retval;
122 {
123
124 *retval = p->p_pptr->p_pid;
125 return (0);
126 }
127
128 /* Get process group ID; note that POSIX getpgrp takes no parameter */
129 getpgrp(p, uap, retval)
130 struct proc *p;
131 void *uap;
132 register_t *retval;
133 {
134
135 *retval = p->p_pgrp->pg_id;
136 return (0);
137 }
138
139 /* Get an arbitary pid's process group id */
140 struct getpgid_args {
141 pid_t pid;
142 };
143
144 int
145 getpgid(p, uap, retval)
146 struct proc *p;
147 struct getpgid_args *uap;
148 register_t *retval;
149 {
150 struct proc *pt;
151
152 pt = p;
153 if (uap->pid == 0)
154 goto found;
155
156 if ((pt = pfind(uap->pid)) == 0)
157 return (ESRCH);
158 found:
159 *retval = pt->p_pgrp->pg_id;
160 return (0);
161 }
162
163 /*
164 * Get an arbitary pid's session id.
165 */
166 struct getsid_args {
167 pid_t pid;
168 };
169
170 int
171 getsid(p, uap, retval)
172 struct proc *p;
173 struct getsid_args *uap;
174 register_t *retval;
175 {
176 struct proc *pt;
177
178 pt = p;
179 if (uap->pid == 0)
180 goto found;
181
182 if ((pt = pfind(uap->pid)) == 0)
183 return (ESRCH);
184 found:
185 *retval = pt->p_session->s_sid;
186 return (0);
187 }
188
189 /* ARGSUSED */
190 getuid(p, uap, retval)
191 struct proc *p;
192 void *uap;
193 register_t *retval;
194 {
195
196 *retval = p->p_cred->p_ruid;
197 #if COMPAT_43
198 retval[1] = p->p_ucred->cr_uid;
199 #endif
200 return (0);
201 }
202
203 /* ARGSUSED */
204 geteuid(p, uap, retval)
205 struct proc *p;
206 void *uap;
207 register_t *retval;
208 {
209
210 *retval = p->p_ucred->cr_uid;
211 return (0);
212 }
213
214 /* ARGSUSED */
215 getgid(p, uap, retval)
216 struct proc *p;
217 void *uap;
218 register_t *retval;
219 {
220
221 *retval = p->p_cred->p_rgid;
222 #if COMPAT_43
223 retval[1] = p->p_ucred->cr_groups[0];
224 #endif
225 return (0);
226 }
227
228 /*
229 * Get effective group ID. The "egid" is groups[0], and could be obtained
230 * via getgroups. This syscall exists because it is somewhat painful to do
231 * correctly in a library function.
232 */
233 /* ARGSUSED */
234 getegid(p, uap, retval)
235 struct proc *p;
236 void *uap;
237 register_t *retval;
238 {
239
240 *retval = p->p_ucred->cr_groups[0];
241 return (0);
242 }
243
244 struct getgroups_args {
245 u_int gidsetsize;
246 gid_t *gidset;
247 };
248 getgroups(p, uap, retval)
249 struct proc *p;
250 register struct getgroups_args *uap;
251 register_t *retval;
252 {
253 register struct pcred *pc = p->p_cred;
254 register u_int ngrp;
255 int error;
256
257 if ((ngrp = uap->gidsetsize) == 0) {
258 *retval = pc->pc_ucred->cr_ngroups;
259 return (0);
260 }
261 if (ngrp < pc->pc_ucred->cr_ngroups)
262 return (EINVAL);
263 pcred_readlock(p);
264 ngrp = pc->pc_ucred->cr_ngroups;
265 if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
266 (caddr_t)uap->gidset, ngrp * sizeof(gid_t))) {
267 pcred_unlock(p);
268 return (error);
269 }
270 pcred_unlock(p);
271 *retval = ngrp;
272 return (0);
273 }
274
275 /* ARGSUSED */
276 setsid(p, uap, retval)
277 register struct proc *p;
278 void *uap;
279 register_t *retval;
280 {
281
282 if (p->p_pgid == p->p_pid || pgfind(p->p_pid) || p->p_flag & P_INVFORK) {
283 return (EPERM);
284 } else {
285 (void)enterpgrp(p, p->p_pid, 1);
286 *retval = p->p_pid;
287 return (0);
288 }
289 }
290
291 /*
292 * set process group (setpgid/old setpgrp)
293 *
294 * caller does setpgid(targpid, targpgid)
295 *
296 * pid must be caller or child of caller (ESRCH)
297 * if a child
298 * pid must be in same session (EPERM)
299 * pid can't have done an exec (EACCES)
300 * if pgid != pid
301 * there must exist some pid in same session having pgid (EPERM)
302 * pid must not be session leader (EPERM)
303 */
304 struct setpgid_args {
305 int pid;
306 int pgid;
307 };
308 /* ARGSUSED */
309 setpgid(curp, uap, retval)
310 struct proc *curp;
311 register struct setpgid_args *uap;
312 register_t *retval;
313 {
314 register struct proc *targp; /* target process */
315 register struct pgrp *pgrp; /* target pgrp */
316
317 if (uap->pid != 0 && uap->pid != curp->p_pid) {
318 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
319 return (ESRCH);
320 if (targp->p_session != curp->p_session)
321 return (EPERM);
322 if (targp->p_flag & P_EXEC)
323 return (EACCES);
324 } else
325 targp = curp;
326 if (SESS_LEADER(targp))
327 return (EPERM);
328 if (uap->pgid == 0)
329 uap->pgid = targp->p_pid;
330 else if (uap->pgid != targp->p_pid)
331 if ((pgrp = pgfind(uap->pgid)) == 0 ||
332 pgrp->pg_session != curp->p_session)
333 return (EPERM);
334 return (enterpgrp(targp, uap->pgid, 0));
335 }
336
337 struct issetugid_args {
338 int dummy;
339 };
340 issetugid(p, uap, retval)
341 struct proc *p;
342 struct issetugid_args *uap;
343 register_t *retval;
344 {
345 /*
346 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
347 * we use P_SUGID because we consider changing the owners as
348 * "tainting" as well.
349 * This is significant for procs that start as root and "become"
350 * a user without an exec - programs cannot know *everything*
351 * that libc *might* have put in their data segment.
352 */
353
354 *retval = (p->p_flag & P_SUGID) ? 1 : 0;
355 return (0);
356 }
357
358 struct setuid_args {
359 uid_t uid;
360 };
361 /* ARGSUSED */
362 setuid(p, uap, retval)
363 struct proc *p;
364 struct setuid_args *uap;
365 register_t *retval;
366 {
367 register struct pcred *pc = p->p_cred;
368 register uid_t uid;
369 int error;
370
371 uid = uap->uid;
372 AUDIT_ARG(uid, uid, 0, 0, 0);
373 if (uid != pc->p_ruid &&
374 (error = suser(pc->pc_ucred, &p->p_acflag)))
375 return (error);
376 /*
377 * Everything's okay, do it.
378 * Transfer proc count to new user.
379 * Copy credentials so other references do not see our changes.
380 */
381
382 /* prepare app access profile files */
383 prepare_profile_database(uap->uid);
384 pcred_writelock(p);
385 (void)chgproccnt(pc->p_ruid, -1);
386 (void)chgproccnt(uid, 1);
387 pc->pc_ucred = crcopy(pc->pc_ucred);
388 pc->pc_ucred->cr_uid = uid;
389 pc->p_ruid = uid;
390 pc->p_svuid = uid;
391 pcred_unlock(p);
392 set_security_token(p);
393 p->p_flag |= P_SUGID;
394 return (0);
395 }
396
397 struct seteuid_args {
398 uid_t euid;
399 };
400 /* ARGSUSED */
401 seteuid(p, uap, retval)
402 struct proc *p;
403 struct seteuid_args *uap;
404 register_t *retval;
405 {
406 register struct pcred *pc = p->p_cred;
407 register uid_t euid;
408 int error;
409
410 euid = uap->euid;
411 AUDIT_ARG(uid, 0, euid, 0, 0);
412 if (euid != pc->p_ruid && euid != pc->p_svuid &&
413 (error = suser(pc->pc_ucred, &p->p_acflag)))
414 return (error);
415 /*
416 * Everything's okay, do it. Copy credentials so other references do
417 * not see our changes.
418 */
419 pcred_writelock(p);
420 pc->pc_ucred = crcopy(pc->pc_ucred);
421 pc->pc_ucred->cr_uid = euid;
422 pcred_unlock(p);
423 set_security_token(p);
424 p->p_flag |= P_SUGID;
425 return (0);
426 }
427
428 struct setgid_args {
429 gid_t gid;
430 };
431 /* ARGSUSED */
432 setgid(p, uap, retval)
433 struct proc *p;
434 struct setgid_args *uap;
435 register_t *retval;
436 {
437 register struct pcred *pc = p->p_cred;
438 register gid_t gid;
439 int error;
440
441 gid = uap->gid;
442 AUDIT_ARG(gid, gid, 0, 0, 0);
443 if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
444 return (error);
445 pcred_writelock(p);
446 pc->pc_ucred = crcopy(pc->pc_ucred);
447 pc->pc_ucred->cr_groups[0] = gid;
448 pc->p_rgid = gid;
449 pc->p_svgid = gid; /* ??? */
450 pcred_unlock(p);
451 set_security_token(p);
452 p->p_flag |= P_SUGID;
453 return (0);
454 }
455
456 struct setegid_args {
457 gid_t egid;
458 };
459 /* ARGSUSED */
460 setegid(p, uap, retval)
461 struct proc *p;
462 struct setegid_args *uap;
463 register_t *retval;
464 {
465 register struct pcred *pc = p->p_cred;
466 register gid_t egid;
467 int error;
468
469 egid = uap->egid;
470 AUDIT_ARG(gid, 0, egid, 0, 0);
471 if (egid != pc->p_rgid && egid != pc->p_svgid &&
472 (error = suser(pc->pc_ucred, &p->p_acflag)))
473 return (error);
474 pcred_writelock(p);
475 pc->pc_ucred = crcopy(pc->pc_ucred);
476 pc->pc_ucred->cr_groups[0] = egid;
477 pcred_unlock(p);
478 set_security_token(p);
479 p->p_flag |= P_SUGID;
480 return (0);
481 }
482
483 struct setgroups_args{
484 u_int gidsetsize;
485 gid_t *gidset;
486 };
487
488 /* ARGSUSED */
489 setgroups(p, uap, retval)
490 struct proc *p;
491 struct setgroups_args *uap;
492 register_t *retval;
493 {
494 register struct pcred *pc = p->p_cred;
495 struct ucred *new, *old;
496 register u_int ngrp;
497 int error;
498
499 if (error = suser(pc->pc_ucred, &p->p_acflag))
500 return (error);
501 ngrp = uap->gidsetsize;
502 if (ngrp > NGROUPS)
503 return (EINVAL);
504 new = crget();
505
506 if ( ngrp < 1 ) {
507 ngrp = 1;
508 }
509 else {
510 error = copyin((caddr_t)uap->gidset,
511 (caddr_t)new->cr_groups, ngrp * sizeof(gid_t));
512 if (error) {
513 crfree(new);
514 return (error);
515 }
516 }
517 new->cr_ngroups = ngrp;
518 AUDIT_ARG(groupset, new->cr_groups, ngrp);
519 pcred_writelock(p);
520 old = pc->pc_ucred;
521 new->cr_uid = old->cr_uid;
522 pc->pc_ucred = new;
523 pcred_unlock(p);
524 set_security_token(p);
525 p->p_flag |= P_SUGID;
526 if (old != NOCRED)
527 crfree(old);
528 return (0);
529 }
530
531 #if COMPAT_43
532 struct osetreuid_args{
533 int ruid;
534 int euid;
535 };
536 /* ARGSUSED */
537 osetreuid(p, uap, retval)
538 register struct proc *p;
539 struct osetreuid_args *uap;
540 register_t *retval;
541 {
542 struct seteuid_args seuidargs;
543 struct setuid_args suidargs;
544
545 /*
546 * There are five cases, and we attempt to emulate them in
547 * the following fashion:
548 * -1, -1: return 0. This is correct emulation.
549 * -1, N: call seteuid(N). This is correct emulation.
550 * N, -1: if we called setuid(N), our euid would be changed
551 * to N as well. the theory is that we don't want to
552 * revoke root access yet, so we call seteuid(N)
553 * instead. This is incorrect emulation, but often
554 * suffices enough for binary compatibility.
555 * N, N: call setuid(N). This is correct emulation.
556 * N, M: call setuid(N). This is close to correct emulation.
557 */
558 if (uap->ruid == (uid_t)-1) {
559 if (uap->euid == (uid_t)-1)
560 return (0); /* -1, -1 */
561 seuidargs.euid = uap->euid; /* -1, N */
562 return (seteuid(p, &seuidargs, retval));
563 }
564 if (uap->euid == (uid_t)-1) {
565 seuidargs.euid = uap->ruid; /* N, -1 */
566 return (seteuid(p, &seuidargs, retval));
567 }
568 suidargs.uid = uap->ruid; /* N, N and N, M */
569 return (setuid(p, &suidargs, retval));
570 }
571
572 struct osetregid_args {
573 int rgid;
574 int egid;
575 };
576 /* ARGSUSED */
577 osetregid(p, uap, retval)
578 register struct proc *p;
579 struct osetregid_args *uap;
580 register_t *retval;
581 {
582 struct setegid_args segidargs;
583 struct setgid_args sgidargs;
584
585 /*
586 * There are five cases, described above in osetreuid()
587 */
588 if (uap->rgid == (gid_t)-1) {
589 if (uap->egid == (gid_t)-1)
590 return (0); /* -1, -1 */
591 segidargs.egid = uap->egid; /* -1, N */
592 return (setegid(p, &segidargs, retval));
593 }
594 if (uap->egid == (gid_t)-1) {
595 segidargs.egid = uap->rgid; /* N, -1 */
596 return (setegid(p, &segidargs, retval));
597 }
598 sgidargs.gid = uap->rgid; /* N, N and N, M */
599 return (setgid(p, &sgidargs, retval));
600 }
601 #endif /* COMPAT_43 */
602
603 /*
604 * Check if gid is a member of the group set.
605 */
606 groupmember(gid, cred)
607 gid_t gid;
608 register struct ucred *cred;
609 {
610 register gid_t *gp;
611 gid_t *egp;
612
613 egp = &(cred->cr_groups[cred->cr_ngroups]);
614 for (gp = cred->cr_groups; gp < egp; gp++)
615 if (*gp == gid)
616 return (1);
617 return (0);
618 }
619
620 /*
621 * Test whether the specified credentials imply "super-user"
622 * privilege; if so, and we have accounting info, set the flag
623 * indicating use of super-powers.
624 * Returns 0 or error.
625 */
626 suser(cred, acflag)
627 struct ucred *cred;
628 u_short *acflag;
629 {
630 #if DIAGNOSTIC
631 if (cred == NOCRED || cred == FSCRED)
632 panic("suser");
633 #endif
634 if (cred->cr_uid == 0) {
635 if (acflag)
636 *acflag |= ASU;
637 return (0);
638 }
639 return (EPERM);
640 }
641
642 int
643 is_suser(void)
644 {
645 struct proc *p = current_proc();
646
647 if (!p)
648 return (0);
649
650 return (suser(p->p_ucred, &p->p_acflag) == 0);
651 }
652
653 int
654 is_suser1(void)
655 {
656 struct proc *p = current_proc();
657
658 if (!p)
659 return (0);
660
661 return (suser(p->p_ucred, &p->p_acflag) == 0 ||
662 p->p_cred->p_ruid == 0 || p->p_cred->p_svuid == 0);
663 }
664
665 /*
666 * Allocate a zeroed cred structure.
667 */
668 struct ucred *
669 crget()
670 {
671 register struct ucred *cr;
672
673 MALLOC_ZONE(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
674 bzero((caddr_t)cr, sizeof(*cr));
675 cr->cr_ref = 1;
676 return (cr);
677 }
678
679 /*
680 * Free a cred structure.
681 * Throws away space when ref count gets to 0.
682 */
683 void
684 crfree(cr)
685 struct ucred *cr;
686 {
687 #if DIAGNOSTIC
688 if (cr == NOCRED || cr == FSCRED)
689 panic("crfree");
690 #endif
691 if (--cr->cr_ref == 0)
692 FREE_ZONE((caddr_t)cr, sizeof *cr, M_CRED);
693 }
694
695 /*
696 * Copy cred structure to a new one and free the old one.
697 */
698 struct ucred *
699 crcopy(cr)
700 struct ucred *cr;
701 {
702 struct ucred *newcr;
703
704 #if DIAGNOSTIC
705 if (cr == NOCRED || cr == FSCRED)
706 panic("crcopy");
707 #endif
708 if (cr->cr_ref == 1)
709 return (cr);
710 newcr = crget();
711 *newcr = *cr;
712 crfree(cr);
713 newcr->cr_ref = 1;
714 return (newcr);
715 }
716
717 /*
718 * Dup cred struct to a new held one.
719 */
720 struct ucred *
721 crdup(cr)
722 struct ucred *cr;
723 {
724 struct ucred *newcr;
725
726 #if DIAGNOSTIC
727 if (cr == NOCRED || cr == FSCRED)
728 panic("crdup");
729 #endif
730 newcr = crget();
731 *newcr = *cr;
732 newcr->cr_ref = 1;
733 return (newcr);
734 }
735
736 /*
737 * compare two cred structs
738 */
739 int
740 crcmp(cr1, cr2)
741 struct ucred *cr1;
742 struct ucred *cr2;
743 {
744 int i;
745
746 if (cr1 == cr2)
747 return 0;
748 if (cr1 == NOCRED || cr1 == FSCRED ||
749 cr2 == NOCRED || cr2 == FSCRED)
750 return 1;
751 if (cr1->cr_uid != cr2->cr_uid)
752 return 1;
753 if (cr1->cr_ngroups != cr2->cr_ngroups)
754 return 1;
755 // XXX assumes groups will always be listed in some order
756 for (i=0; i < cr1->cr_ngroups; i++)
757 if (cr1->cr_groups[i] != cr2->cr_groups[i])
758 return 1;
759 return (0);
760 }
761
762 /*
763 * Get login name, if available.
764 */
765 struct getlogin_args {
766 char *namebuf;
767 u_int namelen;
768 };
769 /* ARGSUSED */
770 getlogin(p, uap, retval)
771 struct proc *p;
772 struct getlogin_args *uap;
773 register_t *retval;
774 {
775
776 if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
777 uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
778 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
779 (caddr_t)uap->namebuf, uap->namelen));
780 }
781
782 /*
783 * Set login name.
784 */
785 struct setlogin_args {
786 char *namebuf;
787 };
788 /* ARGSUSED */
789 setlogin(p, uap, retval)
790 struct proc *p;
791 struct setlogin_args *uap;
792 register_t *retval;
793 {
794 int error;
795 int dummy=0;
796
797 if (error = suser(p->p_ucred, &p->p_acflag))
798 return (error);
799
800 error = copyinstr((caddr_t) uap->namebuf,
801 (caddr_t) p->p_pgrp->pg_session->s_login,
802 sizeof (p->p_pgrp->pg_session->s_login) - 1, (size_t *)&dummy);
803 if(!error)
804 AUDIT_ARG(text, p->p_pgrp->pg_session->s_login);
805 else if (error == ENAMETOOLONG)
806 error = EINVAL;
807 return (error);
808 }
809
810
811 /* Set the secrity token of the task with current euid and eguid */
812 kern_return_t
813 set_security_token(struct proc * p)
814 {
815 security_token_t sec_token;
816 audit_token_t audit_token;
817
818 sec_token.val[0] = p->p_ucred->cr_uid;
819 sec_token.val[1] = p->p_ucred->cr_gid;
820
821 /*
822 * The current layout of the Mach audit token explicitly
823 * adds these fields. But nobody should rely on such
824 * a literal representation. Instead, the BSM library
825 * provides a function to convert an audit token into
826 * a BSM subject. Use of that mechanism will isolate
827 * the user of the trailer from future representation
828 * changes.
829 */
830 audit_token.val[0] = p->p_au->ai_auid;
831 audit_token.val[1] = p->p_ucred->cr_uid;
832 audit_token.val[2] = p->p_ucred->cr_gid;
833 audit_token.val[3] = p->p_cred->p_ruid;
834 audit_token.val[4] = p->p_cred->p_rgid;
835 audit_token.val[5] = p->p_pid;
836 audit_token.val[6] = p->p_au->ai_asid;
837 audit_token.val[7] = p->p_au->ai_termid.port;
838
839 return host_security_set_task_token(host_security_self(),
840 p->task,
841 sec_token,
842 audit_token,
843 (sec_token.val[0]) ?
844 HOST_PRIV_NULL :
845 host_priv_self());
846 }
847
848
849 /*
850 * Fill in a struct xucred based on a struct ucred.
851 */
852 __private_extern__
853 void
854 cru2x(struct ucred *cr, struct xucred *xcr)
855 {
856
857 bzero(xcr, sizeof(*xcr));
858 xcr->cr_version = XUCRED_VERSION;
859 xcr->cr_uid = cr->cr_uid;
860 xcr->cr_ngroups = cr->cr_ngroups;
861 bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups));
862 }