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 <sys/cmn_err.h>
44 #include <netinet/in.h>
46 #define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1))
48 static kmutex_t klpd_mutex
;
50 typedef struct klpd_reg
{
51 struct klpd_reg
*klpd_next
;
52 struct klpd_reg
**klpd_refp
;
53 door_handle_t klpd_door
;
57 int klpd_indel
; /* Disabled */
63 * This data structure hangs off the credential of a process; the
64 * credential is finalized and cannot be changed; but this structure
65 * can be changed when a new door server for the particular group
66 * needs to be registered. It is refcounted and shared between
67 * processes with common ancestry.
69 * The reference count is atomically updated.
71 * But the registration probably needs to be updated under a lock.
73 typedef struct credklpd
{
79 klpd_reg_t
*klpd_list
;
81 static void klpd_unlink(klpd_reg_t
*);
82 static int klpd_unreg_dh(door_handle_t
);
84 static credklpd_t
*crklpd_alloc(void);
86 void crklpd_setreg(credklpd_t
*, klpd_reg_t
*);
88 extern size_t max_vnode_path
;
91 klpd_rele(klpd_reg_t
*p
)
93 if (atomic_dec_32_nv(&p
->klpd_ref
) == 0) {
94 if (p
->klpd_refp
!= NULL
)
96 if (p
->klpd_cred
!= NULL
)
98 door_ki_rele(p
->klpd_door
);
99 kmem_free(p
, sizeof (*p
));
104 * In order to be able to walk the lists, we can't unlink the entry
105 * until the reference count drops to 0. If we remove it too soon,
106 * list walkers will terminate when they happen to call a now orphaned
110 klpd_rele_next(klpd_reg_t
*p
)
112 klpd_reg_t
*r
= p
->klpd_next
;
120 klpd_hold(klpd_reg_t
*p
)
122 atomic_inc_32(&p
->klpd_ref
);
126 * Remove registration from where it is registered. Returns next in list.
129 klpd_unlink(klpd_reg_t
*p
)
131 ASSERT(p
->klpd_refp
== NULL
|| *p
->klpd_refp
== p
);
133 if (p
->klpd_refp
!= NULL
)
134 *p
->klpd_refp
= p
->klpd_next
;
136 if (p
->klpd_next
!= NULL
)
137 p
->klpd_next
->klpd_refp
= p
->klpd_refp
;
142 * Remove all elements of the klpd list and decrement their refcnts.
143 * The lock guarding the list should be held; this function is
144 * called when we are sure we want to destroy the list completely
145 * list but not so sure that the reference counts of all elements have
149 klpd_freelist(klpd_reg_t
**pp
)
153 while ((p
= *pp
) != NULL
) {
160 * Link new entry in list. The Boolean argument specifies whether this
161 * list can contain only a single item or multiple items.
162 * Returns the entry which needs to be released if single is B_TRUE.
165 klpd_link(klpd_reg_t
*p
, klpd_reg_t
**listp
, boolean_t single
)
167 klpd_reg_t
*old
= *listp
;
169 ASSERT(p
->klpd_ref
== 1);
171 ASSERT(old
== NULL
|| *old
->klpd_refp
== old
);
172 p
->klpd_refp
= listp
;
173 p
->klpd_next
= single
? NULL
: old
;
177 ASSERT(old
->klpd_next
== NULL
);
178 old
->klpd_refp
= NULL
;
181 old
->klpd_refp
= &p
->klpd_next
;
187 * The typical call consists of:
189 * - some integer data (type, value)
190 * for now, it's just one bit.
193 klpd_marshall(klpd_reg_t
*p
, const priv_set_t
*rq
, va_list ap
)
198 size_t len
= sizeof (priv_set_t
) + sizeof (klpd_head_t
);
202 klpd_arg_t
*kap
= NULL
;
205 type
= va_arg(ap
, uint_t
);
208 khp
= kmem_zalloc(len
, KM_SLEEP
);
212 len
+= offsetof(klpd_arg_t
, kla_str
);
213 vp
= va_arg(ap
, vnode_t
*);
217 tmp
= va_arg(ap
, char *);
219 if (tmp
!= NULL
&& *tmp
!= '\0')
220 clen
= strlen(tmp
) + 1;
224 len
+= ROUNDUP(MAXPATHLEN
, sizeof (uint_t
));
225 khp
= kmem_zalloc(len
, KM_SLEEP
);
227 khp
->klh_argoff
= sizeof (klpd_head_t
) + sizeof (priv_set_t
);
230 if (vnodetopath(crgetzone(p
->klpd_cred
)->zone_rootvp
,
231 vp
, kap
->kla_str
, MAXPATHLEN
, p
->klpd_cred
) != 0) {
236 plen
= strlen(kap
->kla_str
);
237 if (plen
+ clen
+ 1 >= MAXPATHLEN
) {
241 /* Don't make root into a double "/" */
244 kap
->kla_str
[plen
] = '/';
245 bcopy(tmp
, &kap
->kla_str
[plen
+ 1], clen
);
249 proto
= va_arg(ap
, int);
251 case IPPROTO_TCP
: type
= KLPDARG_TCPPORT
;
253 case IPPROTO_UDP
: type
= KLPDARG_UDPPORT
;
255 case IPPROTO_SCTP
: type
= KLPDARG_SCTPPORT
;
257 case PROTO_SDP
: type
= KLPDARG_SDPPORT
;
262 case KLPDARG_TCPPORT
:
263 case KLPDARG_UDPPORT
:
264 case KLPDARG_SCTPPORT
:
265 case KLPDARG_SDPPORT
:
266 len
+= sizeof (*kap
);
267 khp
= kmem_zalloc(len
, KM_SLEEP
);
268 khp
->klh_argoff
= sizeof (klpd_head_t
) + sizeof (priv_set_t
);
270 kap
->kla_int
= va_arg(ap
, int);
275 khp
->klh_vers
= KLPDCALL_VERS
;
277 khp
->klh_privoff
= sizeof (*khp
);
278 *KLH_PRIVSET(khp
) = *rq
;
280 kap
->kla_type
= type
;
281 kap
->kla_dlen
= len
- khp
->klh_argoff
;
287 klpd_do_call(klpd_reg_t
*p
, const priv_set_t
*req
, va_list ap
)
294 if (p
->klpd_door_pid
== curproc
->p_pid
)
297 klh
= klpd_marshall(p
, req
, ap
);
302 da
.data_ptr
= (char *)klh
;
303 da
.data_size
= klh
->klh_len
;
306 da
.rbuf
= (char *)&res
;
307 da
.rsize
= sizeof (res
);
309 while ((dres
= door_ki_upcall_limited(p
->klpd_door
, &da
, NULL
,
310 SIZE_MAX
, 0)) != 0) {
317 /* Bad door, don't call it again. */
318 (void) klpd_unreg_dh(p
->klpd_door
);
321 /* Pending signal, nothing we can do. */
324 kmem_free(klh
, klh
->klh_len
);
328 kmem_free(klh
, klh
->klh_len
);
329 /* Bogus return value, must be a failure */
330 if (da
.rbuf
!= (char *)&res
) {
331 kmem_free(da
.rbuf
, da
.rsize
);
337 uint32_t klpd_bad_locks
;
340 klpd_call(const cred_t
*cr
, const priv_set_t
*req
, va_list ap
)
348 * These locks must not be held when this code is called;
349 * callbacks to userland with these locks held will result
350 * in issues. That said, the code at the call sides was
351 * restructured not to call with any of the locks held and
352 * no policies operate by default on most processes.
354 if (mutex_owned(&pidlock
) || mutex_owned(&curproc
->p_lock
) ||
355 mutex_owned(&curproc
->p_crlock
)) {
356 atomic_inc_32(&klpd_bad_locks
);
361 * Enforce the limit set for the call process (still).
363 if (!priv_issubset(req
, &CR_LPRIV(cr
)))
366 /* Try 1: get the credential specific klpd */
367 if ((ckp
= crgetcrklpd(cr
)) != NULL
) {
368 mutex_enter(&ckp
->crkl_lock
);
369 if ((p
= ckp
->crkl_reg
) != NULL
&&
370 p
->klpd_indel
== 0 &&
371 priv_issubset(req
, &p
->klpd_pset
)) {
373 mutex_exit(&ckp
->crkl_lock
);
374 rv
= klpd_do_call(p
, req
, ap
);
375 mutex_enter(&ckp
->crkl_lock
);
377 mutex_exit(&ckp
->crkl_lock
);
379 return (rv
== 0 ? 0 : -1);
381 mutex_exit(&ckp
->crkl_lock
);
385 /* Try 2: get the project specific klpd */
386 mutex_enter(&klpd_mutex
);
388 if ((p
= curproj
->kpj_klpd
) != NULL
) {
390 mutex_exit(&klpd_mutex
);
391 if (p
->klpd_indel
== 0 &&
392 priv_issubset(req
, &p
->klpd_pset
)) {
393 rv
= klpd_do_call(p
, req
, ap
);
395 mutex_enter(&klpd_mutex
);
397 mutex_exit(&klpd_mutex
);
400 return (rv
== 0 ? 0 : -1);
402 mutex_exit(&klpd_mutex
);
405 /* Try 3: get the global klpd list */
406 ckzone
= crgetzone(cr
);
407 mutex_enter(&klpd_mutex
);
409 for (p
= klpd_list
; p
!= NULL
; ) {
410 zone_t
*kkzone
= crgetzone(p
->klpd_cred
);
411 if ((kkzone
== &zone0
|| kkzone
== ckzone
) &&
412 p
->klpd_indel
== 0 &&
413 priv_issubset(req
, &p
->klpd_pset
)) {
415 mutex_exit(&klpd_mutex
);
416 rv
= klpd_do_call(p
, req
, ap
);
417 mutex_enter(&klpd_mutex
);
419 p
= klpd_rele_next(p
);
427 mutex_exit(&klpd_mutex
);
428 return (rv
== 0 ? 0 : -1);
433 * If the pid_t passed in is positive, update the registration for
434 * the specific process; that is only possible if the process already
435 * has a registration on it. This change of registration will affect
436 * all processes which share common ancestry.
438 * MY_PID (pid 0) can be used to create or change the context for
439 * the current process, typically done after fork().
441 * A negative value can be used to register a klpd globally.
443 * The per-credential klpd needs to be cleaned up when entering
444 * a zone or unsetting the flag.
447 klpd_reg(int did
, idtype_t type
, id_t id
, priv_set_t
*psetbuf
)
454 credklpd_t
*ckp
= NULL
;
457 kproject_t
*kpp
= NULL
;
459 if (CR_FLAGS(cr
) & PRIV_XPOLICY
)
460 return (set_errno(EINVAL
));
462 if (copyin(psetbuf
, &pset
, sizeof (priv_set_t
)))
463 return (set_errno(EFAULT
));
465 if (!priv_issubset(&pset
, &CR_OEPRIV(cr
)))
466 return (set_errno(EPERM
));
472 pid
= curproc
->p_pid
;
473 if (pid
== curproc
->p_pid
)
474 ckp
= crklpd_alloc();
478 kpp
= project_hold_by_id(proj
, crgetzone(cr
),
481 return (set_errno(ESRCH
));
484 return (set_errno(ENOTSUP
));
489 * Verify the door passed in; it must be a door and we won't
490 * allow processes to be called on their own behalf.
492 dh
= door_ki_lookup(did
);
493 if (dh
== NULL
|| door_ki_info(dh
, &di
) != 0) {
498 return (set_errno(EBADF
));
500 if (type
== P_PID
&& pid
== di
.di_target
) {
504 return (set_errno(EINVAL
));
507 kpd
= kmem_zalloc(sizeof (*kpd
), KM_SLEEP
);
508 crhold(kpd
->klpd_cred
= cr
);
510 kpd
->klpd_door_pid
= di
.di_target
;
512 kpd
->klpd_pset
= pset
;
515 mutex_enter(&klpd_mutex
);
516 kpd
= klpd_link(kpd
, &kpp
->kpj_klpd
, B_TRUE
);
517 mutex_exit(&klpd_mutex
);
521 } else if ((int)pid
< 0) {
523 mutex_enter(&klpd_mutex
);
524 (void) klpd_link(kpd
, &klpd_list
, B_FALSE
);
525 mutex_exit(&klpd_mutex
);
526 } else if (pid
== curproc
->p_pid
) {
528 cred_t
*newcr
= cralloc();
530 /* No need to lock, sole reference to ckp */
531 kpd
= klpd_link(kpd
, &ckp
->crkl_reg
, B_TRUE
);
536 mutex_enter(&p
->p_crlock
);
539 crsetcrklpd(newcr
, ckp
);
540 p
->p_cred
= newcr
; /* Already held for p_cred */
542 crhold(newcr
); /* Hold once for the current thread */
543 mutex_exit(&p
->p_crlock
);
544 crfree(cr
); /* One for the p_cred */
549 mutex_enter(&pidlock
);
551 if (p
== NULL
|| !prochasprocperm(p
, curproc
, CRED())) {
552 mutex_exit(&pidlock
);
554 return (set_errno(p
== NULL
? ESRCH
: EPERM
));
556 mutex_enter(&p
->p_crlock
);
557 crhold(pcr
= p
->p_cred
);
558 mutex_exit(&pidlock
);
559 mutex_exit(&p
->p_crlock
);
561 * We're going to update the credential's ckp in place;
562 * this requires that it exists.
564 ckp
= crgetcrklpd(pcr
);
568 return (set_errno(EINVAL
));
570 crklpd_setreg(ckp
, kpd
);
578 klpd_unreg_dh(door_handle_t dh
)
582 mutex_enter(&klpd_mutex
);
583 for (p
= klpd_list
; p
!= NULL
; p
= p
->klpd_next
) {
584 if (p
->klpd_door
== dh
)
588 mutex_exit(&klpd_mutex
);
591 if (p
->klpd_indel
!= 0) {
592 mutex_exit(&klpd_mutex
);
597 mutex_exit(&klpd_mutex
);
602 klpd_unreg(int did
, idtype_t type
, id_t id
)
609 kproject_t
*kpp
= NULL
;
618 kpp
= project_hold_by_id(proj
, crgetzone(CRED()),
621 return (set_errno(ESRCH
));
624 return (set_errno(ENOTSUP
));
627 dh
= door_ki_lookup(did
);
631 return (set_errno(EINVAL
));
635 mutex_enter(&klpd_mutex
);
636 if (kpp
->kpj_klpd
== NULL
)
639 klpd_freelist(&kpp
->kpj_klpd
);
640 mutex_exit(&klpd_mutex
);
643 } else if ((int)pid
> 0) {
644 mutex_enter(&pidlock
);
647 mutex_exit(&pidlock
);
649 return (set_errno(ESRCH
));
651 mutex_enter(&p
->p_crlock
);
652 mutex_exit(&pidlock
);
653 } else if (pid
== 0) {
655 mutex_enter(&p
->p_crlock
);
657 res
= klpd_unreg_dh(dh
);
661 ckp
= crgetcrklpd(p
->p_cred
);
663 crklpd_setreg(ckp
, NULL
);
667 mutex_exit(&p
->p_crlock
);
673 return (set_errno(res
));
678 crklpd_hold(credklpd_t
*crkpd
)
680 atomic_inc_32(&crkpd
->crkl_ref
);
684 crklpd_rele(credklpd_t
*crkpd
)
686 if (atomic_dec_32_nv(&crkpd
->crkl_ref
) == 0) {
687 if (crkpd
->crkl_reg
!= NULL
)
688 klpd_rele(crkpd
->crkl_reg
);
689 mutex_destroy(&crkpd
->crkl_lock
);
690 kmem_free(crkpd
, sizeof (*crkpd
));
697 credklpd_t
*res
= kmem_alloc(sizeof (*res
), KM_SLEEP
);
699 mutex_init(&res
->crkl_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
701 res
->crkl_reg
= NULL
;
707 crklpd_setreg(credklpd_t
*crk
, klpd_reg_t
*new)
711 mutex_enter(&crk
->crkl_lock
);
717 old
= klpd_link(new, &crk
->crkl_reg
, B_TRUE
);
719 mutex_exit(&crk
->crkl_lock
);
725 /* Allocate and register the pfexec specific callback */
730 int err
= secpolicy_pfexec_register(CRED());
733 zone_t
*myzone
= crgetzone(CRED());
736 return (set_errno(err
));
738 dh
= door_ki_lookup(did
);
739 if (dh
== NULL
|| door_ki_info(dh
, &di
) != 0)
740 return (set_errno(EBADF
));
742 pfx
= kmem_zalloc(sizeof (*pfx
), KM_SLEEP
);
745 pfx
->klpd_door_pid
= di
.di_target
;
747 pfx
->klpd_cred
= NULL
;
748 mutex_enter(&myzone
->zone_lock
);
749 pfx
= klpd_link(pfx
, &myzone
->zone_pfexecd
, B_TRUE
);
750 mutex_exit(&myzone
->zone_lock
);
758 pfexec_unreg(int did
)
762 zone_t
*myzone
= crgetzone(CRED());
765 dh
= door_ki_lookup(did
);
767 return (set_errno(EBADF
));
769 mutex_enter(&myzone
->zone_lock
);
770 pfd
= myzone
->zone_pfexecd
;
771 if (pfd
!= NULL
&& pfd
->klpd_door
== dh
) {
777 mutex_exit(&myzone
->zone_lock
);
780 * crfree() cannot be called with zone_lock held; it is called
781 * indirectly through closing the door handle
786 return (set_errno(err
));
791 get_path(char *buf
, const char *path
, int len
)
799 if (*path
== '/' && len
< MAXPATHLEN
) {
800 (void) strcpy(buf
, path
);
804 * Build the pathname using the current directory + resolve pathname.
805 * The resolve pathname either starts with a normal component and
806 * we can just concatenate them or it starts with one
807 * or more ".." component and we can remove those; the
808 * last one cannot be a ".." and the current directory has
809 * more components than the number of ".." in the resolved pathname.
811 if (dogetcwd(buf
, MAXPATHLEN
) != 0)
816 while (len
> 3 && strncmp("../", path
, 3) == 0) {
820 s
= strrchr(buf
, '/');
821 if (s
== NULL
|| s
== buf
)
827 /* Add a "/" and a NUL */
828 if (lc
< 2 || lc
+ len
+ 2 >= MAXPATHLEN
)
832 (void) strcpy(buf
+ lc
+ 1, path
);
838 * Perform the pfexec upcall.
840 * The pfexec upcall is different from the klpd_upcall in that a failure
841 * will lead to a denial of execution.
844 pfexec_call(const cred_t
*cr
, struct pathname
*rpnp
, cred_t
**pfcr
,
849 pfexec_reply_t pr
, *prp
;
856 zone_t
*myzone
= crgetzone(CRED());
857 size_t pasize
= PFEXEC_ARG_SIZE(MAXPATHLEN
);
859 /* Find registration */
860 mutex_enter(&myzone
->zone_lock
);
861 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
863 mutex_exit(&myzone
->zone_lock
);
866 DTRACE_PROBE2(pfexecd__not__running
,
867 zone_t
*, myzone
, char *, rpnp
->pn_path
);
868 uprintf("pfexecd not running; pid %d privileges not "
869 "elevated\n", curproc
->p_pid
);
873 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
878 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
880 if (get_path(pap
->pfa_path
, rpnp
->pn_path
, rpnp
->pn_pathlen
) == -1)
883 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
884 pap
->pfa_call
= PFEXEC_EXEC_ATTRS
;
885 pap
->pfa_len
= pasize
;
886 pap
->pfa_uid
= crgetruid(cr
);
888 da
.data_ptr
= (char *)pap
;
889 da
.data_size
= pap
->pfa_len
;
892 da
.rbuf
= (char *)&pr
;
893 da
.rsize
= sizeof (pr
);
895 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
906 DTRACE_PROBE4(pfexecd__failure
,
907 int, dres
, zone_t
*, myzone
,
908 char *, rpnp
->pn_path
, klpd_reg_t
*, pfd
);
913 prp
= (pfexec_reply_t
*)da
.rbuf
;
915 * Check the size of the result and the alignment of the
918 if (da
.rsize
< sizeof (pr
) ||
919 prp
->pfr_ioff
> da
.rsize
- sizeof (priv_set_t
) ||
920 prp
->pfr_loff
> da
.rsize
- sizeof (priv_set_t
) ||
921 (prp
->pfr_loff
& (sizeof (priv_chunk_t
) - 1)) != 0 ||
922 (prp
->pfr_ioff
& (sizeof (priv_chunk_t
) - 1)) != 0)
927 * allow/allow with additional credentials/disallow[*]
929 * euid, uid, egid, gid, privs, and limitprivs
930 * We now have somewhat more flexibility we could even set E and P
931 * judiciously but that would break some currently valid assumptions
932 * [*] Disallow is not readily supported by always including
933 * the Basic Solaris User profile in all user's profiles.
936 if (!prp
->pfr_allowed
) {
940 if (!prp
->pfr_setcred
) {
944 ncr
= crdup((cred_t
*)cr
);
947 * Generate the new credential set scrubenv if ruid != euid (or set)
948 * the "I'm set-uid flag" but that is not inherited so scrubbing
949 * the environment is a requirement.
951 /* Set uids or gids, note that -1 will do the right thing */
952 if (crsetresuid(ncr
, prp
->pfr_ruid
, prp
->pfr_euid
, prp
->pfr_euid
) != 0)
954 if (crsetresgid(ncr
, prp
->pfr_rgid
, prp
->pfr_egid
, prp
->pfr_egid
) != 0)
957 *scrub
= prp
->pfr_scrubenv
;
959 if (prp
->pfr_clearflag
)
960 CR_FLAGS(ncr
) &= ~PRIV_PFEXEC
;
962 /* We cannot exceed our Limit set, no matter what */
963 iset
= PFEXEC_REPLY_IPRIV(prp
);
966 if (!priv_issubset(iset
, &CR_LPRIV(ncr
)))
968 priv_union(iset
, &CR_IPRIV(ncr
));
971 /* Nor can we increate our Limit set itself */
972 lset
= PFEXEC_REPLY_LPRIV(prp
);
975 if (!priv_issubset(lset
, &CR_LPRIV(ncr
)))
977 CR_LPRIV(ncr
) = *lset
;
980 /* Exec will do the standard set operations */
984 if (da
.rbuf
!= (char *)&pr
)
985 kmem_free(da
.rbuf
, da
.rsize
);
987 kmem_free(pap
, pasize
);
999 get_forced_privs(const cred_t
*cr
, const char *respn
, priv_set_t
*set
)
1006 priv_set_t
*fset
, pmem
;
1008 zone_t
*myzone
= crgetzone(cr
);
1009 size_t pasize
= PFEXEC_ARG_SIZE(MAXPATHLEN
);
1011 mutex_enter(&myzone
->zone_lock
);
1012 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
1014 mutex_exit(&myzone
->zone_lock
);
1019 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
1024 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
1026 if (get_path(pap
->pfa_path
, respn
, -1) == -1)
1029 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
1030 pap
->pfa_call
= PFEXEC_FORCED_PRIVS
;
1031 pap
->pfa_len
= pasize
;
1032 pap
->pfa_uid
= (uid_t
)-1; /* Not relevant */
1034 da
.data_ptr
= (char *)pap
;
1035 da
.data_size
= pap
->pfa_len
;
1038 da
.rbuf
= (char *)&pmem
;
1039 da
.rsize
= sizeof (pmem
);
1041 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
1055 * Check the size of the result, it's a privilege set.
1057 if (da
.rsize
!= sizeof (priv_set_t
))
1060 fset
= (priv_set_t
*)da
.rbuf
;
1063 * We restrict the forced privileges with whatever is available in
1066 zkcr
= zone_kcred();
1067 priv_intersect(&CR_LPRIV(zkcr
), fset
);
1070 * But we fail if the forced privileges are not found in the current
1073 if (!priv_issubset(fset
, &CR_LPRIV(cr
))) {
1075 } else if (!priv_isemptyset(fset
)) {
1080 if (da
.rbuf
!= (char *)&pmem
)
1081 kmem_free(da
.rbuf
, da
.rsize
);
1083 kmem_free(pap
, pasize
);
1089 check_user_privs(const cred_t
*cr
, const priv_set_t
*set
)
1096 zone_t
*myzone
= crgetzone(cr
);
1097 size_t pasize
= PFEXEC_ARG_SIZE(sizeof (priv_set_t
));
1100 mutex_enter(&myzone
->zone_lock
);
1101 if ((pfd
= myzone
->zone_pfexecd
) != NULL
)
1103 mutex_exit(&myzone
->zone_lock
);
1108 if (pfd
->klpd_door_pid
== curproc
->p_pid
) {
1113 pap
= kmem_zalloc(pasize
, KM_SLEEP
);
1115 *(priv_set_t
*)&pap
->pfa_buf
= *set
;
1117 pap
->pfa_vers
= PFEXEC_ARG_VERS
;
1118 pap
->pfa_call
= PFEXEC_USER_PRIVS
;
1119 pap
->pfa_len
= pasize
;
1120 pap
->pfa_uid
= crgetruid(cr
);
1122 da
.data_ptr
= (char *)pap
;
1123 da
.data_size
= pap
->pfa_len
;
1126 da
.rbuf
= (char *)&res
;
1127 da
.rsize
= sizeof (res
);
1129 while ((dres
= door_ki_upcall(pfd
->klpd_door
, &da
)) != 0) {
1143 * Check the size of the result.
1145 if (da
.rsize
!= sizeof (res
))
1148 if (*(uint32_t *)da
.rbuf
== 1)
1151 if (da
.rbuf
!= (char *)&res
)
1152 kmem_free(da
.rbuf
, da
.rsize
);
1154 kmem_free(pap
, pasize
);