]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/security/mac/mac_vfs.c
This commit was generated by cvs2svn to compensate for changes in r105770,
[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_SWAPON:
1030                         mpc->mpc_ops->mpo_check_vnode_swapon =
1031                             mpe->mpe_function;
1032                         break;
1033                 case MAC_CHECK_VNODE_WRITE:
1034                         mpc->mpc_ops->mpo_check_vnode_write =
1035                             mpe->mpe_function;
1036                         break;
1037 /*
1038                 default:
1039                         printf("MAC policy `%s': unknown operation %d\n",
1040                             mpc->mpc_name, mpe->mpe_constant);
1041                         return (EINVAL);
1042 */
1043                 }
1044         }
1045         MAC_POLICY_LIST_LOCK();
1046         if (mac_policy_list_busy > 0) {
1047                 MAC_POLICY_LIST_UNLOCK();
1048                 FREE(mpc->mpc_ops, M_MACOPVEC);
1049                 mpc->mpc_ops = NULL;
1050                 return (EBUSY);
1051         }
1052         LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
1053                 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
1054                         MAC_POLICY_LIST_UNLOCK();
1055                         FREE(mpc->mpc_ops, M_MACOPVEC);
1056                         mpc->mpc_ops = NULL;
1057                         return (EEXIST);
1058                 }
1059         }
1060         if (mpc->mpc_field_off != NULL) {
1061                 slot = ffs(mac_policy_offsets_free);
1062                 if (slot == 0) {
1063                         MAC_POLICY_LIST_UNLOCK();
1064                         FREE(mpc->mpc_ops, M_MACOPVEC);
1065                         mpc->mpc_ops = NULL;
1066                         return (ENOMEM);
1067                 }
1068                 slot--;
1069                 mac_policy_offsets_free &= ~(1 << slot);
1070                 *mpc->mpc_field_off = slot;
1071         }
1072         mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
1073         LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
1074
1075         /* Per-policy initialization. */
1076         if (mpc->mpc_ops->mpo_init != NULL)
1077                 (*(mpc->mpc_ops->mpo_init))(mpc);
1078         MAC_POLICY_LIST_UNLOCK();
1079
1080         printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
1081             mpc->mpc_name);
1082
1083         return (0);
1084 }
1085
1086 static int
1087 mac_policy_unregister(struct mac_policy_conf *mpc)
1088 {
1089
1090         /*
1091          * If we fail the load, we may get a request to unload.  Check
1092          * to see if we did the run-time registration, and if not,
1093          * silently succeed.
1094          */
1095         MAC_POLICY_LIST_LOCK();
1096         if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
1097                 MAC_POLICY_LIST_UNLOCK();
1098                 return (0);
1099         }
1100 #if 0
1101         /*
1102          * Don't allow unloading modules with private data.
1103          */
1104         if (mpc->mpc_field_off != NULL) {
1105                 MAC_POLICY_LIST_UNLOCK();
1106                 return (EBUSY);
1107         }
1108 #endif
1109         /*
1110          * Only allow the unload to proceed if the module is unloadable
1111          * by its own definition.
1112          */
1113         if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
1114                 MAC_POLICY_LIST_UNLOCK();
1115                 return (EBUSY);
1116         }
1117         /*
1118          * Right now, we EBUSY if the list is in use.  In the future,
1119          * for reliability reasons, we might want to sleep and wakeup
1120          * later to try again.
1121          */
1122         if (mac_policy_list_busy > 0) {
1123                 MAC_POLICY_LIST_UNLOCK();
1124                 return (EBUSY);
1125         }
1126         if (mpc->mpc_ops->mpo_destroy != NULL)
1127                 (*(mpc->mpc_ops->mpo_destroy))(mpc);
1128
1129         LIST_REMOVE(mpc, mpc_list);
1130         MAC_POLICY_LIST_UNLOCK();
1131
1132         FREE(mpc->mpc_ops, M_MACOPVEC);
1133         mpc->mpc_ops = NULL;
1134         mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
1135
1136         printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
1137             mpc->mpc_name);
1138
1139         return (0);
1140 }
1141
1142 /*
1143  * Define an error value precedence, and given two arguments, selects the
1144  * value with the higher precedence.
1145  */
1146 static int
1147 error_select(int error1, int error2)
1148 {
1149
1150         /* Certain decision-making errors take top priority. */
1151         if (error1 == EDEADLK || error2 == EDEADLK)
1152                 return (EDEADLK);
1153
1154         /* Invalid arguments should be reported where possible. */
1155         if (error1 == EINVAL || error2 == EINVAL)
1156                 return (EINVAL);
1157
1158         /* Precedence goes to "visibility", with both process and file. */
1159         if (error1 == ESRCH || error2 == ESRCH)
1160                 return (ESRCH);
1161
1162         if (error1 == ENOENT || error2 == ENOENT)
1163                 return (ENOENT);
1164
1165         /* Precedence goes to DAC/MAC protections. */
1166         if (error1 == EACCES || error2 == EACCES)
1167                 return (EACCES);
1168
1169         /* Precedence goes to privilege. */
1170         if (error1 == EPERM || error2 == EPERM)
1171                 return (EPERM);
1172
1173         /* Precedence goes to error over success; otherwise, arbitrary. */
1174         if (error1 != 0)
1175                 return (error1);
1176         return (error2);
1177 }
1178
1179 static void
1180 mac_init_label(struct label *label)
1181 {
1182
1183         bzero(label, sizeof(*label));
1184         label->l_flags = MAC_FLAG_INITIALIZED;
1185 }
1186
1187 static void
1188 mac_destroy_label(struct label *label)
1189 {
1190
1191         KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1192             ("destroying uninitialized label"));
1193
1194         bzero(label, sizeof(*label));
1195         /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1196 }
1197
1198 void
1199 mac_init_bpfdesc(struct bpf_d *bpf_d)
1200 {
1201
1202         mac_init_label(&bpf_d->bd_label);
1203         MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1204 #ifdef MAC_DEBUG
1205         atomic_add_int(&nmacbpfdescs, 1);
1206 #endif
1207 }
1208
1209 static void
1210 mac_init_cred_label(struct label *label)
1211 {
1212
1213         mac_init_label(label);
1214         MAC_PERFORM(init_cred_label, label);
1215 #ifdef MAC_DEBUG
1216         atomic_add_int(&nmaccreds, 1);
1217 #endif
1218 }
1219
1220 void
1221 mac_init_cred(struct ucred *cred)
1222 {
1223
1224         mac_init_cred_label(&cred->cr_label);
1225 }
1226
1227 void
1228 mac_init_devfsdirent(struct devfs_dirent *de)
1229 {
1230
1231         mac_init_label(&de->de_label);
1232         MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1233 #ifdef MAC_DEBUG
1234         atomic_add_int(&nmacdevfsdirents, 1);
1235 #endif
1236 }
1237
1238 static void
1239 mac_init_ifnet_label(struct label *label)
1240 {
1241
1242         mac_init_label(label);
1243         MAC_PERFORM(init_ifnet_label, label);
1244 #ifdef MAC_DEBUG
1245         atomic_add_int(&nmacifnets, 1);
1246 #endif
1247 }
1248
1249 void
1250 mac_init_ifnet(struct ifnet *ifp)
1251 {
1252
1253         mac_init_ifnet_label(&ifp->if_label);
1254 }
1255
1256 void
1257 mac_init_ipq(struct ipq *ipq)
1258 {
1259
1260         mac_init_label(&ipq->ipq_label);
1261         MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1262 #ifdef MAC_DEBUG
1263         atomic_add_int(&nmacipqs, 1);
1264 #endif
1265 }
1266
1267 int
1268 mac_init_mbuf(struct mbuf *m, int flag)
1269 {
1270         int error;
1271
1272         KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1273
1274         mac_init_label(&m->m_pkthdr.label);
1275
1276         MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
1277         if (error) {
1278                 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1279                 mac_destroy_label(&m->m_pkthdr.label);
1280         }
1281
1282 #ifdef MAC_DEBUG
1283         if (error == 0)
1284                 atomic_add_int(&nmacmbufs, 1);
1285 #endif
1286         return (error);
1287 }
1288
1289 void
1290 mac_init_mount(struct mount *mp)
1291 {
1292
1293         mac_init_label(&mp->mnt_mntlabel);
1294         mac_init_label(&mp->mnt_fslabel);
1295         MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1296         MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1297 #ifdef MAC_DEBUG
1298         atomic_add_int(&nmacmounts, 1);
1299 #endif
1300 }
1301
1302 static void
1303 mac_init_pipe_label(struct label *label)
1304 {
1305
1306         mac_init_label(label);
1307         MAC_PERFORM(init_pipe_label, label);
1308 #ifdef MAC_DEBUG
1309         atomic_add_int(&nmacpipes, 1);
1310 #endif
1311 }
1312
1313 void
1314 mac_init_pipe(struct pipe *pipe)
1315 {
1316         struct label *label;
1317
1318         label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1319         pipe->pipe_label = label;
1320         pipe->pipe_peer->pipe_label = label;
1321         mac_init_pipe_label(label);
1322 }
1323
1324 static int
1325 mac_init_socket_label(struct label *label, int flag)
1326 {
1327         int error;
1328
1329         mac_init_label(label);
1330
1331         MAC_CHECK(init_socket_label, label, flag);
1332         if (error) {
1333                 MAC_PERFORM(destroy_socket_label, label);
1334                 mac_destroy_label(label);
1335         }
1336
1337 #ifdef MAC_DEBUG
1338         if (error == 0)
1339                 atomic_add_int(&nmacsockets, 1);
1340 #endif
1341
1342         return (error);
1343 }
1344
1345 static int
1346 mac_init_socket_peer_label(struct label *label, int flag)
1347 {
1348         int error;
1349
1350         mac_init_label(label);
1351
1352         MAC_CHECK(init_socket_peer_label, label, flag);
1353         if (error) {
1354                 MAC_PERFORM(destroy_socket_label, label);
1355                 mac_destroy_label(label);
1356         }
1357
1358         return (error);
1359 }
1360
1361 int
1362 mac_init_socket(struct socket *socket, int flag)
1363 {
1364         int error;
1365
1366         error = mac_init_socket_label(&socket->so_label, flag);
1367         if (error)
1368                 return (error);
1369
1370         error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1371         if (error)
1372                 mac_destroy_socket_label(&socket->so_label);
1373
1374         return (error);
1375 }
1376
1377 static void
1378 mac_init_vnode_label(struct label *label)
1379 {
1380
1381         mac_init_label(label);
1382         MAC_PERFORM(init_vnode_label, label);
1383 #ifdef MAC_DEBUG
1384         atomic_add_int(&nmacvnodes, 1);
1385 #endif
1386 }
1387
1388 void
1389 mac_init_vnode(struct vnode *vp)
1390 {
1391
1392         mac_init_vnode_label(&vp->v_label);
1393 }
1394
1395 void
1396 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1397 {
1398
1399         MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1400         mac_destroy_label(&bpf_d->bd_label);
1401 #ifdef MAC_DEBUG
1402         atomic_subtract_int(&nmacbpfdescs, 1);
1403 #endif
1404 }
1405
1406 static void
1407 mac_destroy_cred_label(struct label *label)
1408 {
1409
1410         MAC_PERFORM(destroy_cred_label, label);
1411         mac_destroy_label(label);
1412 #ifdef MAC_DEBUG
1413         atomic_subtract_int(&nmaccreds, 1);
1414 #endif
1415 }
1416
1417 void
1418 mac_destroy_cred(struct ucred *cred)
1419 {
1420
1421         mac_destroy_cred_label(&cred->cr_label);
1422 }
1423
1424 void
1425 mac_destroy_devfsdirent(struct devfs_dirent *de)
1426 {
1427
1428         MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1429         mac_destroy_label(&de->de_label);
1430 #ifdef MAC_DEBUG
1431         atomic_subtract_int(&nmacdevfsdirents, 1);
1432 #endif
1433 }
1434
1435 static void
1436 mac_destroy_ifnet_label(struct label *label)
1437 {
1438
1439         MAC_PERFORM(destroy_ifnet_label, label);
1440         mac_destroy_label(label);
1441 #ifdef MAC_DEBUG
1442         atomic_subtract_int(&nmacifnets, 1);
1443 #endif
1444 }
1445
1446 void
1447 mac_destroy_ifnet(struct ifnet *ifp)
1448 {
1449
1450         mac_destroy_ifnet_label(&ifp->if_label);
1451 }
1452
1453 void
1454 mac_destroy_ipq(struct ipq *ipq)
1455 {
1456
1457         MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1458         mac_destroy_label(&ipq->ipq_label);
1459 #ifdef MAC_DEBUG
1460         atomic_subtract_int(&nmacipqs, 1);
1461 #endif
1462 }
1463
1464 void
1465 mac_destroy_mbuf(struct mbuf *m)
1466 {
1467
1468         MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1469         mac_destroy_label(&m->m_pkthdr.label);
1470 #ifdef MAC_DEBUG
1471         atomic_subtract_int(&nmacmbufs, 1);
1472 #endif
1473 }
1474
1475 void
1476 mac_destroy_mount(struct mount *mp)
1477 {
1478
1479         MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1480         MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1481         mac_destroy_label(&mp->mnt_fslabel);
1482         mac_destroy_label(&mp->mnt_mntlabel);
1483 #ifdef MAC_DEBUG
1484         atomic_subtract_int(&nmacmounts, 1);
1485 #endif
1486 }
1487
1488 static void
1489 mac_destroy_pipe_label(struct label *label)
1490 {
1491
1492         MAC_PERFORM(destroy_pipe_label, label);
1493         mac_destroy_label(label);
1494 #ifdef MAC_DEBUG
1495         atomic_subtract_int(&nmacpipes, 1);
1496 #endif
1497 }
1498
1499 void
1500 mac_destroy_pipe(struct pipe *pipe)
1501 {
1502
1503         mac_destroy_pipe_label(pipe->pipe_label);
1504         free(pipe->pipe_label, M_MACPIPELABEL);
1505 }
1506
1507 static void
1508 mac_destroy_socket_label(struct label *label)
1509 {
1510
1511         MAC_PERFORM(destroy_socket_label, label);
1512         mac_destroy_label(label);
1513 #ifdef MAC_DEBUG
1514         atomic_subtract_int(&nmacsockets, 1);
1515 #endif
1516 }
1517
1518 static void
1519 mac_destroy_socket_peer_label(struct label *label)
1520 {
1521
1522         MAC_PERFORM(destroy_socket_peer_label, label);
1523         mac_destroy_label(label);
1524 }
1525
1526 void
1527 mac_destroy_socket(struct socket *socket)
1528 {
1529
1530         mac_destroy_socket_label(&socket->so_label);
1531         mac_destroy_socket_peer_label(&socket->so_peerlabel);
1532 }
1533
1534 static void
1535 mac_destroy_vnode_label(struct label *label)
1536 {
1537
1538         MAC_PERFORM(destroy_vnode_label, label);
1539         mac_destroy_label(label);
1540 #ifdef MAC_DEBUG
1541         atomic_subtract_int(&nmacvnodes, 1);
1542 #endif
1543 }
1544
1545 void
1546 mac_destroy_vnode(struct vnode *vp)
1547 {
1548
1549         mac_destroy_vnode_label(&vp->v_label);
1550 }
1551
1552 static void
1553 mac_copy_pipe_label(struct label *src, struct label *dest)
1554 {
1555
1556         MAC_PERFORM(copy_pipe_label, src, dest);
1557 }
1558
1559 static void
1560 mac_copy_vnode_label(struct label *src, struct label *dest)
1561 {
1562
1563         MAC_PERFORM(copy_vnode_label, src, dest);
1564 }
1565
1566 static int
1567 mac_check_structmac_consistent(struct mac *mac)
1568 {
1569
1570         if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1571                 return (EINVAL);
1572
1573         return (0);
1574 }
1575
1576 static int
1577 mac_externalize_cred_label(struct label *label, char *elements,
1578     char *outbuf, size_t outbuflen, int flags)
1579 {
1580         int error;
1581
1582         MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1583
1584         return (error);
1585 }
1586
1587 static int
1588 mac_externalize_ifnet_label(struct label *label, char *elements,
1589     char *outbuf, size_t outbuflen, int flags)
1590 {
1591         int error;
1592
1593         MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1594
1595         return (error);
1596 }
1597
1598 static int
1599 mac_externalize_pipe_label(struct label *label, char *elements,
1600     char *outbuf, size_t outbuflen, int flags)
1601 {
1602         int error;
1603
1604         MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1605
1606         return (error);
1607 }
1608
1609 static int
1610 mac_externalize_socket_label(struct label *label, char *elements,
1611     char *outbuf, size_t outbuflen, int flags)
1612 {
1613         int error;
1614
1615         MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1616
1617         return (error);
1618 }
1619
1620 static int
1621 mac_externalize_socket_peer_label(struct label *label, char *elements,
1622     char *outbuf, size_t outbuflen, int flags)
1623 {
1624         int error;
1625
1626         MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1627
1628         return (error);
1629 }
1630
1631 static int
1632 mac_externalize_vnode_label(struct label *label, char *elements,
1633     char *outbuf, size_t outbuflen, int flags)
1634 {
1635         int error;
1636
1637         MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1638
1639         return (error);
1640 }
1641
1642 static int
1643 mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac)
1644 {
1645         int error;
1646
1647         MAC_CHECK(externalize_vnode_oldmac, label, extmac);
1648
1649         return (error);
1650 }
1651
1652 static int
1653 mac_internalize_cred_label(struct label *label, char *string)
1654 {
1655         int error;
1656
1657         MAC_INTERNALIZE(cred_label, label, string);
1658
1659         return (error);
1660 }
1661
1662 static int
1663 mac_internalize_ifnet_label(struct label *label, char *string)
1664 {
1665         int error;
1666
1667         MAC_INTERNALIZE(ifnet_label, label, string);
1668
1669         return (error);
1670 }
1671
1672 static int
1673 mac_internalize_pipe_label(struct label *label, char *string)
1674 {
1675         int error;
1676
1677         MAC_INTERNALIZE(pipe_label, label, string);
1678
1679         return (error);
1680 }
1681
1682 static int
1683 mac_internalize_socket_label(struct label *label, char *string)
1684 {
1685         int error;
1686
1687         MAC_INTERNALIZE(socket_label, label, string);
1688
1689         return (error);
1690 }
1691
1692 static int
1693 mac_internalize_vnode_label(struct label *label, char *string)
1694 {
1695         int error;
1696
1697         MAC_INTERNALIZE(vnode_label, label, string);
1698
1699         return (error);
1700 }
1701
1702 /*
1703  * Initialize MAC label for the first kernel process, from which other
1704  * kernel processes and threads are spawned.
1705  */
1706 void
1707 mac_create_proc0(struct ucred *cred)
1708 {
1709
1710         MAC_PERFORM(create_proc0, cred);
1711 }
1712
1713 /*
1714  * Initialize MAC label for the first userland process, from which other
1715  * userland processes and threads are spawned.
1716  */
1717 void
1718 mac_create_proc1(struct ucred *cred)
1719 {
1720
1721         MAC_PERFORM(create_proc1, cred);
1722 }
1723
1724 void
1725 mac_thread_userret(struct thread *td)
1726 {
1727
1728         MAC_PERFORM(thread_userret, td);
1729 }
1730
1731 /*
1732  * When a new process is created, its label must be initialized.  Generally,
1733  * this involves inheritence from the parent process, modulo possible
1734  * deltas.  This function allows that processing to take place.
1735  */
1736 void
1737 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1738 {
1739
1740         MAC_PERFORM(create_cred, parent_cred, child_cred);
1741 }
1742
1743 void
1744 mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1745 {
1746
1747         MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1748 }
1749
1750 void
1751 mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1752 {
1753
1754         MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1755 }
1756
1757 /*
1758  * Support callout for policies that manage their own externalization
1759  * using extended attributes.
1760  */
1761 static int
1762 mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1763 {
1764         int error;
1765
1766         MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1767             &mp->mnt_fslabel);
1768
1769         return (error);
1770 }
1771
1772 /*
1773  * Given an externalized mac label, internalize it and stamp it on a
1774  * vnode.
1775  */
1776 static int
1777 mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac)
1778 {
1779         int error;
1780
1781         MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1782
1783         return (error);
1784 }
1785
1786 /*
1787  * Call out to individual policies to update the label in a vnode from
1788  * the mountpoint.
1789  */
1790 void
1791 mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1792 {
1793
1794         MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1795             &mp->mnt_fslabel);
1796
1797         ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1798         if (mac_cache_fslabel_in_vnode)
1799                 vp->v_vflag |= VV_CACHEDLABEL;
1800 }
1801
1802 /*
1803  * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1804  * to store label data.  Can be referenced by filesystems supporting
1805  * extended attributes.
1806  */
1807 int
1808 vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1809 {
1810         struct vnode *vp = ap->a_vp;
1811         struct oldmac extmac;
1812         int buflen, error;
1813
1814         ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1815
1816         /*
1817          * Call out to external policies first.  Order doesn't really
1818          * matter, as long as failure of one assures failure of all.
1819          */
1820         error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1821         if (error)
1822                 return (error);
1823
1824         buflen = sizeof(extmac);
1825         error = vn_extattr_get(vp, IO_NODELOCKED,
1826             FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1827             (char *)&extmac, curthread);
1828         switch (error) {
1829         case 0:
1830                 /* Got it */
1831                 break;
1832
1833         case ENOATTR:
1834                 /*
1835                  * Use the label from the mount point.
1836                  */
1837                 mac_update_vnode_from_mount(vp, vp->v_mount);
1838                 return (0);
1839
1840         case EOPNOTSUPP:
1841         default:
1842                 /* Fail horribly. */
1843                 return (error);
1844         }
1845
1846         if (buflen != sizeof(extmac))
1847                 error = EPERM;          /* Fail very closed. */
1848         if (error == 0)
1849                 error = mac_update_vnode_from_externalized(vp, &extmac);
1850         if (error == 0)
1851                 vp->v_vflag |= VV_CACHEDLABEL;
1852         else {
1853                 struct vattr va;
1854
1855                 printf("Corrupted label on %s",
1856                     vp->v_mount->mnt_stat.f_mntonname);
1857                 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1858                         printf(" inum %ld", va.va_fileid);
1859 #ifdef MAC_DEBUG
1860                 if (mac_debug_label_fallback) {
1861                         printf(", falling back.\n");
1862                         mac_update_vnode_from_mount(vp, vp->v_mount);
1863                         error = 0;
1864                 } else {
1865 #endif
1866                         printf(".\n");
1867                         error = EPERM;
1868 #ifdef MAC_DEBUG
1869                 }
1870 #endif
1871         }
1872
1873         return (error);
1874 }
1875
1876 /*
1877  * Make sure the vnode label is up-to-date.  If EOPNOTSUPP, then we handle
1878  * the labeling activity outselves.  Filesystems should be careful not
1879  * to change their minds regarding whether they support vop_refreshlabel()
1880  * for a vnode or not.  Don't cache the vnode here, allow the file
1881  * system code to determine if it's safe to cache.  If we update from
1882  * the mount, don't cache since a change to the mount label should affect
1883  * all vnodes.
1884  */
1885 static int
1886 vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1887 {
1888         int error;
1889
1890         ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1891
1892         if (vp->v_mount == NULL) {
1893 /*
1894                 Eventually, we probably want to special-case refreshing
1895                 of deadfs vnodes, and if there's a lock-free race somewhere,
1896                 that case might be handled here.
1897
1898                 mac_update_vnode_deadfs(vp);
1899                 return (0);
1900  */
1901                 /* printf("vn_refreshlabel: null v_mount\n"); */
1902                 if (vp->v_type != VNON)
1903                         printf(
1904                             "vn_refreshlabel: null v_mount with non-VNON\n");
1905                 return (EBADF);
1906         }
1907
1908         if (vp->v_vflag & VV_CACHEDLABEL) {
1909                 mac_vnode_label_cache_hits++;
1910                 return (0);
1911         } else
1912                 mac_vnode_label_cache_misses++;
1913
1914         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1915                 mac_update_vnode_from_mount(vp, vp->v_mount);
1916                 return (0);
1917         }
1918
1919         error = VOP_REFRESHLABEL(vp, cred, curthread);
1920         switch (error) {
1921         case EOPNOTSUPP:
1922                 /*
1923                  * If labels are not supported on this vnode, fall back to
1924                  * the label in the mount and propagate it to the vnode.
1925                  * There should probably be some sort of policy/flag/decision
1926                  * about doing this.
1927                  */
1928                 mac_update_vnode_from_mount(vp, vp->v_mount);
1929                 error = 0;
1930         default:
1931                 return (error);
1932         }
1933 }
1934
1935 /*
1936  * Helper function for file systems using the vop_std*_ea() calls.  This
1937  * function must be called after EA service is available for the vnode,
1938  * but before it's hooked up to the namespace so that the node persists
1939  * if there's a crash, or before it can be accessed.  On successful
1940  * commit of the label to disk (etc), do cache the label.
1941  */
1942 int
1943 vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1944 {
1945         struct oldmac extmac;
1946         int error;
1947
1948         ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1949         if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1950                 mac_update_vnode_from_mount(tvp, tvp->v_mount);
1951         } else {
1952                 error = vn_refreshlabel(dvp, cred);
1953                 if (error)
1954                         return (error);
1955
1956                 /*
1957                  * Stick the label in the vnode.  Then try to write to
1958                  * disk.  If we fail, return a failure to abort the
1959                  * create operation.  Really, this failure shouldn't
1960                  * happen except in fairly unusual circumstances (out
1961                  * of disk, etc).
1962                  */
1963                 mac_create_vnode(cred, dvp, tvp);
1964
1965                 error = mac_stdcreatevnode_ea(tvp);
1966                 if (error)
1967                         return (error);
1968
1969                 /*
1970                  * XXX: Eventually this will go away and all policies will
1971                  * directly manage their extended attributes.
1972                  */
1973                 error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac);
1974                 if (error)
1975                         return (error);
1976
1977                 error = vn_extattr_set(tvp, IO_NODELOCKED,
1978                     FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1979                     sizeof(extmac), (char *)&extmac, curthread);
1980                 if (error == 0)
1981                         tvp->v_vflag |= VV_CACHEDLABEL;
1982                 else {
1983 #if 0
1984                         /*
1985                          * In theory, we could have fall-back behavior here.
1986                          * It would probably be incorrect.
1987                          */
1988 #endif
1989                         return (error);
1990                 }
1991         }
1992
1993         return (0);
1994 }
1995
1996 void
1997 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1998 {
1999         int error;
2000
2001         ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
2002
2003         error = vn_refreshlabel(vp, old);
2004         if (error) {
2005                 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
2006                     error);
2007                 printf("mac_execve_transition: using old vnode label\n");
2008         }
2009
2010         MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
2011 }
2012
2013 int
2014 mac_execve_will_transition(struct ucred *old, struct vnode *vp)
2015 {
2016         int error, result;
2017
2018         error = vn_refreshlabel(vp, old);
2019         if (error)
2020                 return (error);
2021
2022         result = 0;
2023         MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
2024
2025         return (result);
2026 }
2027
2028 int
2029 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
2030 {
2031         int error;
2032
2033         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
2034
2035         if (!mac_enforce_fs)
2036                 return (0);
2037
2038         error = vn_refreshlabel(vp, cred);
2039         if (error)
2040                 return (error);
2041
2042         MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
2043         return (error);
2044 }
2045
2046 int
2047 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
2048 {
2049         int error;
2050
2051         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
2052
2053         if (!mac_enforce_fs)
2054                 return (0);
2055
2056         error = vn_refreshlabel(dvp, cred);
2057         if (error)
2058                 return (error);
2059
2060         MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
2061         return (error);
2062 }
2063
2064 int
2065 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
2066 {
2067         int error;
2068
2069         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
2070
2071         if (!mac_enforce_fs)
2072                 return (0);
2073
2074         error = vn_refreshlabel(dvp, cred);
2075         if (error)
2076                 return (error);
2077
2078         MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
2079         return (error);
2080 }
2081
2082 int
2083 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2084     struct componentname *cnp, struct vattr *vap)
2085 {
2086         int error;
2087
2088         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
2089
2090         if (!mac_enforce_fs)
2091                 return (0);
2092
2093         error = vn_refreshlabel(dvp, cred);
2094         if (error)
2095                 return (error);
2096
2097         MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
2098         return (error);
2099 }
2100
2101 int
2102 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
2103     struct componentname *cnp)
2104 {
2105         int error;
2106
2107         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
2108         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
2109
2110         if (!mac_enforce_fs)
2111                 return (0);
2112
2113         error = vn_refreshlabel(dvp, cred);
2114         if (error)
2115                 return (error);
2116         error = vn_refreshlabel(vp, cred);
2117         if (error)
2118                 return (error);
2119
2120         MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
2121             &vp->v_label, cnp);
2122         return (error);
2123 }
2124
2125 int
2126 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2127     acl_type_t type)
2128 {
2129         int error;
2130
2131         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
2132
2133         if (!mac_enforce_fs)
2134                 return (0);
2135
2136         error = vn_refreshlabel(vp, cred);
2137         if (error)
2138                 return (error);
2139
2140         MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
2141         return (error);
2142 }
2143
2144 int
2145 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
2146 {
2147         int error;
2148
2149         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
2150
2151         if (!mac_enforce_process && !mac_enforce_fs)
2152                 return (0);
2153
2154         error = vn_refreshlabel(vp, cred);
2155         if (error)
2156                 return (error);
2157         MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
2158
2159         return (error);
2160 }
2161
2162 int
2163 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
2164 {
2165         int error;
2166
2167         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
2168
2169         if (!mac_enforce_fs)
2170                 return (0);
2171
2172         error = vn_refreshlabel(vp, cred);
2173         if (error)
2174                 return (error);
2175
2176         MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
2177         return (error);
2178 }
2179
2180 int
2181 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2182     int attrnamespace, const char *name, struct uio *uio)
2183 {
2184         int error;
2185
2186         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
2187
2188         if (!mac_enforce_fs)
2189                 return (0);
2190
2191         error = vn_refreshlabel(vp, cred);
2192         if (error)
2193                 return (error);
2194
2195         MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
2196             attrnamespace, name, uio);
2197         return (error);
2198 }
2199
2200 int
2201 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2202     struct vnode *vp, struct componentname *cnp)
2203 {
2204         int error;
2205
2206         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
2207         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
2208
2209         if (!mac_enforce_fs)
2210                 return (0);
2211
2212         error = vn_refreshlabel(dvp, cred);
2213         if (error)
2214                 return (error);
2215
2216         error = vn_refreshlabel(vp, cred);
2217         if (error)
2218                 return (error);
2219
2220         MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
2221             &vp->v_label, cnp);
2222         return (error);
2223 }
2224
2225 int
2226 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2227     struct componentname *cnp)
2228 {
2229         int error;
2230
2231         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
2232
2233         if (!mac_enforce_fs)
2234                 return (0);
2235
2236         error = vn_refreshlabel(dvp, cred);
2237         if (error)
2238                 return (error);
2239
2240         MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
2241         return (error);
2242 }
2243
2244 int
2245 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
2246 {
2247         int error;
2248
2249         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
2250
2251         if (!mac_enforce_fs || !mac_enforce_vm)
2252                 return (0);
2253
2254         error = vn_refreshlabel(vp, cred);
2255         if (error)
2256                 return (error);
2257
2258         MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
2259         return (error);
2260 }
2261
2262 void
2263 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
2264 {
2265         int result = *prot;
2266
2267         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
2268
2269         if (!mac_enforce_fs || !mac_enforce_vm)
2270                 return;
2271
2272         MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
2273             &result);
2274
2275         *prot = result;
2276 }
2277
2278 int
2279 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
2280 {
2281         int error;
2282
2283         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
2284
2285         if (!mac_enforce_fs || !mac_enforce_vm)
2286                 return (0);
2287
2288         error = vn_refreshlabel(vp, cred);
2289         if (error)
2290                 return (error);
2291
2292         MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
2293         return (error);
2294 }
2295
2296 int
2297 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
2298 {
2299         int error;
2300
2301         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
2302
2303         if (!mac_enforce_fs)
2304                 return (0);
2305
2306         error = vn_refreshlabel(vp, cred);
2307         if (error)
2308                 return (error);
2309
2310         MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
2311         return (error);
2312 }
2313
2314 int
2315 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2316     struct vnode *vp)
2317 {
2318         int error;
2319
2320         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
2321
2322         if (!mac_enforce_fs)
2323                 return (0);
2324
2325         error = vn_refreshlabel(vp, active_cred);
2326         if (error)
2327                 return (error);
2328
2329         MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
2330             &vp->v_label);
2331
2332         return (error);
2333 }
2334
2335 int
2336 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2337     struct vnode *vp)
2338 {
2339         int error;
2340
2341         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
2342
2343         if (!mac_enforce_fs)
2344                 return (0);
2345
2346         error = vn_refreshlabel(vp, active_cred);
2347         if (error)
2348                 return (error);
2349
2350         MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
2351             &vp->v_label);
2352
2353         return (error);
2354 }
2355
2356 int
2357 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
2358 {
2359         int error;
2360
2361         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
2362
2363         if (!mac_enforce_fs)
2364                 return (0);
2365
2366         error = vn_refreshlabel(dvp, cred);
2367         if (error)
2368                 return (error);
2369
2370         MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
2371         return (error);
2372 }
2373
2374 int
2375 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
2376 {
2377         int error;
2378
2379         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
2380
2381         if (!mac_enforce_fs)
2382                 return (0);
2383
2384         error = vn_refreshlabel(vp, cred);
2385         if (error)
2386                 return (error);
2387
2388         MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
2389         return (error);
2390 }
2391
2392 static int
2393 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2394     struct label *newlabel)
2395 {
2396         int error;
2397
2398         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
2399
2400         error = vn_refreshlabel(vp, cred);
2401         if (error)
2402                 return (error);
2403
2404         MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
2405
2406         return (error);
2407 }
2408
2409 int
2410 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2411     struct vnode *vp, struct componentname *cnp)
2412 {
2413         int error;
2414
2415         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
2416         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
2417
2418         if (!mac_enforce_fs)
2419                 return (0);
2420
2421         error = vn_refreshlabel(dvp, cred);
2422         if (error)
2423                 return (error);
2424         error = vn_refreshlabel(vp, cred);
2425         if (error)
2426                 return (error);
2427
2428         MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
2429             &vp->v_label, cnp);
2430         return (error);
2431 }
2432
2433 int
2434 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2435     struct vnode *vp, int samedir, struct componentname *cnp)
2436 {
2437         int error;
2438
2439         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2440         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2441
2442         if (!mac_enforce_fs)
2443                 return (0);
2444
2445         error = vn_refreshlabel(dvp, cred);
2446         if (error)
2447                 return (error);
2448         if (vp != NULL) {
2449                 error = vn_refreshlabel(vp, cred);
2450                 if (error)
2451                         return (error);
2452         }
2453         MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2454             vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2455         return (error);
2456 }
2457
2458 int
2459 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2460 {
2461         int error;
2462
2463         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2464
2465         if (!mac_enforce_fs)
2466                 return (0);
2467
2468         error = vn_refreshlabel(vp, cred);
2469         if (error)
2470                 return (error);
2471
2472         MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2473         return (error);
2474 }
2475
2476 int
2477 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2478     struct acl *acl)
2479 {
2480         int error;
2481
2482         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2483
2484         if (!mac_enforce_fs)
2485                 return (0);
2486
2487         error = vn_refreshlabel(vp, cred);
2488         if (error)
2489                 return (error);
2490
2491         MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2492         return (error);
2493 }
2494
2495 int
2496 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2497     int attrnamespace, const char *name, struct uio *uio)
2498 {
2499         int error;
2500
2501         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2502
2503         if (!mac_enforce_fs)
2504                 return (0);
2505
2506         error = vn_refreshlabel(vp, cred);
2507         if (error)
2508                 return (error);
2509
2510         MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2511             attrnamespace, name, uio);
2512         return (error);
2513 }
2514
2515 int
2516 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2517 {
2518         int error;
2519
2520         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2521
2522         if (!mac_enforce_fs)
2523                 return (0);
2524
2525         error = vn_refreshlabel(vp, cred);
2526         if (error)
2527                 return (error);
2528
2529         MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2530         return (error);
2531 }
2532
2533 int
2534 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2535 {
2536         int error;
2537
2538         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2539
2540         if (!mac_enforce_fs)
2541                 return (0);
2542
2543         error = vn_refreshlabel(vp, cred);
2544         if (error)
2545                 return (error);
2546
2547         MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2548         return (error);
2549 }
2550
2551 int
2552 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2553     gid_t gid)
2554 {
2555         int error;
2556
2557         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2558
2559         if (!mac_enforce_fs)
2560                 return (0);
2561
2562         error = vn_refreshlabel(vp, cred);
2563         if (error)
2564                 return (error);
2565
2566         MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2567         return (error);
2568 }
2569
2570 int
2571 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2572     struct timespec atime, struct timespec mtime)
2573 {
2574         int error;
2575
2576         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2577
2578         if (!mac_enforce_fs)
2579                 return (0);
2580
2581         error = vn_refreshlabel(vp, cred);
2582         if (error)
2583                 return (error);
2584
2585         MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2586             mtime);
2587         return (error);
2588 }
2589
2590 int
2591 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2592     struct vnode *vp)
2593 {
2594         int error;
2595
2596         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2597
2598         if (!mac_enforce_fs)
2599                 return (0);
2600
2601         error = vn_refreshlabel(vp, active_cred);
2602         if (error)
2603                 return (error);
2604
2605         MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2606             &vp->v_label);
2607         return (error);
2608 }
2609
2610 int
2611 mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp)
2612 {
2613         int error;
2614
2615         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon");
2616
2617         if (!mac_enforce_fs)  
2618                 return (0);
2619
2620         error = vn_refreshlabel(vp, cred);
2621         if (error)
2622                 return (error);
2623
2624         MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label);
2625         return (error);
2626 }
2627
2628 int
2629 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2630     struct vnode *vp)
2631 {
2632         int error;
2633
2634         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2635
2636         if (!mac_enforce_fs)
2637                 return (0);
2638
2639         error = vn_refreshlabel(vp, active_cred);
2640         if (error)
2641                 return (error);
2642
2643         MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2644             &vp->v_label);
2645
2646         return (error);
2647 }
2648
2649 /*
2650  * When relabeling a process, call out to the policies for the maximum
2651  * permission allowed for each object type we know about in its
2652  * memory space, and revoke access (in the least surprising ways we
2653  * know) when necessary.  The process lock is not held here.
2654  */
2655 static void
2656 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2657 {
2658
2659         /* XXX freeze all other threads */
2660         mac_cred_mmapped_drop_perms_recurse(td, cred,
2661             &td->td_proc->p_vmspace->vm_map);
2662         /* XXX allow other threads to continue */
2663 }
2664
2665 static __inline const char *
2666 prot2str(vm_prot_t prot)
2667 {
2668
2669         switch (prot & VM_PROT_ALL) {
2670         case VM_PROT_READ:
2671                 return ("r--");
2672         case VM_PROT_READ | VM_PROT_WRITE:
2673                 return ("rw-");
2674         case VM_PROT_READ | VM_PROT_EXECUTE:
2675                 return ("r-x");
2676         case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2677                 return ("rwx");
2678         case VM_PROT_WRITE:
2679                 return ("-w-");
2680         case VM_PROT_EXECUTE:
2681                 return ("--x");
2682         case VM_PROT_WRITE | VM_PROT_EXECUTE:
2683                 return ("-wx");
2684         default:
2685                 return ("---");
2686         }
2687 }
2688
2689 static void
2690 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2691     struct vm_map *map)
2692 {
2693         struct vm_map_entry *vme;
2694         int result;
2695         vm_prot_t revokeperms;
2696         vm_object_t object;
2697         vm_ooffset_t offset;
2698         struct vnode *vp;
2699
2700         if (!mac_mmap_revocation)
2701                 return;
2702
2703         vm_map_lock_read(map);
2704         for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2705                 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2706                         mac_cred_mmapped_drop_perms_recurse(td, cred,
2707                             vme->object.sub_map);
2708                         continue;
2709                 }
2710                 /*
2711                  * Skip over entries that obviously are not shared.
2712                  */
2713                 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2714                     !vme->max_protection)
2715                         continue;
2716                 /*
2717                  * Drill down to the deepest backing object.
2718                  */
2719                 offset = vme->offset;
2720                 object = vme->object.vm_object;
2721                 if (object == NULL)
2722                         continue;
2723                 while (object->backing_object != NULL) {
2724                         object = object->backing_object;
2725                         offset += object->backing_object_offset;
2726                 }
2727                 /*
2728                  * At the moment, vm_maps and objects aren't considered
2729                  * by the MAC system, so only things with backing by a
2730                  * normal object (read: vnodes) are checked.
2731                  */
2732                 if (object->type != OBJT_VNODE)
2733                         continue;
2734                 vp = (struct vnode *)object->handle;
2735                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2736                 result = vme->max_protection;
2737                 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2738                 VOP_UNLOCK(vp, 0, td);
2739                 /*
2740                  * Find out what maximum protection we may be allowing
2741                  * now but a policy needs to get removed.
2742                  */
2743                 revokeperms = vme->max_protection & ~result;
2744                 if (!revokeperms)
2745                         continue;
2746                 printf("pid %ld: revoking %s perms from %#lx:%ld "
2747                     "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2748                     prot2str(revokeperms), (u_long)vme->start,
2749                     (long)(vme->end - vme->start),
2750                     prot2str(vme->max_protection), prot2str(vme->protection));
2751                 vm_map_lock_upgrade(map);
2752                 /*
2753                  * This is the really simple case: if a map has more
2754                  * max_protection than is allowed, but it's not being
2755                  * actually used (that is, the current protection is
2756                  * still allowed), we can just wipe it out and do
2757                  * nothing more.
2758                  */
2759                 if ((vme->protection & revokeperms) == 0) {
2760                         vme->max_protection -= revokeperms;
2761                 } else {
2762                         if (revokeperms & VM_PROT_WRITE) {
2763                                 /*
2764                                  * In the more complicated case, flush out all
2765                                  * pending changes to the object then turn it
2766                                  * copy-on-write.
2767                                  */
2768                                 vm_object_reference(object);
2769                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2770                                 vm_object_page_clean(object,
2771                                     OFF_TO_IDX(offset),
2772                                     OFF_TO_IDX(offset + vme->end - vme->start +
2773                                         PAGE_MASK),
2774                                     OBJPC_SYNC);
2775                                 VOP_UNLOCK(vp, 0, td);
2776                                 vm_object_deallocate(object);
2777                                 /*
2778                                  * Why bother if there's no read permissions
2779                                  * anymore?  For the rest, we need to leave
2780                                  * the write permissions on for COW, or
2781                                  * remove them entirely if configured to.
2782                                  */
2783                                 if (!mac_mmap_revocation_via_cow) {
2784                                         vme->max_protection &= ~VM_PROT_WRITE;
2785                                         vme->protection &= ~VM_PROT_WRITE;
2786                                 } if ((revokeperms & VM_PROT_READ) == 0)
2787                                         vme->eflags |= MAP_ENTRY_COW |
2788                                             MAP_ENTRY_NEEDS_COPY;
2789                         }
2790                         if (revokeperms & VM_PROT_EXECUTE) {
2791                                 vme->max_protection &= ~VM_PROT_EXECUTE;
2792                                 vme->protection &= ~VM_PROT_EXECUTE;
2793                         }
2794                         if (revokeperms & VM_PROT_READ) {
2795                                 vme->max_protection = 0;
2796                                 vme->protection = 0;
2797                         }
2798                         pmap_protect(map->pmap, vme->start, vme->end,
2799                             vme->protection & ~revokeperms);
2800                         vm_map_simplify_entry(map, vme);
2801                 }
2802                 vm_map_lock_downgrade(map);
2803         }
2804         vm_map_unlock_read(map);
2805 }
2806
2807 /*
2808  * When the subject's label changes, it may require revocation of privilege
2809  * to mapped objects.  This can't be done on-the-fly later with a unified
2810  * buffer cache.
2811  */
2812 static void
2813 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2814 {
2815
2816         MAC_PERFORM(relabel_cred, cred, newlabel);
2817 }
2818
2819 void
2820 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2821 {
2822
2823         MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2824 }
2825
2826 void
2827 mac_create_ifnet(struct ifnet *ifnet)
2828 {
2829
2830         MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2831 }
2832
2833 void
2834 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2835 {
2836
2837         MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2838 }
2839
2840 void
2841 mac_create_socket(struct ucred *cred, struct socket *socket)
2842 {
2843
2844         MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2845 }
2846
2847 void
2848 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2849 {
2850
2851         MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2852 }
2853
2854 void
2855 mac_create_socket_from_socket(struct socket *oldsocket,
2856     struct socket *newsocket)
2857 {
2858
2859         MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2860             newsocket, &newsocket->so_label);
2861 }
2862
2863 static void
2864 mac_relabel_socket(struct ucred *cred, struct socket *socket,
2865     struct label *newlabel)
2866 {
2867
2868         MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2869 }
2870
2871 static void
2872 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2873 {
2874
2875         MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2876 }
2877
2878 void
2879 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2880 {
2881
2882         MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2883             socket, &socket->so_peerlabel);
2884 }
2885
2886 void
2887 mac_set_socket_peer_from_socket(struct socket *oldsocket,
2888     struct socket *newsocket)
2889 {
2890
2891         MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2892             &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2893 }
2894
2895 void
2896 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2897 {
2898
2899         MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2900             datagram, &datagram->m_pkthdr.label);
2901 }
2902
2903 void
2904 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2905 {
2906
2907         MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2908             fragment, &fragment->m_pkthdr.label);
2909 }
2910
2911 void
2912 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2913 {
2914
2915         MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2916             &ipq->ipq_label);
2917 }
2918
2919 void
2920 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2921 {
2922
2923         MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2924             newmbuf, &newmbuf->m_pkthdr.label);
2925 }
2926
2927 void
2928 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2929 {
2930
2931         MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2932             &mbuf->m_pkthdr.label);
2933 }
2934
2935 void
2936 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2937 {
2938
2939         MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2940             &mbuf->m_pkthdr.label);
2941 }
2942
2943 void
2944 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2945 {
2946
2947         MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2948             &mbuf->m_pkthdr.label);
2949 }
2950
2951 void
2952 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2953     struct mbuf *newmbuf)
2954 {
2955
2956         MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2957             &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2958             &newmbuf->m_pkthdr.label);
2959 }
2960
2961 void
2962 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2963 {
2964
2965         MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2966             newmbuf, &newmbuf->m_pkthdr.label);
2967 }
2968
2969 int
2970 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2971 {
2972         int result;
2973
2974         result = 1;
2975         MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2976             ipq, &ipq->ipq_label);
2977
2978         return (result);
2979 }
2980
2981 void
2982 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2983 {
2984
2985         MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2986             &ipq->ipq_label);
2987 }
2988
2989 void
2990 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2991 {
2992
2993         MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2994             &mbuf->m_pkthdr.label);
2995 }
2996
2997 void
2998 mac_create_mount(struct ucred *cred, struct mount *mp)
2999 {
3000
3001         MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
3002             &mp->mnt_fslabel);
3003 }
3004
3005 void
3006 mac_create_root_mount(struct ucred *cred, struct mount *mp)
3007 {
3008
3009         MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
3010             &mp->mnt_fslabel);
3011 }
3012
3013 int
3014 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
3015 {
3016         int error;
3017
3018         if (!mac_enforce_network)
3019                 return (0);
3020
3021         MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
3022             &ifnet->if_label);
3023
3024         return (error);
3025 }
3026
3027 static int
3028 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
3029 {
3030         int error;
3031
3032         MAC_CHECK(check_cred_relabel, cred, newlabel);
3033
3034         return (error);
3035 }
3036
3037 int
3038 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
3039 {
3040         int error;
3041
3042         if (!mac_enforce_process)
3043                 return (0);
3044
3045         MAC_CHECK(check_cred_visible, u1, u2);
3046
3047         return (error);
3048 }
3049
3050 int
3051 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
3052 {
3053         int error;
3054
3055         if (!mac_enforce_network)
3056                 return (0);
3057
3058         KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
3059         if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
3060                 if_printf(ifnet, "not initialized\n");
3061
3062         MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
3063             &mbuf->m_pkthdr.label);
3064
3065         return (error);
3066 }
3067
3068 int
3069 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
3070 {
3071         int error;
3072
3073         if (!mac_enforce_fs)
3074                 return (0);
3075
3076         MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
3077
3078         return (error);
3079 }
3080
3081 int
3082 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
3083     void *data)
3084 {
3085         int error;
3086
3087         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3088
3089         if (!mac_enforce_pipe)
3090                 return (0);
3091
3092         MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
3093
3094         return (error);
3095 }
3096
3097 int
3098 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
3099 {
3100         int error;
3101
3102         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3103
3104         if (!mac_enforce_pipe)
3105                 return (0);
3106
3107         MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
3108
3109         return (error);
3110 }
3111
3112 int
3113 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
3114 {
3115         int error;
3116
3117         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3118
3119         if (!mac_enforce_pipe)
3120                 return (0);
3121
3122         MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
3123
3124         return (error);
3125 }
3126
3127 static int
3128 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
3129     struct label *newlabel)
3130 {
3131         int error;
3132
3133         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3134
3135         if (!mac_enforce_pipe)
3136                 return (0);
3137
3138         MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
3139
3140         return (error);
3141 }
3142
3143 int
3144 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
3145 {
3146         int error;
3147
3148         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3149
3150         if (!mac_enforce_pipe)
3151                 return (0);
3152
3153         MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
3154
3155         return (error);
3156 }
3157
3158 int
3159 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
3160 {
3161         int error;
3162
3163         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3164
3165         if (!mac_enforce_pipe)
3166                 return (0);
3167
3168         MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
3169
3170         return (error);
3171 }
3172
3173 int
3174 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
3175 {
3176         int error;
3177
3178         PROC_LOCK_ASSERT(proc, MA_OWNED);
3179
3180         if (!mac_enforce_process)
3181                 return (0);
3182
3183         MAC_CHECK(check_proc_debug, cred, proc);
3184
3185         return (error);
3186 }
3187
3188 int
3189 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
3190 {
3191         int error;
3192
3193         PROC_LOCK_ASSERT(proc, MA_OWNED);
3194
3195         if (!mac_enforce_process)
3196                 return (0);
3197
3198         MAC_CHECK(check_proc_sched, cred, proc);
3199
3200         return (error);
3201 }
3202
3203 int
3204 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
3205 {
3206         int error;
3207
3208         PROC_LOCK_ASSERT(proc, MA_OWNED);
3209
3210         if (!mac_enforce_process)
3211                 return (0);
3212
3213         MAC_CHECK(check_proc_signal, cred, proc, signum);
3214
3215         return (error);
3216 }
3217
3218 int
3219 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
3220     struct sockaddr *sockaddr)
3221 {
3222         int error;
3223
3224         if (!mac_enforce_socket)
3225                 return (0);
3226
3227         MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
3228             sockaddr);
3229
3230         return (error);
3231 }
3232
3233 int
3234 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
3235     struct sockaddr *sockaddr)
3236 {
3237         int error;
3238
3239         if (!mac_enforce_socket)
3240                 return (0);
3241
3242         MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
3243             sockaddr);
3244
3245         return (error);
3246 }
3247
3248 int
3249 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
3250 {
3251         int error;
3252
3253         if (!mac_enforce_socket)
3254                 return (0);
3255
3256         MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
3257             &mbuf->m_pkthdr.label);
3258
3259         return (error);
3260 }
3261
3262 int
3263 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
3264 {
3265         int error;
3266
3267         if (!mac_enforce_socket)
3268                 return (0);
3269
3270         MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
3271         return (error);
3272 }
3273
3274 int
3275 mac_check_socket_receive(struct ucred *cred, struct socket *so)
3276 {
3277         int error;
3278
3279         if (!mac_enforce_socket)
3280                 return (0);
3281
3282         MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
3283
3284         return (error);
3285 }
3286
3287 static int
3288 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
3289     struct label *newlabel)
3290 {
3291         int error;
3292
3293         MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
3294             newlabel);
3295
3296         return (error);
3297 }
3298
3299 int
3300 mac_check_socket_send(struct ucred *cred, struct socket *so)
3301 {
3302         int error;
3303
3304         if (!mac_enforce_socket)
3305                 return (0);
3306
3307         MAC_CHECK(check_socket_send, cred, so, &so->so_label);
3308
3309         return (error);
3310 }
3311
3312 int
3313 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
3314 {
3315         int error;
3316
3317         if (!mac_enforce_socket)
3318                 return (0);
3319
3320         MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
3321
3322         return (error);
3323 }
3324
3325 int
3326 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3327     struct ifnet *ifnet)
3328 {
3329         char *elements, *buffer;
3330         struct mac mac;
3331         int error;
3332
3333         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3334         if (error)
3335                 return (error);
3336
3337         error = mac_check_structmac_consistent(&mac);
3338         if (error)
3339                 return (error);
3340
3341         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3342
3343         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3344         if (error) {
3345                 free(elements, M_MACTEMP);
3346                 return (error);
3347         }
3348
3349         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3350
3351         error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3352             buffer, mac.m_buflen, M_WAITOK);
3353         if (error == 0)
3354                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3355
3356         free(buffer, M_MACTEMP);
3357         free(elements, M_MACTEMP);
3358
3359         return (error);
3360 }
3361
3362 int
3363 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3364     struct ifnet *ifnet)
3365 {
3366         struct label intlabel;
3367         struct mac mac;
3368         char *buffer;
3369         int error;
3370
3371         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3372         if (error)
3373                 return (error);
3374
3375         error = mac_check_structmac_consistent(&mac);
3376         if (error)
3377                 return (error);
3378
3379         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3380
3381         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3382         if (error) {
3383                 free(buffer, M_MACTEMP);
3384                 return (error);
3385         }
3386
3387         mac_init_ifnet_label(&intlabel);
3388         error = mac_internalize_ifnet_label(&intlabel, buffer);
3389         free(buffer, M_MACTEMP);
3390         if (error) {
3391                 mac_destroy_ifnet_label(&intlabel);
3392                 return (error);
3393         }
3394
3395         /*
3396          * XXX: Note that this is a redundant privilege check, since
3397          * policies impose this check themselves if required by the
3398          * policy.  Eventually, this should go away.
3399          */
3400         error = suser_cred(cred, 0);
3401         if (error) {
3402                 mac_destroy_ifnet_label(&intlabel);
3403                 return (error);
3404         }
3405
3406         MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3407             &intlabel);
3408         if (error) {
3409                 mac_destroy_ifnet_label(&intlabel);
3410                 return (error);
3411         }
3412
3413         MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3414
3415         mac_destroy_ifnet_label(&intlabel);
3416         return (0);
3417 }
3418
3419 void
3420 mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3421 {
3422
3423         MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3424 }
3425
3426 void
3427 mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3428 {
3429
3430         MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3431 }
3432
3433 void
3434 mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3435     struct devfs_dirent *de)
3436 {
3437
3438         MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3439             &de->de_label);
3440 }
3441
3442 static int
3443 mac_stdcreatevnode_ea(struct vnode *vp)
3444 {
3445         int error;
3446
3447         MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
3448
3449         return (error);
3450 }
3451
3452 void
3453 mac_create_devfs_directory(char *dirname, int dirnamelen,
3454     struct devfs_dirent *de)
3455 {
3456
3457         MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3458             &de->de_label);
3459 }
3460
3461 /*
3462  * When a new vnode is created, this call will initialize its label.
3463  */
3464 void
3465 mac_create_vnode(struct ucred *cred, struct vnode *parent,
3466     struct vnode *child)
3467 {
3468         int error;
3469
3470         ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
3471         ASSERT_VOP_LOCKED(child, "mac_create_vnode");
3472
3473         error = vn_refreshlabel(parent, cred);
3474         if (error) {
3475                 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
3476                     error);
3477                 printf("mac_create_vnode: using old vnode label\n");
3478         }
3479
3480         MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
3481             &child->v_label);
3482 }
3483
3484 int
3485 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3486     struct mac *mac)
3487 {
3488         struct label intlabel;
3489         char *buffer;
3490         int error;
3491
3492         error = mac_check_structmac_consistent(mac);
3493         if (error)
3494                 return (error);
3495
3496         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3497
3498         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3499         if (error) {
3500                 free(buffer, M_MACTEMP);
3501                 return (error);
3502         }
3503
3504         mac_init_socket_label(&intlabel, M_WAITOK);
3505         error = mac_internalize_socket_label(&intlabel, buffer);
3506         free(buffer, M_MACTEMP);
3507         if (error) {
3508                 mac_destroy_socket_label(&intlabel);
3509                 return (error);
3510         }
3511
3512         mac_check_socket_relabel(cred, so, &intlabel);
3513         if (error) {
3514                 mac_destroy_socket_label(&intlabel);
3515                 return (error);
3516         }
3517
3518         mac_relabel_socket(cred, so, &intlabel);
3519
3520         mac_destroy_socket_label(&intlabel);
3521         return (0);
3522 }
3523
3524 int
3525 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3526 {
3527         int error;
3528
3529         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3530
3531         error = mac_check_pipe_relabel(cred, pipe, label);
3532         if (error)
3533                 return (error);
3534
3535         mac_relabel_pipe(cred, pipe, label);
3536
3537         return (0);
3538 }
3539
3540 int
3541 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3542     struct mac *mac)
3543 {
3544         char *buffer, *elements;
3545         int error;
3546
3547         error = mac_check_structmac_consistent(mac);
3548         if (error)
3549                 return (error);
3550
3551         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3552
3553         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3554         if (error) {
3555                 free(elements, M_MACTEMP);
3556                 return (error);
3557         }
3558
3559         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3560
3561         error = mac_externalize_socket_label(&so->so_label, elements,
3562             buffer, mac->m_buflen, M_WAITOK);
3563         if (error == 0)
3564                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3565
3566         free(buffer, M_MACTEMP);
3567         free(elements, M_MACTEMP);
3568
3569         return (error);
3570 }
3571
3572 int
3573 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3574     struct mac *mac)
3575 {
3576         char *elements, *buffer;
3577         int error;
3578
3579         error = mac_check_structmac_consistent(mac);
3580         if (error)
3581                 return (error);
3582
3583         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3584
3585         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3586         if (error) {
3587                 free(elements, M_MACTEMP);
3588                 return (error);
3589         }
3590
3591         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3592
3593         error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3594             elements, buffer, mac->m_buflen, M_WAITOK);
3595         if (error == 0)
3596                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3597
3598         free(buffer, M_MACTEMP);
3599         free(elements, M_MACTEMP);
3600
3601         return (error);
3602 }
3603
3604 /*
3605  * Implementation of VOP_SETLABEL() that relies on extended attributes
3606  * to store label data.  Can be referenced by filesystems supporting
3607  * extended attributes.
3608  */
3609 int
3610 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3611 {
3612         struct vnode *vp = ap->a_vp;
3613         struct label *intlabel = ap->a_label;
3614         struct oldmac extmac;
3615         int error;
3616
3617         ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3618
3619         /*
3620          * XXX: Eventually call out to EA check/set calls here.
3621          * Be particularly careful to avoid race conditions,
3622          * consistency problems, and stability problems when
3623          * dealing with multiple EAs.  In particular, we require
3624          * the ability to write multiple EAs on the same file in
3625          * a single transaction, which the current EA interface
3626          * does not provide.
3627          */
3628
3629         error = mac_externalize_vnode_oldmac(intlabel, &extmac);
3630         if (error)
3631                 return (error);
3632
3633         error = vn_extattr_set(vp, IO_NODELOCKED,
3634             FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3635             sizeof(extmac), (char *)&extmac, curthread);
3636         if (error)
3637                 return (error);
3638
3639         mac_relabel_vnode(ap->a_cred, vp, intlabel);
3640
3641         vp->v_vflag |= VV_CACHEDLABEL;
3642
3643         return (0);
3644 }
3645
3646 static int
3647 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3648 {
3649         int error;
3650
3651         if (vp->v_mount == NULL) {
3652                 /* printf("vn_setlabel: null v_mount\n"); */
3653                 if (vp->v_type != VNON)
3654                         printf("vn_setlabel: null v_mount with non-VNON\n");
3655                 return (EBADF);
3656         }
3657
3658         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3659                 return (EOPNOTSUPP);
3660
3661         /*
3662          * Multi-phase commit.  First check the policies to confirm the
3663          * change is OK.  Then commit via the filesystem.  Finally,
3664          * update the actual vnode label.  Question: maybe the filesystem
3665          * should update the vnode at the end as part of VOP_SETLABEL()?
3666          */
3667         error = mac_check_vnode_relabel(cred, vp, intlabel);
3668         if (error)
3669                 return (error);
3670
3671         /*
3672          * VADMIN provides the opportunity for the filesystem to make
3673          * decisions about who is and is not able to modify labels
3674          * and protections on files.  This might not be right.  We can't
3675          * assume VOP_SETLABEL() will do it, because we might implement
3676          * that as part of vop_stdsetlabel_ea().
3677          */
3678         error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3679         if (error)
3680                 return (error);
3681
3682         error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3683         if (error)
3684                 return (error);
3685
3686         return (0);
3687 }
3688
3689 int
3690 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3691 {
3692         char *elements, *buffer;
3693         struct mac mac;
3694         struct proc *tproc;
3695         struct ucred *tcred;
3696         int error;
3697
3698         error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3699         if (error)
3700                 return (error);
3701
3702         error = mac_check_structmac_consistent(&mac);
3703         if (error)
3704                 return (error);
3705
3706         tproc = pfind(uap->pid);
3707         if (tproc == NULL)
3708                 return (ESRCH);
3709
3710         tcred = NULL;                           /* Satisfy gcc. */
3711         error = p_cansee(td, tproc);
3712         if (error == 0)
3713                 tcred = crhold(tproc->p_ucred);
3714         PROC_UNLOCK(tproc);
3715         if (error)
3716                 return (error);
3717
3718         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3719
3720         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3721         if (error) {
3722                 free(elements, M_MACTEMP);
3723                 crfree(tcred);
3724                 return (error);
3725         }
3726
3727         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3728
3729         error = mac_externalize_cred_label(&tcred->cr_label, elements,
3730             buffer, mac.m_buflen, M_WAITOK);
3731         if (error == 0)
3732                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3733
3734         free(buffer, M_MACTEMP);
3735         free(elements, M_MACTEMP);
3736         crfree(tcred);
3737         return (error);
3738 }
3739
3740 /*
3741  * MPSAFE
3742  */
3743 int
3744 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3745 {
3746         char *elements, *buffer;
3747         struct mac mac;
3748         int error;
3749
3750         error = copyin(uap->mac_p, &mac, sizeof(mac));
3751         if (error)
3752                 return (error);
3753
3754         error = mac_check_structmac_consistent(&mac);
3755         if (error)
3756                 return (error);
3757
3758         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3759
3760         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3761         if (error) {
3762                 free(elements, M_MACTEMP);
3763                 return (error);
3764         }
3765
3766         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3767
3768         error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3769             elements, buffer, mac.m_buflen, M_WAITOK);
3770         if (error == 0)
3771                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3772
3773         free(buffer, M_MACTEMP);
3774         free(elements, M_MACTEMP);
3775         return (error);
3776 }
3777
3778 /*
3779  * MPSAFE
3780  */
3781 int
3782 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3783 {
3784         struct ucred *newcred, *oldcred;
3785         struct label intlabel;
3786         struct proc *p;
3787         struct mac mac;
3788         char *buffer;
3789         int error;
3790
3791         error = copyin(uap->mac_p, &mac, sizeof(mac));
3792         if (error)
3793                 return (error);
3794
3795         error = mac_check_structmac_consistent(&mac);
3796         if (error)
3797                 return (error);
3798
3799         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3800
3801         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3802         if (error) {
3803                 free(buffer, M_MACTEMP);
3804                 return (error);
3805         }
3806
3807         mac_init_cred_label(&intlabel);
3808         error = mac_internalize_cred_label(&intlabel, buffer);
3809         free(buffer, M_MACTEMP);
3810         if (error) {
3811                 mac_destroy_cred_label(&intlabel);
3812                 return (error);
3813         }
3814
3815         newcred = crget();
3816
3817         p = td->td_proc;
3818         PROC_LOCK(p);
3819         oldcred = p->p_ucred;
3820
3821         error = mac_check_cred_relabel(oldcred, &intlabel);
3822         if (error) {
3823                 PROC_UNLOCK(p);
3824                 crfree(newcred);
3825                 goto out;
3826         }
3827
3828         setsugid(p);
3829         crcopy(newcred, oldcred);
3830         mac_relabel_cred(newcred, &intlabel);
3831         p->p_ucred = newcred;
3832
3833         /*
3834          * Grab additional reference for use while revoking mmaps, prior
3835          * to releasing the proc lock and sharing the cred.
3836          */
3837         crhold(newcred);
3838         PROC_UNLOCK(p);
3839
3840         if (mac_enforce_vm) {
3841                 mtx_lock(&Giant);
3842                 mac_cred_mmapped_drop_perms(td, newcred);
3843                 mtx_unlock(&Giant);
3844         }
3845
3846         crfree(newcred);        /* Free revocation reference. */
3847         crfree(oldcred);
3848
3849 out:
3850         mac_destroy_cred_label(&intlabel);
3851         return (error);
3852 }
3853
3854 /*
3855  * MPSAFE
3856  */
3857 int
3858 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3859 {
3860         char *elements, *buffer;
3861         struct label intlabel;
3862         struct file *fp;
3863         struct mac mac;
3864         struct vnode *vp;
3865         struct pipe *pipe;
3866         short label_type;
3867         int error;
3868
3869         error = copyin(uap->mac_p, &mac, sizeof(mac));
3870         if (error)
3871                 return (error);
3872
3873         error = mac_check_structmac_consistent(&mac);
3874         if (error)
3875                 return (error);
3876
3877         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3878
3879         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3880         if (error) {
3881                 free(elements, M_MACTEMP);
3882                 return (error);
3883         }
3884
3885         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3886
3887         mtx_lock(&Giant);                               /* VFS */
3888         error = fget(td, SCARG(uap, fd), &fp);
3889         if (error)
3890                 goto out;
3891
3892         label_type = fp->f_type;
3893         switch (fp->f_type) {
3894         case DTYPE_FIFO:
3895         case DTYPE_VNODE:
3896                 vp = (struct vnode *)fp->f_data;
3897
3898                 mac_init_vnode_label(&intlabel);
3899
3900                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3901                 error = vn_refreshlabel(vp, td->td_ucred);
3902                 if (error == 0)
3903                         mac_copy_vnode_label(&vp->v_label, &intlabel);
3904                 VOP_UNLOCK(vp, 0, td);
3905
3906                 break;
3907         case DTYPE_PIPE:
3908                 pipe = (struct pipe *)fp->f_data;
3909
3910                 mac_init_pipe_label(&intlabel);
3911
3912                 PIPE_LOCK(pipe);
3913                 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3914                 PIPE_UNLOCK(pipe);
3915                 break;
3916         default:
3917                 error = EINVAL;
3918                 fdrop(fp, td);
3919                 goto out;
3920         }
3921         fdrop(fp, td);
3922
3923         switch (label_type) {
3924         case DTYPE_FIFO:
3925         case DTYPE_VNODE:
3926                 if (error == 0)
3927                         error = mac_externalize_vnode_label(&intlabel,
3928                             elements, buffer, mac.m_buflen, M_WAITOK);
3929                 mac_destroy_vnode_label(&intlabel);
3930                 break;
3931         case DTYPE_PIPE:
3932                 error = mac_externalize_pipe_label(&intlabel, elements,
3933                     buffer, mac.m_buflen, M_WAITOK);
3934                 mac_destroy_pipe_label(&intlabel);
3935                 break;
3936         default:
3937                 panic("__mac_get_fd: corrupted label_type");
3938         }
3939
3940         if (error == 0)
3941                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3942
3943 out:
3944         mtx_unlock(&Giant);                             /* VFS */
3945         free(buffer, M_MACTEMP);
3946         free(elements, M_MACTEMP);
3947
3948         return (error);
3949 }
3950
3951 /*
3952  * MPSAFE
3953  */
3954 int
3955 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3956 {
3957         char *elements, *buffer;
3958         struct nameidata nd;
3959         struct label intlabel;
3960         struct mac mac;
3961         int error;
3962
3963         error = copyin(uap->mac_p, &mac, sizeof(mac));
3964         if (error)
3965                 return (error);
3966
3967         error = mac_check_structmac_consistent(&mac);
3968         if (error)
3969                 return (error);
3970
3971         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3972
3973         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3974         if (error) {
3975                 free(elements, M_MACTEMP);
3976                 return (error);
3977         }
3978
3979         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3980
3981         mtx_lock(&Giant);                               /* VFS */
3982         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3983             td);
3984         error = namei(&nd);
3985         if (error)
3986                 goto out;
3987
3988         mac_init_vnode_label(&intlabel);
3989         error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3990         if (error == 0)
3991                 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3992         if (error == 0)
3993                 error = mac_externalize_vnode_label(&intlabel, elements,
3994                     buffer, mac.m_buflen, M_WAITOK);
3995
3996         NDFREE(&nd, 0);
3997         mac_destroy_vnode_label(&intlabel);
3998
3999         if (error == 0)
4000                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4001
4002 out:
4003         mtx_unlock(&Giant);                             /* VFS */
4004
4005         free(buffer, M_MACTEMP);
4006         free(elements, M_MACTEMP);
4007
4008         return (error);
4009 }
4010
4011 /*
4012  * MPSAFE
4013  */
4014 int
4015 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4016 {
4017         char *elements, *buffer;
4018         struct nameidata nd;
4019         struct label intlabel;
4020         struct mac mac;
4021         int error;
4022
4023         error = copyin(uap->mac_p, &mac, sizeof(mac));
4024         if (error)
4025                 return (error);
4026
4027         error = mac_check_structmac_consistent(&mac);
4028         if (error)
4029                 return (error);
4030
4031         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4032
4033         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
4034         if (error) {
4035                 free(elements, M_MACTEMP);
4036                 return (error);
4037         }
4038
4039         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4040
4041         mtx_lock(&Giant);                               /* VFS */
4042         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4043             td);
4044         error = namei(&nd);
4045         if (error)
4046                 goto out;
4047
4048         mac_init_vnode_label(&intlabel);
4049         error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
4050         if (error == 0)
4051                 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
4052         if (error == 0)
4053                 error = mac_externalize_vnode_label(&intlabel, elements,
4054                     buffer, mac.m_buflen, M_WAITOK);
4055         NDFREE(&nd, 0);
4056         mac_destroy_vnode_label(&intlabel);
4057
4058         if (error == 0)
4059                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4060
4061 out:
4062         mtx_unlock(&Giant);                             /* VFS */
4063
4064         free(buffer, M_MACTEMP);
4065         free(elements, M_MACTEMP);
4066
4067         return (error);
4068 }
4069
4070 /*
4071  * MPSAFE
4072  */
4073 int
4074 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4075 {
4076         struct label intlabel;
4077         struct pipe *pipe;
4078         struct file *fp;
4079         struct mount *mp;
4080         struct vnode *vp;
4081         struct mac mac;
4082         char *buffer;
4083         int error;
4084
4085         error = copyin(uap->mac_p, &mac, sizeof(mac));
4086         if (error)
4087                 return (error);
4088
4089         error = mac_check_structmac_consistent(&mac);
4090         if (error)
4091                 return (error);
4092
4093         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4094
4095         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4096         if (error) {
4097                 free(buffer, M_MACTEMP);
4098                 return (error);
4099         }
4100
4101         mtx_lock(&Giant);                               /* VFS */
4102
4103         error = fget(td, SCARG(uap, fd), &fp);
4104         if (error)
4105                 goto out;
4106
4107         switch (fp->f_type) {
4108         case DTYPE_FIFO:
4109         case DTYPE_VNODE:
4110                 mac_init_vnode_label(&intlabel);
4111                 error = mac_internalize_vnode_label(&intlabel, buffer);
4112                 if (error) {
4113                         mac_destroy_vnode_label(&intlabel);
4114                         break;
4115                 }
4116
4117                 vp = (struct vnode *)fp->f_data;
4118                 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4119                 if (error != 0) {
4120                         mac_destroy_vnode_label(&intlabel);
4121                         break;
4122                 }
4123
4124                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4125                 error = vn_setlabel(vp, &intlabel, td->td_ucred);
4126                 VOP_UNLOCK(vp, 0, td);
4127                 vn_finished_write(mp);
4128
4129                 mac_destroy_vnode_label(&intlabel);
4130                 break;
4131
4132         case DTYPE_PIPE:
4133                 mac_init_pipe_label(&intlabel);
4134                 error = mac_internalize_pipe_label(&intlabel, buffer);
4135                 if (error == 0) {
4136                         pipe = (struct pipe *)fp->f_data;
4137                         PIPE_LOCK(pipe);
4138                         error = mac_pipe_label_set(td->td_ucred, pipe,
4139                             &intlabel);
4140                         PIPE_UNLOCK(pipe);
4141                 }
4142
4143                 mac_destroy_pipe_label(&intlabel);
4144                 break;
4145
4146         default:
4147                 error = EINVAL;
4148         }
4149
4150         fdrop(fp, td);
4151 out:
4152         mtx_unlock(&Giant);                             /* VFS */
4153
4154         free(buffer, M_MACTEMP);
4155
4156         return (error);
4157 }
4158
4159 /*
4160  * MPSAFE
4161  */
4162 int
4163 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4164 {
4165         struct label intlabel;
4166         struct nameidata nd;
4167         struct mount *mp;
4168         struct mac mac;
4169         char *buffer;
4170         int error;
4171
4172         error = copyin(uap->mac_p, &mac, sizeof(mac));
4173         if (error)
4174                 return (error);
4175
4176         error = mac_check_structmac_consistent(&mac);
4177         if (error)
4178                 return (error);
4179
4180         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4181
4182         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4183         if (error) {
4184                 free(buffer, M_MACTEMP);
4185                 return (error);
4186         }
4187
4188         mac_init_vnode_label(&intlabel);
4189         error = mac_internalize_vnode_label(&intlabel, buffer);
4190         free(buffer, M_MACTEMP);
4191         if (error) {
4192                 mac_destroy_vnode_label(&intlabel);
4193                 return (error);
4194         }
4195
4196         mtx_lock(&Giant);                               /* VFS */
4197
4198         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
4199             td);
4200         error = namei(&nd);
4201         if (error == 0) {
4202                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4203                 if (error == 0)
4204                         error = vn_setlabel(nd.ni_vp, &intlabel,
4205                             td->td_ucred);
4206                 vn_finished_write(mp);
4207         }
4208
4209         NDFREE(&nd, 0);
4210         mtx_unlock(&Giant);                             /* VFS */
4211         mac_destroy_vnode_label(&intlabel);
4212
4213         return (error);
4214 }
4215
4216 /*
4217  * MPSAFE
4218  */
4219 int
4220 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4221 {
4222         struct label intlabel;
4223         struct nameidata nd;
4224         struct mount *mp;
4225         struct mac mac;
4226         char *buffer;
4227         int error;
4228
4229         error = copyin(uap->mac_p, &mac, sizeof(mac));
4230         if (error)
4231                 return (error);
4232
4233         error = mac_check_structmac_consistent(&mac);
4234         if (error)
4235                 return (error);
4236
4237         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4238
4239         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4240         if (error) {
4241                 free(buffer, M_MACTEMP);
4242                 return (error);
4243         }
4244
4245         mac_init_vnode_label(&intlabel);
4246         error = mac_internalize_vnode_label(&intlabel, buffer);
4247         free(buffer, M_MACTEMP);
4248         if (error) {
4249                 mac_destroy_vnode_label(&intlabel);
4250                 return (error);
4251         }
4252
4253         mtx_lock(&Giant);                               /* VFS */
4254
4255         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4256             td);
4257         error = namei(&nd);
4258         if (error == 0) {
4259                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4260                 if (error == 0)
4261                         error = vn_setlabel(nd.ni_vp, &intlabel,
4262                             td->td_ucred);
4263                 vn_finished_write(mp);
4264         }
4265
4266         NDFREE(&nd, 0);
4267         mtx_unlock(&Giant);                             /* VFS */
4268         mac_destroy_vnode_label(&intlabel);
4269
4270         return (error);
4271 }
4272
4273 /*
4274  * MPSAFE
4275  */
4276 int
4277 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4278 {
4279         struct mac_policy_conf *mpc;
4280         char target[MAC_MAX_POLICY_NAME];
4281         int error;
4282
4283         error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
4284         if (error)
4285                 return (error);
4286
4287         error = ENOSYS;
4288         MAC_POLICY_LIST_BUSY();
4289         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
4290                 if (strcmp(mpc->mpc_name, target) == 0 &&
4291                     mpc->mpc_ops->mpo_syscall != NULL) {
4292                         error = mpc->mpc_ops->mpo_syscall(td,
4293                             SCARG(uap, call), SCARG(uap, arg));
4294                         goto out;
4295                 }
4296         }
4297
4298 out:
4299         MAC_POLICY_LIST_UNBUSY();
4300         return (error);
4301 }
4302
4303 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
4304 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
4305
4306 #else /* !MAC */
4307
4308 int
4309 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
4310 {
4311
4312         return (ENOSYS);
4313 }
4314
4315 int
4316 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
4317 {
4318
4319         return (ENOSYS);
4320 }
4321
4322 int
4323 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
4324 {
4325
4326         return (ENOSYS);
4327 }
4328
4329 int
4330 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
4331 {
4332
4333         return (ENOSYS);
4334 }
4335
4336 int
4337 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
4338 {
4339
4340         return (ENOSYS);
4341 }
4342
4343 int
4344 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4345 {
4346
4347         return (ENOSYS);
4348 }
4349
4350 int
4351 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4352 {
4353
4354         return (ENOSYS);
4355 }
4356
4357 int
4358 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4359 {
4360
4361         return (ENOSYS);
4362 }
4363
4364 int
4365 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4366 {
4367
4368         return (ENOSYS);
4369 }
4370
4371 int
4372 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4373 {
4374
4375         return (ENOSYS);
4376 }
4377
4378 #endif