mac_internal.h revision 172930
1/*- 2 * Copyright (c) 1999-2002, 2006 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 5 * Copyright (c) 2006 nCircle Network Security, Inc. 6 * Copyright (c) 2006 SPARTA, Inc. 7 * All rights reserved. 8 * 9 * This software was developed by Robert Watson and Ilmar Habibulin for the 10 * TrustedBSD Project. 11 * 12 * This software was developed for the FreeBSD Project in part by Network 13 * Associates Laboratories, the Security Research Division of Network 14 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 15 * as part of the DARPA CHATS research program. 16 * 17 * This software was developed by Robert N. M. Watson for the TrustedBSD 18 * Project under contract to nCircle Network Security, Inc. 19 * 20 * This software was enhanced by SPARTA ISSO under SPAWAR contract 21 * N66001-04-C-6019 ("SEFOS"). 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * $FreeBSD: head/sys/security/mac/mac_internal.h 172930 2007-10-24 19:04:04Z rwatson $ 45 */ 46 47#ifndef _SYS_SECURITY_MAC_MAC_INTERNAL_H_ 48#define _SYS_SECURITY_MAC_MAC_INTERNAL_H_ 49 50#ifndef _KERNEL 51#error "no user-serviceable parts inside" 52#endif 53 54/* 55 * MAC Framework sysctl namespace. 56 */ 57#ifdef SYSCTL_DECL 58SYSCTL_DECL(_security_mac); 59#endif /* SYSCTL_DECL */ 60 61/* 62 * MAC Framework global types and typedefs. 63 */ 64LIST_HEAD(mac_policy_list_head, mac_policy_conf); 65#ifdef MALLOC_DECLARE 66MALLOC_DECLARE(M_MACTEMP); 67#endif 68 69/* 70 * MAC labels -- in-kernel storage format. 71 * 72 * In general, struct label pointers are embedded in kernel data structures 73 * representing objects that may be labeled (and protected). Struct label is 74 * opaque to both kernel services that invoke the MAC Framework and MAC 75 * policy modules. In particular, we do not wish to encode the layout of the 76 * label structure into any ABIs. Historically, the slot array contained 77 * unions of {long, void} but now contains uintptr_t. 78 */ 79#define MAC_MAX_SLOTS 4 80#define MAC_FLAG_INITIALIZED 0x0000001 /* Is initialized for use. */ 81struct label { 82 int l_flags; 83 intptr_t l_perpolicy[MAC_MAX_SLOTS]; 84}; 85 86/* 87 * MAC Framework global variables. 88 */ 89extern struct mac_policy_list_head mac_policy_list; 90extern struct mac_policy_list_head mac_static_policy_list; 91#ifndef MAC_ALWAYS_LABEL_MBUF 92extern int mac_labelmbufs; 93#endif 94 95/* 96 * MAC Framework infrastructure functions. 97 */ 98int mac_error_select(int error1, int error2); 99 100void mac_policy_grab_exclusive(void); 101void mac_policy_assert_exclusive(void); 102void mac_policy_release_exclusive(void); 103void mac_policy_list_busy(void); 104int mac_policy_list_conditional_busy(void); 105void mac_policy_list_unbusy(void); 106 107struct label *mac_labelzone_alloc(int flags); 108void mac_labelzone_free(struct label *label); 109void mac_labelzone_init(void); 110 111void mac_init_label(struct label *label); 112void mac_destroy_label(struct label *label); 113int mac_check_structmac_consistent(struct mac *mac); 114int mac_allocate_slot(void); 115 116/* 117 * MAC Framework per-object type functions. It's not yet clear how the 118 * namespaces, etc, should work for these, so for now, sort by object type. 119 */ 120struct label *mac_pipe_label_alloc(void); 121void mac_pipe_label_free(struct label *label); 122struct label *mac_socket_label_alloc(int flag); 123void mac_socket_label_free(struct label *label); 124 125int mac_cred_check_relabel(struct ucred *cred, struct label *newlabel); 126int mac_cred_externalize_label(struct label *label, char *elements, 127 char *outbuf, size_t outbuflen); 128int mac_cred_internalize_label(struct label *label, char *string); 129void mac_cred_relabel(struct ucred *cred, struct label *newlabel); 130 131struct label *mac_mbuf_to_label(struct mbuf *m); 132 133void mac_pipe_copy_label(struct label *src, struct label *dest); 134int mac_pipe_externalize_label(struct label *label, char *elements, 135 char *outbuf, size_t outbuflen); 136int mac_pipe_internalize_label(struct label *label, char *string); 137 138int mac_socket_label_set(struct ucred *cred, struct socket *so, 139 struct label *label); 140void mac_socket_copy_label(struct label *src, struct label *dest); 141int mac_socket_externalize_label(struct label *label, char *elements, 142 char *outbuf, size_t outbuflen); 143int mac_socket_internalize_label(struct label *label, char *string); 144 145int mac_vnode_externalize_label(struct label *label, char *elements, 146 char *outbuf, size_t outbuflen); 147int mac_vnode_internalize_label(struct label *label, char *string); 148void mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 149 int *prot); 150int vn_setlabel(struct vnode *vp, struct label *intlabel, 151 struct ucred *cred); 152 153/* 154 * MAC_CHECK performs the designated check by walking the policy module list 155 * and checking with each as to how it feels about the request. Note that it 156 * returns its value via 'error' in the scope of the caller. 157 */ 158#define MAC_CHECK(check, args...) do { \ 159 struct mac_policy_conf *mpc; \ 160 int entrycount; \ 161 \ 162 error = 0; \ 163 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 164 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 165 error = mac_error_select( \ 166 mpc->mpc_ops->mpo_ ## check (args), \ 167 error); \ 168 } \ 169 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 170 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 171 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 172 error = mac_error_select( \ 173 mpc->mpc_ops->mpo_ ## check (args), \ 174 error); \ 175 } \ 176 mac_policy_list_unbusy(); \ 177 } \ 178} while (0) 179 180/* 181 * MAC_GRANT performs the designated check by walking the policy module list 182 * and checking with each as to how it feels about the request. Unlike 183 * MAC_CHECK, it grants if any policies return '0', and otherwise returns 184 * EPERM. Note that it returns its value via 'error' in the scope of the 185 * caller. 186 */ 187#define MAC_GRANT(check, args...) do { \ 188 struct mac_policy_conf *mpc; \ 189 int entrycount; \ 190 \ 191 error = EPERM; \ 192 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 193 if (mpc->mpc_ops->mpo_ ## check != NULL) { \ 194 if (mpc->mpc_ops->mpo_ ## check(args) == 0) \ 195 error = 0; \ 196 } \ 197 } \ 198 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 199 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 200 if (mpc->mpc_ops->mpo_ ## check != NULL) { \ 201 if (mpc->mpc_ops->mpo_ ## check (args) \ 202 == 0) \ 203 error = 0; \ 204 } \ 205 } \ 206 mac_policy_list_unbusy(); \ 207 } \ 208} while (0) 209 210/* 211 * MAC_BOOLEAN performs the designated boolean composition by walking the 212 * module list, invoking each instance of the operation, and combining the 213 * results using the passed C operator. Note that it returns its value via 214 * 'result' in the scope of the caller, which should be initialized by the 215 * caller in a meaningful way to get a meaningful result. 216 */ 217#define MAC_BOOLEAN(operation, composition, args...) do { \ 218 struct mac_policy_conf *mpc; \ 219 int entrycount; \ 220 \ 221 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 222 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 223 result = result composition \ 224 mpc->mpc_ops->mpo_ ## operation (args); \ 225 } \ 226 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 227 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 228 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 229 result = result composition \ 230 mpc->mpc_ops->mpo_ ## operation \ 231 (args); \ 232 } \ 233 mac_policy_list_unbusy(); \ 234 } \ 235} while (0) 236 237/* 238 * MAC_EXTERNALIZE queries each policy to see if it can generate an 239 * externalized version of a label element by name. Policies declare whether 240 * they have matched a particular element name, parsed from the string by 241 * MAC_EXTERNALIZE, and an error is returned if any element is matched by no 242 * policy. 243 */ 244#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 245 outbuflen) do { \ 246 int claimed, first, ignorenotfound, savedlen; \ 247 char *element_name, *element_temp; \ 248 struct sbuf sb; \ 249 \ 250 error = 0; \ 251 first = 1; \ 252 sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \ 253 element_temp = elementlist; \ 254 while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 255 if (element_name[0] == '?') { \ 256 element_name++; \ 257 ignorenotfound = 1; \ 258 } else \ 259 ignorenotfound = 0; \ 260 savedlen = sbuf_len(&sb); \ 261 if (first) \ 262 error = sbuf_printf(&sb, "%s/", element_name); \ 263 else \ 264 error = sbuf_printf(&sb, ",%s/", element_name); \ 265 if (error == -1) { \ 266 error = EINVAL; /* XXX: E2BIG? */ \ 267 break; \ 268 } \ 269 claimed = 0; \ 270 MAC_CHECK(type ## _externalize_label, label, \ 271 element_name, &sb, &claimed); \ 272 if (error) \ 273 break; \ 274 if (claimed == 0 && ignorenotfound) { \ 275 /* Revert last label name. */ \ 276 sbuf_setpos(&sb, savedlen); \ 277 } else if (claimed != 1) { \ 278 error = EINVAL; /* XXX: ENOLABEL? */ \ 279 break; \ 280 } else { \ 281 first = 0; \ 282 } \ 283 } \ 284 sbuf_finish(&sb); \ 285} while (0) 286 287/* 288 * MAC_INTERNALIZE presents parsed element names and data to each policy to 289 * see if any is willing to claim it and internalize the label data. If no 290 * policies match, an error is returned. 291 */ 292#define MAC_INTERNALIZE(type, label, instring) do { \ 293 char *element, *element_name, *element_data; \ 294 int claimed; \ 295 \ 296 error = 0; \ 297 element = instring; \ 298 while ((element_name = strsep(&element, ",")) != NULL) { \ 299 element_data = element_name; \ 300 element_name = strsep(&element_data, "/"); \ 301 if (element_data == NULL) { \ 302 error = EINVAL; \ 303 break; \ 304 } \ 305 claimed = 0; \ 306 MAC_CHECK(type ## _internalize_label, label, \ 307 element_name, element_data, &claimed); \ 308 if (error) \ 309 break; \ 310 if (claimed != 1) { \ 311 /* XXXMAC: Another error here? */ \ 312 error = EINVAL; \ 313 break; \ 314 } \ 315 } \ 316} while (0) 317 318/* 319 * MAC_PERFORM performs the designated operation by walking the policy module 320 * list and invoking that operation for each policy. 321 */ 322#define MAC_PERFORM(operation, args...) do { \ 323 struct mac_policy_conf *mpc; \ 324 int entrycount; \ 325 \ 326 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 327 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 328 mpc->mpc_ops->mpo_ ## operation (args); \ 329 } \ 330 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 331 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 332 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 333 mpc->mpc_ops->mpo_ ## operation (args); \ 334 } \ 335 mac_policy_list_unbusy(); \ 336 } \ 337} while (0) 338 339#endif /* !_SYS_SECURITY_MAC_MAC_INTERNAL_H_ */ 340