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