Flask is an operating system security architecture that provides flexible support for security policies. This chapter defines the Flask-related COM interfaces that are defined by header files in the oskit/flask directory. The sections of this chapter are:
An example implementation of an AVC component is available in com/avc.c. An example implementation of a security server component is available in security. An example implementation of file access control wrappers that use these interfaces is available in com/sfs*.c.
This header file defines the basic types and constants used by the Flask-related COM interfaces. The architecture defines two policy-independent types for the set of security attributes associated with each subject and object controlled by the security policy. The security context type (oskit_security_context_t) is defined as a variable-length string that can be interpreted by any application or user with an understanding of the security policy. A security context might consist of several attributes, such as a user identity, a role, a type and a classification level.
To permit most object manager interactions to remain independent of both the format and the content of the security context, the security server defines a security identifier (SID) for each active security context. The SID type (oskit_security_id_t) is defined as a fixed-sized value that is mapped by the security server to a security context. The SID mapping cannot be assumed to be consistent either across executions (reboots) of the security server or across security servers on different nodes. Hence, SIDs may be lightweight; in the implementation, they are simply 32-bit integers.
The null (or zero-valued) SID is never a valid SID, but it may be used in extended object manager calls when no particular SID is specified. A wildcard SID, OSKIT_SECSID_WILD, is defined that matches any other SID when used for certain AVC operations. Certain SIDs (specified in flask/initial_sids) are predefined for system initialization. The corresponding constants are defined in the automatically generated header file flask/flask.h.
The security server computes access decisions based on a pair of SIDs. Typically, the SID pair consists of the SID of a subject invoking an operation and the SID of the object on which the operation was invoked. Rather than providing access decisions individually, the security server groups related access decisions into a bitmap referred to as an access vector. For example, a single access vector expresses the set of file permissions granted for a given SID pair.
The access vector type (oskit_access_vector_t) is defined as an unsigned 32-bit integer value. The bits within an access vector are interpreted differently depending on the class of the object. Each object class is identified by an unsigned 16-bit integer value, with the oskit_security_class_t type. The set of security classes is specified in flask/security_classes, with the corresponding constants in the automatically generated header file flask/flask.h. The permissions for each class are specified in flask/access_vectors, and the corresponding constants are defined in the automatically generated header file flask/av_permissions.h.
The oskit_security interface specifies the methods provided by a security server component for obtaining security decisions. The oskit_security COM interface inherits from IUnknown, and has the following additional methods:
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_compute_av(oskit_security_t *security, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t requested, [out] oskit_access_vector_t *allowed, [out] oskit_access_vector_t *decided, [out] oskit_access_vector_t *auditallow, [out] oskit_access_vector_t *auditdeny, [out] oskit_access_vector_t *notify, [out] oskit_u32_t *seqno);
The oskit_security_compute_av function computes access vectors based on a SID pair for the permissions in a particular class. An access vector cache (AVC) component calls this function when no valid entry exists for the requested permissions in the cache. The first SID parameter, ssid, is referred to as the source SID and the second SID parameter, tsid, is referred to as the target SID. The returned access vectors must contain decisions for every permission specified in the requested access vector.
The security server may optionally return decisions for other permissions in the same class. The decided access vector contains the set of permissions for which a decision was returned. The other returned access vectors may only be used for permissions in this set. The security server may choose to defer computation of permissions until they are explicitly requested.
The allowed access vector contains the set of granted permissions. The seqno parameter contains a sequence number associated with the access granting. If the sequence number provided by the latest policy change is greater than this value, then the access granting may be invalid and must be discarded. The sequence number addresses the issue of an interleaving of an access granting and a policy change.
The auditallow and auditdeny access vectors contain the set of permissions that should be audited when granted or when denied, respectively. These vectors enable the security server to precisely control the auditing of permission checks. The AVC component ensures that auditing is performed in accordance with these vectors.
The notify access vector contains the set of permissions for which the oskit_security_notify_perm function should be called when the operation associated with the permission has successfully completed. This vector permits the security server to request that the AVC component notify the security server of the successful completion of operations so that the security server may base its decisions on the history of operations in the system. This differs from merely basing decisions on the history of granted permissions, since an operation may still fail due to other conditions even if permission is granted for that operation.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_notify_perm(oskit_security_t *security, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t requested);
The oskit_security_notify_perm function notifies the security server that an operation associated with the permissions in the requested access vector has completed successfully. The AVC component calls this function when it is called by an object manager to indicate that the operation has completed successfully if any of the requested permissions are in the corresponding notify vector.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_transition_sid(oskit_security_t *security, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, [out] oskit_security_id_t *out_sid);
The oskit_security_transition_sid function computes a SID for a new object based on a SID pair and a class. The object managers call this function when objects are created if a SID was not specified for the object and there is more than one relevant SID that might be used as input in determining the SID of the new object. In particular, the file system code calls this function to obtain the SID of a new file based on the SID of the creating process and the SID of the parent directory, and the process management code calls this function to obtain the SID of a process transformed by an execve based on the current SID of the process and the SID of the executable program.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_member_sid(oskit_security_t *security, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, [out] oskit_security_id_t *out_sid);
The security_member_sid function computes a SID to use when selecting a member of a polyinstantiated object based on a SID pair and a class. Certain fixed resources, such as the /tmp directory or the TCP/UDP port number spaces, need be polyinstantiated to restrict sharing among processes. Each instantiation is referred to as a member. The object managers call this function when a polyinstantiated object is accessed and then transparently redirect the process to the appropriate member.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_sid_to_context(oskit_security_t *security, oskit_security_id_t sid, [out] oskit_security_context_t *scontext, [out] oskit_u32_t *scontext_len);,
The oskit_security_sid_to_context function returns the security context associated with a particular SID. The scontext parameter is set to point to a dynamically-allocated string of the correct size. The scontext_len parameter is set to the length of the security context string, including the terminating NULL character.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_context_to_sid(oskit_security_t *security, oskit_security_context_t scontext, oskit_u32_t scontext_len, [out] oskit_security_id_t *out_sid);
The oskit_security_context_to_sid function returns a SID associated with a particular security context. The scontext_len parameter specifies the length of the security context string, including the terminating NULL character.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_register_avc(oskit_security_t *security, oskit_security_class_t *classes, oskit_u32_t nclasses, oskit_avc_ss_t *avc);
This method registers an AVC component for policy change notifications.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_unregister_avc(oskit_security_t *security, oskit_avc_ss_t *avc);
This method unregisters an AVC component.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_load_policy(oskit_security_t *security, oskit_openfile_t *openfile);
This method loads a new policy configuration from openfile. The security server notifies any registered AVC components of any policy changes caused by the new configuration.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_fs_sid(oskit_security_t *security, char *name, [out] oskit_security_id_t *fs_sid, [out] oskit_security_id_t *file_sid);
The oskit_security_fs_sid function returns SIDs to use for an unlabeled file system mounted from the device specified by dev. The file system code calls this function when a process attempts to mount an unlabeled file system. The value for the dev parameter is a string of the form “major:minor” where both the major and minor number are in hexadecimal and are right justified in a two character field, as returned by the kdevname function on the device number. The fs_sid parameter is set to the SID to use for the file system, and the file_sid parameter is set to the SID to use for any existing files in the file system.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_port_sid(oskit_security_t *security, oskit_u16_t domain, oskit_u16_t type, oskit_u8_t protocol, oskit_u16_t port, [out] oskit_security_id_t *sid);
The oskit_security_port_sid function returns the SID to use for the port number port in the protocol specified by the triple (domain, type, protocol).
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_netif_sid(oskit_security_t *security, char *name, [out] oskit_security_id_t *if_sid, [out] oskit_security_id_t *msg_sid);
The oskit_security_netif_sid function returns SIDs to use for a network interface. The value for the name parameter is typically the driver name followed by the unit number, e.g. the name eth0 would be used for the first Ethernet interface. The if_sid parameter is set to the SID to use for the interface, and the msg_sid parameter is set to the SID to use for any unlabeled messages received on the interface.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/security.h>
OSKIT_COMDECL oskit_security_node_sid(oskit_security_t *security, oskit_u16_t domain, void *addr, oskit_u32_t addrlen, [out] oskit_security_id_t *sid);
The oskit_security_node_sid function returns the SID to use for the node whose address is specified by addr. The addrlen parameter specifies the length of the address in bytes, and the domain parameter specifies the communications domain or address family in which the address should be interpreted.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_avc interface specifies the methods provided by an access vector cache (AVC) component to object managers. These methods are used by object managers to perform permission checks, to notify the AVC component of completed operations and to register callbacks for policy changes.
The AVC entry reference type (oskit_avc_entry_ref_t) consists of a pointer to an entry in the AVC. The AVC returns a reference to the entry used for a permission check. An object manager may save this reference with the corresponding object for subsequent use in other permission checks on the object. An object manager must initialize a reference before its first use with the OSKIT_AVC_ENTRY_REF_INIT macro. An object manager may copy a reference with the OSKIT_AVC_ENTRY_REF_CPY macro. AVC entry references should only be dereferenced by the AVC functions.
The oskit_avc COM interface inherits from IUnknown, and has the following additional methods:
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_has_perm_ref(oskit_avc_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t requested, [in/out] oskit_avc_entry_ref_t *aeref);
The oskit_avc_has_perm_ref inline function determines whether the requested permissions are granted for the specified SID pair and class. If aeref refers to a valid AVC entry for this permission check, then the referenced entry is used. Otherwise, this function obtains a valid entry and sets aeref to refer to this entry. To obtain a valid entry, this function first searches the cache. If this fails, then this function calls the oskit_security_compute_av interface of the security server to compute the access vectors and adds a new entry to the cache. If the appropriate audit access vector (auditallow or auditdeny) in the entry indicates that the permission check should be audited, then this function audits the permission check.
The object managers call this function to perform permission checks. Object managers may also use a variant of this function, avc_has_perm, in order to omit the reference parameter.
This function returns 0 if permission is granted. If the security server returns an error upon a oskit_security_compute_av call, then this function returns that error. If the security server returns a sequence number that is less than the latest policy change sequence number, then this function discards the security server response and returns OSKIT_EAGAIN. If permission is denied, then this function returns OSKIT_EACCES.
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_notify_perm_ref(oskit_avc_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t requested, [in/out] oskit_avc_entry_ref_t *aeref);
The oskit_avc_notify_perm_ref inline function notifies the AVC component that an operation associated with the requested permissions has completed successfully. If any of the requested permissions are in the notify access vector of the corresponding AVC entry, then this function calls the oskit_security_notify_perm interface of the security server to notify the security server that the operation has completed successfully. If aeref refers to a valid AVC entry for the requested permissions, then the referenced entry is used to obtain the notify vector. Otherwise, this function obtains a valid entry and sets aeref to refer to this entry in the same manner as oskit_avc_has_perm_ref.
The object managers call this function to notify the AVC component of operation completion. Object managers may also use a variant of this function, avc_notify_perm, in order to omit the reference parameter.
This function returns 0 if the notification was successful. If the security server returns an error upon a oskit_security_compute_av or a oskit_security_notify_perm call, then this function returns that error. If the security server returns a sequence number that is less than the latest policy change sequence number, then this function discards the security server response and returns OSKIT_EAGAIN.
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_add_callback(oskit_avc_t *avc, oskit_avc_callback_t *callback, oskit_u32_t events, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms);
The oskit_avc_add_callback function registers an object manager callback function callback with the AVC component for policy change notifications. When the security server calls an AVC interface that corresponds to an event in the set events with a SID pair, class and permissions that match ssid, tsid, tclass and perms, the AVC component calls the registered callback function with the parameters provided by the security server. The callback function may then update any affected permissions that are retained in the state of the object manager. The wildcard SID, OSKIT_SECSID_WILD, may be used for the ssid and tsid parameters to match all SID values. Permission vectors match if they have a non-null intersection. The meaning of each event value is explained in the description of the corresponding interface in the next section.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_remove_callback(oskit_avc_t *avc, oskit_avc_callback_t *callback);
This method removes the specified callback.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_log_contents(oskit_avc_t *avc, int priority, char *tag);
This method logs the contents of the AVC.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc.h>
OSKIT_COMDECL oskit_avc_log_stats(oskit_avc_t *avc, int priority, char *tag);
This method logs the statistics of the AVC.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_avc_ss interface specifies the methods provided by an AVC component to the security server. These methods are used by the security server to manage the cache as needed for policy changes. The oskit_avc_ss COM interface inherits from IUnknown, and has the following additional methods:
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_grant(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno);
The oskit_avc_ss_grant function grants previously denied permissions for a SID pair and class. The wildcard SID, OSKIT_SECSID_WILD, may be used for the ssid and tsid parameters to match all SID values. This function adds the permissions in perms to the allowed vector in any matching entries in the cache. It then calls any callbacks registered by an object manager for the OSKIT_AVC_CALLBACK_GRANT event with a matching SID pair, class and permissions. Permission vectors match if they have a non-null intersection. This function updates the latest policy change sequence number to the greater of its current value and the seqno value.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_try_revoke(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno, [out] oskit_access_vector_t *out_retained);
The oskit_avc_ss_try_revoke function tries to revoke previously granted permissions for a SID pair and class, but only if they are not retained in the state of an object manager. If any of the permissions in perms are retained, the retained permissions are returned in out_retained. The wildcard SID, OSKIT_SECSID_WILD, may be used for the ssid and tsid parameters to match all SID values. This function calls any callbacks registered by an object manager for the OSKIT_AVC_CALLBACK_TRY_REVOKE event with a matching SID pair, class and permissions. Permission vectors match if they have a non-null intersection. Each callback is expected to identify which matching permissions are retained in the state of the object manager. The set of retained permissions returned by each callback is added to out_retained. This function then removes any permissions in perms that were not retained from the allowed vector in any matching entries in the cache. This function updates the latest policy change sequence number to the greater of its current value and the seqno value.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_revoke(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno);
The oskit_avc_ss_revoke function revokes previously granted permissions for a SID pair and class, even if they are retained in the state of an object manager. The wildcard SID, OSKIT_SECSID_WILD, may be used for the ssid and tsid parameters to match all SID values. This function removes any permissions in perms from the allowed vector in any matching entries in the cache. It then calls any callbacks registered by an object manager for the OSKIT_AVC_CALLBACK_REVOKE event with a matching SID pair, class and permissions. Permission vectors match if they have a non-null intersection. Each callback is expected to revoke any matching permissions that are retained in the state of the object manager. This function updates the latest policy change sequence number to the greater of its current value and the seqno value.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_reset(oskit_avc_ss_t *avc, oskit_u32_t seqno);
The oskit_avc_ss_reset function flushes the cache and revalidates all permissions retained in the state of the object managers. This function invalidates all entries in the cache. It then calls any callbacks registered by an object manager for the OSKIT_AVC_CALLBACK_RESET event. Each callback is expected to revalidate permissions that are retained in the state of the object manager by calling oskit_avc_has_perm_ref or one of its variants. This function updates the latest policy change sequence number to the greater of its current value and the seqno value.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_set_auditallow(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno, oskit_bool_t enable);
The oskit_avc_ss_set_auditallow function enables or disables auditing of granted permissions for a SID pair and class. The wildcard SID, OSKIT_SECSID_WILD, may be used for the ssid and tsid parameters to match all SID values. The enable flag should be 1 to enable auditing and 0 to disable auditing. This function adds or removes, depending on the value of enable, the permissions in perms from the auditallow vector in any matching entries in the cache. It then calls any callbacks registered by an object manager for the OSKIT_AVC_CALLBACK_AUDITALLOW_ENABLE or OSKIT_AVC_CALLBACK_AUDITALLOW_DISABLE event with a matching SID pair, class and permissions. Permission vectors match if they have a non-null intersection. This function updates the latest policy change sequence number to the greater of its current value and the seqno value.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_set_auditdeny(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno, oskit_bool_t enable);
The oskit_avc_ss_set_auditdeny function enables or disables auditing of denied permissions for a SID pair and class. It has the same behavior as oskit_avc_ss_set_auditallow, except that it modifies the auditdeny vector and it is associated with the OSKIT_AVC_CALLBACK_AUDITDENY_ENABLE and OSKIT_AVC_CALLBACK_AUDITDENY_DISABLE events.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/flask/avc_ss.h>
OSKIT_COMDECL oskit_avc_ss_set_notify(oskit_avc_ss_t *avc, oskit_security_id_t ssid, oskit_security_id_t tsid, oskit_security_class_t tclass, oskit_access_vector_t perms, oskit_u32_t seqno, oskit_bool_t enable);
The oskit_avc_ss_set_notify function enables or disables notification of completed operations for a SID pair and class. It has the same behavior as oskit_avc_ss_set_auditallow, except that it modifies the notify vector and it is associated with the OSKIT_AVC_CALLBACK_NOTIFY_ENABLE and OSKIT_AVC_CALLBACK_NOTIFY_DISABLE events.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.