17bc82500SRobert Watson /*- 25c95417dSRobert Watson * Copyright (c) 1999-2002, 2006, 2009, 2019 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 4c66b4d8dSRobert Watson * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 5800c9408SRobert Watson * Copyright (c) 2006 nCircle Network Security, Inc. 630d239bcSRobert Watson * Copyright (c) 2006 SPARTA, Inc. 79162f64bSRobert Watson * Copyright (c) 2009 Apple, Inc. 87bc82500SRobert Watson * All rights reserved. 97bc82500SRobert Watson * 107bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 117bc82500SRobert Watson * TrustedBSD Project. 127bc82500SRobert Watson * 136201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 146201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 156201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 166201265bSRobert Watson * as part of the DARPA CHATS research program. 177bc82500SRobert Watson * 18800c9408SRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD 19800c9408SRobert Watson * Project under contract to nCircle Network Security, Inc. 20800c9408SRobert Watson * 2130d239bcSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 2230d239bcSRobert Watson * N66001-04-C-6019 ("SEFOS"). 2330d239bcSRobert Watson * 242087a58cSRobert Watson * This software was developed at the University of Cambridge Computer 252087a58cSRobert Watson * Laboratory with support from a grant from Google, Inc. 262087a58cSRobert Watson * 277bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 287bc82500SRobert Watson * modification, are permitted provided that the following conditions 297bc82500SRobert Watson * are met: 307bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 317bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 327bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 337bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 347bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 357bc82500SRobert Watson * 367bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 377bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 387bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 397bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 407bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 417bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 427bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 437bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 447bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 457bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 467bc82500SRobert Watson * SUCH DAMAGE. 477bc82500SRobert Watson */ 48677b542eSDavid E. O'Brien 49646a9f80SRobert Watson #ifndef _SECURITY_MAC_MAC_INTERNAL_H_ 50646a9f80SRobert Watson #define _SECURITY_MAC_MAC_INTERNAL_H_ 51d02188c1SRobert Watson 52c96ae196SRobert Watson #ifndef _KERNEL 53c96ae196SRobert Watson #error "no user-serviceable parts inside" 54c96ae196SRobert Watson #endif 55c96ae196SRobert Watson 5681fee06fSRobert Watson #include <sys/lock.h> 5781fee06fSRobert Watson #include <sys/rmlock.h> 5881fee06fSRobert Watson 597bc82500SRobert Watson /* 602087a58cSRobert Watson * MAC Framework SDT DTrace probe namespace, macros for declaring entry 612087a58cSRobert Watson * point probes, macros for invoking them. 622087a58cSRobert Watson */ 632087a58cSRobert Watson #ifdef SDT_PROVIDER_DECLARE 642087a58cSRobert Watson SDT_PROVIDER_DECLARE(mac); /* MAC Framework-level events. */ 652087a58cSRobert Watson SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */ 662087a58cSRobert Watson 672087a58cSRobert Watson #define MAC_CHECK_PROBE_DEFINE4(name, arg0, arg1, arg2, arg3) \ 6836160958SMark Johnston SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__err, \ 69d9fae5abSAndriy Gapon "int", arg0, arg1, arg2, arg3); \ 7036160958SMark Johnston SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__ok, \ 71d9fae5abSAndriy Gapon "int", arg0, arg1, arg2, arg3); 722087a58cSRobert Watson 732087a58cSRobert Watson #define MAC_CHECK_PROBE_DEFINE3(name, arg0, arg1, arg2) \ 7436160958SMark Johnston SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__err, \ 75d9fae5abSAndriy Gapon "int", arg0, arg1, arg2); \ 7636160958SMark Johnston SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__ok, \ 77d9fae5abSAndriy Gapon "int", arg0, arg1, arg2); 782087a58cSRobert Watson 792087a58cSRobert Watson #define MAC_CHECK_PROBE_DEFINE2(name, arg0, arg1) \ 8036160958SMark Johnston SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__err, \ 81d9fae5abSAndriy Gapon "int", arg0, arg1); \ 8236160958SMark Johnston SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__ok, \ 83d9fae5abSAndriy Gapon "int", arg0, arg1); 842087a58cSRobert Watson 852087a58cSRobert Watson #define MAC_CHECK_PROBE_DEFINE1(name, arg0) \ 8636160958SMark Johnston SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__err, \ 87d9fae5abSAndriy Gapon "int", arg0); \ 8836160958SMark Johnston SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__ok, \ 89d9fae5abSAndriy Gapon "int", arg0); 902087a58cSRobert Watson 912087a58cSRobert Watson #define MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, arg3) do { \ 926dcf45feSMateusz Guzik if (SDT_PROBES_ENABLED()) { \ 932087a58cSRobert Watson if (error) { \ 9436160958SMark Johnston SDT_PROBE5(mac_framework, , name, mac__check__err,\ 952087a58cSRobert Watson error, arg0, arg1, arg2, arg3); \ 962087a58cSRobert Watson } else { \ 9736160958SMark Johnston SDT_PROBE5(mac_framework, , name, mac__check__ok,\ 982087a58cSRobert Watson 0, arg0, arg1, arg2, arg3); \ 992087a58cSRobert Watson } \ 1006dcf45feSMateusz Guzik } \ 1012087a58cSRobert Watson } while (0) 1022087a58cSRobert Watson 1032087a58cSRobert Watson #define MAC_CHECK_PROBE3(name, error, arg0, arg1, arg2) \ 1042087a58cSRobert Watson MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, 0) 1052087a58cSRobert Watson #define MAC_CHECK_PROBE2(name, error, arg0, arg1) \ 1062087a58cSRobert Watson MAC_CHECK_PROBE3(name, error, arg0, arg1, 0) 1072087a58cSRobert Watson #define MAC_CHECK_PROBE1(name, error, arg0) \ 1082087a58cSRobert Watson MAC_CHECK_PROBE2(name, error, arg0, 0) 1092087a58cSRobert Watson #endif 1102087a58cSRobert Watson 1112087a58cSRobert Watson #define MAC_GRANT_PROBE_DEFINE2(name, arg0, arg1) \ 11236160958SMark Johnston SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__err, \ 113d9fae5abSAndriy Gapon "int", arg0, arg1); \ 11436160958SMark Johnston SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__ok, \ 115d9fae5abSAndriy Gapon "int", arg0, arg1); 1162087a58cSRobert Watson 1172087a58cSRobert Watson #define MAC_GRANT_PROBE2(name, error, arg0, arg1) do { \ 1186dcf45feSMateusz Guzik if (SDT_PROBES_ENABLED()) { \ 1192087a58cSRobert Watson if (error) { \ 12036160958SMark Johnston SDT_PROBE3(mac_framework, , name, mac__grant__err,\ 12136160958SMark Johnston error, arg0, arg1); \ 1222087a58cSRobert Watson } else { \ 12336160958SMark Johnston SDT_PROBE3(mac_framework, , name, mac__grant__ok,\ 12436160958SMark Johnston error, arg0, arg1); \ 1252087a58cSRobert Watson } \ 1266dcf45feSMateusz Guzik } \ 1272087a58cSRobert Watson } while (0) 1282087a58cSRobert Watson 1292087a58cSRobert Watson /* 13086ea834cSRobert Watson * MAC Framework global types and typedefs. 13186ea834cSRobert Watson */ 13286ea834cSRobert Watson LIST_HEAD(mac_policy_list_head, mac_policy_conf); 13357f253a4SBruce Evans #ifdef MALLOC_DECLARE 134138f64b6SRobert Watson MALLOC_DECLARE(M_MACTEMP); 13557f253a4SBruce Evans #endif 1366be0c25eSRobert Watson 13786ea834cSRobert Watson /* 1380142affcSRobert Watson * MAC labels -- in-kernel storage format. 1390142affcSRobert Watson * 1400142affcSRobert Watson * In general, struct label pointers are embedded in kernel data structures 1410142affcSRobert Watson * representing objects that may be labeled (and protected). Struct label is 1420142affcSRobert Watson * opaque to both kernel services that invoke the MAC Framework and MAC 1430142affcSRobert Watson * policy modules. In particular, we do not wish to encode the layout of the 1440142affcSRobert Watson * label structure into any ABIs. Historically, the slot array contained 1450142affcSRobert Watson * unions of {long, void} but now contains uintptr_t. 1460142affcSRobert Watson */ 1470142affcSRobert Watson #define MAC_MAX_SLOTS 4 1480142affcSRobert Watson #define MAC_FLAG_INITIALIZED 0x0000001 /* Is initialized for use. */ 1490142affcSRobert Watson struct label { 1500142affcSRobert Watson int l_flags; 1510142affcSRobert Watson intptr_t l_perpolicy[MAC_MAX_SLOTS]; 1520142affcSRobert Watson }; 1530142affcSRobert Watson 1549162f64bSRobert Watson /* 1559162f64bSRobert Watson * Flags for mac_labeled, a bitmask of object types need across the union of 1569162f64bSRobert Watson * all policies currently registered with the MAC Framework, used to key 1579162f64bSRobert Watson * whether or not labels are allocated and constructors for the type are 1589162f64bSRobert Watson * invoked. 1599162f64bSRobert Watson */ 1609162f64bSRobert Watson #define MPC_OBJECT_CRED 0x0000000000000001 1619162f64bSRobert Watson #define MPC_OBJECT_PROC 0x0000000000000002 1629162f64bSRobert Watson #define MPC_OBJECT_VNODE 0x0000000000000004 1639162f64bSRobert Watson #define MPC_OBJECT_INPCB 0x0000000000000008 1649162f64bSRobert Watson #define MPC_OBJECT_SOCKET 0x0000000000000010 1659162f64bSRobert Watson #define MPC_OBJECT_DEVFS 0x0000000000000020 1669162f64bSRobert Watson #define MPC_OBJECT_MBUF 0x0000000000000040 1679162f64bSRobert Watson #define MPC_OBJECT_IPQ 0x0000000000000080 1689162f64bSRobert Watson #define MPC_OBJECT_IFNET 0x0000000000000100 1699162f64bSRobert Watson #define MPC_OBJECT_BPFDESC 0x0000000000000200 1709162f64bSRobert Watson #define MPC_OBJECT_PIPE 0x0000000000000400 1719162f64bSRobert Watson #define MPC_OBJECT_MOUNT 0x0000000000000800 1729162f64bSRobert Watson #define MPC_OBJECT_POSIXSEM 0x0000000000001000 1739162f64bSRobert Watson #define MPC_OBJECT_POSIXSHM 0x0000000000002000 1749162f64bSRobert Watson #define MPC_OBJECT_SYSVMSG 0x0000000000004000 1759162f64bSRobert Watson #define MPC_OBJECT_SYSVMSQ 0x0000000000008000 1769162f64bSRobert Watson #define MPC_OBJECT_SYSVSEM 0x0000000000010000 1779162f64bSRobert Watson #define MPC_OBJECT_SYSVSHM 0x0000000000020000 1789162f64bSRobert Watson #define MPC_OBJECT_SYNCACHE 0x0000000000040000 1799162f64bSRobert Watson #define MPC_OBJECT_IP6Q 0x0000000000080000 1809162f64bSRobert Watson 1810142affcSRobert Watson /* 18286ea834cSRobert Watson * MAC Framework global variables. 18386ea834cSRobert Watson */ 18486ea834cSRobert Watson extern struct mac_policy_list_head mac_policy_list; 18586ea834cSRobert Watson extern struct mac_policy_list_head mac_static_policy_list; 186f93bfb23SRobert Watson extern u_int mac_policy_count; 1876356dba0SRobert Watson extern uint64_t mac_labeled; 188b9b0dac3SRobert Watson extern struct mtx mac_ifnet_mtx; 189b2f0927aSRobert Watson 19086ea834cSRobert Watson /* 19186ea834cSRobert Watson * MAC Framework infrastructure functions. 19295fab37eSRobert Watson */ 19386ea834cSRobert Watson int mac_error_select(int error1, int error2); 19486ea834cSRobert Watson 19581fee06fSRobert Watson void mac_policy_slock_nosleep(struct rm_priotracker *tracker); 19640202729SRobert Watson void mac_policy_slock_sleep(void); 19781fee06fSRobert Watson void mac_policy_sunlock_nosleep(struct rm_priotracker *tracker); 19840202729SRobert Watson void mac_policy_sunlock_sleep(void); 19986ea834cSRobert Watson 200eca8a663SRobert Watson struct label *mac_labelzone_alloc(int flags); 201eca8a663SRobert Watson void mac_labelzone_free(struct label *label); 202eca8a663SRobert Watson void mac_labelzone_init(void); 203eca8a663SRobert Watson 20486ea834cSRobert Watson void mac_init_label(struct label *label); 20586ea834cSRobert Watson void mac_destroy_label(struct label *label); 206f64a688dSBrooks Davis int mac_check_structmac_consistent(const struct mac *mac); 20786ea834cSRobert Watson int mac_allocate_slot(void); 208a96acd1aSRobert Watson 2095c95417dSRobert Watson /* 2105c95417dSRobert Watson * Lock ifnets to protect labels only if ifnet labels are in use. 2115c95417dSRobert Watson */ 2125c95417dSRobert Watson #define MAC_IFNET_LOCK(ifp, locked) do { \ 2135c95417dSRobert Watson if (mac_labeled & MPC_OBJECT_IFNET) { \ 2145c95417dSRobert Watson mtx_lock(&mac_ifnet_mtx); \ 2155c95417dSRobert Watson locked = 1; \ 2165c95417dSRobert Watson } else { \ 2175c95417dSRobert Watson locked = 0; \ 2185c95417dSRobert Watson } \ 2195c95417dSRobert Watson } while (0) 2205c95417dSRobert Watson 2215c95417dSRobert Watson #define MAC_IFNET_UNLOCK(ifp, locked) do { \ 2225c95417dSRobert Watson if (locked) { \ 2235c95417dSRobert Watson mtx_unlock(&mac_ifnet_mtx); \ 2245c95417dSRobert Watson locked = 0; \ 2255c95417dSRobert Watson } \ 2265c95417dSRobert Watson } while (0) 227b9b0dac3SRobert Watson 228a96acd1aSRobert Watson /* 2295c5a9819SRobert Watson * MAC Framework per-object type functions. It's not yet clear how the 2305c5a9819SRobert Watson * namespaces, etc, should work for these, so for now, sort by object type. 231a96acd1aSRobert Watson */ 2326356dba0SRobert Watson struct label *mac_cred_label_alloc(void); 2336356dba0SRobert Watson void mac_cred_label_free(struct label *label); 234eca8a663SRobert Watson struct label *mac_pipe_label_alloc(void); 235eca8a663SRobert Watson void mac_pipe_label_free(struct label *label); 236b0323ea3SRobert Watson struct label *mac_socket_label_alloc(int flag); 237b0323ea3SRobert Watson void mac_socket_label_free(struct label *label); 238*2fb778faSMichael Tuexen void mac_socketpeer_label_free(struct label *label); 2396356dba0SRobert Watson struct label *mac_vnode_label_alloc(void); 2406356dba0SRobert Watson void mac_vnode_label_free(struct label *label); 241eca8a663SRobert Watson 24230d239bcSRobert Watson int mac_cred_check_relabel(struct ucred *cred, struct label *newlabel); 24330d239bcSRobert Watson int mac_cred_externalize_label(struct label *label, char *elements, 24483b7b0edSRobert Watson char *outbuf, size_t outbuflen); 24530d239bcSRobert Watson int mac_cred_internalize_label(struct label *label, char *string); 24630d239bcSRobert Watson void mac_cred_relabel(struct ucred *cred, struct label *newlabel); 24795fab37eSRobert Watson 248c66b4d8dSRobert Watson struct label *mac_mbuf_to_label(struct mbuf *m); 249c66b4d8dSRobert Watson 25030d239bcSRobert Watson void mac_pipe_copy_label(struct label *src, struct label *dest); 25130d239bcSRobert Watson int mac_pipe_externalize_label(struct label *label, char *elements, 25283b7b0edSRobert Watson char *outbuf, size_t outbuflen); 25330d239bcSRobert Watson int mac_pipe_internalize_label(struct label *label, char *string); 25495fab37eSRobert Watson 255c9ea2dcfSRobert Watson int mac_socket_label_set(struct ucred *cred, struct socket *so, 256c9ea2dcfSRobert Watson struct label *label); 25730d239bcSRobert Watson void mac_socket_copy_label(struct label *src, struct label *dest); 25830d239bcSRobert Watson int mac_socket_externalize_label(struct label *label, char *elements, 259b0323ea3SRobert Watson char *outbuf, size_t outbuflen); 26030d239bcSRobert Watson int mac_socket_internalize_label(struct label *label, char *string); 261c9ea2dcfSRobert Watson 26230d239bcSRobert Watson int mac_vnode_externalize_label(struct label *label, char *elements, 26383b7b0edSRobert Watson char *outbuf, size_t outbuflen); 26430d239bcSRobert Watson int mac_vnode_internalize_label(struct label *label, char *string); 26530d239bcSRobert Watson void mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 26686ea834cSRobert Watson int *prot); 26786ea834cSRobert Watson int vn_setlabel(struct vnode *vp, struct label *intlabel, 26886ea834cSRobert Watson struct ucred *cred); 26995fab37eSRobert Watson 27095fab37eSRobert Watson /* 27140202729SRobert Watson * MAC Framework composition macros invoke all registered MAC policies for a 27240202729SRobert Watson * specific entry point. They come in two forms: one which permits policies 27340202729SRobert Watson * to sleep/block, and another that does not. 27440202729SRobert Watson * 275fa765671SRobert Watson * MAC_POLICY_CHECK performs the designated check by walking the policy 276fa765671SRobert Watson * module list and checking with each as to how it feels about the request. 277fa765671SRobert Watson * Note that it returns its value via 'error' in the scope of the caller. 27895fab37eSRobert Watson */ 279fa765671SRobert Watson #define MAC_POLICY_CHECK(check, args...) do { \ 28095fab37eSRobert Watson struct mac_policy_conf *mpc; \ 28195fab37eSRobert Watson \ 28295fab37eSRobert Watson error = 0; \ 28341a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 28441a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 28586ea834cSRobert Watson error = mac_error_select( \ 28641a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 28741a17fe3SRobert Watson error); \ 28841a17fe3SRobert Watson } \ 28940202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 29040202729SRobert Watson mac_policy_slock_sleep(); \ 29195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 29295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 29386ea834cSRobert Watson error = mac_error_select( \ 29495fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 29595fab37eSRobert Watson error); \ 29695fab37eSRobert Watson } \ 29740202729SRobert Watson mac_policy_sunlock_sleep(); \ 29840202729SRobert Watson } \ 29940202729SRobert Watson } while (0) 30040202729SRobert Watson 301fa765671SRobert Watson #define MAC_POLICY_CHECK_NOSLEEP(check, args...) do { \ 30240202729SRobert Watson struct mac_policy_conf *mpc; \ 30340202729SRobert Watson \ 30440202729SRobert Watson error = 0; \ 30540202729SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 30640202729SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 30740202729SRobert Watson error = mac_error_select( \ 30840202729SRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 30940202729SRobert Watson error); \ 31040202729SRobert Watson } \ 31140202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 31281fee06fSRobert Watson struct rm_priotracker tracker; \ 31381fee06fSRobert Watson \ 31481fee06fSRobert Watson mac_policy_slock_nosleep(&tracker); \ 31540202729SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 31640202729SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 31740202729SRobert Watson error = mac_error_select( \ 31840202729SRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 31940202729SRobert Watson error); \ 32040202729SRobert Watson } \ 32181fee06fSRobert Watson mac_policy_sunlock_nosleep(&tracker); \ 32241a17fe3SRobert Watson } \ 32395fab37eSRobert Watson } while (0) 32495fab37eSRobert Watson 32595fab37eSRobert Watson /* 326fa765671SRobert Watson * MAC_POLICY_GRANT performs the designated check by walking the policy 327fa765671SRobert Watson * module list and checking with each as to how it feels about the request. 328fa765671SRobert Watson * Unlike MAC_POLICY_CHECK, it grants if any policies return '0', and 329fa765671SRobert Watson * otherwise returns EPERM. Note that it returns its value via 'error' in 330fa765671SRobert Watson * the scope of the caller. 331800c9408SRobert Watson */ 332fa765671SRobert Watson #define MAC_POLICY_GRANT_NOSLEEP(check, args...) do { \ 333800c9408SRobert Watson struct mac_policy_conf *mpc; \ 334800c9408SRobert Watson \ 335800c9408SRobert Watson error = EPERM; \ 336800c9408SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 337800c9408SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) { \ 338800c9408SRobert Watson if (mpc->mpc_ops->mpo_ ## check(args) == 0) \ 339800c9408SRobert Watson error = 0; \ 340800c9408SRobert Watson } \ 341800c9408SRobert Watson } \ 34240202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 34381fee06fSRobert Watson struct rm_priotracker tracker; \ 34481fee06fSRobert Watson \ 34581fee06fSRobert Watson mac_policy_slock_nosleep(&tracker); \ 346800c9408SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 347800c9408SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) { \ 348800c9408SRobert Watson if (mpc->mpc_ops->mpo_ ## check (args) \ 349800c9408SRobert Watson == 0) \ 350800c9408SRobert Watson error = 0; \ 351800c9408SRobert Watson } \ 352800c9408SRobert Watson } \ 35381fee06fSRobert Watson mac_policy_sunlock_nosleep(&tracker); \ 354800c9408SRobert Watson } \ 355800c9408SRobert Watson } while (0) 356800c9408SRobert Watson 357800c9408SRobert Watson /* 358fa765671SRobert Watson * MAC_POLICY_BOOLEAN performs the designated boolean composition by walking 359fa765671SRobert Watson * the module list, invoking each instance of the operation, and combining 360fa765671SRobert Watson * the results using the passed C operator. Note that it returns its value 361fa765671SRobert Watson * via 'result' in the scope of the caller, which should be initialized by 362fa765671SRobert Watson * the caller in a meaningful way to get a meaningful result. 36395fab37eSRobert Watson */ 364fa765671SRobert Watson #define MAC_POLICY_BOOLEAN(operation, composition, args...) do { \ 36595fab37eSRobert Watson struct mac_policy_conf *mpc; \ 36695fab37eSRobert Watson \ 36741a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 36895fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 36995fab37eSRobert Watson result = result composition \ 37095fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 37195fab37eSRobert Watson } \ 37240202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 37340202729SRobert Watson mac_policy_slock_sleep(); \ 37441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 37541a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 37641a17fe3SRobert Watson result = result composition \ 37741a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation \ 37841a17fe3SRobert Watson (args); \ 37941a17fe3SRobert Watson } \ 38040202729SRobert Watson mac_policy_sunlock_sleep(); \ 38140202729SRobert Watson } \ 38240202729SRobert Watson } while (0) 38340202729SRobert Watson 384fa765671SRobert Watson #define MAC_POLICY_BOOLEAN_NOSLEEP(operation, composition, args...) do {\ 38540202729SRobert Watson struct mac_policy_conf *mpc; \ 38640202729SRobert Watson \ 38740202729SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 38840202729SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 38940202729SRobert Watson result = result composition \ 39040202729SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 39140202729SRobert Watson } \ 39240202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 39381fee06fSRobert Watson struct rm_priotracker tracker; \ 39481fee06fSRobert Watson \ 39581fee06fSRobert Watson mac_policy_slock_nosleep(&tracker); \ 39640202729SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 39740202729SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 39840202729SRobert Watson result = result composition \ 39940202729SRobert Watson mpc->mpc_ops->mpo_ ## operation \ 40040202729SRobert Watson (args); \ 40140202729SRobert Watson } \ 40281fee06fSRobert Watson mac_policy_sunlock_nosleep(&tracker); \ 40341a17fe3SRobert Watson } \ 40495fab37eSRobert Watson } while (0) 40595fab37eSRobert Watson 4065c5a9819SRobert Watson /* 407fa765671SRobert Watson * MAC_POLICY_EXTERNALIZE queries each policy to see if it can generate an 4085c5a9819SRobert Watson * externalized version of a label element by name. Policies declare whether 4095c5a9819SRobert Watson * they have matched a particular element name, parsed from the string by 410fa765671SRobert Watson * MAC_POLICY_EXTERNALIZE, and an error is returned if any element is matched 411fa765671SRobert Watson * by no policy. 4125c5a9819SRobert Watson */ 413fa765671SRobert Watson #define MAC_POLICY_EXTERNALIZE(type, label, elementlist, outbuf, \ 414f7b951a8SRobert Watson outbuflen) do { \ 415f51e5803SRobert Watson int claimed, first, ignorenotfound, savedlen; \ 416f51e5803SRobert Watson char *element_name, *element_temp; \ 417f51e5803SRobert Watson struct sbuf sb; \ 418f7b951a8SRobert Watson \ 419f7b951a8SRobert Watson error = 0; \ 420f7b951a8SRobert Watson first = 1; \ 421f51e5803SRobert Watson sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \ 422f51e5803SRobert Watson element_temp = elementlist; \ 423f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 424f7b951a8SRobert Watson if (element_name[0] == '?') { \ 425f7b951a8SRobert Watson element_name++; \ 426f7b951a8SRobert Watson ignorenotfound = 1; \ 427f7b951a8SRobert Watson } else \ 428f7b951a8SRobert Watson ignorenotfound = 0; \ 429f51e5803SRobert Watson savedlen = sbuf_len(&sb); \ 43086ea834cSRobert Watson if (first) \ 431f51e5803SRobert Watson error = sbuf_printf(&sb, "%s/", element_name); \ 43286ea834cSRobert Watson else \ 433f51e5803SRobert Watson error = sbuf_printf(&sb, ",%s/", element_name); \ 434f51e5803SRobert Watson if (error == -1) { \ 435f51e5803SRobert Watson error = EINVAL; /* XXX: E2BIG? */ \ 436f7b951a8SRobert Watson break; \ 437f7b951a8SRobert Watson } \ 438f51e5803SRobert Watson claimed = 0; \ 439fa765671SRobert Watson MAC_POLICY_CHECK(type ## _externalize_label, label, \ 440da77b2faSRobert Watson element_name, &sb, &claimed); \ 441f7b951a8SRobert Watson if (error) \ 442f7b951a8SRobert Watson break; \ 443f51e5803SRobert Watson if (claimed == 0 && ignorenotfound) { \ 444f51e5803SRobert Watson /* Revert last label name. */ \ 445f51e5803SRobert Watson sbuf_setpos(&sb, savedlen); \ 446f51e5803SRobert Watson } else if (claimed != 1) { \ 447f51e5803SRobert Watson error = EINVAL; /* XXX: ENOLABEL? */ \ 448f7b951a8SRobert Watson break; \ 44986ea834cSRobert Watson } else { \ 45086ea834cSRobert Watson first = 0; \ 451f7b951a8SRobert Watson } \ 452f7b951a8SRobert Watson } \ 453f51e5803SRobert Watson sbuf_finish(&sb); \ 454f7b951a8SRobert Watson } while (0) 455f7b951a8SRobert Watson 4565c5a9819SRobert Watson /* 457fa765671SRobert Watson * MAC_POLICY_INTERNALIZE presents parsed element names and data to each 458fa765671SRobert Watson * policy to see if any is willing to claim it and internalize the label 459fa765671SRobert Watson * data. If no policies match, an error is returned. 4605c5a9819SRobert Watson */ 461fa765671SRobert Watson #define MAC_POLICY_INTERNALIZE(type, label, instring) do { \ 462f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 463f7b951a8SRobert Watson int claimed; \ 464f7b951a8SRobert Watson \ 465f7b951a8SRobert Watson error = 0; \ 466f7b951a8SRobert Watson element = instring; \ 467f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 468f7b951a8SRobert Watson element_data = element_name; \ 469f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 470f7b951a8SRobert Watson if (element_data == NULL) { \ 471f7b951a8SRobert Watson error = EINVAL; \ 472f7b951a8SRobert Watson break; \ 473f7b951a8SRobert Watson } \ 474f7b951a8SRobert Watson claimed = 0; \ 475fa765671SRobert Watson MAC_POLICY_CHECK(type ## _internalize_label, label, \ 476da77b2faSRobert Watson element_name, element_data, &claimed); \ 477f7b951a8SRobert Watson if (error) \ 478f7b951a8SRobert Watson break; \ 479f7b951a8SRobert Watson if (claimed != 1) { \ 480f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 481f7b951a8SRobert Watson error = EINVAL; \ 482f7b951a8SRobert Watson break; \ 483f7b951a8SRobert Watson } \ 484f7b951a8SRobert Watson } \ 485f7b951a8SRobert Watson } while (0) 486f7b951a8SRobert Watson 48795fab37eSRobert Watson /* 488fa765671SRobert Watson * MAC_POLICY_PERFORM performs the designated operation by walking the policy 489fa765671SRobert Watson * module list and invoking that operation for each policy. 49095fab37eSRobert Watson */ 491fa765671SRobert Watson #define MAC_POLICY_PERFORM(operation, args...) do { \ 49295fab37eSRobert Watson struct mac_policy_conf *mpc; \ 49395fab37eSRobert Watson \ 49441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 49541a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 49641a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 49741a17fe3SRobert Watson } \ 49840202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 49940202729SRobert Watson mac_policy_slock_sleep(); \ 50095fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 50195fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 50295fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 50395fab37eSRobert Watson } \ 50440202729SRobert Watson mac_policy_sunlock_sleep(); \ 50540202729SRobert Watson } \ 50640202729SRobert Watson } while (0) 50740202729SRobert Watson 508fa765671SRobert Watson #define MAC_POLICY_PERFORM_NOSLEEP(operation, args...) do { \ 50940202729SRobert Watson struct mac_policy_conf *mpc; \ 51040202729SRobert Watson \ 51140202729SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 51240202729SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 51340202729SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 51440202729SRobert Watson } \ 51540202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { \ 51681fee06fSRobert Watson struct rm_priotracker tracker; \ 51781fee06fSRobert Watson \ 51881fee06fSRobert Watson mac_policy_slock_nosleep(&tracker); \ 51940202729SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 52040202729SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 52140202729SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 52240202729SRobert Watson } \ 52381fee06fSRobert Watson mac_policy_sunlock_nosleep(&tracker); \ 52441a17fe3SRobert Watson } \ 52595fab37eSRobert Watson } while (0) 526d02188c1SRobert Watson 527646a9f80SRobert Watson #endif /* !_SECURITY_MAC_MAC_INTERNAL_H_ */ 528