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