Date: Wed, 20 Jul 2005 19:21:03 GMT From: Andrew Reisse <areisse@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 80620 for review Message-ID: <200507201921.j6KJL3mI098928@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80620 Change 80620 by areisse@areisse_ibook on 2005/07/20 19:20:45 Updates to mach security report. Note that this is still very much a work in progress. Affected files ... .. //depot/projects/trustedbsd/sedarwin7/docs/mach-security.txt#3 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin7/docs/mach-security.txt#3 (text+ko) ==== @@ -1,57 +1,75 @@ This report summarizes the work on our Mach security extensions. -In securing the Mach operating system, there are two major areas to be -covered: system primitives and servers. Basically, the only primitive provided is -message passing: A task sends a message to a port, which may be received -by another task (including the kernel). -The Mach operating system provides other services, such as device abstraction, -virtual memory, scheduling, etc., but those services -are accessed via messages sent to kernel ports. So, the other services -provided by the Mach kernel can be treated as userspace servers (for -security purposes). +**** Background + +*** Mach + +Mach is a message-passing microkernel system. A running Mach system consists of a +number of tasks, each with their own address space, which can communicate with one +another via messages. Tasks also communicate with the kernel with messages. The kernel +abstraction for messaging is the port right: a handle to a message queue and a set of +operations (sending or receiving) that the task can perform on that port. A port is only +a destination for a message; messages have no "sending" port. As ports +are relatively lightweight, applications often use a port to represent a single higher-level +object, such as a window or hardware device. Unlike Unix IPC mechanisms, only one +task at a time (possibly the kernel) may hold a "receive right" for a particular port. Mach messages contain a variable number of elements, each of which may be -raw data, port names, or memory ranges. The kernel processes the port name and -memory range sections specially, allowing the port names to be used by the -receiving task. Since multiple kernel objects may be transferred via messages, -a single (subject,object) form of access control check is insufficient. +raw data, port rights, or memory ranges. The kernel processes the port right and +memory range sections specially; the raw data is passed to the recipient unmodified. +Receiving port rights in messages is the only way for tasks to receive new port rights +above those that it was given by the parent. + +Mach uses a capability model: holding appropriate port right entitles the task to use the +services of the kernel and other applications. In a pure Mach system, there is no information +about the sender provided when a message is received; the port rights themselves control +access to the services, much as file descriptors (once opened) entirely control access to +the referenced file. Security in a tranditional Mach system is achieved by limited the port +rights a task has access to, rather than by enforcing access controls on ports once they +are held. -A security policy may want to attach a security label to -tasks, messages, and ports. DTOS stores a security identifier in tasks, -ports, and augments the mach_msg calls to return or provide a security -identifier. We are following that model, except we use a policy-agnostic -label structure instead of a security identifier. -Because the Darwin kernel includes a BSD system as well, the security -additions (to both Mach and BSD systems) will need to remain correlated: -for example, a BSD process and its underlying Mach task should have the -same subject label(s). This is accomplished by changing the routines in the -BSD subsystem to update the task labels whenever a process label is changed, -and provide no user callable interface to directly change a task label, forcing -them to use the BSD system calls that will change both subject labels (For locking -reasons, Mach system calls or message handlers cannot acquire BSD-side locks, and -so are unable to change the BSD process label). +** Mach and Applications -Because the MAC framework -originiated with FreeBSD, there is a desire for the Darwin BSD side of -the MAC framework to remain compatible with the FreeBSD version. +A Mach system provides userspace facililities to assist in the development of +message-based applications. One such tool that is the Mach Interface Generator (MiG), +providing a remote procedure call interface over Mach messages. -MiG +* MiG MiG (Mach Interface Generator) is similar to rpcgen on unix systems; MiG reads a specification of data types and method prototypes, and generates client and server stubs which copy the arguments and method ID into a buffer and send it as a Mach message (one of the arguments is a port that will receive the message). The return value and any reference parameters are sent to the client as another Mach -message. Because messages can contain port rights, a MiG method call can be used -to obtain a port right for another service. MiG also supports messages containing -large memory areas, and arranges for those to be transferred via VM operations rather -than multiple copies. +message. In general, the client is not concerned with the semantics of message +passing and port rights and simply uses the stubs. + +Special kinds of message contents are supported by MiG; port rights and shared +memory can be passed in both directions, large arrays are automatically passed as +copy-on-write shared memory, etc. Namespace services (mach_init in Darwin) are +accessed and implemented using MiG. + +The model of "one object, one port" works well with MiG, where the first argument +is used as the destination for the message that the function call produces, +representing the object on which the function operates. +For example, a window server may contain a method to resize a window: + + routine window_resize (window : mach_port_t; + width : int; + height : int); + +where the message is sent to the port passed as the first argument. When the window server +receives the message, the MiG stub can convert the port into an implementation-specific +pointer through a translation type. This removes the need for application developers +to implement wire protocols in many cases. + A set of routines that will all be sent to the same type of port (e.g. namespace server) are called a subsystem. MiG allows a subsystem to contain up to 100 methods; new methods can be added to an existing subsystem without affecting existing clients as long as the new total number of methods is less than 100. + User programs linked with client stubs can call those methods "as if" they existed in the task's address space. A server task (or part of the kernel) implementing a subsystem uses @@ -63,7 +81,55 @@ messaging protocols, especially for kernel servers where the message validity checking and cross-address space copying is handled centrally. -Subsystem Access Control +*** Darwin + +Darwin, the open-source base of the Apple MacOS X operating system, is a combination of +a number of technologies. Here, we are mostly concerned with the kernel and its two primary +components: Mach and BSD (The iokit device driver framework is not included in this study). +Unlike other Mach systems, the BSD kernel in Darwin runs in the kernel address space, +not as a (userspace) task. This is significantly different from Lites-based systems such +as DTOS: the Unix-oriented objects cannot be protected with Mach messaging controls and +therefore need their own controls in the kernel. Controls on Unix objects are provided +by the "original" FreeBSD MAC framework as it was ported to Darwin. + + +**** Security Needs + +*** Overview + +In securing a Mach operating system, there are two major areas to be +covered: system primitives and servers. Basically, the only primitive provided is +message passing. The Mach system provides other services, such as device abstraction, +virtual memory, scheduling, etc., but those services are accessed via messages. +As Darwin contains a BSD kernel, BSD primitives such as sockets, files, and processes +are accessed with BSD system calls and not messages. BSD primitives are mostly outside +this discussion as there is extensive support and documentation available elsewhere. + +*** Kernel + +The entry point for kernel services from userspace is the trap, or system call. Mach +provides very few traps, because services are primarily implemented over messages. +Darwin contains a small number of traps for performance-sensitive operations, such +as operating on semaphores or reading timers. However, those services are unlikely to +need mediation by a policy, and are ignored in our current implementation. The +remaining services are accessed via messaging, and as such can be treated the same +as userspace services for security purposes. + +//Since multiple kernel objects (port rights or memory) may be transferred via messages, +//a single (subject,object) form of access control check is insufficient. + +** Labelling + +A security policy may want to attach a security label to +tasks, messages, and ports. DTOS stores a security identifier in tasks, +ports, and augments the mach_msg calls to return or provide a security +identifier. We are following that model, except we use a policy-agnostic +label structure instead of a security identifier. A label structure is added +to each port (ipc_port_t) and to each task (task). +The convention of using a port to represent a single object means that labels on +ports translate well into labels on objects for policy purposes. + +** Subsystem Access Control There are two approaches to protecting servers: Permission checks in the handlers, or using proxy servers. A permission check embedded in a handler @@ -80,8 +146,34 @@ bootstrap namespace manager will get the proxy server instead of the "real" service port. +** FreeBSD Compatibility + +Because the Darwin kernel includes a BSD system as well, the security +additions (to both Mach and BSD systems) will need to remain correlated: +for example, a BSD process and its underlying Mach task should have the +same subject label(s). This is accomplished by changing the routines in the +BSD subsystem to update the task labels whenever a process label is changed, +and provide no user callable interface to directly change a task label, forcing +them to use the BSD system calls that will change both subject labels (For locking +reasons, Mach system calls or message handlers cannot acquire BSD-side locks, and +so are unable to change the BSD process label). + +Because the security framework originiated with FreeBSD, there is a desire for the +Darwin BSD side of the security framework to remain compatible with the FreeBSD version. +The Mach features of the security framework will not be present on a FreeBSD system, +but the two systems differ in other ways so policies never would have been fully +compatible, although they may share much. + + ****** +Summary of security events + +Object creation is straightforward: when a task or port is created, the kernel requests a new label +from the policies, based on the caller and target task labels. + + + Extensions to MiG We have extended MiG in a number of ways to take advantage of a central implementation @@ -101,14 +193,56 @@ For example, the server can use of the sender's label to label new objects, or perform access control based on the routine's arguments. ++ MiG Example + +The routine specification + + routine print_int (dest : mach_port_t; + value : int); + +produces stubs with the prototype (client and server are the same) + + kern_return_t print_int (mach_port_t dest, int value); +To provide the caller's task label to the server implementation, an additional +argument is added (in a similar way to how security tokens and audit info trailers +are requested in Darwin): + + routine print_int (dest : mach_port_t; + value : int; + servermsglabels labels : msg_labels_t); + +As with other MiG argument flags starting with "server", the labels argument is +included in server stubs but not client stubs (as it is supplied by the kernel and +not the client). The server prototype becomes: + + kern_return_t print_int (mach_port_t dest, int value, msg_labels_t labels); + +and the server can access the caller's task label (as a label handle) with +labels.sender. We do not currently provide the option for the client to receive +remote labels in this way, but it would not be a difficult change. + +When the checkaccess flag is specified to enable automated permission checking, +the prototypes are unchanged for both sides, but the server stub implementation changes +to request the access decision trailer, and then to return failure (without invoking +the server implementation) if access was denied. All MiG calls return +kern_return_t, and a permission denial is one of the standard values (although it rarely +occurs in an ordinary Mach system). + + Extensions to FreeBSD MAC Framework +** Framework overview + The FreeBSD MAC framework consists of a kernel interface, a user interface, a set of policies, and a kernel-to-policy interface. The kernel interface is used by other parts of the kernel (e.g. filesystems) to label objects and request access control decisions. The user interface allows a user program to -change labels, run programs in other domains, or administer the policy. +change labels, run programs in other domains, request policy decisions, +or administer the policy. Complex policies may export arbitrary additional +interfaces to userspace, such as assistance for labelling userspace objects +or handling login sessions. + The kernel interface (called by filesystems and other kernel subsystems) uses the kernel-to-policy interface to request labels and access control decisions from each configured policy. All policies use the same interface, but many @@ -129,7 +263,7 @@ Note that the label represented by the handle is distinct from the label on its port that is used for messaging access control. Currently, the system provides no mechanism for obtaining the access control label of a label handle port, but it can be changed. -Initally, label handles were not backed by actual ports, but just used the port +Initally, label handles were not backed by actual ports, but merely used the port namespace (and ipc_right, ipc_entry structures). This was changed when maintaining the support for an extra type of ipc_object became unwieldly. It also allows label handle ports to be direct recievers of messages. @@ -145,7 +279,11 @@ Labelling events for tasks and ports are defined. Access control checks for message sending and port right transfers (both sending -and receiving) are defined. +and receiving) are defined. All of these checks are based on the model of a +subject performing an operation on one or more objects. The subject is always +a task; objects are either tasks, ports, or higher-level services built on ports. +Note that in userspace all mach kernel objects are accessed via ports. + If requested, the kernel will supply the message sender's task label in a mach message trailer (as a label handle). The message recipient can use the sender's label in making its own access decisions. For example, the @@ -169,13 +307,13 @@ Currently, the only policy that implements the generic access checks is Flask. However, portions -of the bsd kernel may use these MAC entry points as well, because of the +of the kernel may use these entry points as well, because of the greater amount of information available to the policies over POSIX capabilities. Changes to Mach Kernel -Kernel changes made to support the MAC framework were fairly noninvasive, +Kernel changes made to support the security framework were fairly noninvasive, only affecting a few of the data structures and a small number of functions. Tasks and ports received label storage; creation and deallocation routines call labelling event operations. Tasks use label handles, because the built @@ -185,7 +323,17 @@ Changes to the BSD kernel are also necessary, for instance the task and process label storage needs to be kept synchronized, as there really is only one subject and the label needs to be associated with both structures -for synchronization purposes. +for synchronization purposes. Another advantage of using a label handle +reference to store a task label is that the reference can be placed directly +into the message trailer field for the sender's task label, requiring only +an ipc right copyout, rather than a full label allocation & copy, plus the +copyout. + +A task always has an associated task port, which has a port label as well. Our +system changes the task port label whenever the task label is changed, but allows +the task port label to diverge if desired (and permitted by the policies). + + Mach "security" services @@ -195,6 +343,37 @@ The security server will also respond to requests for access control decisions, and allow the creation of label handles. +Security events for messaging + +As all interaction with the +kernel (and userspace mach services) is done through messaging, the messaging security must +be general enough to handle the variety of uses. Security checks on messaging are performed +at both sending and receiving. At sending, the kernel first calls the "check_port_send" +security framework entry point to permit or deny sending the entire message. Next, the +security policies are queried for permission to transfer each port right contained in the +message. If any port right transfers are denied, the message is not sent. Currently, no +special check is performed for transferring out-of-line memory. Information flow policies +need to control this as the memory can be shared between the sender and (eventual) message +recipient. None of the sending checks refer to the receiving task, as it is not known at +time of sending (The receive right for the destination port could be in the process of +moving to a different task at the same time the message is sent). + +Because checks were made on both transferring the port rights out of the sending task, +and into the receiving task, security policies have control over later information flows +resulting from port rights in a message. + + +1. Message sent +2. Check for action of sending (check_port_send) +3. Checks for port rights (check_port_copy_send, etc) +4. Port rights and memory copied from sender +5. Kernel message stored +.... +6. Remove from queue +7. Checks for storing port rights (check_port_hold_send, etc) +8. Port rights and memory copied out to recipient +9. Message received + Mach message trailers When a Mach message is sent, the kernel may append information about the @@ -237,7 +416,7 @@ automated, still requires rebuilding the affected server from source (Clients do not need to be rebuilt or otherwise modified). -Userspace modifications +*** Userspace modifications We have selected mach_init as one system service to augment with the extended security checks, because mach_init is open source, provides a service that @@ -258,77 +437,39 @@ namespace port. Some policies may use different namespace labels for login sessions and system processes for additional protection. -Extensions to Flask policy +*** Extensions to SEDarwin (Flask TE policy) + +** Generic access checks + +We have extended the Flask subsystem with name-based permission checks, where +security classes and permissions are referenced by name rather than by an assigned +number. Name-based checks are useful when there is no kernel knowledge of the object +or service being protected, as is often the case with userspace services. With this +support, developing a policy for a new application does not require rebuilding the +kernel (or policy tools) even if new security classes or permissions are introduced. +This does not change the binary policy file format, nor does it change how other +Flask access control checks are implemented. As long as the new classes and permissions +are added to the Flask definitions correctly (i.e., without re-ordering the built-in +security classes or permissions), the new policy is compatible with existing systems. +Named permission checks are used by check_service_access and check_ipc_methods. +For consistency with other Flask implementations, the numeric permission checks are +used for all other permission checks. + +** Mach access control checks -The Flask subsystem from SELinux has a limitation in that permissions and -object classes are referenced by numbers, which is not extensible in a -convenient and manageable way. We developed an addition to the Flask security -server to allow permission -lookups by name, for use with the generic access check introduced to the -MAC framework. -The policy compiler will then store the permission names -in the policy file; the kernel will use the names when the generic access -check is attempted. For performance reasons, the numeric permission checks -are still used for all other permission checks. +The SEDarwin policy implements the messaging controls in the usual way: security +classes and permissions are defined for ports; each messaging entry point checks +the appropriate permissions. The port permissions are relabelfrom, relabelto, send, +make_send, copy_send, and move_recv. We have extended MiG to automatically generate security classes and permissions from the specifications. These security classes and permissions can then be used in the TE policy to control access to MiG-based services. The policy also builds a translation table mapping message ids to security classes -(from subsystems) and permissions (from individual routines). This table is -loaded separately from the TE policy, so that the TE policy file format is -preserved across systems. - - -Documentation for new Framework entry points - -/** - @brief Request label for new (userspace) object - @param subj Subject label - @param obj Parent or existing object label - @param serv Name of service - @param out Computed label - - Ask the loaded policies to compute a label based on the two input labels - and the service name. There is currently no standard for the service name, - or even what the input labels represent (Subject and parent object are only - a suggestion). If successful, the computed label is stored in out. All labels - must be port (or task) labels. The userspace interfaces to this entry point - allow label handles (ports) to be provided. - - @return 0 on success, or an errno value for failure. -*/ - -typedef int mpo_request_object_label_t( - struct label *subj, - struct label *obj, - const char *serv, - struct label *out -); - -/** - @brief Compute access control check for a Mach message-based service - @param task Sender's task label - @param port Destination port label - @param msgid Message id - - Access control computation for message-based services. This entry point - computes permission to the service requested by the specified port and message - id, for example a single MiG server routine, and is unrelated to the access - check for sending messages to ports (but that check must succeed for the - message to be sent to the destination). The result of this access computation - is stored in the message trailer field msgh_ad (only if requested by the - recipient); it does not actually inhibit the message from being sent or - received. - - @return 0 for access granted, nonzero for access denied. -*/ - -typedef int mpo_check_ipc_method_t( - struct label *task, - struct label *port, - int msgid -); - +(from subsystems) and permissions (from individual routines). The SEDarwin +implementation of check_ipc_methods uses the message id to look up a security +class and permission for that message, then it requests that permission from the AVC. +The translation table is loaded separately from the TE policy, so that the TE policy +file format is preserved across systems.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507201921.j6KJL3mI098928>