4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015, Joyent, Inc.
27 #include <sys/atomic.h>
30 #include <sys/cred_impl.h>
31 #include <sys/policy.h>
34 #include <sys/errno.h>
36 #include <sys/project.h>
37 #include <sys/systm.h>
38 #include <sys/sysmacros.h>
39 #include <sys/pathname.h>
40 #include <sys/varargs.h>
42 #include <netinet/in.h>
44 #define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1))
46 static kmutex_t klpd_mutex
;
48 typedef struct klpd_reg
{
49 struct klpd_reg
*klpd_next
;
50 struct klpd_reg
**klpd_refp
;
51 door_handle_t klpd_door
;
55 int klpd_indel
; /* Disabled */
61 * This data structure hangs off the credential of a process; the
62 * credential is finalized and cannot be changed; but this structure
63 * can be changed when a new door server for the particular group
64 * needs to be registered. It is refcounted and shared between
65 * processes with common ancestry.
67 * The reference count is atomically updated.
69 * But the registration probably needs to be updated under a lock.
71 typedef struct credklpd
{
77 klpd_reg_t
*klpd_list
;
79 static void klpd_unlink(klpd_reg_t
*);
80 static int klpd_unreg_dh(door_handle_t
);
82 static credklpd_t
*crklpd_alloc(void);
84 void crklpd_setreg(credklpd_t
*, klpd_reg_t
*);
86 extern size_t max_vnode_path
;
89 klpd_rele(klpd_reg_t
*p
)
91 if (atomic_dec_32_nv(&p
->klpd_ref
) == 0) {
92 if (p
->klpd_refp
!= NULL
)
94 if (p
->klpd_cred
!= NULL
)
96 door_ki_rele(p
->klpd_door
);
97 kmem_free(p
, sizeof (*p
));
102 * In order to be able to walk the lists, we can't unlink the entry
103 * until the reference count drops to 0. If we remove it too soon,
104 * list walkers will terminate when they happen to call a now orphaned
108 klpd_rele_next(klpd_reg_t
*p
)
110 klpd_reg_t
*r
= p
->klpd_next
;
118 klpd_hold(klpd_reg_t
*p
)
120 atomic_inc_32(&p
->klpd_ref
);
124 * Remove registration from where it is registered. Returns next in list.
127 klpd_unlink(klpd_reg_t
*p
)
129 ASSERT(p
->klpd_refp
== NULL
|| *p
->klpd_refp
== p
);
131 if (p
->klpd_refp
!= NULL
)
132 *p
->klpd_refp
= p
->klpd_next
;
134 if (p
->klpd_next
!= NULL
)
135 p
->klpd_next
->klpd_refp
= p
->klpd_refp
;
140 * Remove all elements of the klpd list and decrement their refcnts.
141 * The lock guarding the list should be held; this function is
142 * called when we are sure we want to destroy the list completely
143 * list but not so sure that the reference counts of all elements have
147 klpd_freelist(klpd_reg_t
**pp
)
151 while ((p
= *pp
) != NULL
) {
158 * Link new entry in list. The Boolean argument specifies whether this
159 * list can contain only a single item or multiple items.
160 * Returns the entry which needs to be released if single is B_TRUE.
163 klpd_link(klpd_reg_t
*p
, klpd_reg_t
**listp
, boolean_t single
)
165 klpd_reg_t
*old
= *listp
;
167 ASSERT(p
->klpd_ref
== 1);
169 ASSERT(old
== NULL
|| *old
->klpd_refp
== old
);
170 p
->klpd_refp
= listp
;
171 p
->klpd_next
= single
? NULL
: old
;
175 ASSERT(old
->klpd_next
== NULL
);
176 old
->klpd_refp
= NULL
;
179 old
->klpd_refp
= &p
->klpd_next
;
185 * The typical call consists of:
187 * - some integer data (type, value)
188 * for now, it's just one bit.
191 klpd_marshall(klpd_reg_t
*p
, const priv_set_t
*rq
, va_list ap
)
196 size_t len
= sizeof (priv_set_t
) + sizeof (klpd_head_t
);
200 klpd_arg_t
*kap
= NULL
;
203 type
= va_arg(ap
, uint_t
);
206 khp
= kmem_zalloc(len
, KM_SLEEP
);
210 len
+= offsetof(klpd_arg_t
, kla_str
);
211 vp
= va_arg(ap
, vnode_t
*);
215 tmp
= va_arg(ap
, char *);
217 if (tmp
!= NULL
&& *tmp
!= '\0')
218 clen
= strlen(tmp
) + 1;
222 len
+= ROUNDUP(MAXPATHLEN
, sizeof (uint_t
));
223 khp
= kmem_zalloc(len
, KM_SLEEP
);
225 khp
->klh_argoff
= sizeof (klpd_head_t
) + sizeof (priv_set_t
);
228 if (vnodetopath(crgetzone(p
->klpd_cred
)->zone_rootvp
,
229 vp
, kap
->kla_str
, MAXPATHLEN
, p
->klpd_cred
) != 0) {
234 plen
= strlen(kap
->kla_str
);
235 if (plen
+ clen
+ 1 >= MAXPATHLEN
) {
239 /* Don't make root into a double "/" */
242 kap
->kla_str
[plen
] = '/';
243 bcopy(tmp
, &kap
->kla_str
[plen
+ 1], clen
);
247 proto
= va_arg(ap
, int);
249 case IPPROTO_TCP
: type
= KLPDARG_TCPPORT
;
251 case IPPROTO_UDP
: type
= KLPDARG_UDPPORT
;
253 case IPPROTO_SCTP
: type
= KLPDARG_SCTPPORT
;
255 case PROTO_SDP
: type
= KLPDARG_SDPPORT
;
260 case KLPDARG_TCPPORT
:
261 case KLPDARG_UDPPORT
:
262 case KLPDARG_SCTPPORT
:
263 case KLPDARG_SDPPORT
:
264 len
+= sizeof (*kap
);
265 khp
= kmem_zalloc(len
, KM_SLEEP
);
266 khp
->klh_argoff
= sizeof (klpd_head_t
) + sizeof (priv_set_t
);
268 kap
->kla_int
= va_arg(ap
, int);
273 khp
->klh_vers
= KLPDCALL_VERS
;
275 khp
->klh_privoff
= sizeof (*khp
);
276 *KLH_PRIVSET(khp
) = *rq
;
278 kap
->kla_type
= type
;
279 kap
->kla_dlen
= len
- khp
->klh_argoff
;
285 klpd_do_call(klpd_reg_t
*p
, const priv_set_t
*req
, va_list ap
)
292 if (p
->klpd_door_pid
== curproc
->p_pid
)
295 klh
= klpd_marshall(p
, req
, ap
);
300 da
.data_ptr
= (char *)klh
;
301 da
.data_size
= klh
->klh_len
;
304 da
.rbuf
= (char *)&res
;
305 da
.rsize
= sizeof (res
);
307 while ((dres
= door_ki_upcall_limited(p
->klpd_door
, &da
, NULL
,
308 SIZE_MAX
, 0)) != 0) {
315 /* Bad door, don't call it again. */
316 (void) klpd_unreg_dh(p
->klpd_door
);
319 /* Pending signal, nothing we can do. */
322 kmem_free(klh
, klh
->klh_len
);
326 kmem_free(klh
, klh
->klh_len
);
327 /* Bogus return value, must be a failure */
328 if (da
.rbuf
!= (char *)&res
) {
329 kmem_free(da
.rbuf
, da
.rsize
);
335 uint32_t klpd_bad_locks
;
338 klpd_call(const cred_t
*cr
, const priv_set_t
*req
, va_list ap
)
346 * These locks must not be held when this code is called;
347 * callbacks to userland with these locks held will result
348 * in issues. That said, the code at the call sides was
349 * restructured not to call with any of the locks held and
350 * no policies operate by default on most processes.
352 if (mutex_owned(&pidlock
) || mutex_owned(&curproc
->p_lock
) ||
353 mutex_owned(&curproc
->p_crlock
)) {
354 atomic_inc_32(&klpd_bad_locks
);
359 * Enforce the limit set for the call process (still).
361 if (!priv_issubset(req
, &CR_LPRIV(cr
)))
364 /* Try 1: get the credential specific klpd */
365 if ((ckp
= crgetcrklpd(cr
)) != NULL
) {
366 mutex_enter(&ckp
->crkl_lock
);
367 if ((p
= ckp
->crkl_reg
) != NULL
&&
368 p
->klpd_indel
== 0 &&
369 priv_issubset(req
, &p
->klpd_pset
)) {
371 mutex_exit(&ckp
->crkl_lock
);
372 rv
= klpd_do_call(p
, req
, ap
);
373 mutex_enter(&ckp
->crkl_lock
);
375 mutex_exit(&ckp
->crkl_lock
);
377 return (rv
== 0 ? 0 : -1);
379 mutex_exit(&ckp
->crkl_lock
);
383 /* Try 2: get the project specific klpd */
384 mutex_enter(&klpd_mutex
);
386 if ((p
= curproj
->kpj_klpd
) != NULL
) {
388 mutex_exit(&klpd_mutex
);
389 if (p
->klpd_indel
== 0 &&
390 priv_issubset(req
, &p
->klpd_pset
)) {
391 rv
= klpd_do_call(p
, req
, ap
);
393 mutex_enter(&klpd_mutex
);
395 mutex_exit(&klpd_mutex
);
398 return (rv
== 0 ? 0 : -1);
400 mutex_exit(&klpd_mutex
);
403 /* Try 3: get the global klpd list */
404 ckzone
= crgetzone(cr
);
405 mutex_enter(&klpd_mutex
);
407 for (p
= klpd_list
; p
!= NULL
; ) {
408 zone_t
*kkzone
= crgetzone(p
->klpd_cred
);
409 if ((kkzone
== &zone0
|| kkzone
== ckzone
) &&
410 p
->klpd_indel
== 0 &&
411 priv_issubset(req
, &p
->klpd_pset
)) {
413 mutex_exit(&klpd_mutex
);
414 rv
= klpd_do_call(p
, req
, ap
);
415 mutex_enter(&klpd_mutex
);
417 p
= klpd_rele_next(p
);
425 mutex_exit(&klpd_mutex
);
426 return (rv
== 0 ? 0 : -1);
431 * If the pid_t passed in is positive, update the registration for
432 * the specific process; that is only possible if the process already
433 * has a registration on it. This change of registration will affect
434 * all processes which share common ancestry.
436 * MY_PID (pid 0) can be used to create or change the context for
437 * the current process, typically done after fork().
439 * A negative value can be used to register a klpd globally.
441 * The per-credential klpd needs to be cleaned up when entering
442 * a zone or unsetting the flag.
445 klpd_reg(int did
, idtype_t type
, id_t id
, priv_set_t
*psetbuf
)
452 credklpd_t
*ckp
= NULL
;
455 kproject_t
*kpp
= NULL
;
457 if (CR_FLAGS(cr
) & PRIV_XPOLICY
)
458 return (set_errno(EINVAL
));
460 if (copyin(psetbuf
, &pset
, sizeof (priv_set_t
)))
461 return (set_errno(EFAULT
));
463 if (!priv_issubset(&pset
, &CR_OEPRIV(cr
)))
464 return (set_errno(EPERM
));
470 pid
= curproc
->p_pid
;
471 if (pid
== curproc
->p_pid
)
472 ckp
= crklpd_alloc();
476 kpp
= project_hold_by_id(proj
, crgetzone(cr
),
479 return (set_errno(ESRCH
));
482 return (set_errno(ENOTSUP
));
487 * Verify the door passed in; it must be a door and we won't
488 * allow processes to be called on their own behalf.
490 dh
= door_ki_lookup(did
);
491 if (dh
== NULL
|| door_ki_info(dh
, &di
) != 0) {
496 return (set_errno(EBADF
));
498 if (type
== P_PID
&& pid
== di
.di_target
) {
502 return (set_errno(EINVAL
));
505 kpd
= kmem_zalloc(sizeof (*kpd
), KM_SLEEP
);
506 crhold(kpd
->klpd_cred
= cr
);
508 kpd
->klpd_door_pid
= di
.di_target
;
510 kpd
->klpd_pset
= pset
;
513 mutex_enter(&klpd_mutex
);
514 kpd
= klpd_link(kpd
, &kpp
->kpj_klpd
, B_TRUE
);
515 mutex_exit(&klpd_mutex
);
519 } else if ((int)pid
< 0) {
521 mutex_enter(&klpd_mutex
);
522 (void) klpd_link(kpd
, &klpd_list
, B_FALSE
);
523 mutex_exit(&klpd_mutex
);
524 } else if (pid
== curproc
->p_pid
) {
526 cred_t
*newcr
= cralloc();
528 /* No need to lock, sole reference to ckp */
529 kpd
= klpd_link(kpd
, &ckp
->crkl_reg
, B_TRUE
);
534 mutex_enter(&p
->p_crlock
);
537 crsetcrklpd(newcr
, ckp
);
538 p
->p_cred
= newcr
; /* Already held for p_cred */
540 crhold(newcr
); /* Hold once for the current thread */
541 mutex_exit(&p
->p_crlock
);
542 crfree(cr
); /* One for the p_cred */
547 mutex_enter(&pidlock
);
549 if (p
== NULL
|| !prochasprocperm(p
, curproc
, CRED())) {
550 mutex_exit(&pidlock
);
552 return (set_errno(p
== NULL
? ESRCH
: EPERM
));
554 mutex_enter(&p
->p_crlock
);
555 crhold(pcr
= p
->p_cred
);
556 mutex_exit(&pidlock
);
557 mutex_exit(&p
->p_crlock
);
559 * We're going to update the credential's ckp in place;
560 * this requires that it exists.
562 ckp
= crgetcrklpd(pcr
);
566 return (set_errno(EINVAL
));
568 crklpd_setreg(ckp
, kpd
);
576 klpd_unreg_dh(door_handle_t dh
)
580 mutex_enter(&klpd_mutex
);
581 for (p
= klpd_list
; p
!= NULL
; p
= p
->klpd_next
) {
582 if (p
->klpd_door
== dh
)
586 mutex_exit(&klpd_mutex
);
589 if (p
->klpd_indel
!= 0) {
590 mutex_exit(&klpd_mutex
);
595 mutex_exit(&klpd_mutex
);
600 klpd_unreg(int did
, idtype_t type
, id_t id
)
607 kproject_t
*kpp
= NULL
;
616 kpp
= project_hold_by_id(proj
, crgetzone(CRED()),
619 return (set_errno(ESRCH
));
622 return (set_errno(ENOTSUP
));
625 dh
= door_ki_lookup(did
);
629 return (set_errno(EINVAL
));
633 mutex_enter(&klpd_mutex
);
634 if (kpp
->kpj_klpd
== NULL
)
637 klpd_freelist(&kpp
->kpj_klpd
);
638 mutex_exit(&klpd_mutex
);
641 } else if ((int)pid
> 0) {
642 mutex_enter(&pidlock
);
645 mutex_exit(&pidlock
);
647 return (set_errno(ESRCH
));
649 mutex_enter(&p
->p_crlock
);
650 mutex_exit(&pidlock
);
651 } else if (pid
== 0) {
653 mutex_enter(&p
->p_crlock
);
655 res
= klpd_unreg_dh(dh
);
659 ckp
= crgetcrklpd(p
->p_cred
);
661 crklpd_setreg(ckp
, NULL
);
665 mutex_exit(&p
->p_crlock
);
671 return (set_errno(res
));
676 crklpd_hold(credklpd_t
*crkpd
)
678 atomic_inc_32(&crkpd
->crkl_ref
);
682 crklpd_rele(credklpd_t
*crkpd
)
684 if (atomic_dec_32_nv(&crkpd
->crkl_ref
) == 0) {
685 if (crkpd
->crkl_reg
!= NULL
)
686 klpd_rele(crkpd
->crkl_reg
);
687 mutex_destroy(&crkpd
->crkl_lock
);
688 kmem_free(crkpd
, sizeof (*crkpd
));
695 credklpd_t
*res
= kmem_alloc(sizeof (*res
), KM_SLEEP
);
697 mutex_init(&res
->crkl_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
699 res
->crkl_reg
= NULL
;
705 crklpd_setreg(credklpd_t
*crk
, klpd_reg_t
*new)
709 mutex_enter(&crk
->crkl_lock
);
715 old
= klpd_link(new, &crk
->crkl_reg
, B_TRUE
);
717 mutex_exit(&crk
->crkl_lock
);
723 /* Allocate and register the pfexec specific callback */
728 int err
= secpolicy_pfexec_register(CRED());
731 zone_t
*myzone
= crgetzone(CRED());
734 return (set_errno(err
));
736 dh
= door_ki_lookup(did
);
737 if (dh
== NULL
|| door_ki_info(dh
, &di
) != 0)
738 return (set_errno(EBADF
));
740 pfx
= kmem_zalloc(sizeof (*pfx
), KM_SLEEP
);
743 pfx
->klpd_door_pid
= di
.di_target
;
745 pfx
->klpd_cred
= NULL
;
746 mutex_enter(&myzone
->zone_lock
);
747 pfx
= klpd_link(pfx
, &myzone
->zone_pfexecd
, B_TRUE
);
748 mutex_exit(&myzone
->zone_lock
);
756 pfexec_unreg(int did
)
760 zone_t
*myzone
= crgetzone(CRED());
763 dh
= door_ki_lookup(did
);
765 return (set_errno(EBADF
));
767 mutex_enter(&myzone
->zone_lock
);
768 pfd
= myzone
->zone_pfexecd
;
769 if (pfd
!= NULL
&& pfd
->klpd_door
== dh
) {
775 mutex_exit(&myzone
->zone_lock
);
778 * crfree() cannot be called with zone_lock held; it is called
779 * indirectly through closing the door handle
784 return (set_errno(err
));
789 get_path(char *buf
, const char *path
, int len
)
797 if (*path
== '/' && len
< MAXPATHLEN
) {
798 (void) strcpy(buf
, path
);
802 * Build the pathname using the current directory + resolve pathname.
803 * The resolve pathname either starts with a normal component and
804 * we can just concatenate them or it starts with one
805 * or more ".." component and we can remove those; the
806 * last one cannot be a ".." and the current directory has
807 * more components than the number of ".." in the resolved pathname.
809 if (dogetcwd(buf
, MAXPATHLEN
) != 0)
814 while (len
> 3 && strncmp("../", path
, 3) == 0) {
818 s
= strrchr(buf
, '/');
819 if (s
== NULL
|| s
== buf
)
825 /* Add a "/" and a NUL */
826 if (lc
< 2 || lc
+ len
+ 2 >= MAXPATHLEN
)
830 (void) strcpy(buf
+ lc
+ 1, path
);
836 * Perform the pfexec upcall.
838 * The pfexec upcall is different from the klpd_upcall in that a failure
839 * will lead to a denial of execution.
842 pfexec_call(const cred_t
*cr
, struct pathname
*rpnp
, cred_t
**pfcr
,
847 pfexec_reply_t pr
, *prp
;
854 zone_t
*myzone
= crgetzone(CRED());
855 size_t pasize
= PFEXEC_ARG_SIZE(MAXPATHLEN
);
857 /* Find registration */
858 mutex_enter(&myzone
->zone_lock
);
859 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
861 mutex_exit(&myzone
->zone_lock
);
866 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
871 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
873 if (get_path(pap
->pfa_path
, rpnp
->pn_path
, rpnp
->pn_pathlen
) == -1)
876 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
877 pap
->pfa_call
= PFEXEC_EXEC_ATTRS
;
878 pap
->pfa_len
= pasize
;
879 pap
->pfa_uid
= crgetruid(cr
);
881 da
.data_ptr
= (char *)pap
;
882 da
.data_size
= pap
->pfa_len
;
885 da
.rbuf
= (char *)&pr
;
886 da
.rsize
= sizeof (pr
);
888 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
903 prp
= (pfexec_reply_t
*)da
.rbuf
;
905 * Check the size of the result and the alignment of the
908 if (da
.rsize
< sizeof (pr
) ||
909 prp
->pfr_ioff
> da
.rsize
- sizeof (priv_set_t
) ||
910 prp
->pfr_loff
> da
.rsize
- sizeof (priv_set_t
) ||
911 (prp
->pfr_loff
& (sizeof (priv_chunk_t
) - 1)) != 0 ||
912 (prp
->pfr_ioff
& (sizeof (priv_chunk_t
) - 1)) != 0)
917 * allow/allow with additional credentials/disallow[*]
919 * euid, uid, egid, gid, privs, and limitprivs
920 * We now have somewhat more flexibility we could even set E and P
921 * judiciously but that would break some currently valid assumptions
922 * [*] Disallow is not readily supported by always including
923 * the Basic Solaris User profile in all user's profiles.
926 if (!prp
->pfr_allowed
) {
930 if (!prp
->pfr_setcred
) {
934 ncr
= crdup((cred_t
*)cr
);
937 * Generate the new credential set scrubenv if ruid != euid (or set)
938 * the "I'm set-uid flag" but that is not inherited so scrubbing
939 * the environment is a requirement.
941 /* Set uids or gids, note that -1 will do the right thing */
942 if (crsetresuid(ncr
, prp
->pfr_ruid
, prp
->pfr_euid
, prp
->pfr_euid
) != 0)
944 if (crsetresgid(ncr
, prp
->pfr_rgid
, prp
->pfr_egid
, prp
->pfr_egid
) != 0)
947 *scrub
= prp
->pfr_scrubenv
;
949 if (prp
->pfr_clearflag
)
950 CR_FLAGS(ncr
) &= ~PRIV_PFEXEC
;
952 /* We cannot exceed our Limit set, no matter what */
953 iset
= PFEXEC_REPLY_IPRIV(prp
);
956 if (!priv_issubset(iset
, &CR_LPRIV(ncr
)))
958 priv_union(iset
, &CR_IPRIV(ncr
));
961 /* Nor can we increate our Limit set itself */
962 lset
= PFEXEC_REPLY_LPRIV(prp
);
965 if (!priv_issubset(lset
, &CR_LPRIV(ncr
)))
967 CR_LPRIV(ncr
) = *lset
;
970 /* Exec will do the standard set operations */
974 if (da
.rbuf
!= (char *)&pr
)
975 kmem_free(da
.rbuf
, da
.rsize
);
977 kmem_free(pap
, pasize
);
989 get_forced_privs(const cred_t
*cr
, const char *respn
, priv_set_t
*set
)
996 priv_set_t
*fset
, pmem
;
998 zone_t
*myzone
= crgetzone(cr
);
999 size_t pasize
= PFEXEC_ARG_SIZE(MAXPATHLEN
);
1001 mutex_enter(&myzone
->zone_lock
);
1002 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
1004 mutex_exit(&myzone
->zone_lock
);
1009 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
1014 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
1016 if (get_path(pap
->pfa_path
, respn
, -1) == -1)
1019 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
1020 pap
->pfa_call
= PFEXEC_FORCED_PRIVS
;
1021 pap
->pfa_len
= pasize
;
1022 pap
->pfa_uid
= (uid_t
)-1; /* Not relevant */
1024 da
.data_ptr
= (char *)pap
;
1025 da
.data_size
= pap
->pfa_len
;
1028 da
.rbuf
= (char *)&pmem
;
1029 da
.rsize
= sizeof (pmem
);
1031 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
1045 * Check the size of the result, it's a privilege set.
1047 if (da
.rsize
!= sizeof (priv_set_t
))
1050 fset
= (priv_set_t
*)da
.rbuf
;
1053 * We restrict the forced privileges with whatever is available in
1056 zkcr
= zone_kcred();
1057 priv_intersect(&CR_LPRIV(zkcr
), fset
);
1060 * But we fail if the forced privileges are not found in the current
1063 if (!priv_issubset(fset
, &CR_LPRIV(cr
))) {
1065 } else if (!priv_isemptyset(fset
)) {
1070 if (da
.rbuf
!= (char *)&pmem
)
1071 kmem_free(da
.rbuf
, da
.rsize
);
1073 kmem_free(pap
, pasize
);
1079 check_user_privs(const cred_t
*cr
, const priv_set_t
*set
)
1086 zone_t
*myzone
= crgetzone(cr
);
1087 size_t pasize
= PFEXEC_ARG_SIZE(sizeof (priv_set_t
));
1090 mutex_enter(&myzone
->zone_lock
);
1091 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
1093 mutex_exit(&myzone
->zone_lock
);
1098 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
1103 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
1105 *(priv_set_t
*)&pap
->pfa_buf
= *set
;
1107 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
1108 pap
->pfa_call
= PFEXEC_USER_PRIVS
;
1109 pap
->pfa_len
= pasize
;
1110 pap
->pfa_uid
= crgetruid(cr
);
1112 da
.data_ptr
= (char *)pap
;
1113 da
.data_size
= pap
->pfa_len
;
1116 da
.rbuf
= (char *)&res
;
1117 da
.rsize
= sizeof (res
);
1119 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
1133 * Check the size of the result.
1135 if (da
.rsize
!= sizeof (res
))
1138 if (*(uint32_t *)da
.rbuf
== 1)
1141 if (da
.rbuf
!= (char *)&res
)
1142 kmem_free(da
.rbuf
, da
.rsize
);
1144 kmem_free(pap
, pasize
);