]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/security/mac/mac_syscalls.c
Slightly change the semantics of vnode labels for MAC: rather than
[FreeBSD/FreeBSD.git] / sys / security / mac / mac_syscalls.c
1 /*-
2  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5  * All rights reserved.
6  *
7  * This software was developed by Robert Watson and Ilmar Habibulin for the
8  * TrustedBSD Project.
9  *
10  * This software was developed for the FreeBSD Project in part by NAI Labs,
11  * the Security Research Division of Network Associates, Inc. under
12  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
13  * CHATS research program.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. The names of the authors may not be used to endorse or promote
24  *    products derived from this software without specific prior written
25  *    permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * $FreeBSD$
40  */
41 /*
42  * Developed by the TrustedBSD Project.
43  *
44  * Framework for extensible kernel access control.  Kernel and userland
45  * interface to the framework, policy registration and composition.
46  */
47
48 #include "opt_mac.h"
49 #include "opt_devfs.h"
50
51 #include <sys/param.h>
52 #include <sys/extattr.h>
53 #include <sys/kernel.h>
54 #include <sys/lock.h>
55 #include <sys/malloc.h>
56 #include <sys/mutex.h>
57 #include <sys/mac.h>
58 #include <sys/module.h>
59 #include <sys/proc.h>
60 #include <sys/systm.h>
61 #include <sys/sysproto.h>
62 #include <sys/sysent.h>
63 #include <sys/vnode.h>
64 #include <sys/mount.h>
65 #include <sys/file.h>
66 #include <sys/namei.h>
67 #include <sys/socket.h>
68 #include <sys/pipe.h>
69 #include <sys/socketvar.h>
70 #include <sys/sysctl.h>
71
72 #include <vm/vm.h>
73 #include <vm/pmap.h>
74 #include <vm/vm_map.h>
75 #include <vm/vm_object.h>
76
77 #include <sys/mac_policy.h>
78
79 #include <fs/devfs/devfs.h>
80
81 #include <net/bpfdesc.h>
82 #include <net/if.h>
83 #include <net/if_var.h>
84
85 #include <netinet/in.h>
86 #include <netinet/ip_var.h>
87
88 #ifdef MAC
89
90 /*
91  * Declare that the kernel provides MAC support, version 1.  This permits
92  * modules to refuse to be loaded if the necessary support isn't present,
93  * even if it's pre-boot.
94  */
95 MODULE_VERSION(kernel_mac_support, 1);
96
97 SYSCTL_DECL(_security);
98
99 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100     "TrustedBSD MAC policy controls");
101
102 #if MAC_MAX_POLICIES > 32
103 #error "MAC_MAX_POLICIES too large"
104 #endif
105
106 static unsigned int mac_max_policies = MAC_MAX_POLICIES;
107 static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
108 SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
109     &mac_max_policies, 0, "");
110
111 /*
112  * Has the kernel started generating labeled objects yet?  All read/write
113  * access to this variable is serialized during the boot process.  Following
114  * the end of serialization, we don't update this flag; no locking.
115  */
116 static int      mac_late = 0;
117
118 /*
119  * Warn about EA transactions only the first time they happen.
120  * Weak coherency, no locking.
121  */
122 static int      ea_warn_once = 0;
123
124 static int      mac_enforce_fs = 1;
125 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
126     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
127 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
128
129 static int      mac_enforce_network = 1;
130 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
131     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
132 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
133
134 static int      mac_enforce_pipe = 1;
135 SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
136     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
137 TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
138
139 static int      mac_enforce_process = 1;
140 SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
141     &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
142 TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
143
144 static int      mac_enforce_socket = 1;
145 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
146     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
147 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
148
149 static int     mac_enforce_vm = 1;
150 SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
151     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
152 TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
153
154 static int      mac_cache_fslabel_in_vnode = 1;
155 SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
156     &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
157 TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
158     &mac_cache_fslabel_in_vnode);
159
160 static int      mac_mmap_revocation = 1;
161 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
162     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
163     "relabel");
164 static int      mac_mmap_revocation_via_cow = 0;
165 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
166     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
167     "copy-on-write semantics, or by removing all write access");
168
169 #ifdef MAC_DEBUG
170 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
171     "TrustedBSD MAC debug info");
172
173 static int      mac_debug_label_fallback = 0;
174 SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
175     &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
176     "when label is corrupted.");
177 TUNABLE_INT("security.mac.debug_label_fallback",
178     &mac_debug_label_fallback);
179
180 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
181     "TrustedBSD MAC object counters");
182
183 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
184     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
185     nmacipqs, nmacpipes;
186
187 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
188     &nmacmbufs, 0, "number of mbufs in use");
189 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
190     &nmaccreds, 0, "number of ucreds in use");
191 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
192     &nmacifnets, 0, "number of ifnets in use");
193 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
194     &nmacipqs, 0, "number of ipqs in use");
195 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
196     &nmacbpfdescs, 0, "number of bpfdescs in use");
197 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
198     &nmacsockets, 0, "number of sockets in use");
199 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
200     &nmacpipes, 0, "number of pipes in use");
201 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
202     &nmacmounts, 0, "number of mounts in use");
203 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
204     &nmactemp, 0, "number of temporary labels in use");
205 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
206     &nmacvnodes, 0, "number of vnodes in use");
207 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
208     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
209 #endif
210
211 static int      error_select(int error1, int error2);
212 static int      mac_policy_register(struct mac_policy_conf *mpc);
213 static int      mac_policy_unregister(struct mac_policy_conf *mpc);
214
215 static void     mac_check_vnode_mmap_downgrade(struct ucred *cred,
216                     struct vnode *vp, int *prot);
217 static void     mac_cred_mmapped_drop_perms_recurse(struct thread *td,
218                     struct ucred *cred, struct vm_map *map);
219
220 static void     mac_destroy_socket_label(struct label *label);
221
222 static int      mac_setlabel_vnode_extattr(struct ucred *cred,
223                     struct vnode *vp, struct label *intlabel);
224
225
226 MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
227 MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
228 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
229
230 /*
231  * mac_policy_list_lock protects the consistency of 'mac_policy_list',
232  * the linked list of attached policy modules.  Read-only consumers of
233  * the list must acquire a shared lock for the duration of their use;
234  * writers must acquire an exclusive lock.  Note that for compound
235  * operations, locks should be held for the entire compound operation,
236  * and that this is not yet done for relabel requests.
237  */
238 static struct mtx mac_policy_list_lock;
239 static LIST_HEAD(, mac_policy_conf) mac_policy_list;
240 static int mac_policy_list_busy;
241 #define MAC_POLICY_LIST_LOCKINIT()      mtx_init(&mac_policy_list_lock, \
242         "mac_policy_list_lock", NULL, MTX_DEF);
243 #define MAC_POLICY_LIST_LOCK()  mtx_lock(&mac_policy_list_lock);
244 #define MAC_POLICY_LIST_UNLOCK()        mtx_unlock(&mac_policy_list_lock);
245
246 #define MAC_POLICY_LIST_BUSY() do {                                     \
247         MAC_POLICY_LIST_LOCK();                                         \
248         mac_policy_list_busy++;                                         \
249         MAC_POLICY_LIST_UNLOCK();                                       \
250 } while (0)
251
252 #define MAC_POLICY_LIST_UNBUSY() do {                                   \
253         MAC_POLICY_LIST_LOCK();                                         \
254         mac_policy_list_busy--;                                         \
255         if (mac_policy_list_busy < 0)                                   \
256                 panic("Extra mac_policy_list_busy--");                  \
257         MAC_POLICY_LIST_UNLOCK();                                       \
258 } while (0)
259
260 /*
261  * MAC_CHECK performs the designated check by walking the policy
262  * module list and checking with each as to how it feels about the
263  * request.  Note that it returns its value via 'error' in the scope
264  * of the caller.
265  */
266 #define MAC_CHECK(check, args...) do {                                  \
267         struct mac_policy_conf *mpc;                                    \
268                                                                         \
269         error = 0;                                                      \
270         MAC_POLICY_LIST_BUSY();                                         \
271         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
272                 if (mpc->mpc_ops->mpo_ ## check != NULL)                \
273                         error = error_select(                           \
274                             mpc->mpc_ops->mpo_ ## check (args),         \
275                             error);                                     \
276         }                                                               \
277         MAC_POLICY_LIST_UNBUSY();                                       \
278 } while (0)
279
280 /*
281  * MAC_BOOLEAN performs the designated boolean composition by walking
282  * the module list, invoking each instance of the operation, and
283  * combining the results using the passed C operator.  Note that it
284  * returns its value via 'result' in the scope of the caller, which
285  * should be initialized by the caller in a meaningful way to get
286  * a meaningful result.
287  */
288 #define MAC_BOOLEAN(operation, composition, args...) do {               \
289         struct mac_policy_conf *mpc;                                    \
290                                                                         \
291         MAC_POLICY_LIST_BUSY();                                         \
292         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
293                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
294                         result = result composition                     \
295                             mpc->mpc_ops->mpo_ ## operation (args);     \
296         }                                                               \
297         MAC_POLICY_LIST_UNBUSY();                                       \
298 } while (0)
299
300 #define MAC_EXTERNALIZE(type, label, elementlist, outbuf,               \
301     outbuflen) do {                                                     \
302         char *curptr, *curptr_start, *element_name, *element_temp;      \
303         size_t left, left_start, len;                                   \
304         int claimed, first, first_start, ignorenotfound;                \
305                                                                         \
306         error = 0;                                                      \
307         element_temp = elementlist;                                     \
308         curptr = outbuf;                                                \
309         curptr[0] = '\0';                                               \
310         left = outbuflen;                                               \
311         first = 1;                                                      \
312         while ((element_name = strsep(&element_temp, ",")) != NULL) {   \
313                 curptr_start = curptr;                                  \
314                 left_start = left;                                      \
315                 first_start = first;                                    \
316                 if (element_name[0] == '?') {                           \
317                         element_name++;                                 \
318                         ignorenotfound = 1;                             \
319                 } else                                                  \
320                         ignorenotfound = 0;                             \
321                 claimed = 0;                                            \
322                 if (first) {                                            \
323                         len = snprintf(curptr, left, "%s/",             \
324                             element_name);                              \
325                         first = 0;                                      \
326                 } else                                                  \
327                         len = snprintf(curptr, left, ",%s/",            \
328                             element_name);                              \
329                 if (len >= left) {                                      \
330                         error = EINVAL;         /* XXXMAC: E2BIG */     \
331                         break;                                          \
332                 }                                                       \
333                 curptr += len;                                          \
334                 left -= len;                                            \
335                                                                         \
336                 MAC_CHECK(externalize_ ## type, label, element_name,    \
337                     curptr, left, &len, &claimed);                      \
338                 if (error)                                              \
339                         break;                                          \
340                 if (claimed == 1) {                                     \
341                         if (len >= outbuflen) {                         \
342                                 error = EINVAL; /* XXXMAC: E2BIG */     \
343                                 break;                                  \
344                         }                                               \
345                         curptr += len;                                  \
346                         left -= len;                                    \
347                 } else if (claimed == 0 && ignorenotfound) {            \
348                         /*                                              \
349                          * Revert addition of the label element         \
350                          * name.                                        \
351                          */                                             \
352                         curptr = curptr_start;                          \
353                         *curptr = '\0';                                 \
354                         left = left_start;                              \
355                         first = first_start;                            \
356                 } else {                                                \
357                         error = EINVAL;         /* XXXMAC: ENOLABEL */  \
358                         break;                                          \
359                 }                                                       \
360         }                                                               \
361 } while (0)
362
363 #define MAC_INTERNALIZE(type, label, instring) do {                     \
364         char *element, *element_name, *element_data;                    \
365         int claimed;                                                    \
366                                                                         \
367         error = 0;                                                      \
368         element = instring;                                             \
369         while ((element_name = strsep(&element, ",")) != NULL) {        \
370                 element_data = element_name;                            \
371                 element_name = strsep(&element_data, "/");              \
372                 if (element_data == NULL) {                             \
373                         error = EINVAL;                                 \
374                         break;                                          \
375                 }                                                       \
376                 claimed = 0;                                            \
377                 MAC_CHECK(internalize_ ## type, label, element_name,    \
378                     element_data, &claimed);                            \
379                 if (error)                                              \
380                         break;                                          \
381                 if (claimed != 1) {                                     \
382                         /* XXXMAC: Another error here? */               \
383                         error = EINVAL;                                 \
384                         break;                                          \
385                 }                                                       \
386         }                                                               \
387 } while (0)
388
389 /*
390  * MAC_PERFORM performs the designated operation by walking the policy
391  * module list and invoking that operation for each policy.
392  */
393 #define MAC_PERFORM(operation, args...) do {                            \
394         struct mac_policy_conf *mpc;                                    \
395                                                                         \
396         MAC_POLICY_LIST_BUSY();                                         \
397         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
398                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
399                         mpc->mpc_ops->mpo_ ## operation (args);         \
400         }                                                               \
401         MAC_POLICY_LIST_UNBUSY();                                       \
402 } while (0)
403
404 /*
405  * Initialize the MAC subsystem, including appropriate SMP locks.
406  */
407 static void
408 mac_init(void)
409 {
410
411         LIST_INIT(&mac_policy_list);
412         MAC_POLICY_LIST_LOCKINIT();
413 }
414
415 /*
416  * For the purposes of modules that want to know if they were loaded
417  * "early", set the mac_late flag once we've processed modules either
418  * linked into the kernel, or loaded before the kernel startup.
419  */
420 static void
421 mac_late_init(void)
422 {
423
424         mac_late = 1;
425 }
426
427 /*
428  * Allow MAC policy modules to register during boot, etc.
429  */
430 int
431 mac_policy_modevent(module_t mod, int type, void *data)
432 {
433         struct mac_policy_conf *mpc;
434         int error;
435
436         error = 0;
437         mpc = (struct mac_policy_conf *) data;
438
439         switch (type) {
440         case MOD_LOAD:
441                 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
442                     mac_late) {
443                         printf("mac_policy_modevent: can't load %s policy "
444                             "after booting\n", mpc->mpc_name);
445                         error = EBUSY;
446                         break;
447                 }
448                 error = mac_policy_register(mpc);
449                 break;
450         case MOD_UNLOAD:
451                 /* Don't unregister the module if it was never registered. */
452                 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
453                     != 0)
454                         error = mac_policy_unregister(mpc);
455                 else
456                         error = 0;
457                 break;
458         default:
459                 break;
460         }
461
462         return (error);
463 }
464
465 static int
466 mac_policy_register(struct mac_policy_conf *mpc)
467 {
468         struct mac_policy_conf *tmpc;
469         struct mac_policy_op_entry *mpe;
470         int slot;
471
472         MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops),
473             M_MACOPVEC, M_WAITOK | M_ZERO);
474         for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
475                 switch (mpe->mpe_constant) {
476                 case MAC_OP_LAST:
477                         /*
478                          * Doesn't actually happen, but this allows checking
479                          * that all enumerated values are handled.
480                          */
481                         break;
482                 case MAC_DESTROY:
483                         mpc->mpc_ops->mpo_destroy =
484                             mpe->mpe_function;
485                         break;
486                 case MAC_INIT:
487                         mpc->mpc_ops->mpo_init =
488                             mpe->mpe_function;
489                         break;
490                 case MAC_SYSCALL:
491                         mpc->mpc_ops->mpo_syscall =
492                             mpe->mpe_function;
493                         break;
494                 case MAC_INIT_BPFDESC_LABEL:
495                         mpc->mpc_ops->mpo_init_bpfdesc_label =
496                             mpe->mpe_function;
497                         break;
498                 case MAC_INIT_CRED_LABEL:
499                         mpc->mpc_ops->mpo_init_cred_label =
500                             mpe->mpe_function;
501                         break;
502                 case MAC_INIT_DEVFSDIRENT_LABEL:
503                         mpc->mpc_ops->mpo_init_devfsdirent_label =
504                             mpe->mpe_function;
505                         break;
506                 case MAC_INIT_IFNET_LABEL:
507                         mpc->mpc_ops->mpo_init_ifnet_label =
508                             mpe->mpe_function;
509                         break;
510                 case MAC_INIT_IPQ_LABEL:
511                         mpc->mpc_ops->mpo_init_ipq_label =
512                             mpe->mpe_function;
513                         break;
514                 case MAC_INIT_MBUF_LABEL:
515                         mpc->mpc_ops->mpo_init_mbuf_label =
516                             mpe->mpe_function;
517                         break;
518                 case MAC_INIT_MOUNT_LABEL:
519                         mpc->mpc_ops->mpo_init_mount_label =
520                             mpe->mpe_function;
521                         break;
522                 case MAC_INIT_MOUNT_FS_LABEL:
523                         mpc->mpc_ops->mpo_init_mount_fs_label =
524                             mpe->mpe_function;
525                         break;
526                 case MAC_INIT_PIPE_LABEL:
527                         mpc->mpc_ops->mpo_init_pipe_label =
528                             mpe->mpe_function;
529                         break;
530                 case MAC_INIT_SOCKET_LABEL:
531                         mpc->mpc_ops->mpo_init_socket_label =
532                             mpe->mpe_function;
533                         break;
534                 case MAC_INIT_SOCKET_PEER_LABEL:
535                         mpc->mpc_ops->mpo_init_socket_peer_label =
536                             mpe->mpe_function;
537                         break;
538                 case MAC_INIT_VNODE_LABEL:
539                         mpc->mpc_ops->mpo_init_vnode_label =
540                             mpe->mpe_function;
541                         break;
542                 case MAC_DESTROY_BPFDESC_LABEL:
543                         mpc->mpc_ops->mpo_destroy_bpfdesc_label =
544                             mpe->mpe_function;
545                         break;
546                 case MAC_DESTROY_CRED_LABEL:
547                         mpc->mpc_ops->mpo_destroy_cred_label =
548                             mpe->mpe_function;
549                         break;
550                 case MAC_DESTROY_DEVFSDIRENT_LABEL:
551                         mpc->mpc_ops->mpo_destroy_devfsdirent_label =
552                             mpe->mpe_function;
553                         break;
554                 case MAC_DESTROY_IFNET_LABEL:
555                         mpc->mpc_ops->mpo_destroy_ifnet_label =
556                             mpe->mpe_function;
557                         break;
558                 case MAC_DESTROY_IPQ_LABEL:
559                         mpc->mpc_ops->mpo_destroy_ipq_label =
560                             mpe->mpe_function;
561                         break;
562                 case MAC_DESTROY_MBUF_LABEL:
563                         mpc->mpc_ops->mpo_destroy_mbuf_label =
564                             mpe->mpe_function;
565                         break;
566                 case MAC_DESTROY_MOUNT_LABEL:
567                         mpc->mpc_ops->mpo_destroy_mount_label =
568                             mpe->mpe_function;
569                         break;
570                 case MAC_DESTROY_MOUNT_FS_LABEL:
571                         mpc->mpc_ops->mpo_destroy_mount_fs_label =
572                             mpe->mpe_function;
573                         break;
574                 case MAC_DESTROY_PIPE_LABEL:
575                         mpc->mpc_ops->mpo_destroy_pipe_label =
576                             mpe->mpe_function;
577                         break;
578                 case MAC_DESTROY_SOCKET_LABEL:
579                         mpc->mpc_ops->mpo_destroy_socket_label =
580                             mpe->mpe_function;
581                         break;
582                 case MAC_DESTROY_SOCKET_PEER_LABEL:
583                         mpc->mpc_ops->mpo_destroy_socket_peer_label =
584                             mpe->mpe_function;
585                         break;
586                 case MAC_DESTROY_VNODE_LABEL:
587                         mpc->mpc_ops->mpo_destroy_vnode_label =
588                             mpe->mpe_function;
589                         break;
590                 case MAC_COPY_PIPE_LABEL:
591                         mpc->mpc_ops->mpo_copy_pipe_label =
592                             mpe->mpe_function;
593                         break;
594                 case MAC_COPY_VNODE_LABEL:
595                         mpc->mpc_ops->mpo_copy_vnode_label =
596                             mpe->mpe_function;
597                         break;
598                 case MAC_EXTERNALIZE_CRED_LABEL:
599                         mpc->mpc_ops->mpo_externalize_cred_label =
600                             mpe->mpe_function;
601                         break;
602                 case MAC_EXTERNALIZE_IFNET_LABEL:
603                         mpc->mpc_ops->mpo_externalize_ifnet_label =
604                             mpe->mpe_function;
605                         break;
606                 case MAC_EXTERNALIZE_PIPE_LABEL:
607                         mpc->mpc_ops->mpo_externalize_pipe_label =
608                             mpe->mpe_function;
609                         break;
610                 case MAC_EXTERNALIZE_SOCKET_LABEL:
611                         mpc->mpc_ops->mpo_externalize_socket_label =
612                             mpe->mpe_function;
613                         break;
614                 case MAC_EXTERNALIZE_SOCKET_PEER_LABEL:
615                         mpc->mpc_ops->mpo_externalize_socket_peer_label =
616                             mpe->mpe_function;
617                         break;
618                 case MAC_EXTERNALIZE_VNODE_LABEL:
619                         mpc->mpc_ops->mpo_externalize_vnode_label =
620                             mpe->mpe_function;
621                         break;
622                 case MAC_INTERNALIZE_CRED_LABEL:
623                         mpc->mpc_ops->mpo_internalize_cred_label =
624                             mpe->mpe_function;
625                         break;
626                 case MAC_INTERNALIZE_IFNET_LABEL:
627                         mpc->mpc_ops->mpo_internalize_ifnet_label =
628                             mpe->mpe_function;
629                         break;
630                 case MAC_INTERNALIZE_PIPE_LABEL:
631                         mpc->mpc_ops->mpo_internalize_pipe_label =
632                             mpe->mpe_function;
633                         break;
634                 case MAC_INTERNALIZE_SOCKET_LABEL:
635                         mpc->mpc_ops->mpo_internalize_socket_label =
636                             mpe->mpe_function;
637                         break;
638                 case MAC_INTERNALIZE_VNODE_LABEL:
639                         mpc->mpc_ops->mpo_internalize_vnode_label =
640                             mpe->mpe_function;
641                         break;
642                 case MAC_CREATE_DEVFS_DEVICE:
643                         mpc->mpc_ops->mpo_create_devfs_device =
644                             mpe->mpe_function;
645                         break;
646                 case MAC_CREATE_DEVFS_DIRECTORY:
647                         mpc->mpc_ops->mpo_create_devfs_directory =
648                             mpe->mpe_function;
649                         break;
650                 case MAC_CREATE_DEVFS_SYMLINK:
651                         mpc->mpc_ops->mpo_create_devfs_symlink =
652                             mpe->mpe_function;
653                         break;
654                 case MAC_CREATE_DEVFS_VNODE:
655                         mpc->mpc_ops->mpo_create_devfs_vnode =
656                             mpe->mpe_function;
657                         break;
658                 case MAC_CREATE_MOUNT:
659                         mpc->mpc_ops->mpo_create_mount =
660                             mpe->mpe_function;
661                         break;
662                 case MAC_CREATE_ROOT_MOUNT:
663                         mpc->mpc_ops->mpo_create_root_mount =
664                             mpe->mpe_function;
665                         break;
666                 case MAC_RELABEL_VNODE:
667                         mpc->mpc_ops->mpo_relabel_vnode =
668                             mpe->mpe_function;
669                         break;
670                 case MAC_UPDATE_DEVFSDIRENT:
671                         mpc->mpc_ops->mpo_update_devfsdirent =
672                             mpe->mpe_function;
673                         break;
674                 case MAC_ASSOCIATE_VNODE_DEVFS:
675                         mpc->mpc_ops->mpo_associate_vnode_devfs =
676                             mpe->mpe_function;
677                         break;
678                 case MAC_ASSOCIATE_VNODE_EXTATTR:
679                         mpc->mpc_ops->mpo_associate_vnode_extattr =
680                             mpe->mpe_function;
681                         break;
682                 case MAC_ASSOCIATE_VNODE_SINGLELABEL:
683                         mpc->mpc_ops->mpo_associate_vnode_singlelabel =
684                             mpe->mpe_function;
685                         break;
686                 case MAC_CREATE_VNODE_EXTATTR:
687                         mpc->mpc_ops->mpo_create_vnode_extattr =
688                             mpe->mpe_function;
689                         break;
690                 case MAC_SETLABEL_VNODE_EXTATTR:
691                         mpc->mpc_ops->mpo_setlabel_vnode_extattr =
692                             mpe->mpe_function;
693                         break;
694                 case MAC_CREATE_MBUF_FROM_SOCKET:
695                         mpc->mpc_ops->mpo_create_mbuf_from_socket =
696                             mpe->mpe_function;
697                         break;
698                 case MAC_CREATE_PIPE:
699                         mpc->mpc_ops->mpo_create_pipe =
700                             mpe->mpe_function;
701                         break;
702                 case MAC_CREATE_SOCKET:
703                         mpc->mpc_ops->mpo_create_socket =
704                             mpe->mpe_function;
705                         break;
706                 case MAC_CREATE_SOCKET_FROM_SOCKET:
707                         mpc->mpc_ops->mpo_create_socket_from_socket =
708                             mpe->mpe_function;
709                         break;
710                 case MAC_RELABEL_PIPE:
711                         mpc->mpc_ops->mpo_relabel_pipe =
712                             mpe->mpe_function;
713                         break;
714                 case MAC_RELABEL_SOCKET:
715                         mpc->mpc_ops->mpo_relabel_socket =
716                             mpe->mpe_function;
717                         break;
718                 case MAC_SET_SOCKET_PEER_FROM_MBUF:
719                         mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
720                             mpe->mpe_function;
721                         break;
722                 case MAC_SET_SOCKET_PEER_FROM_SOCKET:
723                         mpc->mpc_ops->mpo_set_socket_peer_from_socket =
724                             mpe->mpe_function;
725                         break;
726                 case MAC_CREATE_BPFDESC:
727                         mpc->mpc_ops->mpo_create_bpfdesc =
728                             mpe->mpe_function;
729                         break;
730                 case MAC_CREATE_DATAGRAM_FROM_IPQ:
731                         mpc->mpc_ops->mpo_create_datagram_from_ipq =
732                             mpe->mpe_function;
733                         break;
734                 case MAC_CREATE_FRAGMENT:
735                         mpc->mpc_ops->mpo_create_fragment =
736                             mpe->mpe_function;
737                         break;
738                 case MAC_CREATE_IFNET:
739                         mpc->mpc_ops->mpo_create_ifnet =
740                             mpe->mpe_function;
741                         break;
742                 case MAC_CREATE_IPQ:
743                         mpc->mpc_ops->mpo_create_ipq =
744                             mpe->mpe_function;
745                         break;
746                 case MAC_CREATE_MBUF_FROM_MBUF:
747                         mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
748                             mpe->mpe_function;
749                         break;
750                 case MAC_CREATE_MBUF_LINKLAYER:
751                         mpc->mpc_ops->mpo_create_mbuf_linklayer =
752                             mpe->mpe_function;
753                         break;
754                 case MAC_CREATE_MBUF_FROM_BPFDESC:
755                         mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
756                             mpe->mpe_function;
757                         break;
758                 case MAC_CREATE_MBUF_FROM_IFNET:
759                         mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
760                             mpe->mpe_function;
761                         break;
762                 case MAC_CREATE_MBUF_MULTICAST_ENCAP:
763                         mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
764                             mpe->mpe_function;
765                         break;
766                 case MAC_CREATE_MBUF_NETLAYER:
767                         mpc->mpc_ops->mpo_create_mbuf_netlayer =
768                             mpe->mpe_function;
769                         break;
770                 case MAC_FRAGMENT_MATCH:
771                         mpc->mpc_ops->mpo_fragment_match =
772                             mpe->mpe_function;
773                         break;
774                 case MAC_RELABEL_IFNET:
775                         mpc->mpc_ops->mpo_relabel_ifnet =
776                             mpe->mpe_function;
777                         break;
778                 case MAC_UPDATE_IPQ:
779                         mpc->mpc_ops->mpo_update_ipq =
780                             mpe->mpe_function;
781                         break;
782                 case MAC_CREATE_CRED:
783                         mpc->mpc_ops->mpo_create_cred =
784                             mpe->mpe_function;
785                         break;
786                 case MAC_EXECVE_TRANSITION:
787                         mpc->mpc_ops->mpo_execve_transition =
788                             mpe->mpe_function;
789                         break;
790                 case MAC_EXECVE_WILL_TRANSITION:
791                         mpc->mpc_ops->mpo_execve_will_transition =
792                             mpe->mpe_function;
793                         break;
794                 case MAC_CREATE_PROC0:
795                         mpc->mpc_ops->mpo_create_proc0 =
796                             mpe->mpe_function;
797                         break;
798                 case MAC_CREATE_PROC1:
799                         mpc->mpc_ops->mpo_create_proc1 =
800                             mpe->mpe_function;
801                         break;
802                 case MAC_RELABEL_CRED:
803                         mpc->mpc_ops->mpo_relabel_cred =
804                             mpe->mpe_function;
805                         break;
806                 case MAC_THREAD_USERRET:
807                         mpc->mpc_ops->mpo_thread_userret =
808                             mpe->mpe_function;
809                         break;
810                 case MAC_CHECK_BPFDESC_RECEIVE:
811                         mpc->mpc_ops->mpo_check_bpfdesc_receive =
812                             mpe->mpe_function;
813                         break;
814                 case MAC_CHECK_CRED_RELABEL:
815                         mpc->mpc_ops->mpo_check_cred_relabel =
816                             mpe->mpe_function;
817                         break;
818                 case MAC_CHECK_CRED_VISIBLE:
819                         mpc->mpc_ops->mpo_check_cred_visible =
820                             mpe->mpe_function;
821                         break;
822                 case MAC_CHECK_IFNET_RELABEL:
823                         mpc->mpc_ops->mpo_check_ifnet_relabel =
824                             mpe->mpe_function;
825                         break;
826                 case MAC_CHECK_IFNET_TRANSMIT:
827                         mpc->mpc_ops->mpo_check_ifnet_transmit =
828                             mpe->mpe_function;
829                         break;
830                 case MAC_CHECK_MOUNT_STAT:
831                         mpc->mpc_ops->mpo_check_mount_stat =
832                             mpe->mpe_function;
833                         break;
834                 case MAC_CHECK_PIPE_IOCTL:
835                         mpc->mpc_ops->mpo_check_pipe_ioctl =
836                             mpe->mpe_function;
837                         break;
838                 case MAC_CHECK_PIPE_POLL:
839                         mpc->mpc_ops->mpo_check_pipe_poll =
840                             mpe->mpe_function;
841                         break;
842                 case MAC_CHECK_PIPE_READ:
843                         mpc->mpc_ops->mpo_check_pipe_read =
844                             mpe->mpe_function;
845                         break;
846                 case MAC_CHECK_PIPE_RELABEL:
847                         mpc->mpc_ops->mpo_check_pipe_relabel =
848                             mpe->mpe_function;
849                         break;
850                 case MAC_CHECK_PIPE_STAT:
851                         mpc->mpc_ops->mpo_check_pipe_stat =
852                             mpe->mpe_function;
853                         break;
854                 case MAC_CHECK_PIPE_WRITE:
855                         mpc->mpc_ops->mpo_check_pipe_write =
856                             mpe->mpe_function;
857                         break;
858                 case MAC_CHECK_PROC_DEBUG:
859                         mpc->mpc_ops->mpo_check_proc_debug =
860                             mpe->mpe_function;
861                         break;
862                 case MAC_CHECK_PROC_SCHED:
863                         mpc->mpc_ops->mpo_check_proc_sched =
864                             mpe->mpe_function;
865                         break;
866                 case MAC_CHECK_PROC_SIGNAL:
867                         mpc->mpc_ops->mpo_check_proc_signal =
868                             mpe->mpe_function;
869                         break;
870                 case MAC_CHECK_SOCKET_BIND:
871                         mpc->mpc_ops->mpo_check_socket_bind =
872                             mpe->mpe_function;
873                         break;
874                 case MAC_CHECK_SOCKET_CONNECT:
875                         mpc->mpc_ops->mpo_check_socket_connect =
876                             mpe->mpe_function;
877                         break;
878                 case MAC_CHECK_SOCKET_DELIVER:
879                         mpc->mpc_ops->mpo_check_socket_deliver =
880                             mpe->mpe_function;
881                         break;
882                 case MAC_CHECK_SOCKET_LISTEN:
883                         mpc->mpc_ops->mpo_check_socket_listen =
884                             mpe->mpe_function;
885                         break;
886                 case MAC_CHECK_SOCKET_RECEIVE:
887                         mpc->mpc_ops->mpo_check_socket_receive =
888                             mpe->mpe_function;
889                         break;
890                 case MAC_CHECK_SOCKET_RELABEL:
891                         mpc->mpc_ops->mpo_check_socket_relabel =
892                             mpe->mpe_function;
893                         break;
894                 case MAC_CHECK_SOCKET_SEND:
895                         mpc->mpc_ops->mpo_check_socket_send =
896                             mpe->mpe_function;
897                         break;
898                 case MAC_CHECK_SOCKET_VISIBLE:
899                         mpc->mpc_ops->mpo_check_socket_visible =
900                             mpe->mpe_function;
901                         break;
902                 case MAC_CHECK_VNODE_ACCESS:
903                         mpc->mpc_ops->mpo_check_vnode_access =
904                             mpe->mpe_function;
905                         break;
906                 case MAC_CHECK_VNODE_CHDIR:
907                         mpc->mpc_ops->mpo_check_vnode_chdir =
908                             mpe->mpe_function;
909                         break;
910                 case MAC_CHECK_VNODE_CHROOT:
911                         mpc->mpc_ops->mpo_check_vnode_chroot =
912                             mpe->mpe_function;
913                         break;
914                 case MAC_CHECK_VNODE_CREATE:
915                         mpc->mpc_ops->mpo_check_vnode_create =
916                             mpe->mpe_function;
917                         break;
918                 case MAC_CHECK_VNODE_DELETE:
919                         mpc->mpc_ops->mpo_check_vnode_delete =
920                             mpe->mpe_function;
921                         break;
922                 case MAC_CHECK_VNODE_DELETEACL:
923                         mpc->mpc_ops->mpo_check_vnode_deleteacl =
924                             mpe->mpe_function;
925                         break;
926                 case MAC_CHECK_VNODE_EXEC:
927                         mpc->mpc_ops->mpo_check_vnode_exec =
928                             mpe->mpe_function;
929                         break;
930                 case MAC_CHECK_VNODE_GETACL:
931                         mpc->mpc_ops->mpo_check_vnode_getacl =
932                             mpe->mpe_function;
933                         break;
934                 case MAC_CHECK_VNODE_GETEXTATTR:
935                         mpc->mpc_ops->mpo_check_vnode_getextattr =
936                             mpe->mpe_function;
937                         break;
938                 case MAC_CHECK_VNODE_LINK:
939                         mpc->mpc_ops->mpo_check_vnode_link =
940                             mpe->mpe_function;
941                         break;
942                 case MAC_CHECK_VNODE_LOOKUP:
943                         mpc->mpc_ops->mpo_check_vnode_lookup =
944                             mpe->mpe_function;
945                         break;
946                 case MAC_CHECK_VNODE_MMAP:
947                         mpc->mpc_ops->mpo_check_vnode_mmap =
948                             mpe->mpe_function;
949                         break;
950                 case MAC_CHECK_VNODE_MMAP_DOWNGRADE:
951                         mpc->mpc_ops->mpo_check_vnode_mmap_downgrade =
952                             mpe->mpe_function;
953                         break;
954                 case MAC_CHECK_VNODE_MPROTECT:
955                         mpc->mpc_ops->mpo_check_vnode_mprotect =
956                             mpe->mpe_function;
957                         break;
958                 case MAC_CHECK_VNODE_OPEN:
959                         mpc->mpc_ops->mpo_check_vnode_open =
960                             mpe->mpe_function;
961                         break;
962                 case MAC_CHECK_VNODE_POLL:
963                         mpc->mpc_ops->mpo_check_vnode_poll =
964                             mpe->mpe_function;
965                         break;
966                 case MAC_CHECK_VNODE_READ:
967                         mpc->mpc_ops->mpo_check_vnode_read =
968                             mpe->mpe_function;
969                         break;
970                 case MAC_CHECK_VNODE_READDIR:
971                         mpc->mpc_ops->mpo_check_vnode_readdir =
972                             mpe->mpe_function;
973                         break;
974                 case MAC_CHECK_VNODE_READLINK:
975                         mpc->mpc_ops->mpo_check_vnode_readlink =
976                             mpe->mpe_function;
977                         break;
978                 case MAC_CHECK_VNODE_RELABEL:
979                         mpc->mpc_ops->mpo_check_vnode_relabel =
980                             mpe->mpe_function;
981                         break;
982                 case MAC_CHECK_VNODE_RENAME_FROM:
983                         mpc->mpc_ops->mpo_check_vnode_rename_from =
984                             mpe->mpe_function;
985                         break;
986                 case MAC_CHECK_VNODE_RENAME_TO:
987                         mpc->mpc_ops->mpo_check_vnode_rename_to =
988                             mpe->mpe_function;
989                         break;
990                 case MAC_CHECK_VNODE_REVOKE:
991                         mpc->mpc_ops->mpo_check_vnode_revoke =
992                             mpe->mpe_function;
993                         break;
994                 case MAC_CHECK_VNODE_SETACL:
995                         mpc->mpc_ops->mpo_check_vnode_setacl =
996                             mpe->mpe_function;
997                         break;
998                 case MAC_CHECK_VNODE_SETEXTATTR:
999                         mpc->mpc_ops->mpo_check_vnode_setextattr =
1000                             mpe->mpe_function;
1001                         break;
1002                 case MAC_CHECK_VNODE_SETFLAGS:
1003                         mpc->mpc_ops->mpo_check_vnode_setflags =
1004                             mpe->mpe_function;
1005                         break;
1006                 case MAC_CHECK_VNODE_SETMODE:
1007                         mpc->mpc_ops->mpo_check_vnode_setmode =
1008                             mpe->mpe_function;
1009                         break;
1010                 case MAC_CHECK_VNODE_SETOWNER:
1011                         mpc->mpc_ops->mpo_check_vnode_setowner =
1012                             mpe->mpe_function;
1013                         break;
1014                 case MAC_CHECK_VNODE_SETUTIMES:
1015                         mpc->mpc_ops->mpo_check_vnode_setutimes =
1016                             mpe->mpe_function;
1017                         break;
1018                 case MAC_CHECK_VNODE_STAT:
1019                         mpc->mpc_ops->mpo_check_vnode_stat =
1020                             mpe->mpe_function;
1021                         break;
1022                 case MAC_CHECK_VNODE_SWAPON:
1023                         mpc->mpc_ops->mpo_check_vnode_swapon =
1024                             mpe->mpe_function;
1025                         break;
1026                 case MAC_CHECK_VNODE_WRITE:
1027                         mpc->mpc_ops->mpo_check_vnode_write =
1028                             mpe->mpe_function;
1029                         break;
1030 /*
1031                 default:
1032                         printf("MAC policy `%s': unknown operation %d\n",
1033                             mpc->mpc_name, mpe->mpe_constant);
1034                         return (EINVAL);
1035 */
1036                 }
1037         }
1038         MAC_POLICY_LIST_LOCK();
1039         if (mac_policy_list_busy > 0) {
1040                 MAC_POLICY_LIST_UNLOCK();
1041                 FREE(mpc->mpc_ops, M_MACOPVEC);
1042                 mpc->mpc_ops = NULL;
1043                 return (EBUSY);
1044         }
1045         LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
1046                 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
1047                         MAC_POLICY_LIST_UNLOCK();
1048                         FREE(mpc->mpc_ops, M_MACOPVEC);
1049                         mpc->mpc_ops = NULL;
1050                         return (EEXIST);
1051                 }
1052         }
1053         if (mpc->mpc_field_off != NULL) {
1054                 slot = ffs(mac_policy_offsets_free);
1055                 if (slot == 0) {
1056                         MAC_POLICY_LIST_UNLOCK();
1057                         FREE(mpc->mpc_ops, M_MACOPVEC);
1058                         mpc->mpc_ops = NULL;
1059                         return (ENOMEM);
1060                 }
1061                 slot--;
1062                 mac_policy_offsets_free &= ~(1 << slot);
1063                 *mpc->mpc_field_off = slot;
1064         }
1065         mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
1066         LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
1067
1068         /* Per-policy initialization. */
1069         if (mpc->mpc_ops->mpo_init != NULL)
1070                 (*(mpc->mpc_ops->mpo_init))(mpc);
1071         MAC_POLICY_LIST_UNLOCK();
1072
1073         printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
1074             mpc->mpc_name);
1075
1076         return (0);
1077 }
1078
1079 static int
1080 mac_policy_unregister(struct mac_policy_conf *mpc)
1081 {
1082
1083         /*
1084          * If we fail the load, we may get a request to unload.  Check
1085          * to see if we did the run-time registration, and if not,
1086          * silently succeed.
1087          */
1088         MAC_POLICY_LIST_LOCK();
1089         if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
1090                 MAC_POLICY_LIST_UNLOCK();
1091                 return (0);
1092         }
1093 #if 0
1094         /*
1095          * Don't allow unloading modules with private data.
1096          */
1097         if (mpc->mpc_field_off != NULL) {
1098                 MAC_POLICY_LIST_UNLOCK();
1099                 return (EBUSY);
1100         }
1101 #endif
1102         /*
1103          * Only allow the unload to proceed if the module is unloadable
1104          * by its own definition.
1105          */
1106         if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
1107                 MAC_POLICY_LIST_UNLOCK();
1108                 return (EBUSY);
1109         }
1110         /*
1111          * Right now, we EBUSY if the list is in use.  In the future,
1112          * for reliability reasons, we might want to sleep and wakeup
1113          * later to try again.
1114          */
1115         if (mac_policy_list_busy > 0) {
1116                 MAC_POLICY_LIST_UNLOCK();
1117                 return (EBUSY);
1118         }
1119         if (mpc->mpc_ops->mpo_destroy != NULL)
1120                 (*(mpc->mpc_ops->mpo_destroy))(mpc);
1121
1122         LIST_REMOVE(mpc, mpc_list);
1123         MAC_POLICY_LIST_UNLOCK();
1124
1125         FREE(mpc->mpc_ops, M_MACOPVEC);
1126         mpc->mpc_ops = NULL;
1127         mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
1128
1129         printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
1130             mpc->mpc_name);
1131
1132         return (0);
1133 }
1134
1135 /*
1136  * Define an error value precedence, and given two arguments, selects the
1137  * value with the higher precedence.
1138  */
1139 static int
1140 error_select(int error1, int error2)
1141 {
1142
1143         /* Certain decision-making errors take top priority. */
1144         if (error1 == EDEADLK || error2 == EDEADLK)
1145                 return (EDEADLK);
1146
1147         /* Invalid arguments should be reported where possible. */
1148         if (error1 == EINVAL || error2 == EINVAL)
1149                 return (EINVAL);
1150
1151         /* Precedence goes to "visibility", with both process and file. */
1152         if (error1 == ESRCH || error2 == ESRCH)
1153                 return (ESRCH);
1154
1155         if (error1 == ENOENT || error2 == ENOENT)
1156                 return (ENOENT);
1157
1158         /* Precedence goes to DAC/MAC protections. */
1159         if (error1 == EACCES || error2 == EACCES)
1160                 return (EACCES);
1161
1162         /* Precedence goes to privilege. */
1163         if (error1 == EPERM || error2 == EPERM)
1164                 return (EPERM);
1165
1166         /* Precedence goes to error over success; otherwise, arbitrary. */
1167         if (error1 != 0)
1168                 return (error1);
1169         return (error2);
1170 }
1171
1172 static void
1173 mac_init_label(struct label *label)
1174 {
1175
1176         bzero(label, sizeof(*label));
1177         label->l_flags = MAC_FLAG_INITIALIZED;
1178 }
1179
1180 static void
1181 mac_destroy_label(struct label *label)
1182 {
1183
1184         KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1185             ("destroying uninitialized label"));
1186
1187         bzero(label, sizeof(*label));
1188         /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1189 }
1190
1191 void
1192 mac_init_bpfdesc(struct bpf_d *bpf_d)
1193 {
1194
1195         mac_init_label(&bpf_d->bd_label);
1196         MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1197 #ifdef MAC_DEBUG
1198         atomic_add_int(&nmacbpfdescs, 1);
1199 #endif
1200 }
1201
1202 static void
1203 mac_init_cred_label(struct label *label)
1204 {
1205
1206         mac_init_label(label);
1207         MAC_PERFORM(init_cred_label, label);
1208 #ifdef MAC_DEBUG
1209         atomic_add_int(&nmaccreds, 1);
1210 #endif
1211 }
1212
1213 void
1214 mac_init_cred(struct ucred *cred)
1215 {
1216
1217         mac_init_cred_label(&cred->cr_label);
1218 }
1219
1220 void
1221 mac_init_devfsdirent(struct devfs_dirent *de)
1222 {
1223
1224         mac_init_label(&de->de_label);
1225         MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1226 #ifdef MAC_DEBUG
1227         atomic_add_int(&nmacdevfsdirents, 1);
1228 #endif
1229 }
1230
1231 static void
1232 mac_init_ifnet_label(struct label *label)
1233 {
1234
1235         mac_init_label(label);
1236         MAC_PERFORM(init_ifnet_label, label);
1237 #ifdef MAC_DEBUG
1238         atomic_add_int(&nmacifnets, 1);
1239 #endif
1240 }
1241
1242 void
1243 mac_init_ifnet(struct ifnet *ifp)
1244 {
1245
1246         mac_init_ifnet_label(&ifp->if_label);
1247 }
1248
1249 void
1250 mac_init_ipq(struct ipq *ipq)
1251 {
1252
1253         mac_init_label(&ipq->ipq_label);
1254         MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1255 #ifdef MAC_DEBUG
1256         atomic_add_int(&nmacipqs, 1);
1257 #endif
1258 }
1259
1260 int
1261 mac_init_mbuf(struct mbuf *m, int flag)
1262 {
1263         int error;
1264
1265         KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1266
1267         mac_init_label(&m->m_pkthdr.label);
1268
1269         MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
1270         if (error) {
1271                 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1272                 mac_destroy_label(&m->m_pkthdr.label);
1273         }
1274
1275 #ifdef MAC_DEBUG
1276         if (error == 0)
1277                 atomic_add_int(&nmacmbufs, 1);
1278 #endif
1279         return (error);
1280 }
1281
1282 void
1283 mac_init_mount(struct mount *mp)
1284 {
1285
1286         mac_init_label(&mp->mnt_mntlabel);
1287         mac_init_label(&mp->mnt_fslabel);
1288         MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1289         MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1290 #ifdef MAC_DEBUG
1291         atomic_add_int(&nmacmounts, 1);
1292 #endif
1293 }
1294
1295 static void
1296 mac_init_pipe_label(struct label *label)
1297 {
1298
1299         mac_init_label(label);
1300         MAC_PERFORM(init_pipe_label, label);
1301 #ifdef MAC_DEBUG
1302         atomic_add_int(&nmacpipes, 1);
1303 #endif
1304 }
1305
1306 void
1307 mac_init_pipe(struct pipe *pipe)
1308 {
1309         struct label *label;
1310
1311         label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1312         pipe->pipe_label = label;
1313         pipe->pipe_peer->pipe_label = label;
1314         mac_init_pipe_label(label);
1315 }
1316
1317 static int
1318 mac_init_socket_label(struct label *label, int flag)
1319 {
1320         int error;
1321
1322         mac_init_label(label);
1323
1324         MAC_CHECK(init_socket_label, label, flag);
1325         if (error) {
1326                 MAC_PERFORM(destroy_socket_label, label);
1327                 mac_destroy_label(label);
1328         }
1329
1330 #ifdef MAC_DEBUG
1331         if (error == 0)
1332                 atomic_add_int(&nmacsockets, 1);
1333 #endif
1334
1335         return (error);
1336 }
1337
1338 static int
1339 mac_init_socket_peer_label(struct label *label, int flag)
1340 {
1341         int error;
1342
1343         mac_init_label(label);
1344
1345         MAC_CHECK(init_socket_peer_label, label, flag);
1346         if (error) {
1347                 MAC_PERFORM(destroy_socket_label, label);
1348                 mac_destroy_label(label);
1349         }
1350
1351         return (error);
1352 }
1353
1354 int
1355 mac_init_socket(struct socket *socket, int flag)
1356 {
1357         int error;
1358
1359         error = mac_init_socket_label(&socket->so_label, flag);
1360         if (error)
1361                 return (error);
1362
1363         error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1364         if (error)
1365                 mac_destroy_socket_label(&socket->so_label);
1366
1367         return (error);
1368 }
1369
1370 void
1371 mac_init_vnode_label(struct label *label)
1372 {
1373
1374         mac_init_label(label);
1375         MAC_PERFORM(init_vnode_label, label);
1376 #ifdef MAC_DEBUG
1377         atomic_add_int(&nmacvnodes, 1);
1378 #endif
1379 }
1380
1381 void
1382 mac_init_vnode(struct vnode *vp)
1383 {
1384
1385         mac_init_vnode_label(&vp->v_label);
1386 }
1387
1388 void
1389 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1390 {
1391
1392         MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1393         mac_destroy_label(&bpf_d->bd_label);
1394 #ifdef MAC_DEBUG
1395         atomic_subtract_int(&nmacbpfdescs, 1);
1396 #endif
1397 }
1398
1399 static void
1400 mac_destroy_cred_label(struct label *label)
1401 {
1402
1403         MAC_PERFORM(destroy_cred_label, label);
1404         mac_destroy_label(label);
1405 #ifdef MAC_DEBUG
1406         atomic_subtract_int(&nmaccreds, 1);
1407 #endif
1408 }
1409
1410 void
1411 mac_destroy_cred(struct ucred *cred)
1412 {
1413
1414         mac_destroy_cred_label(&cred->cr_label);
1415 }
1416
1417 void
1418 mac_destroy_devfsdirent(struct devfs_dirent *de)
1419 {
1420
1421         MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1422         mac_destroy_label(&de->de_label);
1423 #ifdef MAC_DEBUG
1424         atomic_subtract_int(&nmacdevfsdirents, 1);
1425 #endif
1426 }
1427
1428 static void
1429 mac_destroy_ifnet_label(struct label *label)
1430 {
1431
1432         MAC_PERFORM(destroy_ifnet_label, label);
1433         mac_destroy_label(label);
1434 #ifdef MAC_DEBUG
1435         atomic_subtract_int(&nmacifnets, 1);
1436 #endif
1437 }
1438
1439 void
1440 mac_destroy_ifnet(struct ifnet *ifp)
1441 {
1442
1443         mac_destroy_ifnet_label(&ifp->if_label);
1444 }
1445
1446 void
1447 mac_destroy_ipq(struct ipq *ipq)
1448 {
1449
1450         MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1451         mac_destroy_label(&ipq->ipq_label);
1452 #ifdef MAC_DEBUG
1453         atomic_subtract_int(&nmacipqs, 1);
1454 #endif
1455 }
1456
1457 void
1458 mac_destroy_mbuf(struct mbuf *m)
1459 {
1460
1461         MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1462         mac_destroy_label(&m->m_pkthdr.label);
1463 #ifdef MAC_DEBUG
1464         atomic_subtract_int(&nmacmbufs, 1);
1465 #endif
1466 }
1467
1468 void
1469 mac_destroy_mount(struct mount *mp)
1470 {
1471
1472         MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1473         MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1474         mac_destroy_label(&mp->mnt_fslabel);
1475         mac_destroy_label(&mp->mnt_mntlabel);
1476 #ifdef MAC_DEBUG
1477         atomic_subtract_int(&nmacmounts, 1);
1478 #endif
1479 }
1480
1481 static void
1482 mac_destroy_pipe_label(struct label *label)
1483 {
1484
1485         MAC_PERFORM(destroy_pipe_label, label);
1486         mac_destroy_label(label);
1487 #ifdef MAC_DEBUG
1488         atomic_subtract_int(&nmacpipes, 1);
1489 #endif
1490 }
1491
1492 void
1493 mac_destroy_pipe(struct pipe *pipe)
1494 {
1495
1496         mac_destroy_pipe_label(pipe->pipe_label);
1497         free(pipe->pipe_label, M_MACPIPELABEL);
1498 }
1499
1500 static void
1501 mac_destroy_socket_label(struct label *label)
1502 {
1503
1504         MAC_PERFORM(destroy_socket_label, label);
1505         mac_destroy_label(label);
1506 #ifdef MAC_DEBUG
1507         atomic_subtract_int(&nmacsockets, 1);
1508 #endif
1509 }
1510
1511 static void
1512 mac_destroy_socket_peer_label(struct label *label)
1513 {
1514
1515         MAC_PERFORM(destroy_socket_peer_label, label);
1516         mac_destroy_label(label);
1517 }
1518
1519 void
1520 mac_destroy_socket(struct socket *socket)
1521 {
1522
1523         mac_destroy_socket_label(&socket->so_label);
1524         mac_destroy_socket_peer_label(&socket->so_peerlabel);
1525 }
1526
1527 void
1528 mac_destroy_vnode_label(struct label *label)
1529 {
1530
1531         MAC_PERFORM(destroy_vnode_label, label);
1532         mac_destroy_label(label);
1533 #ifdef MAC_DEBUG
1534         atomic_subtract_int(&nmacvnodes, 1);
1535 #endif
1536 }
1537
1538 void
1539 mac_destroy_vnode(struct vnode *vp)
1540 {
1541
1542         mac_destroy_vnode_label(&vp->v_label);
1543 }
1544
1545 static void
1546 mac_copy_pipe_label(struct label *src, struct label *dest)
1547 {
1548
1549         MAC_PERFORM(copy_pipe_label, src, dest);
1550 }
1551
1552 void
1553 mac_copy_vnode_label(struct label *src, struct label *dest)
1554 {
1555
1556         MAC_PERFORM(copy_vnode_label, src, dest);
1557 }
1558
1559 static int
1560 mac_check_structmac_consistent(struct mac *mac)
1561 {
1562
1563         if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1564                 return (EINVAL);
1565
1566         return (0);
1567 }
1568
1569 static int
1570 mac_externalize_cred_label(struct label *label, char *elements,
1571     char *outbuf, size_t outbuflen, int flags)
1572 {
1573         int error;
1574
1575         MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1576
1577         return (error);
1578 }
1579
1580 static int
1581 mac_externalize_ifnet_label(struct label *label, char *elements,
1582     char *outbuf, size_t outbuflen, int flags)
1583 {
1584         int error;
1585
1586         MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1587
1588         return (error);
1589 }
1590
1591 static int
1592 mac_externalize_pipe_label(struct label *label, char *elements,
1593     char *outbuf, size_t outbuflen, int flags)
1594 {
1595         int error;
1596
1597         MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1598
1599         return (error);
1600 }
1601
1602 static int
1603 mac_externalize_socket_label(struct label *label, char *elements,
1604     char *outbuf, size_t outbuflen, int flags)
1605 {
1606         int error;
1607
1608         MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1609
1610         return (error);
1611 }
1612
1613 static int
1614 mac_externalize_socket_peer_label(struct label *label, char *elements,
1615     char *outbuf, size_t outbuflen, int flags)
1616 {
1617         int error;
1618
1619         MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1620
1621         return (error);
1622 }
1623
1624 static int
1625 mac_externalize_vnode_label(struct label *label, char *elements,
1626     char *outbuf, size_t outbuflen, int flags)
1627 {
1628         int error;
1629
1630         MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1631
1632         return (error);
1633 }
1634
1635 static int
1636 mac_internalize_cred_label(struct label *label, char *string)
1637 {
1638         int error;
1639
1640         MAC_INTERNALIZE(cred_label, label, string);
1641
1642         return (error);
1643 }
1644
1645 static int
1646 mac_internalize_ifnet_label(struct label *label, char *string)
1647 {
1648         int error;
1649
1650         MAC_INTERNALIZE(ifnet_label, label, string);
1651
1652         return (error);
1653 }
1654
1655 static int
1656 mac_internalize_pipe_label(struct label *label, char *string)
1657 {
1658         int error;
1659
1660         MAC_INTERNALIZE(pipe_label, label, string);
1661
1662         return (error);
1663 }
1664
1665 static int
1666 mac_internalize_socket_label(struct label *label, char *string)
1667 {
1668         int error;
1669
1670         MAC_INTERNALIZE(socket_label, label, string);
1671
1672         return (error);
1673 }
1674
1675 static int
1676 mac_internalize_vnode_label(struct label *label, char *string)
1677 {
1678         int error;
1679
1680         MAC_INTERNALIZE(vnode_label, label, string);
1681
1682         return (error);
1683 }
1684
1685 /*
1686  * Initialize MAC label for the first kernel process, from which other
1687  * kernel processes and threads are spawned.
1688  */
1689 void
1690 mac_create_proc0(struct ucred *cred)
1691 {
1692
1693         MAC_PERFORM(create_proc0, cred);
1694 }
1695
1696 /*
1697  * Initialize MAC label for the first userland process, from which other
1698  * userland processes and threads are spawned.
1699  */
1700 void
1701 mac_create_proc1(struct ucred *cred)
1702 {
1703
1704         MAC_PERFORM(create_proc1, cred);
1705 }
1706
1707 void
1708 mac_thread_userret(struct thread *td)
1709 {
1710
1711         MAC_PERFORM(thread_userret, td);
1712 }
1713
1714 /*
1715  * When a new process is created, its label must be initialized.  Generally,
1716  * this involves inheritence from the parent process, modulo possible
1717  * deltas.  This function allows that processing to take place.
1718  */
1719 void
1720 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1721 {
1722
1723         MAC_PERFORM(create_cred, parent_cred, child_cred);
1724 }
1725
1726 void
1727 mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1728 {
1729
1730         MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1731 }
1732
1733 void
1734 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1735     struct vnode *vp)
1736 {
1737
1738         MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1739             &de->de_label, vp, &vp->v_label);
1740 }
1741
1742 int
1743 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1744 {
1745         int error;
1746
1747         ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1748
1749         MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1750             &vp->v_label);
1751
1752         return (error);
1753 }
1754
1755 void
1756 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1757 {
1758
1759         MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1760             &vp->v_label);
1761 }
1762
1763 int
1764 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1765     struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1766 {
1767         int error;
1768
1769         ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1770         ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1771
1772         error = VOP_OPENEXTATTR(vp, cred, curthread);
1773         if (error == EOPNOTSUPP) {
1774                 /* XXX: Optionally abort if transactions not supported. */
1775                 if (ea_warn_once == 0) {
1776                         printf("Warning: transactions not supported "
1777                             "in EA write.\n");
1778                         ea_warn_once = 1;
1779                 }
1780         } else if (error)
1781                 return (error);
1782
1783         MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1784             dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1785
1786         if (error) {
1787                 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1788                 return (error);
1789         }
1790
1791         error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1792
1793         if (error == EOPNOTSUPP)
1794                 error = 0;                              /* XXX */
1795
1796         return (error);
1797 }
1798
1799 static int
1800 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1801     struct label *intlabel)
1802 {
1803         int error;
1804
1805         ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1806
1807         error = VOP_OPENEXTATTR(vp, cred, curthread);
1808         if (error == EOPNOTSUPP) {
1809                 /* XXX: Optionally abort if transactions not supported. */
1810                 if (ea_warn_once == 0) {
1811                         printf("Warning: transactions not supported "
1812                             "in EA write.\n");
1813                         ea_warn_once = 1;
1814                 }
1815         } else if (error)
1816                 return (error);
1817
1818         MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1819
1820         if (error) {
1821                 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1822                 return (error);
1823         }
1824
1825         error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1826
1827         if (error == EOPNOTSUPP)
1828                 error = 0;                              /* XXX */
1829
1830         return (error);
1831 }
1832
1833 void
1834 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1835 {
1836
1837         ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1838
1839         MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1840 }
1841
1842 int
1843 mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1844 {
1845         int result;
1846
1847         result = 0;
1848         MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1849
1850         return (result);
1851 }
1852
1853 int
1854 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
1855 {
1856         int error;
1857
1858         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1859
1860         if (!mac_enforce_fs)
1861                 return (0);
1862
1863         MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
1864         return (error);
1865 }
1866
1867 int
1868 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1869 {
1870         int error;
1871
1872         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1873
1874         if (!mac_enforce_fs)
1875                 return (0);
1876
1877         MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1878         return (error);
1879 }
1880
1881 int
1882 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1883 {
1884         int error;
1885
1886         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1887
1888         if (!mac_enforce_fs)
1889                 return (0);
1890
1891         MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1892         return (error);
1893 }
1894
1895 int
1896 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1897     struct componentname *cnp, struct vattr *vap)
1898 {
1899         int error;
1900
1901         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1902
1903         if (!mac_enforce_fs)
1904                 return (0);
1905
1906         MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1907         return (error);
1908 }
1909
1910 int
1911 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1912     struct componentname *cnp)
1913 {
1914         int error;
1915
1916         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1917         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1918
1919         if (!mac_enforce_fs)
1920                 return (0);
1921
1922         MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1923             &vp->v_label, cnp);
1924         return (error);
1925 }
1926
1927 int
1928 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1929     acl_type_t type)
1930 {
1931         int error;
1932
1933         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1934
1935         if (!mac_enforce_fs)
1936                 return (0);
1937
1938         MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1939         return (error);
1940 }
1941
1942 int
1943 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1944 {
1945         int error;
1946
1947         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1948
1949         if (!mac_enforce_process && !mac_enforce_fs)
1950                 return (0);
1951
1952         MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1953
1954         return (error);
1955 }
1956
1957 int
1958 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1959 {
1960         int error;
1961
1962         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1963
1964         if (!mac_enforce_fs)
1965                 return (0);
1966
1967         MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1968         return (error);
1969 }
1970
1971 int
1972 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1973     int attrnamespace, const char *name, struct uio *uio)
1974 {
1975         int error;
1976
1977         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1978
1979         if (!mac_enforce_fs)
1980                 return (0);
1981
1982         MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1983             attrnamespace, name, uio);
1984         return (error);
1985 }
1986
1987 int
1988 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1989     struct vnode *vp, struct componentname *cnp)
1990 {
1991         int error;
1992
1993         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1994         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1995
1996         if (!mac_enforce_fs)
1997                 return (0);
1998
1999         MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
2000             &vp->v_label, cnp);
2001         return (error);
2002 }
2003
2004 int
2005 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2006     struct componentname *cnp)
2007 {
2008         int error;
2009
2010         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
2011
2012         if (!mac_enforce_fs)
2013                 return (0);
2014
2015         MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
2016         return (error);
2017 }
2018
2019 int
2020 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
2021 {
2022         int error;
2023
2024         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
2025
2026         if (!mac_enforce_fs || !mac_enforce_vm)
2027                 return (0);
2028
2029         MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
2030         return (error);
2031 }
2032
2033 void
2034 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
2035 {
2036         int result = *prot;
2037
2038         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
2039
2040         if (!mac_enforce_fs || !mac_enforce_vm)
2041                 return;
2042
2043         MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
2044             &result);
2045
2046         *prot = result;
2047 }
2048
2049 int
2050 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
2051 {
2052         int error;
2053
2054         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
2055
2056         if (!mac_enforce_fs || !mac_enforce_vm)
2057                 return (0);
2058
2059         MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
2060         return (error);
2061 }
2062
2063 int
2064 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
2065 {
2066         int error;
2067
2068         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
2069
2070         if (!mac_enforce_fs)
2071                 return (0);
2072
2073         MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
2074         return (error);
2075 }
2076
2077 int
2078 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2079     struct vnode *vp)
2080 {
2081         int error;
2082
2083         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
2084
2085         if (!mac_enforce_fs)
2086                 return (0);
2087
2088         MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
2089             &vp->v_label);
2090
2091         return (error);
2092 }
2093
2094 int
2095 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2096     struct vnode *vp)
2097 {
2098         int error;
2099
2100         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
2101
2102         if (!mac_enforce_fs)
2103                 return (0);
2104
2105         MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
2106             &vp->v_label);
2107
2108         return (error);
2109 }
2110
2111 int
2112 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
2113 {
2114         int error;
2115
2116         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
2117
2118         if (!mac_enforce_fs)
2119                 return (0);
2120
2121         MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
2122         return (error);
2123 }
2124
2125 int
2126 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
2127 {
2128         int error;
2129
2130         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
2131
2132         if (!mac_enforce_fs)
2133                 return (0);
2134
2135         MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
2136         return (error);
2137 }
2138
2139 static int
2140 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2141     struct label *newlabel)
2142 {
2143         int error;
2144
2145         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
2146
2147         MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
2148
2149         return (error);
2150 }
2151
2152 int
2153 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2154     struct vnode *vp, struct componentname *cnp)
2155 {
2156         int error;
2157
2158         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
2159         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
2160
2161         if (!mac_enforce_fs)
2162                 return (0);
2163
2164         MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
2165             &vp->v_label, cnp);
2166         return (error);
2167 }
2168
2169 int
2170 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2171     struct vnode *vp, int samedir, struct componentname *cnp)
2172 {
2173         int error;
2174
2175         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2176         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2177
2178         if (!mac_enforce_fs)
2179                 return (0);
2180
2181         MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2182             vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2183         return (error);
2184 }
2185
2186 int
2187 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2188 {
2189         int error;
2190
2191         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2192
2193         if (!mac_enforce_fs)
2194                 return (0);
2195
2196         MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2197         return (error);
2198 }
2199
2200 int
2201 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2202     struct acl *acl)
2203 {
2204         int error;
2205
2206         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2207
2208         if (!mac_enforce_fs)
2209                 return (0);
2210
2211         MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2212         return (error);
2213 }
2214
2215 int
2216 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2217     int attrnamespace, const char *name, struct uio *uio)
2218 {
2219         int error;
2220
2221         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2222
2223         if (!mac_enforce_fs)
2224                 return (0);
2225
2226         MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2227             attrnamespace, name, uio);
2228         return (error);
2229 }
2230
2231 int
2232 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2233 {
2234         int error;
2235
2236         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2237
2238         if (!mac_enforce_fs)
2239                 return (0);
2240
2241         MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2242         return (error);
2243 }
2244
2245 int
2246 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2247 {
2248         int error;
2249
2250         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2251
2252         if (!mac_enforce_fs)
2253                 return (0);
2254
2255         MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2256         return (error);
2257 }
2258
2259 int
2260 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2261     gid_t gid)
2262 {
2263         int error;
2264
2265         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2266
2267         if (!mac_enforce_fs)
2268                 return (0);
2269
2270         MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2271         return (error);
2272 }
2273
2274 int
2275 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2276     struct timespec atime, struct timespec mtime)
2277 {
2278         int error;
2279
2280         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2281
2282         if (!mac_enforce_fs)
2283                 return (0);
2284
2285         MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2286             mtime);
2287         return (error);
2288 }
2289
2290 int
2291 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2292     struct vnode *vp)
2293 {
2294         int error;
2295
2296         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2297
2298         if (!mac_enforce_fs)
2299                 return (0);
2300
2301         MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2302             &vp->v_label);
2303         return (error);
2304 }
2305
2306 int
2307 mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp)
2308 {
2309         int error;
2310
2311         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon");
2312
2313         if (!mac_enforce_fs)
2314                 return (0);
2315
2316         MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label);
2317         return (error);
2318 }
2319
2320 int
2321 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2322     struct vnode *vp)
2323 {
2324         int error;
2325
2326         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2327
2328         if (!mac_enforce_fs)
2329                 return (0);
2330
2331         MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2332             &vp->v_label);
2333
2334         return (error);
2335 }
2336
2337 /*
2338  * When relabeling a process, call out to the policies for the maximum
2339  * permission allowed for each object type we know about in its
2340  * memory space, and revoke access (in the least surprising ways we
2341  * know) when necessary.  The process lock is not held here.
2342  */
2343 static void
2344 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2345 {
2346
2347         /* XXX freeze all other threads */
2348         mac_cred_mmapped_drop_perms_recurse(td, cred,
2349             &td->td_proc->p_vmspace->vm_map);
2350         /* XXX allow other threads to continue */
2351 }
2352
2353 static __inline const char *
2354 prot2str(vm_prot_t prot)
2355 {
2356
2357         switch (prot & VM_PROT_ALL) {
2358         case VM_PROT_READ:
2359                 return ("r--");
2360         case VM_PROT_READ | VM_PROT_WRITE:
2361                 return ("rw-");
2362         case VM_PROT_READ | VM_PROT_EXECUTE:
2363                 return ("r-x");
2364         case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2365                 return ("rwx");
2366         case VM_PROT_WRITE:
2367                 return ("-w-");
2368         case VM_PROT_EXECUTE:
2369                 return ("--x");
2370         case VM_PROT_WRITE | VM_PROT_EXECUTE:
2371                 return ("-wx");
2372         default:
2373                 return ("---");
2374         }
2375 }
2376
2377 static void
2378 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2379     struct vm_map *map)
2380 {
2381         struct vm_map_entry *vme;
2382         int result;
2383         vm_prot_t revokeperms;
2384         vm_object_t object;
2385         vm_ooffset_t offset;
2386         struct vnode *vp;
2387
2388         if (!mac_mmap_revocation)
2389                 return;
2390
2391         vm_map_lock_read(map);
2392         for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2393                 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2394                         mac_cred_mmapped_drop_perms_recurse(td, cred,
2395                             vme->object.sub_map);
2396                         continue;
2397                 }
2398                 /*
2399                  * Skip over entries that obviously are not shared.
2400                  */
2401                 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2402                     !vme->max_protection)
2403                         continue;
2404                 /*
2405                  * Drill down to the deepest backing object.
2406                  */
2407                 offset = vme->offset;
2408                 object = vme->object.vm_object;
2409                 if (object == NULL)
2410                         continue;
2411                 while (object->backing_object != NULL) {
2412                         object = object->backing_object;
2413                         offset += object->backing_object_offset;
2414                 }
2415                 /*
2416                  * At the moment, vm_maps and objects aren't considered
2417                  * by the MAC system, so only things with backing by a
2418                  * normal object (read: vnodes) are checked.
2419                  */
2420                 if (object->type != OBJT_VNODE)
2421                         continue;
2422                 vp = (struct vnode *)object->handle;
2423                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2424                 result = vme->max_protection;
2425                 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2426                 VOP_UNLOCK(vp, 0, td);
2427                 /*
2428                  * Find out what maximum protection we may be allowing
2429                  * now but a policy needs to get removed.
2430                  */
2431                 revokeperms = vme->max_protection & ~result;
2432                 if (!revokeperms)
2433                         continue;
2434                 printf("pid %ld: revoking %s perms from %#lx:%ld "
2435                     "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2436                     prot2str(revokeperms), (u_long)vme->start,
2437                     (long)(vme->end - vme->start),
2438                     prot2str(vme->max_protection), prot2str(vme->protection));
2439                 vm_map_lock_upgrade(map);
2440                 /*
2441                  * This is the really simple case: if a map has more
2442                  * max_protection than is allowed, but it's not being
2443                  * actually used (that is, the current protection is
2444                  * still allowed), we can just wipe it out and do
2445                  * nothing more.
2446                  */
2447                 if ((vme->protection & revokeperms) == 0) {
2448                         vme->max_protection -= revokeperms;
2449                 } else {
2450                         if (revokeperms & VM_PROT_WRITE) {
2451                                 /*
2452                                  * In the more complicated case, flush out all
2453                                  * pending changes to the object then turn it
2454                                  * copy-on-write.
2455                                  */
2456                                 vm_object_reference(object);
2457                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2458                                 vm_object_page_clean(object,
2459                                     OFF_TO_IDX(offset),
2460                                     OFF_TO_IDX(offset + vme->end - vme->start +
2461                                         PAGE_MASK),
2462                                     OBJPC_SYNC);
2463                                 VOP_UNLOCK(vp, 0, td);
2464                                 vm_object_deallocate(object);
2465                                 /*
2466                                  * Why bother if there's no read permissions
2467                                  * anymore?  For the rest, we need to leave
2468                                  * the write permissions on for COW, or
2469                                  * remove them entirely if configured to.
2470                                  */
2471                                 if (!mac_mmap_revocation_via_cow) {
2472                                         vme->max_protection &= ~VM_PROT_WRITE;
2473                                         vme->protection &= ~VM_PROT_WRITE;
2474                                 } if ((revokeperms & VM_PROT_READ) == 0)
2475                                         vme->eflags |= MAP_ENTRY_COW |
2476                                             MAP_ENTRY_NEEDS_COPY;
2477                         }
2478                         if (revokeperms & VM_PROT_EXECUTE) {
2479                                 vme->max_protection &= ~VM_PROT_EXECUTE;
2480                                 vme->protection &= ~VM_PROT_EXECUTE;
2481                         }
2482                         if (revokeperms & VM_PROT_READ) {
2483                                 vme->max_protection = 0;
2484                                 vme->protection = 0;
2485                         }
2486                         pmap_protect(map->pmap, vme->start, vme->end,
2487                             vme->protection & ~revokeperms);
2488                         vm_map_simplify_entry(map, vme);
2489                 }
2490                 vm_map_lock_downgrade(map);
2491         }
2492         vm_map_unlock_read(map);
2493 }
2494
2495 /*
2496  * When the subject's label changes, it may require revocation of privilege
2497  * to mapped objects.  This can't be done on-the-fly later with a unified
2498  * buffer cache.
2499  */
2500 static void
2501 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2502 {
2503
2504         MAC_PERFORM(relabel_cred, cred, newlabel);
2505 }
2506
2507 void
2508 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2509 {
2510
2511         MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2512 }
2513
2514 void
2515 mac_create_ifnet(struct ifnet *ifnet)
2516 {
2517
2518         MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2519 }
2520
2521 void
2522 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2523 {
2524
2525         MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2526 }
2527
2528 void
2529 mac_create_socket(struct ucred *cred, struct socket *socket)
2530 {
2531
2532         MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2533 }
2534
2535 void
2536 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2537 {
2538
2539         MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2540 }
2541
2542 void
2543 mac_create_socket_from_socket(struct socket *oldsocket,
2544     struct socket *newsocket)
2545 {
2546
2547         MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2548             newsocket, &newsocket->so_label);
2549 }
2550
2551 static void
2552 mac_relabel_socket(struct ucred *cred, struct socket *socket,
2553     struct label *newlabel)
2554 {
2555
2556         MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2557 }
2558
2559 static void
2560 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2561 {
2562
2563         MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2564 }
2565
2566 void
2567 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2568 {
2569
2570         MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2571             socket, &socket->so_peerlabel);
2572 }
2573
2574 void
2575 mac_set_socket_peer_from_socket(struct socket *oldsocket,
2576     struct socket *newsocket)
2577 {
2578
2579         MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2580             &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2581 }
2582
2583 void
2584 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2585 {
2586
2587         MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2588             datagram, &datagram->m_pkthdr.label);
2589 }
2590
2591 void
2592 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2593 {
2594
2595         MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2596             fragment, &fragment->m_pkthdr.label);
2597 }
2598
2599 void
2600 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2601 {
2602
2603         MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2604             &ipq->ipq_label);
2605 }
2606
2607 void
2608 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2609 {
2610
2611         MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2612             newmbuf, &newmbuf->m_pkthdr.label);
2613 }
2614
2615 void
2616 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2617 {
2618
2619         MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2620             &mbuf->m_pkthdr.label);
2621 }
2622
2623 void
2624 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2625 {
2626
2627         MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2628             &mbuf->m_pkthdr.label);
2629 }
2630
2631 void
2632 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2633 {
2634
2635         MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2636             &mbuf->m_pkthdr.label);
2637 }
2638
2639 void
2640 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2641     struct mbuf *newmbuf)
2642 {
2643
2644         MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2645             &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2646             &newmbuf->m_pkthdr.label);
2647 }
2648
2649 void
2650 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2651 {
2652
2653         MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2654             newmbuf, &newmbuf->m_pkthdr.label);
2655 }
2656
2657 int
2658 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2659 {
2660         int result;
2661
2662         result = 1;
2663         MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2664             ipq, &ipq->ipq_label);
2665
2666         return (result);
2667 }
2668
2669 void
2670 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2671 {
2672
2673         MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2674             &ipq->ipq_label);
2675 }
2676
2677 void
2678 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2679 {
2680
2681         MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2682             &mbuf->m_pkthdr.label);
2683 }
2684
2685 void
2686 mac_create_mount(struct ucred *cred, struct mount *mp)
2687 {
2688
2689         MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2690             &mp->mnt_fslabel);
2691 }
2692
2693 void
2694 mac_create_root_mount(struct ucred *cred, struct mount *mp)
2695 {
2696
2697         MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2698             &mp->mnt_fslabel);
2699 }
2700
2701 int
2702 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2703 {
2704         int error;
2705
2706         if (!mac_enforce_network)
2707                 return (0);
2708
2709         MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2710             &ifnet->if_label);
2711
2712         return (error);
2713 }
2714
2715 static int
2716 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2717 {
2718         int error;
2719
2720         MAC_CHECK(check_cred_relabel, cred, newlabel);
2721
2722         return (error);
2723 }
2724
2725 int
2726 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2727 {
2728         int error;
2729
2730         if (!mac_enforce_process)
2731                 return (0);
2732
2733         MAC_CHECK(check_cred_visible, u1, u2);
2734
2735         return (error);
2736 }
2737
2738 int
2739 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2740 {
2741         int error;
2742
2743         if (!mac_enforce_network)
2744                 return (0);
2745
2746         KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2747         if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2748                 if_printf(ifnet, "not initialized\n");
2749
2750         MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2751             &mbuf->m_pkthdr.label);
2752
2753         return (error);
2754 }
2755
2756 int
2757 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2758 {
2759         int error;
2760
2761         if (!mac_enforce_fs)
2762                 return (0);
2763
2764         MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2765
2766         return (error);
2767 }
2768
2769 int
2770 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2771     void *data)
2772 {
2773         int error;
2774
2775         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2776
2777         if (!mac_enforce_pipe)
2778                 return (0);
2779
2780         MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2781
2782         return (error);
2783 }
2784
2785 int
2786 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2787 {
2788         int error;
2789
2790         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2791
2792         if (!mac_enforce_pipe)
2793                 return (0);
2794
2795         MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2796
2797         return (error);
2798 }
2799
2800 int
2801 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2802 {
2803         int error;
2804
2805         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2806
2807         if (!mac_enforce_pipe)
2808                 return (0);
2809
2810         MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2811
2812         return (error);
2813 }
2814
2815 static int
2816 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2817     struct label *newlabel)
2818 {
2819         int error;
2820
2821         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2822
2823         if (!mac_enforce_pipe)
2824                 return (0);
2825
2826         MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2827
2828         return (error);
2829 }
2830
2831 int
2832 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2833 {
2834         int error;
2835
2836         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2837
2838         if (!mac_enforce_pipe)
2839                 return (0);
2840
2841         MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2842
2843         return (error);
2844 }
2845
2846 int
2847 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2848 {
2849         int error;
2850
2851         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2852
2853         if (!mac_enforce_pipe)
2854                 return (0);
2855
2856         MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2857
2858         return (error);
2859 }
2860
2861 int
2862 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2863 {
2864         int error;
2865
2866         PROC_LOCK_ASSERT(proc, MA_OWNED);
2867
2868         if (!mac_enforce_process)
2869                 return (0);
2870
2871         MAC_CHECK(check_proc_debug, cred, proc);
2872
2873         return (error);
2874 }
2875
2876 int
2877 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2878 {
2879         int error;
2880
2881         PROC_LOCK_ASSERT(proc, MA_OWNED);
2882
2883         if (!mac_enforce_process)
2884                 return (0);
2885
2886         MAC_CHECK(check_proc_sched, cred, proc);
2887
2888         return (error);
2889 }
2890
2891 int
2892 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2893 {
2894         int error;
2895
2896         PROC_LOCK_ASSERT(proc, MA_OWNED);
2897
2898         if (!mac_enforce_process)
2899                 return (0);
2900
2901         MAC_CHECK(check_proc_signal, cred, proc, signum);
2902
2903         return (error);
2904 }
2905
2906 int
2907 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2908     struct sockaddr *sockaddr)
2909 {
2910         int error;
2911
2912         if (!mac_enforce_socket)
2913                 return (0);
2914
2915         MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2916             sockaddr);
2917
2918         return (error);
2919 }
2920
2921 int
2922 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2923     struct sockaddr *sockaddr)
2924 {
2925         int error;
2926
2927         if (!mac_enforce_socket)
2928                 return (0);
2929
2930         MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2931             sockaddr);
2932
2933         return (error);
2934 }
2935
2936 int
2937 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2938 {
2939         int error;
2940
2941         if (!mac_enforce_socket)
2942                 return (0);
2943
2944         MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2945             &mbuf->m_pkthdr.label);
2946
2947         return (error);
2948 }
2949
2950 int
2951 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2952 {
2953         int error;
2954
2955         if (!mac_enforce_socket)
2956                 return (0);
2957
2958         MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2959         return (error);
2960 }
2961
2962 int
2963 mac_check_socket_receive(struct ucred *cred, struct socket *so)
2964 {
2965         int error;
2966
2967         if (!mac_enforce_socket)
2968                 return (0);
2969
2970         MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2971
2972         return (error);
2973 }
2974
2975 static int
2976 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2977     struct label *newlabel)
2978 {
2979         int error;
2980
2981         MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2982             newlabel);
2983
2984         return (error);
2985 }
2986
2987 int
2988 mac_check_socket_send(struct ucred *cred, struct socket *so)
2989 {
2990         int error;
2991
2992         if (!mac_enforce_socket)
2993                 return (0);
2994
2995         MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2996
2997         return (error);
2998 }
2999
3000 int
3001 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
3002 {
3003         int error;
3004
3005         if (!mac_enforce_socket)
3006                 return (0);
3007
3008         MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
3009
3010         return (error);
3011 }
3012
3013 int
3014 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3015     struct ifnet *ifnet)
3016 {
3017         char *elements, *buffer;
3018         struct mac mac;
3019         int error;
3020
3021         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3022         if (error)
3023                 return (error);
3024
3025         error = mac_check_structmac_consistent(&mac);
3026         if (error)
3027                 return (error);
3028
3029         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3030         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3031         if (error) {
3032                 free(elements, M_MACTEMP);
3033                 return (error);
3034         }
3035
3036         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3037         error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3038             buffer, mac.m_buflen, M_WAITOK);
3039         if (error == 0)
3040                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3041
3042         free(buffer, M_MACTEMP);
3043         free(elements, M_MACTEMP);
3044
3045         return (error);
3046 }
3047
3048 int
3049 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3050     struct ifnet *ifnet)
3051 {
3052         struct label intlabel;
3053         struct mac mac;
3054         char *buffer;
3055         int error;
3056
3057         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3058         if (error)
3059                 return (error);
3060
3061         error = mac_check_structmac_consistent(&mac);
3062         if (error)
3063                 return (error);
3064
3065         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3066         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3067         if (error) {
3068                 free(buffer, M_MACTEMP);
3069                 return (error);
3070         }
3071
3072         mac_init_ifnet_label(&intlabel);
3073         error = mac_internalize_ifnet_label(&intlabel, buffer);
3074         free(buffer, M_MACTEMP);
3075         if (error) {
3076                 mac_destroy_ifnet_label(&intlabel);
3077                 return (error);
3078         }
3079
3080         /*
3081          * XXX: Note that this is a redundant privilege check, since
3082          * policies impose this check themselves if required by the
3083          * policy.  Eventually, this should go away.
3084          */
3085         error = suser_cred(cred, 0);
3086         if (error) {
3087                 mac_destroy_ifnet_label(&intlabel);
3088                 return (error);
3089         }
3090
3091         MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3092             &intlabel);
3093         if (error) {
3094                 mac_destroy_ifnet_label(&intlabel);
3095                 return (error);
3096         }
3097
3098         MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3099
3100         mac_destroy_ifnet_label(&intlabel);
3101         return (0);
3102 }
3103
3104 void
3105 mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3106 {
3107
3108         MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3109 }
3110
3111 void
3112 mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3113 {
3114
3115         MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3116 }
3117
3118 void
3119 mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3120     struct devfs_dirent *de)
3121 {
3122
3123         MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3124             &de->de_label);
3125 }
3126
3127 void
3128 mac_create_devfs_directory(char *dirname, int dirnamelen,
3129     struct devfs_dirent *de)
3130 {
3131
3132         MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3133             &de->de_label);
3134 }
3135
3136 int
3137 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3138     struct mac *mac)
3139 {
3140         struct label intlabel;
3141         char *buffer;
3142         int error;
3143
3144         error = mac_check_structmac_consistent(mac);
3145         if (error)
3146                 return (error);
3147
3148         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3149         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3150         if (error) {
3151                 free(buffer, M_MACTEMP);
3152                 return (error);
3153         }
3154
3155         mac_init_socket_label(&intlabel, M_WAITOK);
3156         error = mac_internalize_socket_label(&intlabel, buffer);
3157         free(buffer, M_MACTEMP);
3158         if (error) {
3159                 mac_destroy_socket_label(&intlabel);
3160                 return (error);
3161         }
3162
3163         mac_check_socket_relabel(cred, so, &intlabel);
3164         if (error) {
3165                 mac_destroy_socket_label(&intlabel);
3166                 return (error);
3167         }
3168
3169         mac_relabel_socket(cred, so, &intlabel);
3170
3171         mac_destroy_socket_label(&intlabel);
3172         return (0);
3173 }
3174
3175 int
3176 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3177 {
3178         int error;
3179
3180         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3181
3182         error = mac_check_pipe_relabel(cred, pipe, label);
3183         if (error)
3184                 return (error);
3185
3186         mac_relabel_pipe(cred, pipe, label);
3187
3188         return (0);
3189 }
3190
3191 int
3192 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3193     struct mac *mac)
3194 {
3195         char *buffer, *elements;
3196         int error;
3197
3198         error = mac_check_structmac_consistent(mac);
3199         if (error)
3200                 return (error);
3201
3202         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3203         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3204         if (error) {
3205                 free(elements, M_MACTEMP);
3206                 return (error);
3207         }
3208
3209         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3210         error = mac_externalize_socket_label(&so->so_label, elements,
3211             buffer, mac->m_buflen, M_WAITOK);
3212         if (error == 0)
3213                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3214
3215         free(buffer, M_MACTEMP);
3216         free(elements, M_MACTEMP);
3217
3218         return (error);
3219 }
3220
3221 int
3222 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3223     struct mac *mac)
3224 {
3225         char *elements, *buffer;
3226         int error;
3227
3228         error = mac_check_structmac_consistent(mac);
3229         if (error)
3230                 return (error);
3231
3232         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3233         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3234         if (error) {
3235                 free(elements, M_MACTEMP);
3236                 return (error);
3237         }
3238
3239         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3240         error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3241             elements, buffer, mac->m_buflen, M_WAITOK);
3242         if (error == 0)
3243                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3244
3245         free(buffer, M_MACTEMP);
3246         free(elements, M_MACTEMP);
3247
3248         return (error);
3249 }
3250
3251 /*
3252  * Implementation of VOP_SETLABEL() that relies on extended attributes
3253  * to store label data.  Can be referenced by filesystems supporting
3254  * extended attributes.
3255  */
3256 int
3257 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3258 {
3259         struct vnode *vp = ap->a_vp;
3260         struct label *intlabel = ap->a_label;
3261         int error;
3262
3263         ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3264
3265         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3266                 return (EOPNOTSUPP);
3267
3268         error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3269         if (error)
3270                 return (error);
3271
3272         mac_relabel_vnode(ap->a_cred, vp, intlabel);
3273
3274         return (0);
3275 }
3276
3277 static int
3278 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3279 {
3280         int error;
3281
3282         if (vp->v_mount == NULL) {
3283                 /* printf("vn_setlabel: null v_mount\n"); */
3284                 if (vp->v_type != VNON)
3285                         printf("vn_setlabel: null v_mount with non-VNON\n");
3286                 return (EBADF);
3287         }
3288
3289         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3290                 return (EOPNOTSUPP);
3291
3292         /*
3293          * Multi-phase commit.  First check the policies to confirm the
3294          * change is OK.  Then commit via the filesystem.  Finally,
3295          * update the actual vnode label.  Question: maybe the filesystem
3296          * should update the vnode at the end as part of VOP_SETLABEL()?
3297          */
3298         error = mac_check_vnode_relabel(cred, vp, intlabel);
3299         if (error)
3300                 return (error);
3301
3302         /*
3303          * VADMIN provides the opportunity for the filesystem to make
3304          * decisions about who is and is not able to modify labels
3305          * and protections on files.  This might not be right.  We can't
3306          * assume VOP_SETLABEL() will do it, because we might implement
3307          * that as part of vop_stdsetlabel_ea().
3308          */
3309         error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3310         if (error)
3311                 return (error);
3312
3313         error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3314         if (error)
3315                 return (error);
3316
3317         return (0);
3318 }
3319
3320 int
3321 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3322 {
3323         char *elements, *buffer;
3324         struct mac mac;
3325         struct proc *tproc;
3326         struct ucred *tcred;
3327         int error;
3328
3329         error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3330         if (error)
3331                 return (error);
3332
3333         error = mac_check_structmac_consistent(&mac);
3334         if (error)
3335                 return (error);
3336
3337         tproc = pfind(uap->pid);
3338         if (tproc == NULL)
3339                 return (ESRCH);
3340
3341         tcred = NULL;                           /* Satisfy gcc. */
3342         error = p_cansee(td, tproc);
3343         if (error == 0)
3344                 tcred = crhold(tproc->p_ucred);
3345         PROC_UNLOCK(tproc);
3346         if (error)
3347                 return (error);
3348
3349         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3350         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3351         if (error) {
3352                 free(elements, M_MACTEMP);
3353                 crfree(tcred);
3354                 return (error);
3355         }
3356
3357         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3358         error = mac_externalize_cred_label(&tcred->cr_label, elements,
3359             buffer, mac.m_buflen, M_WAITOK);
3360         if (error == 0)
3361                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3362
3363         free(buffer, M_MACTEMP);
3364         free(elements, M_MACTEMP);
3365         crfree(tcred);
3366         return (error);
3367 }
3368
3369 /*
3370  * MPSAFE
3371  */
3372 int
3373 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3374 {
3375         char *elements, *buffer;
3376         struct mac mac;
3377         int error;
3378
3379         error = copyin(uap->mac_p, &mac, sizeof(mac));
3380         if (error)
3381                 return (error);
3382
3383         error = mac_check_structmac_consistent(&mac);
3384         if (error)
3385                 return (error);
3386
3387         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3388         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3389         if (error) {
3390                 free(elements, M_MACTEMP);
3391                 return (error);
3392         }
3393
3394         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3395         error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3396             elements, buffer, mac.m_buflen, M_WAITOK);
3397         if (error == 0)
3398                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3399
3400         free(buffer, M_MACTEMP);
3401         free(elements, M_MACTEMP);
3402         return (error);
3403 }
3404
3405 /*
3406  * MPSAFE
3407  */
3408 int
3409 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3410 {
3411         struct ucred *newcred, *oldcred;
3412         struct label intlabel;
3413         struct proc *p;
3414         struct mac mac;
3415         char *buffer;
3416         int error;
3417
3418         error = copyin(uap->mac_p, &mac, sizeof(mac));
3419         if (error)
3420                 return (error);
3421
3422         error = mac_check_structmac_consistent(&mac);
3423         if (error)
3424                 return (error);
3425
3426         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3427         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3428         if (error) {
3429                 free(buffer, M_MACTEMP);
3430                 return (error);
3431         }
3432
3433         mac_init_cred_label(&intlabel);
3434         error = mac_internalize_cred_label(&intlabel, buffer);
3435         free(buffer, M_MACTEMP);
3436         if (error) {
3437                 mac_destroy_cred_label(&intlabel);
3438                 return (error);
3439         }
3440
3441         newcred = crget();
3442
3443         p = td->td_proc;
3444         PROC_LOCK(p);
3445         oldcred = p->p_ucred;
3446
3447         error = mac_check_cred_relabel(oldcred, &intlabel);
3448         if (error) {
3449                 PROC_UNLOCK(p);
3450                 crfree(newcred);
3451                 goto out;
3452         }
3453
3454         setsugid(p);
3455         crcopy(newcred, oldcred);
3456         mac_relabel_cred(newcred, &intlabel);
3457         p->p_ucred = newcred;
3458
3459         /*
3460          * Grab additional reference for use while revoking mmaps, prior
3461          * to releasing the proc lock and sharing the cred.
3462          */
3463         crhold(newcred);
3464         PROC_UNLOCK(p);
3465
3466         if (mac_enforce_vm) {
3467                 mtx_lock(&Giant);
3468                 mac_cred_mmapped_drop_perms(td, newcred);
3469                 mtx_unlock(&Giant);
3470         }
3471
3472         crfree(newcred);        /* Free revocation reference. */
3473         crfree(oldcred);
3474
3475 out:
3476         mac_destroy_cred_label(&intlabel);
3477         return (error);
3478 }
3479
3480 /*
3481  * MPSAFE
3482  */
3483 int
3484 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3485 {
3486         char *elements, *buffer;
3487         struct label intlabel;
3488         struct file *fp;
3489         struct mac mac;
3490         struct vnode *vp;
3491         struct pipe *pipe;
3492         short label_type;
3493         int error;
3494
3495         error = copyin(uap->mac_p, &mac, sizeof(mac));
3496         if (error)
3497                 return (error);
3498
3499         error = mac_check_structmac_consistent(&mac);
3500         if (error)
3501                 return (error);
3502
3503         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3504         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3505         if (error) {
3506                 free(elements, M_MACTEMP);
3507                 return (error);
3508         }
3509
3510         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3511         mtx_lock(&Giant);                               /* VFS */
3512         error = fget(td, SCARG(uap, fd), &fp);
3513         if (error)
3514                 goto out;
3515
3516         label_type = fp->f_type;
3517         switch (fp->f_type) {
3518         case DTYPE_FIFO:
3519         case DTYPE_VNODE:
3520                 vp = (struct vnode *)fp->f_data;
3521
3522                 mac_init_vnode_label(&intlabel);
3523
3524                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3525                 mac_copy_vnode_label(&vp->v_label, &intlabel);
3526                 VOP_UNLOCK(vp, 0, td);
3527
3528                 break;
3529         case DTYPE_PIPE:
3530                 pipe = (struct pipe *)fp->f_data;
3531
3532                 mac_init_pipe_label(&intlabel);
3533
3534                 PIPE_LOCK(pipe);
3535                 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3536                 PIPE_UNLOCK(pipe);
3537                 break;
3538         default:
3539                 error = EINVAL;
3540                 fdrop(fp, td);
3541                 goto out;
3542         }
3543         fdrop(fp, td);
3544
3545         switch (label_type) {
3546         case DTYPE_FIFO:
3547         case DTYPE_VNODE:
3548                 if (error == 0)
3549                         error = mac_externalize_vnode_label(&intlabel,
3550                             elements, buffer, mac.m_buflen, M_WAITOK);
3551                 mac_destroy_vnode_label(&intlabel);
3552                 break;
3553         case DTYPE_PIPE:
3554                 error = mac_externalize_pipe_label(&intlabel, elements,
3555                     buffer, mac.m_buflen, M_WAITOK);
3556                 mac_destroy_pipe_label(&intlabel);
3557                 break;
3558         default:
3559                 panic("__mac_get_fd: corrupted label_type");
3560         }
3561
3562         if (error == 0)
3563                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3564
3565 out:
3566         mtx_unlock(&Giant);                             /* VFS */
3567         free(buffer, M_MACTEMP);
3568         free(elements, M_MACTEMP);
3569
3570         return (error);
3571 }
3572
3573 /*
3574  * MPSAFE
3575  */
3576 int
3577 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3578 {
3579         char *elements, *buffer;
3580         struct nameidata nd;
3581         struct label intlabel;
3582         struct mac mac;
3583         int error;
3584
3585         error = copyin(uap->mac_p, &mac, sizeof(mac));
3586         if (error)
3587                 return (error);
3588
3589         error = mac_check_structmac_consistent(&mac);
3590         if (error)
3591                 return (error);
3592
3593         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3594         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3595         if (error) {
3596                 free(elements, M_MACTEMP);
3597                 return (error);
3598         }
3599
3600         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3601         mtx_lock(&Giant);                               /* VFS */
3602         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3603             td);
3604         error = namei(&nd);
3605         if (error)
3606                 goto out;
3607
3608         mac_init_vnode_label(&intlabel);
3609         mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3610         error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3611             mac.m_buflen, M_WAITOK);
3612
3613         NDFREE(&nd, 0);
3614         mac_destroy_vnode_label(&intlabel);
3615
3616         if (error == 0)
3617                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3618
3619 out:
3620         mtx_unlock(&Giant);                             /* VFS */
3621
3622         free(buffer, M_MACTEMP);
3623         free(elements, M_MACTEMP);
3624
3625         return (error);
3626 }
3627
3628 /*
3629  * MPSAFE
3630  */
3631 int
3632 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3633 {
3634         char *elements, *buffer;
3635         struct nameidata nd;
3636         struct label intlabel;
3637         struct mac mac;
3638         int error;
3639
3640         error = copyin(uap->mac_p, &mac, sizeof(mac));
3641         if (error)
3642                 return (error);
3643
3644         error = mac_check_structmac_consistent(&mac);
3645         if (error)
3646                 return (error);
3647
3648         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3649         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3650         if (error) {
3651                 free(elements, M_MACTEMP);
3652                 return (error);
3653         }
3654
3655         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3656         mtx_lock(&Giant);                               /* VFS */
3657         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3658             td);
3659         error = namei(&nd);
3660         if (error)
3661                 goto out;
3662
3663         mac_init_vnode_label(&intlabel);
3664         mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3665         error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3666             mac.m_buflen, M_WAITOK);
3667         NDFREE(&nd, 0);
3668         mac_destroy_vnode_label(&intlabel);
3669
3670         if (error == 0)
3671                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3672
3673 out:
3674         mtx_unlock(&Giant);                             /* VFS */
3675
3676         free(buffer, M_MACTEMP);
3677         free(elements, M_MACTEMP);
3678
3679         return (error);
3680 }
3681
3682 /*
3683  * MPSAFE
3684  */
3685 int
3686 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3687 {
3688         struct label intlabel;
3689         struct pipe *pipe;
3690         struct file *fp;
3691         struct mount *mp;
3692         struct vnode *vp;
3693         struct mac mac;
3694         char *buffer;
3695         int error;
3696
3697         error = copyin(uap->mac_p, &mac, sizeof(mac));
3698         if (error)
3699                 return (error);
3700
3701         error = mac_check_structmac_consistent(&mac);
3702         if (error)
3703                 return (error);
3704
3705         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3706         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3707         if (error) {
3708                 free(buffer, M_MACTEMP);
3709                 return (error);
3710         }
3711
3712         mtx_lock(&Giant);                               /* VFS */
3713
3714         error = fget(td, SCARG(uap, fd), &fp);
3715         if (error)
3716                 goto out;
3717
3718         switch (fp->f_type) {
3719         case DTYPE_FIFO:
3720         case DTYPE_VNODE:
3721                 mac_init_vnode_label(&intlabel);
3722                 error = mac_internalize_vnode_label(&intlabel, buffer);
3723                 if (error) {
3724                         mac_destroy_vnode_label(&intlabel);
3725                         break;
3726                 }
3727
3728                 vp = (struct vnode *)fp->f_data;
3729                 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3730                 if (error != 0) {
3731                         mac_destroy_vnode_label(&intlabel);
3732                         break;
3733                 }
3734
3735                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3736                 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3737                 VOP_UNLOCK(vp, 0, td);
3738                 vn_finished_write(mp);
3739
3740                 mac_destroy_vnode_label(&intlabel);
3741                 break;
3742
3743         case DTYPE_PIPE:
3744                 mac_init_pipe_label(&intlabel);
3745                 error = mac_internalize_pipe_label(&intlabel, buffer);
3746                 if (error == 0) {
3747                         pipe = (struct pipe *)fp->f_data;
3748                         PIPE_LOCK(pipe);
3749                         error = mac_pipe_label_set(td->td_ucred, pipe,
3750                             &intlabel);
3751                         PIPE_UNLOCK(pipe);
3752                 }
3753
3754                 mac_destroy_pipe_label(&intlabel);
3755                 break;
3756
3757         default:
3758                 error = EINVAL;
3759         }
3760
3761         fdrop(fp, td);
3762 out:
3763         mtx_unlock(&Giant);                             /* VFS */
3764
3765         free(buffer, M_MACTEMP);
3766
3767         return (error);
3768 }
3769
3770 /*
3771  * MPSAFE
3772  */
3773 int
3774 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3775 {
3776         struct label intlabel;
3777         struct nameidata nd;
3778         struct mount *mp;
3779         struct mac mac;
3780         char *buffer;
3781         int error;
3782
3783         error = copyin(uap->mac_p, &mac, sizeof(mac));
3784         if (error)
3785                 return (error);
3786
3787         error = mac_check_structmac_consistent(&mac);
3788         if (error)
3789                 return (error);
3790
3791         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3792         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3793         if (error) {
3794                 free(buffer, M_MACTEMP);
3795                 return (error);
3796         }
3797
3798         mac_init_vnode_label(&intlabel);
3799         error = mac_internalize_vnode_label(&intlabel, buffer);
3800         free(buffer, M_MACTEMP);
3801         if (error) {
3802                 mac_destroy_vnode_label(&intlabel);
3803                 return (error);
3804         }
3805
3806         mtx_lock(&Giant);                               /* VFS */
3807
3808         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3809             td);
3810         error = namei(&nd);
3811         if (error == 0) {
3812                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3813                 if (error == 0)
3814                         error = vn_setlabel(nd.ni_vp, &intlabel,
3815                             td->td_ucred);
3816                 vn_finished_write(mp);
3817         }
3818
3819         NDFREE(&nd, 0);
3820         mtx_unlock(&Giant);                             /* VFS */
3821         mac_destroy_vnode_label(&intlabel);
3822
3823         return (error);
3824 }
3825
3826 /*
3827  * MPSAFE
3828  */
3829 int
3830 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3831 {
3832         struct label intlabel;
3833         struct nameidata nd;
3834         struct mount *mp;
3835         struct mac mac;
3836         char *buffer;
3837         int error;
3838
3839         error = copyin(uap->mac_p, &mac, sizeof(mac));
3840         if (error)
3841                 return (error);
3842
3843         error = mac_check_structmac_consistent(&mac);
3844         if (error)
3845                 return (error);
3846
3847         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3848         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3849         if (error) {
3850                 free(buffer, M_MACTEMP);
3851                 return (error);
3852         }
3853
3854         mac_init_vnode_label(&intlabel);
3855         error = mac_internalize_vnode_label(&intlabel, buffer);
3856         free(buffer, M_MACTEMP);
3857         if (error) {
3858                 mac_destroy_vnode_label(&intlabel);
3859                 return (error);
3860         }
3861
3862         mtx_lock(&Giant);                               /* VFS */
3863
3864         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3865             td);
3866         error = namei(&nd);
3867         if (error == 0) {
3868                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3869                 if (error == 0)
3870                         error = vn_setlabel(nd.ni_vp, &intlabel,
3871                             td->td_ucred);
3872                 vn_finished_write(mp);
3873         }
3874
3875         NDFREE(&nd, 0);
3876         mtx_unlock(&Giant);                             /* VFS */
3877         mac_destroy_vnode_label(&intlabel);
3878
3879         return (error);
3880 }
3881
3882 /*
3883  * MPSAFE
3884  */
3885 int
3886 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3887 {
3888         struct mac_policy_conf *mpc;
3889         char target[MAC_MAX_POLICY_NAME];
3890         int error;
3891
3892         error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3893         if (error)
3894                 return (error);
3895
3896         error = ENOSYS;
3897         MAC_POLICY_LIST_BUSY();
3898         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3899                 if (strcmp(mpc->mpc_name, target) == 0 &&
3900                     mpc->mpc_ops->mpo_syscall != NULL) {
3901                         error = mpc->mpc_ops->mpo_syscall(td,
3902                             SCARG(uap, call), SCARG(uap, arg));
3903                         goto out;
3904                 }
3905         }
3906
3907 out:
3908         MAC_POLICY_LIST_UNBUSY();
3909         return (error);
3910 }
3911
3912 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3913 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3914
3915 #else /* !MAC */
3916
3917 int
3918 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3919 {
3920
3921         return (ENOSYS);
3922 }
3923
3924 int
3925 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3926 {
3927
3928         return (ENOSYS);
3929 }
3930
3931 int
3932 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3933 {
3934
3935         return (ENOSYS);
3936 }
3937
3938 int
3939 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3940 {
3941
3942         return (ENOSYS);
3943 }
3944
3945 int
3946 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3947 {
3948
3949         return (ENOSYS);
3950 }
3951
3952 int
3953 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3954 {
3955
3956         return (ENOSYS);
3957 }
3958
3959 int
3960 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3961 {
3962
3963         return (ENOSYS);
3964 }
3965
3966 int
3967 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3968 {
3969
3970         return (ENOSYS);
3971 }
3972
3973 int
3974 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3975 {
3976
3977         return (ENOSYS);
3978 }
3979
3980 int
3981 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3982 {
3983
3984         return (ENOSYS);
3985 }
3986
3987 #endif