Security/Application installation and Manifest
Tizen 3
In Tizen 3 Smack domains are not defined in the manifest files. Instead, they are explicitly defined by the security architects. This page describes the mechanics of creating Tizen manifest files and is documentation for cases that require explicit labeling. See the Smack Three Domain Model for package configuration directions for Tizen 3.
Introduction
RPM system applications are packaged and delivered to devices from different software sources. A software source may be a application store's software repository or a single developer publishing his/her application on his/her personal web page. Users can also perform offline application installation for other application packages (email attachment from friends, memory stick and etc.).
During each application installation the package manager (RPM) should place a newly installed application into a proper security context (Smack AC domain), configure security attributes of files installed from a package and perform other security-related activities. Upstream RPM implementation doesn't have the same functionality, but it can be implemented in a form of a plugin (separate shared library). Creating the security plug-in for RPM allows separate implementation for different existing security frameworks (mainstream such as Smack, SELinux and etc., as well as any proprietary security frameworks). RPM can call associated plug-in functions at certain defined points during package installation and wait for the plug-in reply to determine if installation can be continued or must be stopped for security reasons. All necessary security-related functionality for application/system installation and update is separated from the RPM and implemented inside a security plug-in (for example, the MSM security plugin). The following figure shows the interaction between RPM and the MSM security plugin (later referred simply as "the security plug-in" as an example of a possible security plug-in). The MSM security framework is used in this Wiki as an example of potential implementation.
The security plug-in needs to have information about the AC domain application and needs to be running to work correctly to place a newly installed application in the correct access control domain. This information is presented with the help of a manifest file (see section Manifest file for more details). However, the security plug-in must not rely only on the manifest file, because a malicious developer may distribute an application package containing malware that would request to run in one of system's sensitive domains and therefore compromise the system. This attack is possible because of an assumption that applications can be installed on a device from any software source, and not all of these software sources would have the means or even a need to verify distributed applications. The device security policy is introduced to mitigate such an attack. It defines a list of known software sources together with their trust levels and ac domains that applications from these sources can request. The security plug-in installs an application to an access control domain requested in the manifest file only if the device security policy permits such domain to be given to an application coming from a particular software source. Section Device security policy provides more information about the device security policy. The installation process of a package is described in more detail in the Installation flow section.
Manifest file
Each RPM package in MSM must have a manifest file where developers can specify the access control domain in which their application should be running and potentially additional security policies for the application. Developers can either choose to belong to an existing domain (defined by the manufacturer, operator or other developers) or define their own domain. For most of the typical cases, developers will only need to belong to an already defined domain, and there won't be much burden for developers to write a manifest file. The section "Request for domain membership" shows how simple is to write such a request.
When this package gets distributed, it is up to an application store to decide wherever this package with a manifest file should be accepted or declined. The application store is also responsible for performing validation and security testing of submitted applications.
A manifest file is an XML file ([package_name].manifest inside rpm source file) with its content placed between the following tags:
<manifest> ... </manifest>
Request for domain membership
When a developer chooses to include an application in an existing domain the access control rules for the application will be defined according to the device domain policy. Domain policy is specified by the entity that defines the domain. To belong to an existing domain, a developer have to use the following declaration inside of a manifest file:
<request> <domain name=”System” /> </request>
This manifest states that applications and data inside of this package should belong to the "System" domain. When this package is submitted to an application store, the store can later decline the package with such manifest request if the application developer doesn’t have the right to have his/her application and associated objects belong to the requested domain. The package manager can decide during installation if a particular package can be installed in the requested domain based on the package source identified by the package signature. Decisions are based on the security policy that specifies the allowed package sources and domains where packages can be installed. If a package requests to belong to a domain that hasn’t been defined on the device yet, the package is missing dependency to a package that defines this domain. The package manager rejects the package. If this situation is identified in an application store the package will be rejected because of the missing dependency.
Defining a new domain
If a developer chooses to define their own domain, the domain name should be a maximum of 255 characters and use only characters “A-Z”, “a-z”, “0-9” and the following symbols: “_”, “-” and “.”. The domain name must not contain symbol“:”. The name should be as unique as possible to avoid confusion with other domain names. For this reason use of a package name is recommended for the domain name. For example, the following is the syntax to declare a new domain called “Camera”:
<define> <domain name="Camera"/> </define>
The domain is private by default. Only applications and objects from the defining package can belong to the domain. If a package installed later requests to belong to this domain, the request is rejected by the package manager and the package isn't installed. If this situation is detected during the testing phase by an application store the package will be rejected and explanations sent to the developer. If two different packages define a domain with the same name, then the first package installed defines this domain and the second package is rejected (this is the reason to keep domain names as package names). If two of the same packages with different versions define the same domain and an upgrade of the package is allowed by the package manager based on security rules, the domain will be redefined based on the upgraded version of the package. A shared domain can be created for developers who want others to install their applications on it. To define a shared domain:
<define> <domain name="Camera" policy=”shared”/> </define>
In this case, an application store decides when an application can belong to this new defined domain. To define domain access for a specific list of packages use the "restricted" value for the policy tag:
<define> <domain name="Camera" policy=”restricted” plist=”package1,package2”/> </define>
The plist tag defines a list of package names without versions, separated by a single comma. When this policy tag is used only packages defined in a list can request to belong to this AC domain (other than the package that originally defined the domain.) The main reason for using the package list option is that it reduces reliance on particular features of application stores. Not all application stores can support application-defined AC domains and restrict domain requests based on the origin of the package (single developer or organisation.) This also allows developers to retain control and ensure only listed packages belong to a domain. New domains declared in the define section don't have access to other domains unless explicitly requested. Domain access can be requested in the request section within the domain definition section:
<define> <domain name="Camera" policy="shared" /> <request> <smack request="Graphics” type=”w" /> </request> </define>
The previous example shows the newly created Camera domain with a request for write access to the Graphics domain. When the package is submitted to the application store it may still decline the Graphics access request. If access is decline the package will be rejected from the application store. Requests for domain accesses can be combined within the domain request section:
<define> <domain name="Camera" policy="shared" /> <request> <smack request="Graphics" type=”w” /> <smack request="System” type=”w" /> </request> </define>
It is also possible to request domain label access (see the domain label section) in the package request section:
<define> <domain name="Camera" policy="shared" /> <request> <smack request="System::statistics” type=”r" /> </request> </define>
To allow other domains access to newly defined domains developers can use permit causes:
<define> <domain name="Camera" policy="shared" /> <permit> <smack permit="Gallery” type=”w" /> </permit> </define>
The previous example permits the Gallery domain to write data to the Camera domain. Use the permit clause carefully; in this example it allows Gallery to write to all Camera domain sockets.
Requesting and defining different domains
To install a package to an existing domain and define a new domain at the same time:
<manifest> <define> <domain name="Camera" policy="shared" /> <permit> <smack permit="Gallery” type=”w" /> </permit> </define> <request> <domain name=”System” /> </request> </manifest>
This example defines a new domain, called Camera, but requests installation on the System domain.
Defining new labels
A domain may need to label some of its components separately for better access control. For example, the Camera domain may have two files: statistics (stores some general statistics about camera use) and timings (stores photo timing information.) Certain domains may need access to the statistics file but not the timings file or vice versa. Some domains may need access to both statistics and timings files. To label file system components, first declare a set of labels:
<define> <domain name="Camera" policy="shared" /> <provide> <label name=”Camera::statistics” /> <label name=”Camera::timings” /> <label name=”Camera::public” /> </provide> </define>
Each label name has the same length restriction as a domain name: 255 characters. Label name must consist of two parts: a domain name and the actual label, separated with a double “:” character.
The syntax is: label_name = domain_name::label. The domain name may need to be shortened if it is too long to fit with the desired label (but it must still be unique.) This section can be omitted if a developer uses already defined labels rather than defining new labels.
Use the following syntax to grant a specific domain access to a sub-label only:
<define> <domain name="Camera" policy="shared" /> <provide> <label name=”Camera::statistics” /> <label name=”Camera::timings” /> </provide> <permit> <smack permit="Gallery" to=”Camera::statistics” type="r" /> </permit> </define>
This example allows the Gallery domain to read components marked "Camera::statistics", but doesn’t allow the Gallery domain to read components labelled “Camera” or “Camera::timings”.
Labelling filesystem objects
Use the following syntax to assign the newly created labels to the filesystem components:
<assign> <filesystem path=”/opt/share/Camera_statistic” label=”Camera::statistics”/> <filesystem path=”/opt/share/Camera_timings” label=”Camera::timings” /> <filesystem path=”/opt/share/Camera_public/” label=”Camera::public” /> </assign>
In this example the directory /opt/share/Camera_public/ receives the label Camera::public. In Smack terms this means a file on the file system will have Smack64 extended attribute set to "Camera::public". If a filesystem object is executable then a SMACK64EXEC extended attribute is also set on the installed file. By default it is always a domain name ("Camera" for this example), but for some programs, there can be a need not to set SMACK64EXEC attribute, and therefore make an executable to inherit the smack subject label of the caller. This can be done with the following syntax:
<assign> <filesystem path=”/usr/bin/tool” exec_label=”none” /> </assign>
Define SMACK64 and SMACK64EXEC at the same time for the file as follows:
<assign> <filesystem path=”/usr/bin/tool” label="Camera::tools" exec_label=”none” /> </assign>
During the package installation, if a package assigns some labels that haven't been defined yet (because the package that defines them hasn’t been installed yet) to its filesystem objects, the labels are created by the package manager and filesystem objects are labelled as specified. Later, if the package that defines these labels is installed, then the labels won’t be redefined; the existing labels will be used. It is important to remember to request the corresponding access rights for a domain when changing the default labels from a package to these labels. Otherwise applications from the package won’t be able to access the filesystem objects. Use the following syntax to request access rights:
<define> <domain name="Camera" policy="shared" /> <provide> <label name=”Camera::statistics” /> <label name=”Camera::timings” /> <label name=”Camera::public” /> </provide> <request> <smack request="Graphics" type="r" /> <smack request="System" type="r" /> <smack request="Camera::statistics" type="rw" /> <smack request="Camera::timings" type="rw" /> <smack request="Camera::public" type="rw" /> </request> </define> <assign> <filesystem path=”/opt/share/Camera_statistic” label=”Camera::statistics”/> <filesystem path=”/opt/share/Camera_timings” label=”Camera::timings” /> <filesystem path=”/opt/share/Camera_public/” label=”Camera::public” /> </assign>
An alternative labelling option uses the already defined name of another domain:
<define> <domain name="Camera" policy="shared" /> <request> <smack request="Graphics" type="w" /> <smack request="System" type="w" /> </request> </define> <assign> <filesystem path=”/opt/share/Camera_graphic_data” label=”Graphics” /> </assign>
In this example the Camera domain labels its file /opt/share/Camera_graphic_data as part of the Graphics domain. This means that Graphics domain processes have full access to this file. The Camera domain also requests read access to Graphic domain to be able to read this file.
An additional parameter can be specified with a directory label for filesystem objects. A directory can be marked as transmutable, meaning that all the files created inside this directory get the directory label and not a process label (default choice). Use the following syntax to declare a directory transmutable:
<assign> <filesystem path=”/opt/share/Camera_graphic_data” label=”Graphics” type=”transmutable”/> </assign>
Specify the wild card for the file path using the "*" character. For example the following assign section states that all filesystem objects (files and directories) in the folder Camera_graphic_data should be labelled as "Graphics". This statement is recursive.
<assign> <filesystem path=”/opt/share/Camera_graphic_data/*” label=”Graphics”/> </assign>
Specify exceptions to the rule using the full path:
<assign> <filesystem path=”/opt/share/Camera_graphic_data/*” label=”Graphics”/> <filesystem path=”/opt/share/Camera_graphic_data/internal_data” label=”Camera”/> </assign>
Protection of dbus interfaces
In some cases, an application within a domain may provide service interfaces over Dbus and therefore become a dbus server. For example, a camera application in the Camera domain may provide an interface com.tizen.camera on a system bus with two different methods: capture (capture a photo) and setSettings (set some capture parameters) allowing different camera operations. By default any client with write access to the Camera domain can call these methods. Developers may choose to set different access control rules for provided interfaces. For example, a developer can allow any client that belongs to the System domain to call the setSettings interface, while clients from the Application domain call a method capture. The developer may also define that an application must belong to the Camera domain to own the com.tizen.camera interface. This type of rule is expressed in the manifest dbus section:
<assign> <dbus name="com.tizen.camera" own="Camera" bus="system"> <node name="/com/tizen/camera"> <interface name="com.tizen.camera"> <annotation name="com.tizen.smack" value="*"/> <method name="setSettings"> <annotation name="com.tizen.smack" value="System"/> </method> <method name="capture"> <annotation name="com.tizen.smack" value="Application"/> </method> </interface> </node> </dbus> </assign>
This section of manifest follows Dbus introspection format [1] with a new annotation name defined as com.tizen.smack. The interface or method label is defined inside a value=”” statement and can contain either the domain name or the label name (including labels defined in the provide section of a domain). In this example, a developer specifies access control rules per method and therefore access to the interface itself is allowed for any application (value=”*”). Use the following syntax to specify access control rules for the whole interface and for all methods in that interface:
<dbus name="com.tizen.camera" own="Camera" bus="system"> <node name="/com/tizen/camera"> <interface name="com.tizen.camera"> <annotation name="com.tizen.smack" value="Camera::dbus-access"/> </interface> </node> </dbus>
In this example,an application should have write access to the Camera::dbus-access label to send a message to the com.tizen.camera interface.
Full example
Example of defining and requesting a new Camera domain:
<manifest> <define> <domain name="Camera" policy="shared" /> <provide> <label name=”Camera::statistics” /> <label name=”Camera::timings” /> <label name=”Camera::public” /> <label name=”Camera::dbus-access” /> </provide> <request> <smack request="Graphics" type="w" /> <smack request="System" type="w" /> <smack request="Camera::statistics" type="rw" /> <smack request="Camera::timings" type="rw" /> <smack request="Camera::public" type="rw" /> <smack request="Camera::dbus-access" type="rw" /> </request> </define> <assign> <filesystem path=”/opt/share/Camera_statistic” label=”Camera::statistics”/> <filesystem path=”/opt/share/Camera_timings” label=”Camera::timings” /> <filesystem path=”/opt/share/Camera_public/” label=”Camera::public” /> <dbus name="com.tizen.camera" own="Camera" bus="system"> <node name="/com/tizen/camera"> <interface name="com.tizen.camera"> <annotation name="com.tizen.smack" value="Camera::dbus-access"/> </interface> </node> </dbus> </assign> <request> <domain name="Camera"/> </request> </manifest>
Adding manifest to the rpm package
There are two ways to add the manifest to the rpm package. The manifest file (named binary_package_name.manifest) can be placed in the root of the source package (and should get packaged to tar ball after) or it can be added to the OBS as a separate file. When placed in the root the only change to the spec file is the following line under the %file section of binary package that should get the manifest:
%manifest binary_package_name.manifest
For example:
%files %defattr(-,root,root,-) %manifest binary_package_name.manifest
A source package can have a number of binary packages; each %file section for each binary package needs the line to include an appropriate manifest. As a last step the package should be built using the modified rpm-build command.
If the manifest file is placed in the root of the OBS project the following changes are needed in the spec file:
The manifest file name must be added to the source list of the package:
Source0 %{name}-%{_version}.tar.bz2 Source1 binary_package_name.manifest
The %install section of the spec file must contain the code to install the manifest file in some part of the build-root (the location doesn't matter since the file will only be used during the packaging phase). For example:
cp -a %{SOURCE1} %{buildroot}%{_datadir}/binary_package_name.manifest
The %files section of the corresponding binary rpm must contain the line to include the manifest from the location mentioned in the install section:
%files %defattr(-,root,root,-) %manifest %{_datadir}/binary_package_name.manifest
Device Security Policy
As mentioned above, on installation the RPM security plug-in identifies a software source for each application’s package based on the package signature. The plug-in maintains a list of known software sources and their associated public keys for this purpose. Some of the software sources may perform application security testing and validation and be trusted sources; some of them may be less trusted and their level of quality assurance may not be known. A device security policy is introduced to protect a device from malicious applications. The goal of the device security policy is to maintain mapping of the known software sources and the list of access control domains for each source. For example, applications from less trusted sources may be denied access to the “System” AC domain because this domain has many privileges and installation of a malicious application could have severe consequences.
In addition each software source is assigned a trust level that defines the process for package updates. A rule dictates that a package can be updated only from a software source that has the same or higher trust level. This rule is necessary to avoid situations where trusted packages are replaced with less trusted and potentially malicious packages by providing a higher version package available for installation. For a more detailed explanation about trust level assignment and SW source ordering see Ordering of Software Sources.
The device security policy also allows configuring the MSM security framework in a number of different ways to obtain a different set of mobile devices targeted for different purposes. The policy may be very strict by defining only a small set of known trusted sources and denying access to any AC domains for applications coming from any other sources. On the contrary the policy may be quite relaxed by allowing even applications from less trusted sources to belong to high-privilege domains. The device security policy can be remotely updated allowing a manufacturer or operator to adjust the security settings based on the threat landscape. In addition to maintaining a list of known software sources, the RPM security plug-in has a default software source called “Unknown”. This source is used in cases where the software source for an application package can’t be identified due to an inability to validate a package’s signature.
The following table shows an abstracted example of a simple device security policy. This policy has two defined software sources (Main and sourceforge.org). It also has a default “Unknown” software source. The “Main” source is the most trusted; applications coming from this source can request to belong to both the System and Applications AC domains. “Sourceforge.org” is a less trusted source (but more trusted than the “Unknown” source) and applications from this source are only allowed installation in the “Applications” AC domain. The same rule applies in this policy for the “Unknown” source, but it has the smallest trust level, so updates from this source can be installed only for the packages that have been previously installed from the same “Unknown” source.
SW Source name | Trust level | Public Key info | Allowed AC domains |
---|---|---|---|
Main | 100 | ABCDEF... | System, Applications |
sourceforge.org | 10 | DEFABC... | Applications |
Unknown | 10 | --------------- | Applications |
Installation flow
Figure 2 shows a simplified view of the installation process. When an application package arrives to the RPM package manager a set of callbacks are made to the security plug-in. The security plug-in checks that the manifest file is present and analyzes its content. If the manifest file is correct and the security plug-in found the requested access control domain then it verifies that the device security policy allows this domain for this application. If the request is allowed then it sets up the correct security extended attributes for the files from the package and adds needed Smack rules to the kernel with the help of the libsmack library. In this case the application only requests to belong to the already defined access control domain and no new Smack rules are added.