diff --git a/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml index 1f465a8145..29138c5ca1 100644 --- a/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml @@ -1,755 +1,755 @@ Evan Sarmiento
evms@cs.bu.edu
2001 Evan Sarmiento
The Jail Subsystem security Jail root On most &unix; systems, root has omnipotent power. This promotes insecurity. If an attacker gained root on a system, he would have every function at his fingertips. In FreeBSD there are sysctls which dilute the power of root, in order to minimize the damage caused by an attacker. Specifically, one of these functions is called secure levels. Similarly, another function which is present from FreeBSD 4.0 and onward, is a utility called &man.jail.8;. Jail chroots an environment and sets certain restrictions on processes which are forked within the jail. For example, a jailed process cannot affect processes outside the jail, utilize certain system calls, or inflict any damage on the host environment. Jail is becoming the new security model. People are running potentially vulnerable servers such as Apache, BIND, and sendmail within jails, so that if an attacker gains root within the jail, it is only an annoyance, and not a devastation. This article mainly focuses on the internals (source code) of jail. If you are looking for a how-to on setting up a jail, I suggest you look at my other article in Sys Admin Magazine, May 2001, entitled "Securing FreeBSD using Jail." Architecture Jail consists of two realms: the userland program, &man.jail.8;, and the code implemented within the kernel: the &man.jail.2; system call and associated restrictions. I will be discussing the userland program and then how jail is implemented within the kernel. Userland Code Jail Userland Program The source for the userland jail is located in /usr/src/usr.sbin/jail, consisting of one file, jail.c. The program takes these arguments: the path of the jail, hostname, IP address, and the command to be executed. Data Structures In jail.c, the first thing I would note is the declaration of an important structure struct jail j; which was included from /usr/include/sys/jail.h. The definition of the jail structure is: /usr/include/sys/jail.h: struct jail { u_int32_t version; char *path; char *hostname; u_int32_t ip_number; }; As you can see, there is an entry for each of the arguments passed to the &man.jail.8; program, and indeed, they are set during its execution. /usr/src/usr.sbin/jail/jail.c char path[PATH_MAX]; ... if (realpath(argv[0], path) == NULL) err(1, "realpath: %s", argv[0]); if (chdir(path) != 0) err(1, "chdir: %s", path); memset(&j, 0, sizeof(j)); j.version = 0; j.path = path; j.hostname = argv[1]; Networking One of the arguments passed to the &man.jail.8; program is an IP address with which the jail can be accessed over the network. &man.jail.8; translates the IP address given into host byte order and then stores it in j (the jail structure). /usr/src/usr.sbin/jail/jail.c: struct in_addr in; ... if (inet_aton(argv[2], &in) == 0) errx(1, "Could not make sense of ip-number: %s", argv[2]); j.ip_number = ntohl(in.s_addr); The &man.inet.aton.3; function "interprets the specified character string as an Internet address, placing the address into the structure provided." The ip_number member in the jail structure is set only when the IP address placed onto the in structure by &man.inet.aton.3; is translated into host byte order by &man.ntohl.3;. Jailing The Process Finally, the userland program jails the process. Jail now becomes an imprisoned process itself and then executes the command given using &man.execv.3;. /usr/src/usr.sbin/jail/jail.c i = jail(&j); ... if (execv(argv[3], argv + 3) != 0) err(1, "execv: %s", argv[3]); As you can see, the jail() function is called, and its argument is the jail structure which has been filled with the arguments given to the program. Finally, the program you specify is executed. I will now discuss how jail is implemented within the kernel. Kernel Space Jail Kernel Architecture We will now be looking at the file /usr/src/sys/kern/kern_jail.c. This is the file where the &man.jail.2; system call, appropriate sysctls, and networking functions are defined. sysctls sysctl In kern_jail.c, the following sysctls are defined: /usr/src/sys/kern/kern_jail.c: int jail_set_hostname_allowed = 1; SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, &jail_set_hostname_allowed, 0, "Processes in jail can set their hostnames"); int jail_socket_unixiproute_only = 1; SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, &jail_socket_unixiproute_only, 0, "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); int jail_sysvipc_allowed = 0; SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, &jail_sysvipc_allowed, 0, "Processes in jail can use System V IPC primitives"); static int jail_enforce_statfs = 2; SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW, &jail_enforce_statfs, 0, "Processes in jail cannot see all mounted file systems"); int jail_allow_raw_sockets = 0; SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, &jail_allow_raw_sockets, 0, "Prison root can create raw sockets"); int jail_chflags_allowed = 0; SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, &jail_chflags_allowed, 0, "Processes in jail can alter system file flags"); int jail_mount_allowed = 0; SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW, &jail_mount_allowed, 0, "Processes in jail can mount/unmount jail-friendly file systems"); Each of these sysctls can be accessed by the user through the &man.sysctl.8; program. Throughout the kernel, these specific sysctls are recognized by their name. For example, the name of the first sysctl is security.jail.set_hostname_allowed. &man.jail.2; system call Like all system calls, the &man.jail.2; system call takes two arguments, struct thread *td and struct jail_args *uap. td is a pointer to the thread structure which describes the calling thread. In this context, uap is a pointer to the structure in which a pointer to the jail structure passed by the userland jail.c is contained. When I described the userland program before, you saw that the &man.jail.2; system call was given a jail structure as its own argument. /usr/src/sys/kern/kern_jail.c: /* * struct jail_args { * struct jail *jail; * }; */ int jail(struct thread *td, struct jail_args *uap) Therefore, uap->jail can be used to access the jail structure which was passed to the system call. Next, the system call copies the jail structure into kernel space using the &man.copyin.9; function. &man.copyin.9; takes three arguments: the address of the data which is to be copied into kernel space, uap->jail, where to store it, j and the size of the storage. The jail structure pointed by uap->jail is copied into kernel space and is stored in another jail structure, j. /usr/src/sys/kern/kern_jail.c: error = copyin(uap->jail, &j, sizeof(j)); There is another important structure defined in jail.h. It is the prison structure. The prison structure is used exclusively within kernel space. Here is the definition of the prison structure. /usr/include/sys/jail.h: struct prison { LIST_ENTRY(prison) pr_list; /* (a) all prisons */ int pr_id; /* (c) prison id */ int pr_ref; /* (p) refcount */ char pr_path[MAXPATHLEN]; /* (c) chroot path */ struct vnode *pr_root; /* (c) vnode to rdir */ char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */ u_int32_t pr_ip; /* (c) ip addr host */ void *pr_linux; /* (p) linux abi */ int pr_securelevel; /* (p) securelevel */ struct task pr_task; /* (d) destroy task */ struct mtx pr_mtx; void **pr_slots; /* (p) additional data */ }; The &man.jail.2; system call then allocates memory for a prison structure and copies data between the jail and prison structure. /usr/src/sys/kern/kern_jail.c: MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); ... error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); if (error) goto e_killmtx; ... error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); if (error) goto e_dropvnref; pr->pr_ip = j.ip_number; Next, we will discuss another important system call &man.jail.attach.2;, which implements the function to put a process into the jail. /usr/src/sys/kern/kern_jail.c: /* * struct jail_attach_args { * int jid; * }; */ int jail_attach(struct thread *td, struct jail_attach_args *uap) This system call makes the changes that can distinguish a jailed process from those unjailed ones. To understand what &man.jail.attach.2; does for us, certain background information is needed. On FreeBSD, each kernel visible thread is identified by its thread structure, while the processes are described by their proc structures. You can find the definitions of the thread and proc structure in /usr/include/sys/proc.h. For example, the td argument in any system call is actually a pointer to the calling thread's thread structure, as stated before. The td_proc member in the thread structure pointed by td is a pointer to the proc structure which represents the process that contains the thread represented by td. The proc structure contains members which can describe the owner's identity(p_ucred), the process resource limits(p_limit), and so on. In the ucred structure pointed by p_ucred member in the proc structure, there is a pointer to the prison structure(cr_prison). /usr/include/sys/proc.h: struct thread { ... struct proc *td_proc; ... }; struct proc { ... struct ucred *p_ucred; ... }; /usr/include/sys/ucred.h struct ucred { ... struct prison *cr_prison; ... }; In kern_jail.c, the function jail() then calls function jail_attach() with a given jid. And jail_attach() calls function change_root() to change the root directory of the calling process. The jail_attach() then creates a new ucred structure, and attaches the newly created ucred structure to the calling process after it has successfully attached the prison structure to the ucred structure. From then on, the calling process is recognized as jailed. When the kernel routine jailed() is called in the kernel with the newly created ucred structure as its argument, it returns 1 to tell that the credential is connected with a jail. The public ancestor process of all the process forked within the jail, is the process which runs &man.jail.8;, as it calls the &man.jail.2; system call. When a program is executed through &man.execve.2;, it inherits the jailed property of its parent's ucred structure, therefore it has a jailed ucred structure. /usr/src/sys/kern/kern_jail.c int jail(struct thread *td, struct jail_args *uap) { ... struct jail_attach_args jaa; ... error = jail_attach(td, &jaa); if (error) goto e_dropprref; ... } int jail_attach(struct thread *td, struct jail_attach_args *uap) { struct proc *p; struct ucred *newcred, *oldcred; struct prison *pr; ... p = td->td_proc; ... pr = prison_find(uap->jid); ... change_root(pr->pr_root, td); ... newcred->cr_prison = pr; p->p_ucred = newcred; ... } When a process is forked from its parent process, the &man.fork.2; system call uses crhold() to maintain the credential for the newly forked process. It inherently keep the newly forked child's credential consistent with its parent, so the child process is also jailed. /usr/src/sys/kern/kern_fork.c: p2->p_ucred = crhold(td->td_ucred); ... td2->td_ucred = crhold(p2->p_ucred); Restrictions Throughout the kernel there are access restrictions relating to jailed processes. Usually, these restrictions only check whether the process is jailed, and if so, returns an error. For example: if (jailed(td->td_ucred)) return (EPERM); SysV IPC System V IPC System V IPC is based on messages. Processes can send each other these messages which tell them how to act. The functions which deal with messages are: &man.msgctl.3;, &man.msgget.3;, &man.msgsnd.3; and &man.msgrcv.3;. Earlier, I mentioned that there were certain sysctls you could turn on or off in order to affect the behavior of jail. One of these sysctls was security.jail.sysvipc_allowed. By default, this sysctl is set to 0. If it were set to 1, it would defeat the whole purpose of having a jail; privileged users from the jail would be able to affect processes outside the jailed environment. The difference between a message and a signal is that the message only consists of the signal number. /usr/src/sys/kern/sysv_msg.c: msgget(key, msgflg): msgget returns (and possibly creates) a message descriptor that designates a message queue for use in other functions. msgctl(msgid, cmd, buf): Using this function, a process can query the status of a message descriptor. msgsnd(msgid, msgp, msgsz, msgflg): msgsnd sends a message to a process. msgrcv(msgid, msgp, msgsz, msgtyp, msgflg): a process receives messages using this function In each of the system calls corresponding to these functions, there is this conditional: /usr/src/sys/kern/sysv_msg.c: if (!jail_sysvipc_allowed && jailed(td->td_ucred)) return (ENOSYS); semaphores Semaphore system calls allow processes to synchronize execution by doing a set of operations atomically on a set of semaphores. Basically semaphores provide another way for processes lock resources. However, process waiting on a semaphore, that is being used, will sleep until the resources are relinquished. The following semaphore system calls are blocked inside a jail: &man.semget.2;, &man.semctl.2; and &man.semop.2;. /usr/src/sys/kern/sysv_sem.c: semctl(semid, semnum, cmd, ...): semctl does the specified cmd on the semaphore queue indicated by semid. semget(key, nsems, flag): semget creates an array of semaphores, corresponding to key. key and flag take on the same meaning as they do in msgget. semop(semid, array, nops): semop performs a group of operations indicated by array, to the set of semaphores identified by semid. shared memory System V IPC allows for processes to share memory. Processes can communicate directly with each other by sharing parts of their virtual address space and then reading and writing data stored in the shared memory. These system calls are blocked within a jailed environment: &man.shmdt.2;, &man.shmat.2;, &man.shmctl.2; and &man.shmget.2;. /usr/src/sys/kern/sysv_shm.c: shmctl(shmid, cmd, buf): shmctl does various control operations on the shared memory region identified by shmid. shmget(key, size, flag): shmget accesses or creates a shared memory region of size bytes. shmat(shmid, addr, flag): shmat attaches a shared memory region identified by shmid to the address space of a process. shmdt(addr): shmdt detaches the shared memory region previously attached at addr. Sockets sockets Jail treats the &man.socket.2; system call and related lower-level socket functions in a special manner. In order to determine whether a certain socket is allowed to be created, it first checks to see if the sysctl security.jail.socket_unixiproute_only is set. If set, sockets are only allowed to be created if the family specified is either PF_LOCAL, PF_INET or PF_ROUTE. Otherwise, it returns an error. /usr/src/sys/kern/uipc_socket.c: int socreate(int dom, struct socket **aso, int type, int proto, struct ucred *cred, struct thread *td) { struct protosw *prp; ... if (jailed(cred) && jail_socket_unixiproute_only && prp->pr_domain->dom_family != PF_LOCAL && prp->pr_domain->dom_family != PF_INET && prp->pr_domain->dom_family != PF_ROUTE) { return (EPROTONOSUPPORT); } ... } Berkeley Packet Filter Berkeley Packet Filter data link layer The Berkeley Packet Filter provides a raw interface to data link layers in a protocol independent fashion. BPF is now controlled by the &man.devfs.8; whether it can be used in a jailed environment. Protocols protocols There are certain protocols which are very common, such as TCP, UDP, IP and ICMP. IP and ICMP are on the same level: the network layer 2. There are certain precautions which are taken in order to prevent a jailed process from binding a protocol to a certain address only if the nam parameter is set. nam is a pointer to a sockaddr structure, which describes the address on which to bind the service. A more exact definition is that sockaddr "may be used as a template for referring to the identifying tag and length of each address". In the function in_pcbbind_setup(), sin is a pointer to a sockaddr_in structure, which contains the port, address, length and domain family of the socket which is to be bound. Basically, this disallows any processes from jail to be able to specify the address that doesn't belong to the jail in which the calling process exists. /usr/src/sys/netinet/in_pcb.c: int in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, u_short *lportp, struct ucred *cred) { ... struct sockaddr_in *sin; ... if (nam) { sin = (struct sockaddr_in *)nam; ... if (sin->sin_addr.s_addr != INADDR_ANY) if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) return(EINVAL); ... if (lport) { ... if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr)) return (EADDRNOTAVAIL); ... } } if (lport == 0) { ... if (laddr.s_addr != INADDR_ANY) if (prison_ip(cred, 0, &laddr.s_addr)) return (EINVAL); ... } ... if (prison_ip(cred, 0, &laddr.s_addr)) return (EINVAL); ... } You might be wondering what function prison_ip() does. prison_ip() is given three arguments, a pointer to the credential(represented by cred), any flags, and an IP address. It returns 1 if the IP address does NOT belong to the jail or 0 otherwise. As you can see from the code, if it is indeed an IP address not belonging to the - jail, the protcol is not allowed to bind + jail, the protocol is not allowed to bind to that address. /usr/src/sys/kern/kern_jail.c: int prison_ip(struct ucred *cred, int flag, u_int32_t *ip) { u_int32_t tmp; if (!jailed(cred)) return (0); if (flag) tmp = *ip; else tmp = ntohl(*ip); if (tmp == INADDR_ANY) { if (flag) *ip = cred->cr_prison->pr_ip; else *ip = htonl(cred->cr_prison->pr_ip); return (0); } if (tmp == INADDR_LOOPBACK) { if (flag) *ip = cred->cr_prison->pr_ip; else *ip = htonl(cred->cr_prison->pr_ip); return (0); } if (cred->cr_prison->pr_ip != tmp) return (1); return (0); } Filesystem filesystem Even root users within the jail are not allowed to unset or modify any file flags, such as immutable, append-only, and undeleteable flags, if the securelevel is greater than 0. /usr/src/sys/ufs/ufs/ufs_vnops.c: static int ufs_setattr(ap) ... { ... if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { error = securelevel_gt(cred, 0); if (error) return (error); } ... } } /usr/src/sys/kern/kern_priv.c int priv_check_cred(struct ucred *cred, int priv, int flags) { ... error = prison_priv_check(cred, priv); if (error) return (error); ... } /usr/src/sys/kern/kern_jail.c int prison_priv_check(struct ucred *cred, int priv) { ... switch (priv) { ... case PRIV_VFS_SYSFLAGS: if (jail_chflags_allowed) return (0); else return (EPERM); ... } ... }
diff --git a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml index 10e2089e2e..14c2f00542 100644 --- a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml @@ -1,8028 +1,8028 @@ Chris Costello TrustedBSD Project
chris@FreeBSD.org
Robert Watson TrustedBSD Project
rwatson@FreeBSD.org
The TrustedBSD MAC Framework MAC Documentation Copyright This documentation was developed for the FreeBSD Project by Chris Costello at Safeport Network Services and Network Associates Laboratories, the Security Research Division of Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 (CBOSS), as part of the DARPA CHATS research program. Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without modification, are permitted provided that the following conditions are met: Redistributions of source code (SGML DocBook) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS DOCUMENTATION IS PROVIDED BY THE NETWORKS ASSOCIATES TECHNOLOGY, INC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETWORKS ASSOCIATES TECHNOLOGY, INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Synopsis FreeBSD includes experimental support for several mandatory access control policies, as well as a framework for kernel security extensibility, the TrustedBSD MAC Framework. The MAC Framework is a pluggable access control framework, permitting new security policies to be easily linked into the kernel, loaded at boot, or loaded dynamically at run-time. The framework provides a variety of features to make it easier to implement new security policies, including the ability to easily tag security labels (such as confidentiality information) onto system objects. This chapter introduces the MAC policy framework and provides documentation for a sample MAC policy module. Introduction The TrustedBSD MAC framework provides a mechanism to allow the compile-time or run-time extension of the kernel access control model. New system policies may be implemented as kernel modules and linked to the kernel; if multiple policy modules are present, their results will be composed. The MAC Framework provides a variety of access control infrastructure services to assist policy writers, including support for transient and persistent policy-agnostic object security labels. This support is currently considered experimental. This chapter provides information appropriate for developers of policy modules, as well as potential consumers of MAC-enabled environments, to learn about how the MAC Framework supports access control extension of the kernel. Policy Background Mandatory Access Control (MAC), refers to a set of access control policies that are mandatorily enforced on users by the operating system. MAC policies may be contrasted with Discretionary Access Control (DAC) protections, by which non-administrative users may (at their discretion) protect objects. In traditional UNIX systems, DAC protections include file permissions and access control lists; MAC protections include process controls preventing inter-user debugging and firewalls. A variety of MAC policies have been formulated by operating system designers and security researches, including the Multi-Level Security (MLS) confidentiality policy, the Biba integrity policy, Role-Based Access Control (RBAC), Domain and Type Enforcement (DTE), and Type Enforcement (TE). Each model bases decisions on a variety of factors, including user identity, role, and security clearance, as well as security labels on objects representing concepts such as data sensitivity and integrity. The TrustedBSD MAC Framework is capable of supporting policy modules that implement all of these policies, as well as a broad class of system hardening policies, which may use existing security attributes, such as user and group IDs, as well as extended attributes on files, and other system properties. In addition, despite the name, the MAC Framework can also be used to implement purely discretionary policies, as policy modules are given substantial flexibility in how they authorize protections. MAC Framework Kernel Architecture The TrustedBSD MAC Framework permits kernel modules to extend the operating system security policy, as well as providing infrastructure functionality required by many access control modules. If multiple policies are simultaneously loaded, the MAC Framework will usefully (for some definition of useful) compose the results of the policies. Kernel Elements The MAC Framework contains a number of kernel elements: Framework management interfaces Concurrency and synchronization primitives. Policy registration Extensible security label for kernel objects Policy entry point composition operators Label management primitives Entry point API invoked by kernel services Entry point API to policy modules Entry points implementations (policy life cycle, object life cycle/label management, access control checks). Policy-agnostic label-management system calls mac_syscall() multiplex system call Various security policies implemented as MAC policy modules Framework Management Interfaces The TrustedBSD MAC Framework may be directly managed using sysctl's, loader tunables, and system calls. In most cases, sysctl's and loader tunables of the same name modify the same parameters, and control behavior such as enforcement of protections relating to various kernel subsystems. In addition, if MAC debugging support is compiled into the kernel, several counters will be maintained tracking label allocation. It is generally advisable that per-subsystem enforcement controls not be used to control policy behavior in production environments, as they broadly impact the operation of all active policies. Instead, per-policy controls should be preferred, as they provide greater granularity and greater operational consistency for policy modules. Loading and unloading of policy modules is performed using the system module management system calls and other system interfaces, including boot loader variables; policy modules will have the opportunity to influence load and unload events, including preventing undesired unloading of the policy. Policy List Concurrency and Synchronization As the set of active policies may change at run-time, and the invocation of entry points is non-atomic, synchronization is required to prevent loading or unloading of policies while an entry point invocation is in progress, freezing the set of active policies for the duration. This is accomplished by means of a framework busy count: whenever an entry point is entered, the busy count is incremented; whenever it is exited, the busy count is decremented. While the busy count is elevated, policy list changes are not permitted, and threads attempting to modify the policy list will sleep until the list is not busy. The busy count is protected by a mutex, and a condition variable is used to wake up sleepers waiting on policy list modifications. One side effect of this synchronization model is that recursion into the MAC Framework from within a policy module is permitted, although not generally used. Various optimizations are used to reduce the overhead of the busy count, including avoiding the full cost of incrementing and decrementing if the list is empty or contains only static entries (policies that are loaded before the system starts, and cannot be unloaded). A compile-time option is also provided which prevents any change in the set of loaded policies at run-time, which eliminates the mutex locking costs associated with supporting dynamically loaded and unloaded policies as synchronization is no longer required. As the MAC Framework is not permitted to block in some entry points, a normal sleep lock cannot be used; as a result, it is possible for the load or unload attempt to block for a substantial period of time waiting for the framework to become idle. Label Synchronization As kernel objects of interest may generally be accessed from more than one thread at a time, and simultaneous entry of more than one thread into the MAC Framework is permitted, security attribute storage maintained by the MAC Framework is carefully synchronized. In general, existing kernel synchronization on kernel object data is used to protect MAC Framework security labels on the object: for example, MAC labels on sockets are protected using the existing socket mutex. Likewise, semantics for concurrent access are generally identical to those of the container objects: for credentials, copy-on-write semantics are maintained for label contents as with the remainder of the credential structure. The MAC Framework asserts necessary locks on objects when invoked with an object reference. Policy authors must be aware of these synchronization semantics, as they will sometimes limit the types of accesses permitted on labels: for example, when a read-only reference to a credential is passed to a policy via an entry point, only read operations are permitted on the label state attached to the credential. Policy Synchronization and Concurrency Policy modules must be written to assume that many kernel threads may simultaneously enter one more policy entry points due to the parallel and preemptive nature of the FreeBSD kernel. If the policy module makes use of mutable state, this may require the use of synchronization primitives within the policy to prevent inconsistent views on that state resulting in incorrect operation of the policy. Policies will generally be able to make use of existing FreeBSD synchronization primitives for this purpose, including mutexes, sleep locks, condition variables, and counting semaphores. However, policies should be written to employ these primitives carefully, respecting existing kernel lock orders, and recognizing that some entry points are not permitted to sleep, limiting the use of primitives in those entry points to mutexes and wakeup operations. - When policy modules call out to other kernel subsytems, + When policy modules call out to other kernel subsystems, they will generally need to release any in-policy locks in order to avoid violating the kernel lock order or risking lock recursion. This will maintain policy locks as leaf locks in the global lock order, helping to avoid deadlock. Policy Registration The MAC Framework maintains two lists of active policies: a static list, and a dynamic list. The lists differ only with regards to their locking semantics: an elevated reference count is not required to make use of the static list. When kernel modules containing MAC Framework policies are loaded, the policy module will use SYSINIT to invoke a registration function; when a policy module is unloaded, SYSINIT will likewise invoke a de-registration function. Registration may fail if a policy module is loaded more than once, if insufficient resources are available for the registration (for example, the policy might require labeling and insufficient labeling state might be available), or other policy prerequisites might not be met (some policies may only be loaded prior to boot). Likewise, de-registration may fail if a policy is flagged as not unloadable. Entry Points Kernel services interact with the MAC Framework in two ways: they invoke a series of APIs to notify the framework of relevant events, and they provide a policy-agnostic label structure pointer in security-relevant objects. The label pointer is maintained by the MAC Framework via label management entry points, and permits the Framework to offer a labeling service to policy modules through relatively non-invasive changes to the kernel subsystem maintaining the object. For example, label pointers have been added to processes, process credentials, sockets, pipes, vnodes, Mbufs, network interfaces, IP reassembly queues, and a variety of other security-relevant structures. Kernel services also invoke the MAC Framework when they perform important security decisions, permitting policy modules to augment those decisions based on their own criteria (possibly including data stored in security labels). Most of these security critical decisions will be explicit access control checks; however, some affect more general decision functions such as packet matching for sockets and label transition at program execution. Policy Composition When more than one policy module is loaded into the kernel at a time, the results of the policy modules will be composed by the framework using a composition operator. This operator is currently hard-coded, and requires that all active policies must approve a request for it to return success. As policies may return a variety of error conditions (success, access denied, object does not exist, ...), a precedence operator selects the resulting error from the set of errors returned by policies. In general, errors indicating that an object does not exist will be preferred to errors indicating that access to an object is denied. While it is not guaranteed that the resulting composition will be useful or secure, we have found that it is for many useful selections of policies. For example, traditional trusted systems often ship with two or more policies using a similar composition. Labeling Support As many interesting access control extensions rely on security labels on objects, the MAC Framework provides a set of policy-agnostic label management system calls covering a variety of user-exposed objects. Common label types include partition identifiers, sensitivity labels, integrity labels, compartments, domains, roles, and types. By policy agnostic, we mean that policy modules are able to completely define the semantics of meta-data associated with an object. Policy modules participate in the internalization and externalization of string-based labels provides by user applications, and can expose multiple label elements to applications if desired. In-memory labels are stored in slab-allocated struct label, which consists of a fixed-length array of unions, each holding a void * pointer and a long. Policies registering for label storage will be assigned a "slot" identifier, which may be used to dereference the label storage. The semantics of the storage are left entirely up to the policy module: modules are provided with a variety of entry points associated with the kernel object life cycle, including initialization, association/creation, and destruction. Using these interfaces, it is possible to implement reference counting and other storage models. Direct access to the object structure is generally not required by policy modules to retrieve a label, as the MAC Framework generally passes both a pointer to the object and a direct pointer to the object's label into entry points. The primary exception to this rule is the process credential, which must be manually dereferenced to access the credential label. This may change in future revisions of the MAC Framework. Initialization entry points frequently include a sleeping disposition flag indicating whether or not an initialization is permitted to sleep; if sleeping is not permitted, a failure may be returned to cancel allocation of the label (and hence object). This may occur, for example, in the network stack during interrupt handling, where sleeping is not permitted, or while the caller holds a mutex. Due to the performance cost of maintaining labels on in-flight network packets (Mbufs), policies must specifically declare a requirement that Mbuf labels be allocated. Dynamically loaded policies making use of labels must be able to handle the case where their init function has not been called on an object, as objects may already exist when the policy is loaded. The MAC Framework guarantees that uninitialized label slots will hold a 0 or NULL value, which policies may use to detect uninitialized values. However, as allocation of Mbuf labels is conditional, policies must also be able to handle a NULL label pointer for Mbufs if they have been loaded dynamically. In the case of file system labels, special support is provided for the persistent storage of security labels in extended attributes. Where available, extended attribute transactions are used to permit consistent compound updates of security labels on vnodes--currently this support is present only in the UFS2 file system. Policy authors may choose to implement multilabel file system object labels using one (or more) extended attributes. For efficiency reasons, the vnode label (v_label) is a cache of any on-disk label; policies are able to load values into the cache when the vnode is instantiated, and update the cache as needed. As a result, the extended attribute need not be directly accessed with every access control check. Currently, if a labeled policy permits dynamic unloading, its state slot cannot be reclaimed, which places a strict (and relatively low) bound on the number of unload-reload operations for labeled policies. System Calls The MAC Framework implements a number of system calls: most of these calls support the policy-agnostic label retrieval and manipulation APIs exposed to user applications. The label management calls accept a label description structure, struct mac, which contains a series of MAC label elements. Each element contains a character string name, and character string value. Each policy will be given the chance to claim a particular element name, permitting policies to expose multiple independent elements if desired. Policy modules perform the internalization and externalization between kernel labels and user-provided labels via entry points, permitting a variety of semantics. Label management system calls are generally wrapped by user library functions to perform memory allocation and error handling, simplifying user applications that must manage labels. The following MAC-related system calls are present in the FreeBSD kernel: mac_get_proc() may be used to retrieve the label of the current process. mac_set_proc() may be used to request a change in the label of the current process. mac_get_fd() may be used to retrieve the label of an object (file, socket, pipe, ...) referenced by a file descriptor. mac_get_file() may be used to retrieve the label of an object referenced by a file system path. mac_set_fd() may be used to request a change in the label of an object (file, socket, pipe, ...) referenced by a file descriptor. mac_set_file() may be used to request a change in the label of an object referenced by a file system path. mac_syscall() permits policy modules to create new system calls without modifying the system call table; it accepts a target policy name, operation number, and opaque argument for use by the policy. mac_get_pid() may be used to request the label of another process by process id. mac_get_link() is identical to mac_get_file(), only it will not follow a symbolic link if it is the final entry in the path, so may be used to retrieve the label on a symlink. mac_set_link() is identical to mac_set_file(), only it will not follow a symbolic link if it is the final entry in a path, so may be used to manipulate the label on a symlink. mac_execve() is identical to the execve() system call, only it also accepts a requested label to set the process label to when beginning execution of a new program. This change in label on execution is referred to as a "transition". mac_get_peer(), actually implemented via a socket option, retrieves the label of a remote peer on a socket, if available. In addition to these system calls, the SIOCSIGMAC and SIOCSIFMAC network interface ioctls permit the labels on network interfaces to be retrieved and set. MAC Policy Architecture Security policies are either linked directly into the kernel, or compiled into loadable kernel modules that may be loaded at boot, or dynamically using the module loading system calls at runtime. Policy modules interact with the system through a set of declared entry points, providing access to a stream of system events and permitting the policy to influence access control decisions. Each policy contains a number of elements: Optional configuration parameters for policy. Centralized implementation of the policy logic and parameters. Optional implementation of policy life cycle events, such as initialization and destruction. Optional support for initializing, maintaining, and destroying labels on selected kernel objects. Optional support for user process inspection and modification of labels on selected objects. Implementation of selected access control entry points that are of interest to the policy. Declaration of policy identity, module entry points, and policy properties. Policy Declaration Modules may be declared using the MAC_POLICY_SET() macro, which names the policy, provides a reference to the MAC entry point vector, provides load-time flags determining how the policy framework should handle the policy, and optionally requests the allocation of label state by the framework. static struct mac_policy_ops mac_policy_ops = { .mpo_destroy = mac_policy_destroy, .mpo_init = mac_policy_init, .mpo_init_bpfdesc_label = mac_policy_init_bpfdesc_label, .mpo_init_cred_label = mac_policy_init_label, /* ... */ .mpo_check_vnode_setutimes = mac_policy_check_vnode_setutimes, .mpo_check_vnode_stat = mac_policy_check_vnode_stat, .mpo_check_vnode_write = mac_policy_check_vnode_write, }; The MAC policy entry point vector, mac_policy_ops in this example, associates functions defined in the module with specific entry points. A complete listing of available entry points and their prototypes may be found in the MAC entry point reference section. Of specific interest during module registration are the .mpo_destroy and .mpo_init entry points. .mpo_init will be invoked once a policy is successfully registered with the module framework but prior to any other entry points becoming active. This permits the policy to perform any policy-specific allocation and initialization, such as initialization of any data or locks. .mpo_destroy will be invoked when a policy module is unloaded to permit releasing of any allocated memory and destruction of locks. Currently, these two entry points are invoked with the MAC policy list mutex held to prevent any other entry points from being invoked: this will be changed, but in the mean time, policies should be careful about what kernel primitives they invoke so as to avoid lock ordering or sleeping problems. The policy declaration's module name field exists so that the module may be uniquely identified for the purposes of module dependencies. An appropriate string should be selected. The full string name of the policy is displayed to the user via the kernel log during load and unload events, and also exported when providing status information to userland processes. Policy Flags The policy declaration flags field permits the module to provide the framework with information about its capabilities at the time the module is loaded. Currently, three flags are defined: MPC_LOADTIME_FLAG_UNLOADOK This flag indicates that the policy module may be unloaded. If this flag is not provided, then the policy framework will reject requests to unload the module. This flag might be used by modules that allocate label state and are unable to free that state at runtime. MPC_LOADTIME_FLAG_NOTLATE This flag indicates that the policy module must be loaded and initialized early in the boot process. If the flag is specified, attempts to register the module following boot will be rejected. The flag may be used by policies that require pervasive labeling of all system objects, and cannot handle objects that have not been properly initialized by the policy. MPC_LOADTIME_FLAG_LABELMBUFS This flag indicates that the policy module requires labeling of Mbufs, and that memory should always be allocated for the storage of Mbuf labels. By default, the MAC Framework will not allocate label storage for Mbufs unless at least one loaded policy has this flag set. This measurably improves network performance when policies do not require Mbuf labeling. A kernel option, MAC_ALWAYS_LABEL_MBUF, exists to force the MAC Framework to allocate Mbuf label storage regardless of the setting of this flag, and may be useful in some environments. Policies using the MPC_LOADTIME_FLAG_LABELMBUFS without the MPC_LOADTIME_FLAG_NOTLATE flag set must be able to correctly handle NULL Mbuf label pointers passed into entry points. This is necessary as in-flight Mbufs without label storage may persist after a policy enabling Mbuf labeling has been loaded. If a policy is loaded before the network subsystem is active (i.e., the policy is not being loaded late), then all Mbufs are guaranteed to have label storage. Policy Entry Points Four classes of entry points are offered to policies registered with the framework: entry points associated with the registration and management of policies, entry points denoting initialization, creation, destruction, and other life cycle events for kernel objects, events associated with access control decisions that the policy module may influence, and calls associated with the management of labels on objects. In addition, a mac_syscall() entry point is provided so that policies may extend the kernel interface without registering new system calls. Policy module writers should be aware of the kernel locking strategy, as well as what object locks are available during which entry points. Writers should attempt to avoid deadlock scenarios by avoiding grabbing non-leaf locks inside of entry points, and also follow the locking protocol for object access and modification. In particular, writers should be aware that while necessary locks to access objects and their labels are generally held, sufficient locks to modify an object or its label may not be present for all entry points. Locking information for arguments is documented in the MAC framework entry point document. Policy entry points will pass a reference to the object label along with the object itself. This permits labeled policies to be unaware of the internals of the object yet still make decisions based on the label. The exception to this is the process credential, which is assumed to be understood by policies as a first class security object in the kernel. MAC Policy Entry Point Reference General-Purpose Module Entry Points <function>&mac.mpo;_init</function> void &mac.mpo;_init struct mac_policy_conf *conf &mac.thead; conf MAC policy definition Policy load event. The policy list mutex is held, so sleep operations cannot be performed, and calls out to other kernel subsystems must be made with caution. If potentially sleeping memory allocations are required during policy initialization, they should be made using a separate module SYSINIT(). <function>&mac.mpo;_destroy</function> void &mac.mpo;_destroy struct mac_policy_conf *conf &mac.thead; conf MAC policy definition Policy load event. The policy list mutex is held, so caution should be applied. <function>&mac.mpo;_syscall</function> int &mac.mpo;_syscall struct thread *td int call void *arg &mac.thead; td Calling thread call Policy-specific syscall number arg Pointer to syscall arguments This entry point provides a policy-multiplexed system call so that policies may provide additional services to user processes without registering specific system calls. The policy name provided during registration is used to demux calls from userland, and the arguments will be forwarded to this entry point. When implementing new services, security modules should be sure to invoke appropriate access control checks from the MAC framework as needed. For example, if a policy implements an augmented signal functionality, it should call the necessary signal access control checks to invoke the MAC framework and other registered policies. Modules must currently perform the copyin() of the syscall data on their own. <function>&mac.mpo;_thread_userret</function> void &mac.mpo;_thread_userret struct thread *td &mac.thead; td Returning thread This entry point permits policy modules to perform MAC-related events when a thread returns to user space, via a system call return, trap return, or otherwise. This is required for policies that have floating process labels, as it is not always possible to acquire the process lock at arbitrary points in the stack during system call processing; process labels might represent traditional authentication data, process history information, or other data. To employ this mechanism, intended changes to the process credential label may be stored in the p_label protected by a per-policy spin lock, and then set the per-thread TDF_ASTPENDING flag and per-process PS_MACPENDM flag to schedule a call to the userret entry point. From this entry point, the policy may create a replacement credential with less concern about the locking context. Policy writers are cautioned that event ordering relating to scheduling an AST and the AST being performed may be complex and interlaced in multithreaded applications. Label Operations <function>&mac.mpo;_init_bpfdesc_label</function> void &mac.mpo;_init_bpfdesc_label struct label *label &mac.thead; label New label to apply Initialize the label on a newly instantiated bpfdesc (BPF descriptor). Sleeping is permitted. <function>&mac.mpo;_init_cred_label</function> void &mac.mpo;_init_cred_label struct label *label &mac.thead; label New label to initialize Initialize the label for a newly instantiated user credential. Sleeping is permitted. <function>&mac.mpo;_init_devfsdirent_label</function> void &mac.mpo;_init_devfsdirent_label struct label *label &mac.thead; label New label to apply Initialize the label on a newly instantiated devfs entry. Sleeping is permitted. <function>&mac.mpo;_init_ifnet_label</function> void &mac.mpo;_init_ifnet_label struct label *label &mac.thead; label New label to apply Initialize the label on a newly instantiated network interface. Sleeping is permitted. <function>&mac.mpo;_init_ipq_label</function> void &mac.mpo;_init_ipq_label struct label *label int flag &mac.thead; label New label to apply flag Sleeping/non-sleeping &man.malloc.9;; see below Initialize the label on a newly instantiated IP fragment reassembly queue. The flag field may be one of M_WAITOK and M_NOWAIT, and should be employed to avoid performing a sleeping &man.malloc.9; during this initialization call. IP fragment reassembly queue allocation frequently occurs in performance sensitive environments, and the implementation should be careful to avoid sleeping or long-lived operations. This entry point is permitted to fail resulting in the failure to allocate the IP fragment reassembly queue. <function>&mac.mpo;_init_mbuf_label</function> void &mac.mpo;_init_mbuf_label int flag struct label *label &mac.thead; flag Sleeping/non-sleeping &man.malloc.9;; see below label Policy label to initialize Initialize the label on a newly instantiated mbuf packet header (mbuf). The flag field may be one of M_WAITOK and M_NOWAIT, and should be employed to avoid performing a sleeping &man.malloc.9; during this initialization call. Mbuf allocation frequently occurs in performance sensitive environments, and the implementation should be careful to avoid sleeping or long-lived operations. This entry point is permitted to fail resulting in the failure to allocate the mbuf header. <function>&mac.mpo;_init_mount_label</function> void &mac.mpo;_init_mount_label struct label *mntlabel struct label *fslabel &mac.thead; mntlabel Policy label to be initialized for the mount itself fslabel Policy label to be initialized for the file system Initialize the labels on a newly instantiated mount point. Sleeping is permitted. <function>&mac.mpo;_init_mount_fs_label</function> void &mac.mpo;_init_mount_fs_label struct label *label &mac.thead; label Label to be initialized Initialize the label on a newly mounted file system. Sleeping is permitted <function>&mac.mpo;_init_pipe_label</function> void &mac.mpo;_init_pipe_label struct label*label &mac.thead; label Label to be filled in Initialize a label for a newly instantiated pipe. Sleeping is permitted. <function>&mac.mpo;_init_socket_label</function> void &mac.mpo;_init_socket_label struct label *label int flag &mac.thead; label New label to initialize flag &man.malloc.9; flags Initialize a label for a newly instantiated socket. The flag field may be one of M_WAITOK and M_NOWAIT, and should be employed to avoid performing a sleeping &man.malloc.9; during this initialization call. <function>&mac.mpo;_init_socket_peer_label</function> void &mac.mpo;_init_socket_peer_label struct label *label int flag &mac.thead; label New label to initialize flag &man.malloc.9; flags Initialize the peer label for a newly instantiated socket. The flag field may be one of M_WAITOK and M_NOWAIT, and should be employed to avoid performing a sleeping &man.malloc.9; during this initialization call. <function>&mac.mpo;_init_proc_label</function> void &mac.mpo;_init_proc_label struct label *label &mac.thead; label New label to initialize Initialize the label for a newly instantiated process. Sleeping is permitted. <function>&mac.mpo;_init_vnode_label</function> void &mac.mpo;_init_vnode_label struct label *label &mac.thead; label New label to initialize Initialize the label on a newly instantiated vnode. Sleeping is permitted. <function>&mac.mpo;_destroy_bpfdesc_label</function> void &mac.mpo;_destroy_bpfdesc_label struct label *label &mac.thead; label bpfdesc label Destroy the label on a BPF descriptor. In this entry point a policy should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_cred_label</function> void &mac.mpo;_destroy_cred_label struct label *label &mac.thead; label Label being destroyed Destroy the label on a credential. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_devfsdirent_label</function> void &mac.mpo;_destroy_devfsdirent_label struct label *label &mac.thead; label Label being destroyed Destroy the label on a devfs entry. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_ifnet_label</function> void &mac.mpo;_destroy_ifnet_label struct label *label &mac.thead; label Label being destroyed Destroy the label on a removed interface. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_ipq_label</function> void &mac.mpo;_destroy_ipq_label struct label *label &mac.thead; label Label being destroyed Destroy the label on an IP fragment queue. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_mbuf_label</function> void &mac.mpo;_destroy_mbuf_label struct label *label &mac.thead; label Label being destroyed Destroy the label on an mbuf header. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_mount_label</function> void &mac.mpo;_destroy_mount_label struct label *label &mac.thead; label Mount point label being destroyed Destroy the labels on a mount point. In this entry point, a policy module should free the internal storage associated with mntlabel so that they may be destroyed. <function>&mac.mpo;_destroy_mount_label</function> void &mac.mpo;_destroy_mount_label struct label *mntlabel struct label *fslabel &mac.thead; mntlabel Mount point label being destroyed fslabel File system label being destroyed> Destroy the labels on a mount point. In this entry point, a policy module should free the internal storage associated with mntlabel and fslabel so that they may be destroyed. <function>&mac.mpo;_destroy_socket_label</function> void &mac.mpo;_destroy_socket_label struct label *label &mac.thead; label Socket label being destroyed Destroy the label on a socket. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_socket_peer_label</function> void &mac.mpo;_destroy_socket_peer_label struct label *peerlabel &mac.thead; peerlabel Socket peer label being destroyed Destroy the peer label on a socket. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_pipe_label</function> void &mac.mpo;_destroy_pipe_label struct label *label &mac.thead; label Pipe label Destroy the label on a pipe. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_proc_label</function> void &mac.mpo;_destroy_proc_label struct label *label &mac.thead; label Process label Destroy the label on a process. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_destroy_vnode_label</function> void &mac.mpo;_destroy_vnode_label struct label *label &mac.thead; label Process label Destroy the label on a vnode. In this entry point, a policy module should free any internal storage associated with label so that it may be destroyed. <function>&mac.mpo;_copy_mbuf_label</function> void &mac.mpo;_copy_mbuf_label struct label *src struct label *dest &mac.thead; src Source label dest Destination label Copy the label information in src into dest. <function>&mac.mpo;_copy_pipe_label</function> void &mac.mpo;_copy_pipe_label struct label *src struct label *dest &mac.thead; src Source label dest Destination label Copy the label information in src into dest. <function>&mac.mpo;_copy_vnode_label</function> void &mac.mpo;_copy_vnode_label struct label *src struct label *dest &mac.thead; src Source label dest Destination label Copy the label information in src into dest. <function>&mac.mpo;_externalize_cred_label</function> int &mac.mpo;_externalize_cred_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_externalize_ifnet_label</function> int &mac.mpo;_externalize_ifnet_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_externalize_pipe_label</function> int &mac.mpo;_externalize_pipe_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_externalize_socket_label</function> int &mac.mpo;_externalize_socket_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_externalize_socket_peer_label</function> int &mac.mpo;_externalize_socket_peer_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_externalize_vnode_label</function> int &mac.mpo;_externalize_vnode_label &mac.externalize.paramdefs; &mac.thead; &mac.externalize.tbody; &mac.externalize.para; <function>&mac.mpo;_internalize_cred_label</function> int &mac.mpo;_internalize_cred_label &mac.internalize.paramdefs; &mac.thead; &mac.internalize.tbody; &mac.internalize.para; <function>&mac.mpo;_internalize_ifnet_label</function> int &mac.mpo;_internalize_ifnet_label &mac.internalize.paramdefs; &mac.thead; &mac.internalize.tbody; &mac.internalize.para; <function>&mac.mpo;_internalize_pipe_label</function> int &mac.mpo;_internalize_pipe_label &mac.internalize.paramdefs; &mac.thead; &mac.internalize.tbody; &mac.internalize.para; <function>&mac.mpo;_internalize_socket_label</function> int &mac.mpo;_internalize_socket_label &mac.internalize.paramdefs; &mac.thead; &mac.internalize.tbody; &mac.internalize.para; <function>&mac.mpo;_internalize_vnode_label</function> int &mac.mpo;_internalize_vnode_label &mac.internalize.paramdefs; &mac.thead; &mac.internalize.tbody; &mac.internalize.para; Label Events This class of entry points is used by the MAC framework to permit policies to maintain label information on kernel objects. For each labeled kernel object of interest to a MAC policy, entry points may be registered for relevant life cycle events. All objects implement initialization, creation, and destruction hooks. Some objects will also implement relabeling, allowing user processes to change the labels on objects. Some objects will also implement object-specific events, such as label events associated with IP reassembly. A typical labeled object will have the following life cycle of entry points: Label initialization o (object-specific wait) \ Label creation o \ Relabel events, o--<--. Various object-specific, | | Access control events ~-->--o \ Label destruction o Label initialization permits policies to allocate memory and set initial values for labels without context for the use of the object. The label slot allocated to a policy will be zeroed by default, so some policies may not need to perform initialization. Label creation occurs when the kernel structure is associated with an actual kernel object. For example, Mbufs may be allocated and remain unused in a pool until they are required. mbuf allocation causes label initialization on the mbuf to take place, but mbuf creation occurs when the mbuf is associated with a datagram. Typically, context will be provided for a creation event, including the circumstances of the creation, and labels of other relevant objects in the creation process. For example, when an mbuf is created from a socket, the socket and its label will be presented to registered policies in addition to the new mbuf and its label. Memory allocation in creation events is discouraged, as it may occur in performance sensitive ports of the kernel; in addition, creation calls are not permitted to fail so a failure to allocate memory cannot be reported. Object specific events do not generally fall into the other broad classes of label events, but will generally provide an opportunity to modify or update the label on an object based on additional context. For example, the label on an IP fragment reassembly queue may be updated during the MAC_UPDATE_IPQ entry point as a result of the acceptance of an additional mbuf to that queue. Access control events are discussed in detail in the following section. Label destruction permits policies to release storage or state associated with a label during its association with an object so that the kernel data structures supporting the object may be reused or released. In addition to labels associated with specific kernel objects, an additional class of labels exists: temporary labels. These labels are used to store update information submitted by user processes. These labels are initialized and destroyed as with other label types, but the creation event is MAC_INTERNALIZE, which accepts a user label to be converted to an in-kernel representation. File System Object Labeling Event Operations <function>&mac.mpo;_associate_vnode_devfs</function> void &mac.mpo;_associate_vnode_devfs struct mount *mp struct label *fslabel struct devfs_dirent *de struct label *delabel struct vnode *vp struct label *vlabel &mac.thead; mp Devfs mount point fslabel Devfs file system label (mp->mnt_fslabel) de Devfs directory entry delabel Policy label associated with de vp vnode associated with de vlabel Policy label associated with vp Fill in the label (vlabel) for a newly created devfs vnode based on the devfs directory entry passed in de and its label. <function>&mac.mpo;_associate_vnode_extattr</function> int &mac.mpo;_associate_vnode_extattr struct mount *mp struct label *fslabel struct vnode *vp struct label *vlabel &mac.thead; mp File system mount point fslabel File system label vp Vnode to label vlabel Policy label associated with vp Attempt to retrieve the label for vp from the file system extended attributes. Upon success, the value 0 is returned. Should extended attribute retrieval not be supported, an accepted fallback is to copy fslabel into vlabel. In the event of an error, an appropriate value for errno should be returned. <function>&mac.mpo;_associate_vnode_singlelabel</function> void &mac.mpo;_associate_vnode_singlelabel struct mount *mp struct label *fslabel struct vnode *vp struct label *vlabel &mac.thead; mp File system mount point fslabel File system label vp Vnode to label vlabel Policy label associated with vp On non-multilabel file systems, this entry point is called to set the policy label for vp based on the file system label, fslabel. <function>&mac.mpo;_create_devfs_device</function> void &mac.mpo;_create_devfs_device dev_t dev struct devfs_dirent *devfs_dirent struct label *label &mac.thead; dev Device corresponding with devfs_dirent devfs_dirent Devfs directory entry to be labeled. label Label for devfs_dirent to be filled in. Fill out the label on a devfs_dirent being created for the passed device. This call will be made when the device file system is mounted, regenerated, or a new device is made available. <function>&mac.mpo;_create_devfs_directory</function> void &mac.mpo;_create_devfs_directory char *dirname int dirnamelen struct devfs_dirent *devfs_dirent struct label *label &mac.thead; dirname Name of directory being created namelen Length of string dirname devfs_dirent Devfs directory entry for directory being created. Fill out the label on a devfs_dirent being created for the passed directory. This call will be made when the device file system is mounted, regenerated, or a new device requiring a specific directory hierarchy is made available. <function>&mac.mpo;_create_devfs_symlink</function> void &mac.mpo;_create_devfs_symlink struct ucred *cred struct mount *mp struct devfs_dirent *dd struct label *ddlabel struct devfs_dirent *de struct label *delabel &mac.thead; cred Subject credential mp Devfs mount point dd Link destination ddlabel Label associated with dd de Symlink entry delabel Label associated with de Fill in the label (delabel) for a newly created &man.devfs.5; symbolic link entry. <function>&mac.mpo;_create_vnode_extattr</function> int &mac.mpo;_create_vnode_extattr struct ucred *cred struct mount *mp struct label *fslabel struct vnode *dvp struct label *dlabel struct vnode *vp struct label *vlabel struct componentname *cnp &mac.thead; cred Subject credential mount File system mount point label File system label dvp Parent directory vnode dlabel Label associated with dvp vp Newly created vnode vlabel Policy label associated with vp cnp Component name for vp Write out the label for vp to the appropriate extended attribute. If the write succeeds, fill in vlabel with the label, and return 0. Otherwise, return an appropriate error. <function>&mac.mpo;_create_mount</function> void &mac.mpo;_create_mount struct ucred *cred struct mount *mp struct label *mnt struct label *fslabel &mac.thead; cred Subject credential mp Object; file system being mounted mntlabel Policy label to be filled in for mp fslabel Policy label for the file system mp mounts. Fill out the labels on the mount point being created by the passed subject credential. This call will be made when a new file system is mounted. <function>&mac.mpo;_create_root_mount</function> void &mac.mpo;_create_root_mount struct ucred *cred struct mount *mp struct label *mntlabel struct label *fslabel &mac.thead; See . Fill out the labels on the mount point being created by the passed subject credential. This call will be made when the root file system is mounted, after &mac.mpo;_create_mount;. <function>&mac.mpo;_relabel_vnode</function> void &mac.mpo;_relabel_vnode struct ucred *cred struct vnode *vp struct label *vnodelabel struct label *newlabel &mac.thead; cred Subject credential vp vnode to relabel vnodelabel Existing policy label for vp newlabel New, possibly partial label to replace vnodelabel Update the label on the passed vnode given the passed update vnode label and the passed subject credential. <function>&mac.mpo;_setlabel_vnode_extattr</function> int &mac.mpo;_setlabel_vnode_extattr struct ucred *cred struct vnode *vp struct label *vlabel struct label *intlabel &mac.thead; cred Subject credential vp Vnode for which the label is being written vlabel Policy label associated with vp intlabel Label to write out Write out the policy from intlabel to an extended attribute. This is called from vop_stdcreatevnode_ea. <function>&mac.mpo;_update_devfsdirent</function> void &mac.mpo;_update_devfsdirent struct devfs_dirent *devfs_dirent struct label *direntlabel struct vnode *vp struct label *vnodelabel &mac.thead; devfs_dirent Object; devfs directory entry direntlabel Policy label for devfs_dirent to be updated. vp Parent vnode Locked vnodelabel Policy label for vp Update the devfs_dirent label from the passed devfs vnode label. This call will be made when a devfs vnode has been successfully relabeled to commit the label change such that it lasts even if the vnode is recycled. It will also be made when when a symlink is created in devfs, following a call to mac_vnode_create_from_vnode to initialize the vnode label. IPC Object Labeling Event Operations <function>&mac.mpo;_create_mbuf_from_socket</function> void &mac.mpo;_create_mbuf_from_socket struct socket *so struct label *socketlabel struct mbuf *m struct label *mbuflabel &mac.thead; socket Socket Socket locking WIP socketlabel Policy label for socket m Object; mbuf mbuflabel Policy label to fill in for m Set the label on a newly created mbuf header from the passed socket label. This call is made when a new datagram or message is generated by the socket and stored in the passed mbuf. <function>&mac.mpo;_create_pipe</function> void &mac.mpo;_create_pipe struct ucred *cred struct pipe *pipe struct label *pipelabel &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe Set the label on a newly created pipe from the passed subject credential. This call is made when a new pipe is created. <function>&mac.mpo;_create_socket</function> void &mac.mpo;_create_socket struct ucred *cred struct socket *so struct label *socketlabel &mac.thead; cred Subject credential Immutable so Object; socket to label socketlabel Label to fill in for so Set the label on a newly created socket from the passed subject credential. This call is made when a socket is created. <function>&mac.mpo;_create_socket_from_socket</function> void &mac.mpo;_create_socket_from_socket struct socket *oldsocket struct label *oldsocketlabel struct socket *newsocket struct label *newsocketlabel &mac.thead; oldsocket Listening socket oldsocketlabel Policy label associated with oldsocket newsocket New socket newsocketlabel Policy label associated with newsocketlabel Label a socket, newsocket, newly &man.accept.2;ed, based on the &man.listen.2; socket, oldsocket. <function>&mac.mpo;_relabel_pipe</function> void &mac.mpo;_relabel_pipe struct ucred *cred struct pipe *pipe struct label *oldlabel struct label *newlabel &mac.thead; cred Subject credential pipe Pipe oldlabel Current policy label associated with pipe newlabel Policy label update to apply to pipe Apply a new label, newlabel, to pipe. <function>&mac.mpo;_relabel_socket</function> void &mac.mpo;_relabel_socket struct ucred *cred struct socket *so struct label *oldlabel struct label *newlabel &mac.thead; cred Subject credential Immutable so Object; socket oldlabel Current label for so newlabel Label update for so Update the label on a socket from the passed socket label update. <function>&mac.mpo;_set_socket_peer_from_mbuf</function> void &mac.mpo;_set_socket_peer_from_mbuf struct mbuf *mbuf struct label *mbuflabel struct label *oldlabel struct label *newlabel &mac.thead; mbuf First datagram received over socket mbuflabel Label for mbuf oldlabel Current label for the socket newlabel Policy label to be filled out for the socket Set the peer label on a stream socket from the passed mbuf label. This call will be made when the first datagram is received by the stream socket, with the exception of Unix domain sockets. <function>&mac.mpo;_set_socket_peer_from_socket</function> void &mac.mpo;_set_socket_peer_from_socket struct socket *oldsocket struct label *oldsocketlabel struct socket *newsocket struct label *newsocketpeerlabel &mac.thead; oldsocket Local socket oldsocketlabel Policy label for oldsocket newsocket Peer socket newsocketpeerlabel Policy label to fill in for newsocket Set the peer label on a stream UNIX domain socket from the passed remote socket endpoint. This call will be made when the socket pair is connected, and will be made for both endpoints. Network Object Labeling Event Operations <function>&mac.mpo;_create_bpfdesc</function> void &mac.mpo;_create_bpfdesc struct ucred *cred struct bpf_d *bpf_d struct label *bpflabel &mac.thead; cred Subject credential Immutable bpf_d Object; bpf descriptor bpf Policy label to be filled in for bpf_d Set the label on a newly created BPF descriptor from the passed subject credential. This call will be made when a BPF device node is opened by a process with the passed subject credential. <function>&mac.mpo;_create_ifnet</function> void &mac.mpo;_create_ifnet struct ifnet *ifnet struct label *ifnetlabel &mac.thead; ifnet Network interface ifnetlabel Policy label to fill in for ifnet Set the label on a newly created interface. This call may be made when a new physical interface becomes available to the system, or when a pseudo-interface is instantiated during the boot or as a result of a user action. <function>&mac.mpo;_create_ipq</function> void &mac.mpo;_create_ipq struct mbuf *fragment struct label *fragmentlabel struct ipq *ipq struct label *ipqlabel &mac.thead; fragment First received IP fragment fragmentlabel Policy label for fragment ipq IP reassembly queue to be labeled ipqlabel Policy label to be filled in for ipq Set the label on a newly created IP fragment reassembly queue from the mbuf header of the first received fragment. <function>&mac.mpo;_create_datagram_from_ipq</function> void &mac.mpo;_create_create_datagram_from_ipq struct ipq *ipq struct label *ipqlabel struct mbuf *datagram struct label *datagramlabel &mac.thead; ipq IP reassembly queue ipqlabel Policy label for ipq datagram Datagram to be labeled datagramlabel Policy label to be filled in for datagramlabel Set the label on a newly reassembled IP datagram from the IP fragment reassembly queue from which it was generated. <function>&mac.mpo;_create_fragment</function> void &mac.mpo;_create_fragment struct mbuf *datagram struct label *datagramlabel struct mbuf *fragment struct label *fragmentlabel &mac.thead; datagram Datagram datagramlabel Policy label for datagram fragment Fragment to be labeled fragmentlabel Policy label to be filled in for datagram Set the label on the mbuf header of a newly created IP fragment from the label on the mbuf header of the datagram it was generate from. <function>&mac.mpo;_create_mbuf_from_mbuf</function> void &mac.mpo;_create_mbuf_from_mbuf struct mbuf *oldmbuf struct label *oldmbuflabel struct mbuf *newmbuf struct label *newmbuflabel &mac.thead; oldmbuf Existing (source) mbuf oldmbuflabel Policy label for oldmbuf newmbuf New mbuf to be labeled newmbuflabel Policy label to be filled in for newmbuf Set the label on the mbuf header of a newly created datagram from the mbuf header of an existing datagram. This call may be made in a number of situations, including when an mbuf is re-allocated for alignment purposes. <function>&mac.mpo;_create_mbuf_linklayer</function> void &mac.mpo;_create_mbuf_linklayer struct ifnet *ifnet struct label *ifnetlabel struct mbuf *mbuf struct label *mbuflabel &mac.thead; ifnet Network interface ifnetlabel Policy label for ifnet mbuf mbuf header for new datagram mbuflabel Policy label to be filled in for mbuf Set the label on the mbuf header of a newly created datagram generated for the purposes of a link layer response for the passed interface. This call may be made in a number of situations, including for ARP or ND6 responses in the IPv4 and IPv6 stacks. <function>&mac.mpo;_create_mbuf_from_bpfdesc</function> void &mac.mpo;_create_mbuf_from_bpfdesc struct bpf_d *bpf_d struct label *bpflabel struct mbuf *mbuf struct label *mbuflabel &mac.thead; bpf_d BPF descriptor bpflabel Policy label for bpflabel mbuf New mbuf to be labeled mbuflabel Policy label to fill in for mbuf Set the label on the mbuf header of a newly created datagram generated using the passed BPF descriptor. This call is made when a write is performed to the BPF device associated with the passed BPF descriptor. <function>&mac.mpo;_create_mbuf_from_ifnet</function> void &mac.mpo;_create_mbuf_from_ifnet struct ifnet *ifnet struct label *ifnetlabel struct mbuf *mbuf struct label *mbuflabel &mac.thead; ifnet Network interface ifnetlabel Policy label for ifnetlabel mbuf mbuf header for new datagram mbuflabel Policy label to be filled in for mbuf Set the label on the mbuf header of a newly created datagram generated from the passed network interface. <function>&mac.mpo;_create_mbuf_multicast_encap</function> void &mac.mpo;_create_mbuf_multicast_encap struct mbuf *oldmbuf struct label *oldmbuflabel struct ifnet *ifnet struct label *ifnetlabel struct mbuf *newmbuf struct label *newmbuflabel &mac.thead; oldmbuf mbuf header for existing datagram oldmbuflabel Policy label for oldmbuf ifnet Network interface ifnetlabel Policy label for ifnet newmbuf mbuf header to be labeled for new datagram newmbuflabel Policy label to be filled in for newmbuf Set the label on the mbuf header of a newly created datagram generated from the existing passed datagram when it is processed by the passed multicast encapsulation interface. This call is made when an mbuf is to be delivered using the virtual interface. <function>&mac.mpo;_create_mbuf_netlayer</function> void &mac.mpo;_create_mbuf_netlayer struct mbuf *oldmbuf struct label *oldmbuflabel struct mbuf *newmbuf struct label *newmbuflabel &mac.thead; oldmbuf Received datagram oldmbuflabel Policy label for oldmbuf newmbuf Newly created datagram newmbuflabel Policy label for newmbuf Set the label on the mbuf header of a newly created datagram generated by the IP stack in response to an existing received datagram (oldmbuf). This call may be made in a number of situations, including when responding to ICMP request datagrams. <function>&mac.mpo;_fragment_match</function> int &mac.mpo;_fragment_match struct mbuf *fragment struct label *fragmentlabel struct ipq *ipq struct label *ipqlabel &mac.thead; fragment IP datagram fragment fragmentlabel Policy label for fragment ipq IP fragment reassembly queue ipqlabel Policy label for ipq Determine whether an mbuf header containing an IP datagram (fragment) fragment matches the label of the passed IP fragment reassembly queue (ipq). Return (1) for a successful match, or (0) for no match. This call is made when the IP stack attempts to find an existing fragment reassembly queue for a newly received fragment; if this fails, a new fragment reassembly queue may be instantiated for the fragment. Policies may use this entry point to prevent the reassembly of otherwise matching IP fragments if policy does not permit them to be reassembled based on the label or other information. <function>&mac.mpo;_relabel_ifnet</function> void &mac.mpo;_relabel_ifnet struct ucred *cred struct ifnet *ifnet struct label *ifnetlabel struct label *newlabel &mac.thead; cred Subject credential ifnet Object; Network interface ifnetlabel Policy label for ifnet newlabel Label update to apply to ifnet Update the label of network interface, ifnet, based on the passed update label, newlabel, and the passed subject credential, cred. <function>&mac.mpo;_update_ipq</function> void &mac.mpo;_update_ipq struct mbuf *fragment struct label *fragmentlabel struct ipq *ipq struct label *ipqlabel &mac.thead; mbuf IP fragment mbuflabel Policy label for mbuf ipq IP fragment reassembly queue ipqlabel Policy label to be updated for ipq Update the label on an IP fragment reassembly queue (ipq) based on the acceptance of the passed IP fragment mbuf header (mbuf). Process Labeling Event Operations <function>&mac.mpo;_create_cred</function> void &mac.mpo;_create_cred struct ucred *parent_cred struct ucred *child_cred &mac.thead; parent_cred Parent subject credential child_cred Child subject credential Set the label of a newly created subject credential from the passed subject credential. This call will be made when &man.crcopy.9; is invoked on a newly created struct ucred. This call should not be confused with a process forking or creation event. <function>&mac.mpo;_execve_transition</function> void &mac.mpo;_execve_transition struct ucred *old struct ucred *new struct vnode *vp struct label *vnodelabel &mac.thead; old Existing subject credential Immutable new New subject credential to be labeled vp File to execute Locked vnodelabel Policy label for vp Update the label of a newly created subject credential (new) from the passed existing subject credential (old) based on a label transition caused by executing the passed vnode (vp). This call occurs when a process executes the passed vnode and one of the policies returns a success from the mpo_execve_will_transition entry point. Policies may choose to implement this call simply by invoking mpo_create_cred and passing the two subject credentials so as not to implement a transitioning event. Policies should not leave this entry point unimplemented if they implement mpo_create_cred, even if they do not implement mpo_execve_will_transition. <function>&mac.mpo;_execve_will_transition</function> int &mac.mpo;_execve_will_transition struct ucred *old struct vnode *vp struct label *vnodelabel &mac.thead; old Subject credential prior to &man.execve.2; Immutable vp File to execute vnodelabel Policy label for vp Determine whether the policy will want to perform a transition event as a result of the execution of the passed vnode by the passed subject credential. Return 1 if a transition is required, 0 if not. Even if a policy returns 0, it should behave correctly in the presence of an unexpected invocation of mpo_execve_transition, as that call may happen as a result of another policy requesting a transition. <function>&mac.mpo;_create_proc0</function> void &mac.mpo;_create_proc0 struct ucred *cred &mac.thead; cred Subject credential to be filled in Create the subject credential of process 0, the parent of all kernel processes. <function>&mac.mpo;_create_proc1</function> void &mac.mpo;_create_proc1 struct ucred *cred &mac.thead; cred Subject credential to be filled in Create the subject credential of process 1, the parent of all user processes. <function>&mac.mpo;_relabel_cred</function> void &mac.mpo;_relabel_cred struct ucred *cred struct label *newlabel &mac.thead; cred Subject credential newlabel Label update to apply to cred Update the label on a subject credential from the passed update label. Access Control Checks Access control entry points permit policy modules to influence access control decisions made by the kernel. Generally, although not always, arguments to an access control entry point will include one or more authorizing credentials, information (possibly including a label) for any other objects involved in the operation. An access control entry point may return 0 to permit the operation, or an &man.errno.2; error value. The results of invoking the entry point across various registered policy modules will be composed as follows: if all modules permit the operation to succeed, success will be returned. If one or modules returns a failure, a failure will be returned. If more than one module returns a failure, the errno value to return to the user will be selected using the following precedence, implemented by the error_select() function in kern_mac.c: Most precedence EDEADLK EINVAL ESRCH EACCES Least precedence EPERM If none of the error values returned by all modules are listed in the precedence chart then an arbitrarily selected value from the set will be returned. In general, the rules provide precedence to errors in the following order: kernel failures, invalid arguments, object not present, access not permitted, other. <function>&mac.mpo;_check_bpfdesc_receive</function> int &mac.mpo;_check_bpfdesc_receive struct bpf_d *bpf_d struct label *bpflabel struct ifnet *ifnet struct label *ifnetlabel &mac.thead; bpf_d Subject; BPF descriptor bpflabel Policy label for bpf_d ifnet Object; network interface ifnetlabel Policy label for ifnet Determine whether the MAC framework should permit datagrams from the passed interface to be delivered to the buffers of the passed BPF descriptor. Return (0) for success, or an errno value for failure Suggested failure: EACCES for label mismatches, EPERM for lack of privilege. <function>&mac.mpo;_check_kenv_dump</function> int &mac.mpo;_check_kenv_dump struct ucred *cred &mac.thead; cred Subject credential Determine whether the subject should be allowed to retrieve the kernel environment (see &man.kenv.2;). <function>&mac.mpo;_check_kenv_get</function> int &mac.mpo;_check_kenv_get struct ucred *cred char *name &mac.thead; cred Subject credential name Kernel environment variable name Determine whether the subject should be allowed to retrieve the value of the specified kernel environment variable. <function>&mac.mpo;_check_kenv_set</function> int &mac.mpo;_check_kenv_set struct ucred *cred char *name &mac.thead; cred Subject credential name Kernel environment variable name Determine whether the subject should be allowed to set the specified kernel environment variable. <function>&mac.mpo;_check_kenv_unset</function> int &mac.mpo;_check_kenv_unset struct ucred *cred char *name &mac.thead; cred Subject credential name Kernel environment variable name Determine whether the subject should be allowed to unset the specified kernel environment variable. <function>&mac.mpo;_check_kld_load</function> int &mac.mpo;_check_kld_load struct ucred *cred struct vnode *vp struct label *vlabel &mac.thead; cred Subject credential vp Kernel module vnode vlabel Label associated with vp Determine whether the subject should be allowed to load the specified module file. <function>&mac.mpo;_check_kld_stat</function> int &mac.mpo;_check_kld_stat struct ucred *cred &mac.thead; cred Subject credential Determine whether the subject should be allowed to retrieve a list of loaded kernel module files and associated statistics. <function>&mac.mpo;_check_kld_unload</function> int &mac.mpo;_check_kld_unload struct ucred *cred &mac.thead; cred Subject credential Determine whether the subject should be allowed to unload a kernel module. <function>&mac.mpo;_check_pipe_ioctl</function> int &mac.mpo;_check_pipe_ioctl struct ucred *cred struct pipe *pipe struct label *pipelabel unsigned long cmd void *data &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe cmd &man.ioctl.2; command data &man.ioctl.2; data Determine whether the subject should be allowed to make the specified &man.ioctl.2; call. <function>&mac.mpo;_check_pipe_poll</function> int &mac.mpo;_check_pipe_poll struct ucred *cred struct pipe *pipe struct label *pipelabel &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe Determine whether the subject should be allowed to poll pipe. <function>&mac.mpo;_check_pipe_read</function> int &mac.mpo;_check_pipe_read struct ucred *cred struct pipe *pipe struct label *pipelabel &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe Determine whether the subject should be allowed read access to pipe. <function>&mac.mpo;_check_pipe_relabel</function> int &mac.mpo;_check_pipe_relabel struct ucred *cred struct pipe *pipe struct label *pipelabel struct label *newlabel &mac.thead; cred Subject credential pipe Pipe pipelabel Current policy label associated with pipe newlabel Label update to pipelabel Determine whether the subject should be allowed to relabel pipe. <function>&mac.mpo;_check_pipe_stat</function> int &mac.mpo;_check_pipe_stat struct ucred *cred struct pipe *pipe struct label *pipelabel &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe Determine whether the subject should be allowed to retrieve statistics related to pipe. <function>&mac.mpo;_check_pipe_write</function> int &mac.mpo;_check_pipe_write struct ucred *cred struct pipe *pipe struct label *pipelabel &mac.thead; cred Subject credential pipe Pipe pipelabel Policy label associated with pipe Determine whether the subject should be allowed to write to pipe. <function>&mac.mpo;_check_socket_bind</function> int &mac.mpo;_check_socket_bind struct ucred *cred struct socket *socket struct label *socketlabel struct sockaddr *sockaddr &mac.thead; cred Subject credential socket Socket to be bound socketlabel Policy label for socket sockaddr Address of socket <function>&mac.mpo;_check_socket_connect</function> int &mac.mpo;_check_socket_connect struct ucred *cred struct socket *socket struct label *socketlabel struct sockaddr *sockaddr &mac.thead; cred Subject credential socket Socket to be connected socketlabel Policy label for socket sockaddr Address of socket Determine whether the subject credential (cred) can connect the passed socket (socket) to the passed socket address (sockaddr). Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatches, EPERM for lack of privilege. <function>&mac.mpo;_check_socket_receive</function> int &mac.mpo;_check_socket_receive struct ucred *cred struct socket *so struct label *socketlabel &mac.thead; cred Subject credential so Socket socketlabel Policy label associated with so Determine whether the subject should be allowed to receive information from the socket so. <function>&mac.mpo;_check_socket_send</function> int &mac.mpo;_check_socket_send struct ucred *cred struct socket *so struct label *socketlabel &mac.thead; cred Subject credential so Socket socketlabel Policy label associated with so Determine whether the subject should be allowed to send information across the socket so. <function>&mac.mpo;_check_cred_visible</function> int &mac.mpo;_check_cred_visible struct ucred *u1 struct ucred *u2 &mac.thead; u1 Subject credential u2 Object credential Determine whether the subject credential u1 can see other subjects with the passed subject credential u2. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatches, EPERM for lack of privilege, or ESRCH to hide visibility. This call may be made in a number of situations, including inter-process status sysctl's used by ps, and in procfs lookups. <function>&mac.mpo;_check_socket_visible</function> int &mac.mpo;_check_socket_visible struct ucred *cred struct socket *socket struct label *socketlabel &mac.thead; cred Subject credential socket Object; socket socketlabel Policy label for socket <function>&mac.mpo;_check_ifnet_relabel</function> int &mac.mpo;_check_ifnet_relabel struct ucred *cred struct ifnet *ifnet struct label *ifnetlabel struct label *newlabel &mac.thead; cred Subject credential ifnet Object; network interface ifnetlabel Existing policy label for ifnet newlabel Policy label update to later be applied to ifnet Determine whether the subject credential can relabel the passed network interface to the passed label update. <function>&mac.mpo;_check_socket_relabel</function> int &mac.mpo;_check_socket_relabel struct ucred *cred struct socket *socket struct label *socketlabel struct label *newlabel &mac.thead; cred Subject credential socket Object; socket socketlabel Existing policy label for socket newlabel Label update to later be applied to socketlabel Determine whether the subject credential can relabel the passed socket to the passed label update. <function>&mac.mpo;_check_cred_relabel</function> int &mac.mpo;_check_cred_relabel struct ucred *cred struct label *newlabel &mac.thead; cred Subject credential newlabel Label update to later be applied to cred Determine whether the subject credential can relabel itself to the passed label update. <function>&mac.mpo;_check_vnode_relabel</function> int &mac.mpo;_check_vnode_relabel struct ucred *cred struct vnode *vp struct label *vnodelabel struct label *newlabel &mac.thead; cred Subject credential Immutable vp Object; vnode Locked vnodelabel Existing policy label for vp newlabel Policy label update to later be applied to vp Determine whether the subject credential can relabel the passed vnode to the passed label update. <function>&mac.mpo;_check_mount_stat</function> int &mac.mpo;_check_mount_stat struct ucred *cred struct mount *mp struct label *mountlabel &mac.thead; cred Subject credential mp Object; file system mount mountlabel Policy label for mp Determine whether the subject credential can see the results of a statfs performed on the file system. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatches or EPERM for lack of privilege. This call may be made in a number of situations, including during invocations of &man.statfs.2; and related calls, as well as to determine what file systems to exclude from listings of file systems, such as when &man.getfsstat.2; is invoked. <function>&mac.mpo;_check_proc_debug</function> int &mac.mpo;_check_proc_debug struct ucred *cred struct proc *proc &mac.thead; cred Subject credential Immutable proc Object; process Determine whether the subject credential can debug the passed process. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, EPERM for lack of privilege, or ESRCH to hide visibility of the target. This call may be made in a number of situations, including use of the &man.ptrace.2; and &man.ktrace.2; APIs, as well as for some types of procfs operations. <function>&mac.mpo;_check_vnode_access</function> int &mac.mpo;_check_vnode_access struct ucred *cred struct vnode *vp struct label *label int flags &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp flags &man.access.2; flags Determine how invocations of &man.access.2; and related calls by the subject credential should return when performed on the passed vnode using the passed access flags. This should generally be implemented using the same semantics used in &mac.mpo;_check_vnode_open. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatches or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_chdir</function> int &mac.mpo;_check_vnode_chdir struct ucred *cred struct vnode *dvp struct label *dlabel &mac.thead; cred Subject credential dvp Object; vnode to &man.chdir.2; into dlabel Policy label for dvp Determine whether the subject credential can change the process working directory to the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_chroot</function> int &mac.mpo;_check_vnode_chroot struct ucred *cred struct vnode *dvp struct label *dlabel &mac.thead; cred Subject credential dvp Directory vnode dlabel Policy label associated with dvp Determine whether the subject should be allowed to &man.chroot.2; into the specified directory (dvp). <function>&mac.mpo;_check_vnode_create</function> int &mac.mpo;_check_vnode_create struct ucred *cred struct vnode *dvp struct label *dlabel struct componentname *cnp struct vattr *vap &mac.thead; cred Subject credential dvp Object; vnode dlabel Policy label for dvp cnp Component name for dvp vap vnode attributes for vap Determine whether the subject credential can create a vnode with the passed parent directory, passed name information, and passed attribute information. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. This call may be made in a number of situations, including as a result of calls to &man.open.2; with O_CREAT, &man.mknod.2;, &man.mkfifo.2;, and others. <function>&mac.mpo;_check_vnode_delete</function> int &mac.mpo;_check_vnode_delete struct ucred *cred struct vnode *dvp struct label *dlabel struct vnode *vp void *label struct componentname *cnp &mac.thead; cred Subject credential dvp Parent directory vnode dlabel Policy label for dvp vp Object; vnode to delete label Policy label for vp cnp Component name for vp Determine whether the subject credential can delete a vnode from the passed parent directory and passed name information. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. This call may be made in a number of situations, including as a result of calls to &man.unlink.2; and &man.rmdir.2;. Policies implementing this entry point should also implement mpo_check_rename_to to authorize deletion of objects as a result of being the target of a rename. <function>&mac.mpo;_check_vnode_deleteacl</function> int &mac.mpo;_check_vnode_deleteacl struct ucred *cred struct vnode *vp struct label *label acl_type_t type &mac.thead; cred Subject credential Immutable vp Object; vnode Locked label Policy label for vp type ACL type Determine whether the subject credential can delete the ACL of passed type from the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_exec</function> int &mac.mpo;_check_vnode_exec struct ucred *cred struct vnode *vp struct label *label &mac.thead; cred Subject credential vp Object; vnode to execute label Policy label for vp Determine whether the subject credential can execute the passed vnode. Determination of execute privilege is made separately from decisions about any transitioning event. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_getacl</function> int &mac.mpo;_check_vnode_getacl struct ucred *cred struct vnode *vp struct label *label acl_type_t type &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp type ACL type Determine whether the subject credential can retrieve the ACL of passed type from the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_getextattr</function> int &mac.mpo;_check_vnode_getextattr struct ucred *cred struct vnode *vp struct label *label int attrnamespace const char *name struct uio *uio &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp attrnamespace Extended attribute namespace name Extended attribute name uio I/O structure pointer; see &man.uio.9; Determine whether the subject credential can retrieve the extended attribute with the passed namespace and name from the passed vnode. Policies implementing labeling using extended attributes may be interested in special handling of operations on those extended attributes. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_link</function> int &mac.mpo;_check_vnode_link struct ucred *cred struct vnode *dvp struct label *dlabel struct vnode *vp struct label *label struct componentname *cnp &mac.thead; cred Subject credential dvp Directory vnode dlabel Policy label associated with dvp vp Link destination vnode label Policy label associated with vp cnp Component name for the link being created Determine whether the subject should be allowed to create a link to the vnode vp with the name specified by cnp. <function>&mac.mpo;_check_vnode_mmap</function> int &mac.mpo;_check_vnode_mmap struct ucred *cred struct vnode *vp struct label *label int prot &mac.thead; cred Subject credential vp Vnode to map label Policy label associated with vp prot Mmap protections (see &man.mmap.2;) Determine whether the subject should be allowed to map the vnode vp with the protections specified in prot. <function>&mac.mpo;_check_vnode_mmap_downgrade</function> void &mac.mpo;_check_vnode_mmap_downgrade struct ucred *cred struct vnode *vp struct label *label int *prot &mac.thead; cred See . vp label prot Mmap protections to be downgraded Downgrade the mmap protections based on the subject and object labels. <function>&mac.mpo;_check_vnode_mprotect</function> int &mac.mpo;_check_vnode_mprotect struct ucred *cred struct vnode *vp struct label *label int prot &mac.thead; cred Subject credential vp Mapped vnode prot Memory protections Determine whether the subject should be allowed to set the specified memory protections on memory mapped from the vnode vp. <function>&mac.mpo;_check_vnode_poll</function> int &mac.mpo;_check_vnode_poll struct ucred *active_cred struct ucred *file_cred struct vnode *vp struct label *label &mac.thead; active_cred Subject credential file_cred Credential associated with the struct file vp Polled vnode label Policy label associated with vp Determine whether the subject should be allowed to poll the vnode vp. <function>&mac.mpo;_check_vnode_rename_from</function> int &mac.mpo;_vnode_rename_from struct ucred *cred struct vnode *dvp struct label *dlabel struct vnode *vp struct label *label struct componentname *cnp &mac.thead; cred Subject credential dvp Directory vnode dlabel Policy label associated with dvp vp Vnode to be renamed label Policy label associated with vp cnp Component name for vp Determine whether the subject should be allowed to rename the vnode vp to something else. <function>&mac.mpo;_check_vnode_rename_to</function> int &mac.mpo;_check_vnode_rename_to struct ucred *cred struct vnode *dvp struct label *dlabel struct vnode *vp struct label *label int samedir struct componentname *cnp &mac.thead; cred Subject credential dvp Directory vnode dlabel Policy label associated with dvp vp Overwritten vnode label Policy label associated with vp samedir Boolean; 1 if the source and destination directories are the same cnp Destination component name Determine whether the subject should be allowed to rename to the vnode vp, into the directory dvp, or to the name represented by cnp. If there is no existing file to overwrite, vp and label will be NULL. <function>&mac.mpo;_check_socket_listen</function> int &mac.mpo;_check_socket_listen struct ucred *cred struct socket *socket struct label *socketlabel &mac.thead; cred Subject credential socket Object; socket socketlabel Policy label for socket Determine whether the subject credential can listen on the passed socket. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_lookup</function> int &mac.mpo;_check_vnode_lookup struct ucred *cred struct vnode *dvp struct label *dlabel struct componentname *cnp &mac.thead; cred Subject credential dvp Object; vnode dlabel Policy label for dvp cnp Component name being looked up Determine whether the subject credential can perform a lookup in the passed directory vnode for the passed name. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_open</function> int &mac.mpo;_check_vnode_open struct ucred *cred struct vnode *vp struct label *label int acc_mode &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp acc_mode &man.open.2; access mode Determine whether the subject credential can perform an open operation on the passed vnode with the passed access mode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_readdir</function> int &mac.mpo;_check_vnode_readdir struct ucred *cred struct vnode *dvp struct label *dlabel &mac.thead; cred Subject credential dvp Object; directory vnode dlabel Policy label for dvp Determine whether the subject credential can perform a readdir operation on the passed directory vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_readlink</function> int &mac.mpo;_check_vnode_readlink struct ucred *cred struct vnode *vp struct label *label &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp Determine whether the subject credential can perform a readlink operation on the passed symlink vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. This call may be made in a number of situations, including an explicit readlink call by the user process, or as a result of an implicit readlink during a name lookup by the process. <function>&mac.mpo;_check_vnode_revoke</function> int &mac.mpo;_check_vnode_revoke struct ucred *cred struct vnode *vp struct label *label &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp Determine whether the subject credential can revoke access to the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setacl</function> int &mac.mpo;_check_vnode_setacl struct ucred *cred struct vnode *vp struct label *label acl_type_t type struct acl *acl &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp type ACL type acl ACL Determine whether the subject credential can set the passed ACL of passed type on the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setextattr</function> int &mac.mpo;_check_vnode_setextattr struct ucred *cred struct vnode *vp struct label *label int attrnamespace const char *name struct uio *uio &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp attrnamespace Extended attribute namespace name Extended attribute name uio I/O structure pointer; see &man.uio.9; Determine whether the subject credential can set the extended attribute of passed name and passed namespace on the passed vnode. Policies implementing security labels backed into extended attributes may want to provide additional protections for those attributes. Additionally, policies should avoid making decisions based on the data referenced from uio, as there is a potential race condition between this check and the actual operation. The uio may also be NULL if a delete operation is being performed. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setflags</function> int &mac.mpo;_check_vnode_setflags struct ucred *cred struct vnode *vp struct label *label u_long flags &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp flags File flags; see &man.chflags.2; Determine whether the subject credential can set the passed flags on the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setmode</function> int &mac.mpo;_check_vnode_setmode struct ucred *cred struct vnode *vp struct label *label mode_t mode &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp mode File mode; see &man.chmod.2; Determine whether the subject credential can set the passed mode on the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setowner</function> int &mac.mpo;_check_vnode_setowner struct ucred *cred struct vnode *vp struct label *label uid_t uid gid_t gid &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp uid User ID gid Group ID Determine whether the subject credential can set the passed uid and passed gid as file uid and file gid on the passed vnode. The IDs may be set to (-1) to request no update. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_vnode_setutimes</function> int &mac.mpo;_check_vnode_setutimes struct ucred *cred struct vnode *vp struct label *label struct timespec atime struct timespec mtime &mac.thead; cred Subject credential vp Object; vp label Policy label for vp atime Access time; see &man.utimes.2; mtime Modification time; see &man.utimes.2; Determine whether the subject credential can set the passed access timestamps on the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_proc_sched</function> int &mac.mpo;_check_proc_sched struct ucred *ucred struct proc *proc &mac.thead; cred Subject credential proc Object; process Determine whether the subject credential can change the scheduling parameters of the passed process. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, EPERM for lack of privilege, or ESRCH to limit visibility. See &man.setpriority.2; for more information. <function>&mac.mpo;_check_proc_signal</function> int &mac.mpo;_check_proc_signal struct ucred *cred struct proc *proc int signal &mac.thead; cred Subject credential proc Object; process signal Signal; see &man.kill.2; Determine whether the subject credential can deliver the passed signal to the passed process. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, EPERM for lack of privilege, or ESRCH to limit visibility. <function>&mac.mpo;_check_vnode_stat</function> int &mac.mpo;_check_vnode_stat struct ucred *cred struct vnode *vp struct label *label &mac.thead; cred Subject credential vp Object; vnode label Policy label for vp Determine whether the subject credential can stat the passed vnode. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. See &man.stat.2; for more information. <function>&mac.mpo;_check_ifnet_transmit</function> int &mac.mpo;_check_ifnet_transmit struct ucred *cred struct ifnet *ifnet struct label *ifnetlabel struct mbuf *mbuf struct label *mbuflabel &mac.thead; cred Subject credential ifnet Network interface ifnetlabel Policy label for ifnet mbuf Object; mbuf to be sent mbuflabel Policy label for mbuf Determine whether the network interface can transmit the passed mbuf. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_socket_deliver</function> int &mac.mpo;_check_socket_deliver struct ucred *cred struct ifnet *ifnet struct label *ifnetlabel struct mbuf *mbuf struct label *mbuflabel &mac.thead; cred Subject credential ifnet Network interface ifnetlabel Policy label for ifnet mbuf Object; mbuf to be delivered mbuflabel Policy label for mbuf Determine whether the socket may receive the datagram stored in the passed mbuf header. Return 0 for success, or an errno value for failure. Suggested failures: EACCES for label mismatch, or EPERM for lack of privilege. <function>&mac.mpo;_check_socket_visible</function> int &mac.mpo;_check_socket_visible struct ucred *cred struct socket *so struct label *socketlabel &mac.thead; cred Subject credential Immutable so Object; socket socketlabel Policy label for so Determine whether the subject credential cred can "see" the passed socket (socket) using system monitoring functions, such as those employed by &man.netstat.8; and &man.sockstat.1;. Return 0 for success, or an errno value for failure. Suggested failure: EACCES for label mismatches, EPERM for lack of privilege, or ESRCH to hide visibility. <function>&mac.mpo;_check_system_acct</function> int &mac.mpo;_check_system_acct struct ucred *ucred struct vnode *vp struct label *vlabel &mac.thead; ucred Subject credential vp Accounting file; &man.acct.5; vlabel Label associated with vp Determine whether the subject should be allowed to enable accounting, based on its label and the label of the accounting log file. <function>&mac.mpo;_check_system_nfsd</function> int &mac.mpo;_check_system_nfsd struct ucred *cred &mac.thead; cred Subject credential Determine whether the subject should be allowed to call &man.nfssvc.2;. <function>&mac.mpo;_check_system_reboot</function> int &mac.mpo;_check_system_reboot struct ucred *cred int howto &mac.thead; cred Subject credential howto howto parameter from &man.reboot.2; Determine whether the subject should be allowed to reboot the system in the specified manner. <function>&mac.mpo;_check_system_settime</function> int &mac.mpo;_check_system_settime struct ucred *cred &mac.thead; cred Subject credential Determine whether the user should be allowed to set the system clock. <function>&mac.mpo;_check_system_swapon</function> int &mac.mpo;_check_system_swapon struct ucred *cred struct vnode *vp struct label *vlabel &mac.thead; cred Subject credential vp Swap device vlabel Label associated with vp Determine whether the subject should be allowed to add vp as a swap device. <function>&mac.mpo;_check_system_sysctl</function> int &mac.mpo;_check_system_sysctl struct ucred *cred int *name u_int *namelen void *old size_t *oldlenp int inkernel void *new size_t newlen &mac.thead; cred Subject credential name See &man.sysctl.3; namelen old oldlenp inkernel Boolean; 1 if called from kernel new See &man.sysctl.3; newlen Determine whether the subject should be allowed to make the specified &man.sysctl.3; transaction. Label Management Calls Relabel events occur when a user process has requested that the label on an object be modified. A two-phase update occurs: first, an access control check will be performed to determine if the update is both valid and permitted, and then the update itself is performed via a separate entry point. Relabel entry points typically accept the object, object label reference, and an update label submitted by the process. Memory allocation during relabel is discouraged, as relabel calls are not permitted to fail (failure should be reported earlier in the relabel check). Userland Architecture The TrustedBSD MAC Framework includes a number of policy-agnostic elements, including MAC library interfaces for abstractly managing labels, modifications to the system credential management and login libraries to support the assignment of MAC labels to users, and a set of tools to monitor and modify labels on processes, files, and network interfaces. More details on the user architecture will be added to this section in the near future. APIs for Policy-Agnostic Label Management The TrustedBSD MAC Framework provides a number of library and system calls permitting applications to manage MAC labels on objects using a policy-agnostic interface. This permits applications to manipulate labels for a variety of policies without being written to support specific policies. These interfaces are used by general-purpose tools such as &man.ifconfig.8;, &man.ls.1; and &man.ps.1; to view labels on network interfaces, files, and processes. The APIs also support MAC management tools including &man.getfmac.8;, &man.getpmac.8;, &man.setfmac.8;, &man.setfsmac.8;, and &man.setpmac.8;. The MAC APIs are documented in &man.mac.3;. Applications handle MAC labels in two forms: an internalized form used to return and set labels on processes and objects (mac_t), and externalized form based on C strings appropriate for storage in configuration files, display to the user, or input from the user. Each MAC label contains a number of elements, each consisting of a name and value pair. Policy modules in the kernel bind to specific names and interpret the values in policy-specific ways. In the externalized string form, labels are represented by a comma-delimited list of name and value pairs separated by the / character. Labels may be directly converted to and from text using provided APIs; when retrieving labels from the kernel, internalized label storage must first be prepared for the desired label element set. Typically, this is done in one of two ways: using &man.mac.prepare.3; and an arbitrary list of desired label elements, or one of the variants of the call that loads a default element set from the &man.mac.conf.5; configuration file. Per-object defaults permit application writers to usefully display labels associated with objects without being aware of the policies present in the system. Currently, direct manipulation of label elements other than by conversion to a text string, string editing, and conversion back to an internalized label is not supported by the MAC library. Such interfaces may be added in the future if they prove necessary for application writers. Binding of Labels to Users The standard user context management interface, &man.setusercontext.3;, has been modified to retrieve MAC labels associated with a user's class from &man.login.conf.5;. These labels are then set along with other user context when either LOGIN_SETALL is specified, or when LOGIN_SETMAC is explicitly specified. It is expected that, in a future version of FreeBSD, the MAC label database will be separated from the login.conf user class abstraction, and be maintained in a separate database. However, the &man.setusercontext.3; API should remain the same following such a change. Conclusion The TrustedBSD MAC framework permits kernel modules to augment the system security policy in a highly integrated manner. They may do this based on existing object properties, or based on label data that is maintained with the assistance of the MAC framework. The framework is sufficiently flexible to implement a variety of policy types, including information flow security policies such as MLS and Biba, as well as policies based on existing BSD credentials or file protections. Policy authors may wish to consult this documentation as well as existing security modules when implementing a new security service.
diff --git a/en_US.ISO8859-1/books/arch-handbook/usb/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/usb/chapter.sgml index 20402dba3f..2ae71a9d2c 100644 --- a/en_US.ISO8859-1/books/arch-handbook/usb/chapter.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/usb/chapter.sgml @@ -1,649 +1,649 @@ Nick Hibma Written by Murray Stokely Modifications for Handbook made by USB Devices Introduction Universal Serial Bus (USB) NetBSD The Universal Serial Bus (USB) is a new way of attaching devices to personal computers. The bus architecture features two-way communication and has been developed as a response to devices becoming smarter and requiring more interaction with the host. USB support is included in all current PC chipsets and is therefore available in all recently built PCs. Apple's introduction of the USB-only iMac has been a major incentive for hardware manufacturers to produce USB versions of their devices. The future PC specifications specify that all legacy connectors on PCs should be replaced by one or more USB connectors, providing generic plug and play capabilities. Support for USB hardware was available at a very early stage in NetBSD and was developed by Lennart Augustsson for the NetBSD project. The code has been ported to FreeBSD and we are currently maintaining a shared code base. For the implementation of the USB subsystem a number of features of USB are important. Lennart Augustsson has done most of the implementation of the USB support for the NetBSD project. Many thanks for this incredible amount of work. Many thanks also to Ardy and Dirk for their comments and proofreading of this paper. Devices connect to ports on the computer directly or on devices called hubs, forming a treelike device structure. The devices can be connected and disconnected at run time. Devices can suspend themselves and trigger resumes of the host system As the devices can be powered from the bus, the host software has to keep track of power budgets for each hub. Different quality of service requirements by the different device types together with the maximum of 126 devices that can be connected to the same bus, require proper scheduling of transfers on the shared bus to take full advantage of the 12Mbps bandwidth available. (over 400Mbps with USB 2.0) Devices are intelligent and contain easily accessible information about themselves The development of drivers for the USB subsystem and devices connected to it is supported by the specifications that have been developed and will be developed. These specifications are publicly available from the USB home pages. Apple has been very strong in pushing for standards based drivers, by making drivers for the generic classes available in their operating system MacOS and discouraging the use of separate drivers for each new device. This chapter tries to collate essential information for a basic understanding of the present implementation of the USB stack in FreeBSD/NetBSD. It is recommended however to read it together with the relevant specifications mentioned in the references below. Structure of the USB Stack The USB support in FreeBSD can be split into three layers. The lowest layer contains the host controller driver, providing a generic interface to the hardware and its scheduling facilities. It supports initialisation of the hardware, scheduling of transfers and handling of completed and/or failed transfers. Each host controller driver implements a virtual hub providing hardware independent access to the registers controlling the root ports on the back of the machine. The middle layer handles the device connection and disconnection, basic initialisation of the device, driver selection, the communication channels (pipes) and does resource management. This services layer also controls the default pipes and the device requests transferred over them. The top layer contains the individual drivers supporting specific (classes of) devices. These drivers implement the protocol that is used over the pipes other than the default pipe. They also implement additional functionality to make the device available to other parts of the kernel or userland. They use the USB driver interface (USBDI) exposed by the services layer. Host Controllers USBhost controllers The host controller (HC) controls the transmission of packets on the bus. Frames of 1 millisecond are used. At the start of each frame the host controller generates a Start of Frame (SOF) packet. The SOF packet is used to synchronise to the start of the frame and to keep track of the frame number. Within each frame packets are transferred, either from host to device (out) or from device to host (in). Transfers are always initiated by the host (polled transfers). Therefore there can only be one host per USB bus. Each transfer of a packet has a status stage in which the recipient of the data can return either ACK (acknowledge reception), NAK (retry), STALL (error condition) or nothing (garbled data stage, device not available or disconnected). Section 8.5 of the USB specification explains the details of packets in more detail. Four different types of transfers can occur on a USB bus: control, bulk, interrupt and isochronous. The types of transfers and their characteristics are described below (`Pipes' subsection). Large transfers between the device on the USB bus and the device driver are split up into multiple packets by the host controller or the HC driver. Device requests (control transfers) to the default endpoints are special. They consist of two or three phases: SETUP, DATA (optional) and STATUS. The set-up packet is sent to the device. If there is a data phase, the direction of the data packet(s) is given in the set-up packet. The direction in the status phase is the opposite of the direction during the data phase, or IN if there was no data phase. The host controller hardware also provides registers with the current status of the root ports and the changes that have occurred since the last reset of the status change register. Access to these registers is provided through a virtualised hub as suggested in the USB specification [ 2]. The virtual hub must comply with the hub device class given in chapter 11 of that specification. It must provide a default pipe through which device requests can be sent to it. It returns the standard andhub class specific set of descriptors. It should also provide an interrupt pipe that reports changes happening at its ports. There are currently two specifications for host controllers available: Universal Host Controller Interface (UHCI; Intel) and Open Host Controller Interface (OHCI; Compaq, Microsoft, National Semiconductor). The UHCI specification has been designed to reduce hardware complexity by requiring the host controller driver to supply a complete schedule of the transfers for each frame. OHCI type controllers are much more independent - by providing a more abstract interface doing alot of work + by providing a more abstract interface doing a lot of work themselves. UHCI USBUHCI The UHCI host controller maintains a framelist with 1024 pointers to per frame data structures. It understands two different data types: transfer descriptors (TD) and queue heads (QH). Each TD represents a packet to be communicated to or from a device endpoint. QHs are a means to groupTDs (and QHs) together. Each transfer consists of one or more packets. The UHCI driver splits large transfers into multiple packets. For every transfer, apart from isochronous transfers, a QH is allocated. For every type of transfer these QHs are collected at a QH for that type. Isochronous transfers have to be executed first because of the fixed latency requirement and are directly referred to by the pointer in the framelist. The last isochronous TD refers to the QH for interrupt transfers for that frame. All QHs for interrupt transfers point at the QH for control transfers, which in turn points at the QH for bulk transfers. The following diagram gives a graphical overview of this: This results in the following schedule being run in each frame. After fetching the pointer for the current frame from the framelist the controller first executes the TDs for all the isochronous packets in that frame. The last of these TDs refers to the QH for the interrupt transfers for thatframe. The host controller will then descend from that QH to the QHs for the individual interrupt transfers. After finishing that queue, the QH for the interrupt transfers will refer the controller to the QH for all control transfers. It will execute all the subqueues scheduled there, followed by all the transfers queued at the bulk QH. To facilitate the handling of finished or failed transfers different types of interrupts are generated by the hardware at the end of each frame. In the last TD for a transfer the Interrupt-On Completion bit is set by the HC driver to flag an interrupt when the transfer has completed. An error interrupt is flagged if a TD reaches its maximum error count. If the short packet detect bit is set in a TD and less than the set packet length is transferred this interrupt is flagged to notify the controller driver of the completed transfer. It is the host controller driver's task to find out which transfer has completed or produced an error. When called the interrupt service routine will locate all the finished transfers and call their callbacks. See for a more elaborate description the UHCI specification. OHCI USBOHCI Programming an OHCI host controller is much simpler. The controller assumes that a set of endpoints is available, and is aware of scheduling priorities and the ordering of the types of transfers in a frame. The main data structure used by the host controller is the endpoint descriptor (ED) to which - aqueue of transfer descriptors (TDs) is attached. The ED + a queue of transfer descriptors (TDs) is attached. The ED contains the maximum packet size allowed for an endpoint and the controller hardware does the splitting into packets. The pointers to the data buffers are updated after each transfer and when the start and end pointer are equal, the TD is retired to the done-queue. The four types of endpoints have their own queues. Control and bulk endpoints are queued each at their own queue. Interrupt EDs are queued in a tree, with the level in the tree defining the frequency at which they run. framelist interruptisochronous control bulk The schedule being run by the host controller in each frame looks as follows. The controller will first run the non-periodic control and bulk queues, up to a time limit set by the HC driver. Then the interrupt transfers for that frame number are run, by using the lower five bits of the frame number as an index into level 0 of the tree of interrupts EDs. At the end of this tree the isochronous EDs are connected and these are traversed subsequently. The isochronous TDs contain the frame number of the first frame the transfer should be run in. After all the periodic transfers have been run, the control and bulk queues are traversed again. Periodically the interrupt service routine is called to process the done queue and call the callbacks for each transfer and reschedule interrupt and isochronous endpoints. See for a more elaborate description the OHCI specification. Services layer The middle layer provides access to the device in a controlled way and maintains resources in use by the different drivers and the services layer. The layer takes care of the following aspects: The device configuration information The pipes to communicate with a device Probing and attaching and detaching form a device. USB Device Information Device configuration information Each device provides different levels of configuration information. Each device has one or more configurations, of which one is selected during probe/attach. A configuration provides power and bandwidth requirements. Within each configuration there can be multiple interfaces. A device interface is a collection of endpoints. For example USB speakers can have an interface for the audio data (Audio Class) and an interface for the knobs, dials and buttons (HID Class). All interfaces in a configuration are active at the same time and can be attached to by different drivers. Each interface can have alternates, providing different quality of service parameters. In for example cameras this is used to provide different frame sizes and numbers of frames per second. Within each interface 0 or more endpoints can be specified. Endpoints are the unidirectional access points for communicating with a device. They provide buffers to temporarily store incoming or outgoing data from the device. Each endpoint has a unique address within a configuration, the endpoint's number plus its direction. The default endpoint, endpoint 0, is not part of any interface and available in all configurations. It is managed by the services layer and not directly available to device drivers. Level 0 Level 1 Level 2 Slot 0 Slot 3 Slot 2 Slot 1 (Only 4 out of 32 slots shown) This hierarchical configuration information is described in the device by a standard set of descriptors (see section 9.6 of the USB specification [ 2]). They can be requested through the Get Descriptor Request. The services layer caches these descriptors to avoid unnecessary transfers on the USB bus. Access to the descriptors is provided through function calls. Device descriptors: General information about the device, like Vendor, Product and Revision Id, supported device class, subclass and protocol if applicable, maximum packet size for the default endpoint, etc. Configuration descriptors: The number of interfaces in this configuration, suspend and resume functionality supported and power requirements. Interface descriptors: interface class, subclass and protocol if applicable, number of alternate settings for the interface and the number of endpoints. Endpoint descriptors: Endpoint address, direction and type, maximum packet size supported and polling frequency if type is interrupt endpoint. There is no descriptor for the default endpoint (endpoint 0) and it is never counted in an interface descriptor. String descriptors: In the other descriptors string indices are supplied for some fields.These can be used to retrieve descriptive strings, possibly in multiple languages. Class specifications can add their own descriptor types that are available through the GetDescriptor Request. Pipes Communication to end points on a device flows through so-called pipes. Drivers submit transfers to endpoints to a pipe and provide a callback to be called on completion or failure of the transfer (asynchronous transfers) or wait for completion (synchronous transfer). Transfers to an endpoint are serialised in the pipe. A transfer can either complete, fail or time-out (if a time-out has been set). There are two types of time-outs for transfers. Time-outs can happen due to time-out on the USBbus (milliseconds). These time-outs are seen as failures and can be due to disconnection of the device. A second form of time-out is implemented in software and is triggered when a transfer does not complete within a specified amount of time (seconds). These are caused by a device acknowledging negatively (NAK) the transferred packets. The cause for this is the device not being ready to receive data, buffer under- or overrun or protocol errors. If a transfer over a pipe is larger than the maximum packet size specified in the associated endpoint descriptor, the host controller (OHCI) or the HC driver (UHCI) will split the transfer into packets of maximum packet size, with the last packet possibly smaller than the maximum packet size. Sometimes it is not a problem for a device to return less data than requested. For example abulk-in-transfer to a modem might request 200 bytes of data, but the modem has only 5 bytes available at that time. The driver can set the short packet (SPD) flag. It allows the host controller to accept a packet even if the amount of data transferred is less than requested. This flag is only valid for in-transfers, as the amount of data to be sent to a device is always known beforehand. If an unrecoverable error occurs in a device during a transfer the pipe is stalled. Before any more data is accepted or sent the driver needs to resolve the cause of the stall and clear the endpoint stall condition through send the clear endpoint halt device request over the default pipe. The default endpoint should never stall. There are four different types of endpoints and corresponding pipes: - Control pipe / default pipe: There is one control pipe per device, connected to the default endpoint (endpoint 0). The pipe carries the device requests and associated data. The difference between transfers over the default pipe and other pipes is that the protocol for the transfers is described in the USB specification [ 2]. These requests are used to reset and configure the device. A basic set of commands that must be supported by each device is provided in chapter 9 of the USB specification [ 2]. The commands supported on this pipe can be extended by a device class specification to support additional functionality. Bulk pipe: This is the USB equivalent to a raw transmission medium. Interrupt pipe: The host sends a request for data to the device and if the device has nothing to send, it will NAK the data packet. Interrupt transfers are scheduled at a frequency specified when creating the pipe. Isochronous pipe: These pipes are intended for isochronous data, for example video or audio streams, with fixed latency, but no guaranteed delivery. Some support for pipes of this type is available in the current implementation. Packets in control, bulk and interrupt transfers are retried if an error occurs during transmission or the device acknowledges the packet negatively (NAK) due to for example lack of buffer space to store the incoming data. Isochronous packets are however not retried in case of failed delivery or NAK of a packet as this might violate the timing constraints. The availability of the necessary bandwidth is calculated during the creation of the pipe. Transfers are scheduled within frames of 1 millisecond. The bandwidth allocation within a frame is prescribed by the USB specification, section 5.6 [ 2]. Isochronous and interrupt transfers are allowed to consume up to 90% of the bandwidth within a frame. Packets for control and bulk transfers are scheduled after all isochronous and interrupt packets and will consume all the remaining bandwidth. More information on scheduling of transfers and bandwidth reclamation can be found in chapter 5of the USB specification [ 2], section 1.3 of the UHCI specification [ 3] and section 3.4.2 of the OHCI specification [4]. Device probe and attach USBprobe After the notification by the hub that a new device has been connected, the service layer switches on the port, providing the device with 100 mA of current. At this point the device is in its default state and listening to device address 0. The services layer will proceed to retrieve the various descriptors through the default pipe. After that it will send a Set Address request to move the device away from the default device address (address 0). Multiple device drivers might be able to support the device. For example a modem driver might be able to support an ISDN TA through the AT compatibility interface. A driver for that specific model of the ISDN adapter might however be able to provide much better support for this device. To support this flexibility, the probes return priorities indicating their level of support. Support for a specific revision of a product ranks the highest and the generic driver the lowest priority. It might also be that multiple drivers could attach to one device if there are multiple interfaces within one configuration. Each driver only needs to support a subset of the interfaces. The probing for a driver for a newly attached device checks first for device specific drivers. If not found, the probe code iterates over all supported configurations until a driver attaches in a configuration. To support devices with multiple drivers on different interfaces, the probe iterates over all interfaces in a configuration that have not yet been claimed by a driver. Configurations that exceed the power budget for the hub are ignored. During attach the driver should initialise the device to its proper state, but not reset it, as this will make the device disconnect itself from the bus and restart the probing process for it. To avoid consuming unnecessary bandwidth should not claim the interrupt pipe at attach time, but should postpone allocating the pipe until the file is opened and the data is actually used. When the file is closed the pipe should be closed again, even though the device might still be attached. Device disconnect and detach USBdisconnect A device driver should expect to receive errors during any transaction with the device. The design of USB supports and encourages the disconnection of devices at any point in time. Drivers should make sure that they do the right thing when the device disappears. Furthermore a device that has been disconnected and reconnected will not be reattached at the same device instance. This might change in the future when more devices support serial numbers (see the device descriptor) or other means of defining an identity for a device have been developed. The disconnection of a device is signaled by a hub in the interrupt packet delivered to the hub driver. The status change information indicates which port has seen a connection change. The device detach method for all device drivers for the device connected on that port are called and the structures cleaned up. If the port status indicates that in the mean time a device has been connected to that port, the procedure for probing and attaching the device will be started. A device reset will produce a disconnect-connect sequence on the hub and will be handled as described above. USB Drivers Protocol Information The protocol used over pipes other than the default pipe is undefined by the USB specification. Information on this can be found from various sources. The most accurate source is the developer's section on the USB home pages [ 1]. From these pages a growing number of deviceclass specifications are available. These specifications specify what a compliant device should look like from a driver perspective, basic functionality it needs to provide and the protocol that is to be used over the communication channels. The USB specification [ 2] includes the description of the Hub Class. A class specification for Human Interface Devices (HID) has been created to cater for keyboards, tablets, bar-code readers, buttons, knobs, switches, etc. A third example is the class specification for mass storage devices. For a full list of device classes see the developers section on the USB home pages [ 1]. For many devices the protocol information has not yet been published however. Information on the protocol being used might be available from the company making the device. Some companies will require you to sign a Non -Disclosure Agreement (NDA) before giving you the specifications. This in most cases precludes making the driver open source. Another good source of information is the Linux driver sources, as a number of companies have started to provide drivers for Linux for their devices. It is always a good idea to contact the authors of those drivers for their source of information. Example: Human Interface Devices The specification for the Human Interface Devices like keyboards, mice, tablets, buttons, dials,etc. is referred to in other device class specifications and is used in many devices. For example audio speakers provide endpoints to the digital to analogue converters and possibly an extra pipe for a microphone. They also provide a HID endpoint in a separate interface for the buttons and dials on the front of the device. The same is true for the monitor control class. It is straightforward to build support for these interfaces through the available kernel and userland libraries together with the HID class driver or the generic driver. Another device that serves as an example for interfaces within one configuration driven by different device drivers is a cheap keyboard with built-in legacy mouse port. To avoid having the cost of including the hardware for a USB hub in the device, manufacturers combined the mouse data received from the PS/2 port on the back of the keyboard and the key presses from the keyboard into two separate interfaces in the same configuration. The mouse and keyboard drivers each attach to the appropriate interface and allocate the pipes to the two independent endpoints. USBfirmware Example: Firmware download Many devices that have been developed are based on a general purpose processor with an additional USB core added to it. Because the development of drivers and firmware for USB devices is still very new, many devices require the downloading of the firmware after they have been connected. The procedure followed is straightforward. The device identifies itself through a vendor and product Id. The first driver probes and attaches to it and downloads the firmware into it. After that the device soft resets itself and the driver is detached. After a short pause the device announces its presence on the bus. The device will have changed its vendor/product/revision Id to reflect the fact that it has been supplied with firmware and as a consequence a second driver will probe it and attach to it. An example of these types of devices is the ActiveWire I/O board, based on the EZ-USB chip. For this chip a generic firmware downloader is available. The firmware downloaded into the ActiveWire board changes the revision Id. It will then perform a soft reset of the USB part of the EZ-USB chip to disconnect from the USB bus and again reconnect. Example: Mass Storage Devices Support for mass storage devices is mainly built around existing protocols. The Iomega USB Zipdrive is based on the SCSI version of their drive. The SCSI commands and status messages are wrapped in blocks and transferred over the bulk pipes to and from the device, emulating a SCSI controller over the USB wire. ATAPI and UFI commands are supported in a similar fashion. ATAPI The Mass Storage Specification supports 2 different types of wrapping of the command block.The initial attempt was based on sending the command and status through the default pipe and using bulk transfers for the data to be moved between the host and the device. Based on experience a second approach was designed that was based on wrapping the command and status blocks and sending them over the bulk out and in endpoint. The specification specifies exactly what has to happen when and what has to be done in case an error condition is encountered. The biggest challenge when writing drivers for these devices is to fit USB based protocol into the existing support for mass storage devices. CAM provides hooks to do this in a fairly straight forward way. ATAPI is less simple as historically the IDE interface has never had many different appearances. The support for the USB floppy from Y-E Data is again less straightforward as a new command set has been designed.