This paper was converted on www.awesomepapers.org from LaTeX by an anonymous user.
Want to know more? Visit the Converter page.

11institutetext: Universidad Nacional de Rosario, Argentina.
11email: [email protected]
22institutetext: InCo, Facultad de Ingeniería, Universidad de la República, Uruguay.
22email: [email protected]

Towards a certified reference monitor of the Android 10 permission system

Guido De Luca 11    Carlos Luna 22
Abstract

Android is a platform for mobile devices that captures more than 85% of the total market-share [14]. Currently, mobile devices allow people to develop multiple tasks in different areas. Regrettably, the benefits of using mobile devices are counteracted by increasing security risks. The important and critical role of these systems makes them a prime target for formal verification. In our previous work [10], we exhibited a formal specification of an idealized formulation of the permission model of version 6 of Android. In this paper we present an enhanced version of the model in the proof-assistant Coq, including the most relevant changes concerning the permission system introduced on versions Nougat, Oreo, Pie and 10. The properties that we had proved earlier for the security model has been either revalidated or refuted, and new ones have been formulated and proved. Additionally, we make observations on the security of the most recent versions of Android. Using the programming language of Coq we have developed a functional implementation of a reference validation mechanism and certified its correctness. The formal development is about 23k LOC of Coq, including proofs.

Keywords:
Android, Permission model, Formal idealized model, Reference monitor, Formal proofs, Certified implementation, Coq.

1 Introduction

Android [23] is the most used mobile OS in the world, capturing approximately the 85% of the total market-share [14]. It offers a huge variety of applications in its official store that aim to help people in their daily activities, many of them critical in terms of privacy. In order to guarantee their users the security they expect, Android relies on a multi-party consensus system where user, OS and application must be all in favour of performing a task. This security framework is built upon a system of permissions, which are basically tags that developers declare on their applications to gain access to sensitive resources. Whenever an action that requires some of this permissions is executed for the first time, the user will be asked for authorization and if provided, the OS will ensure that only the required access is granted. The important and critical role of this security mechanism makes it a prime target for (formal) verification.

Security models play an important role in the design and evaluation of security mechanisms of systems. Earlier, their importance was already pointed in the Anderson report [1], where the concept of reference monitor was first introduced. This concept defines the design requirements for implementing what is called a reference validation mechanism, which shall be responsible for enforcing the access control policy of a system. For ensuring the correct working of this mechanism three design requirements are specified: i) the reference validation mechanism (RVM) must always be invoked (complete mediation); ii) the RVM must always be tamper-proof (tamper-proof); and iii) the RVM must be small enough to be subject to analysis and tests, the completeness of which can be assured (verifiable).

The work presented here is concerned with the verifiability requirement. In particular we put forward an approach where formal analysis and verification of properties is performed on an idealized model that abstracts away the specifics of any particular implementation, and yet provides a realistic setting in which to explore the issues that pertain to the realm of (critical) security mechanisms of Android. The formal specification of the reference monitor shall be used to establish and prove that the security properties that constitute the intended access control policy are satisfied by the modeled behavior of the validation mechanisms.

Contributions

In our previous work [10] we presented a formal specification of an idealized formulation of the permission model of version 6 of Android. We also developed, using the programming language of Coq [26], an executable (functional) specification of the reference validation mechanism and we proved its correctness conforming the specified model. Lastly, we used the program extraction mechanism provided by Coq [18] to derive a certified Haskell implementation of the reference validation mechanism. Here we present an enhanced version of the model, including the most relevant changes concerning the permission system introduced on versions Nougat, Oreo, Pie and 10. Some of these changes don’t have a direct impact on our abstract model. In those cases, an informal analysis is included. The executable specification was also updated, and with that, the derived implementation as well. The properties that we had proved for the security model has been either revalidated or refuted, and new ones have been formulated and proved. The formal development is about 23k LOC of Coq, including various lemmas and their proofs.

Organization of the paper

Section 2 reviews the security mechanisms of Android and briefly describes the changes introduced in the later versions. Sections 3 and 4 present the formal axiomatic specification and the semantics of the certified implementation, respectively. Both sections discuss relevant properties concerning the new features. Section 5 considers related work and finally, Section 6 concludes with a summary of our contributions and directions for future work. The full formalization is available at:
https://www.fing.edu.uy/~cluna/Android10-Coq.zip [19] and can be verified using the Coq proof assistant.

2 Android’s security model

2.1 Basic security mechanisms

The Android security model is primarily based on a sandbox and permission mechanism. Each application runs in a private virtual machine with a unique ID assigned to it, which means that one application’s code is isolated from the code of all others. This way of protection entails the existence of a decision procedure (a reference validation mechanism) that arbitrates the access to sensitive data whenever an application wants to share resources with another (or the system). Decisions are made by following security policies using a simple notion of permission.

Every permission is identified by a unique name/text, has a protection level and may belong to a permission group. Furthermore, permissions can be classified into two groups: the ones defined by an application, for the sake of self-protection; and those predefined by Android, which are required to gain access to certain system features, like internet or location. Depending on the protection level of the permission, the system defines the corresponding decision procedure. There are three classes of permission levels [4]: i) normal, this permissions can be automatically granted since they cover data or resources where there’s very little risk to the user’s privacy or the operation of other apps; ii) dangerous, permissions of this level provide access to data or resources that may be sensitive or could potentially affect the operation of other applications, and explicit user approval is needed to be granted; and iii) signature, a permission of this level is granted only if the application that requires it and the application that defined it are both signed with the same certificate. An application must declare –in an XML file called AndroidManifest– the set of permissions it needs to acquire further capacities than the default ones. From version 6 of Android, dangerous permissions are granted on runtime whereas both normal and signature are given when the application is installed.

Permissions may belong to groups that reunites a device’s capabilities. The main purpose of grouping permissions this way is to handle permission requests at the group level, in order to avoid overwhelming the user with too many questions. For example, the SMS group includes the permission needed to read the text messages as well as the one needed to receive them (both considered to be dangerous). Whenever an application needs one of those for the first time, the user will be asked to authorize the whole group. On Section 2.2, we explain what authorizing a group means depending on the platform version.

An Android application is built up from components. A component is a basic unit that provides a particular functionality and that can be run by any other application with the right permissions. There exist four types of components [2]: i) activity, which is essentially a user interface of the application; ii) service, a component that executes in background without providing an interface to the user; iii) content provider, a component intended to share information among applications; and iv) broadcast receiver, a component whose objective is to receive messages, sent either by the system or an application, and trigger the corresponding actions. The communication between components is achieved with the exchange of special messages called intents, which can be either i) explicit, meaning that the target application is specified; or ii) implicit, where only the action to be performed is declared and the system determines which application will run the task (if there is more than one capable application, the user is allowed to choose). In order to be candidates for the implicit intents resolutions, an application must declare on their manifest an intent filter that indicates the types of intents it can respond to.

Android provides two mechanisms by which an application can delegate its own permissions to another one. These mechanisms are called pending intents and URI permissions. An intent may be defined by a developer to perform a particular action. A PendingIntent specifies a reference to an action, which might be used by another application to perform the operation with the same permissions and identity of the one that created the intent. The URI permissions mechanism can be used by an application that has read/write access to a content provider to temporarily delegate those permissions to another application. These permissions are revoked once the receiver activity or service become inactive.

2.2 A brief review on the changelog

As we described in our previous work [10], the sixth version of Android introduced an important change to the system, allowing the users to handle permissions at runtime. In this section, we give a short account of the changes introduced between Android Nougat (7) and Android 10, that had a significant impact on the permission system.

Filesystem

In order to improve security, the private directory of applications targeting111Applications can target a particular version of the system. Android uses this setting to determine whether to enable any compatibility behaviors or features. Android 7.0 or higher has restricted access: only the owner is capable of reading, writing or executing files stored in there. This configuration prevents leakage of metadata of private files, like the size or existence. With this change, applications are no longer able to share files simply by changing the file permissions and sharing their private URI; a content provider must be used in order to generate a reference to the file. With this approach, a new kind of URI is generated, which grants a temporary permission that will be available for the receiver activity or service only while they are active/running.

Our previous model already allowed granting temporary permissions to content providers URIs, so no change was required to formalize this new feature.

Grouped permissions

Prior to Android 8, if an application requested a grouped permission at runtime and the user authorized it, the system also granted the rest of the permissions from the same group that were declared on the manifest. This behaviour was incorrect since it violated the intended least privilege security policy claimed by the designers of the platform. For applications targeting Android 8 or higher, this action was corrected and only the requested permission is granted. However, once the user authorized a group, all subsequent requests for permissions in that group are automatically granted. This change was added to the model.

Normal grouped permissions.

According to Android’s official documentation, any permission can belong to a permission group regardless of protection level [3]. However, it is not specified if normal and dangerous permissions can share a group nor, in case that it is possible, how the system should handle this situation. A few questions we have raised ourselves are the following: i) Is the authorization to automatically concede permissions from that group granted at installation time together with the normal permissions?; ii) Is the user warned about that decision?; iii) If that is the case, then there’s a contradiction with the documentation, since it claims that a permission’s group only affects the user experience if the permission is dangerous; and iv) If it’s not, how does the system avoid that dangerous permissions from the same group are not automatically granted later by the system?

In this work we formalized a worst-case scenario (that still suits the informal specification given by the authors of the platform), where a normal permission enables the automatic granting of dangerous permissions belonging to the same group. We formally discuss this situation in Section 3.4.

Privacy changes

Android Pie (9) introduced several changes aiming to enhance users’ privacy, such as limiting background apps’ access to device sensors, restricting information retrieved from Wi-Fi scans, and adding new permission groups and rules to reorganize phone calls and phone state related permissions. Later, the tenth version of the platform continued adding limitations to services: a new permission for accessing the location in the background was added. Furthermore, Android 10 placed restrictions on when a service can start an activity, in order to minimize interruptions for the user and keep the user more in control of what’s shown on their screen.

These changes are specific to the implementation, meaning that they have no impact on an abstract representation like ours.

Permission check on legacy apps

Applications that target Android 5.1 or lower are considered to be old222We can also refer to them as legacy applications.. If an old application runs on an Android 10 system for the first time, a prompt appears on the screen, giving the user an opportunity to revoke access to permissions that the system previously granted at install time. This feature has been added to our model.

3 Formalization of Android’s permission system

In this section we describe the axiomatic semantics of our model of the system, focusing on the features introduced in the later versions. We also discuss some of the verified properties.

Formal language used

Coq is an interactive theorem prover based on higher order logic that allows to write formal specifications and interactively generate machine-checked proofs of theorems. It also provides a (dependently typed) functional programming language that can be used to write executable algorithms. The Coq environment also provides program extraction towards languages like Ocaml and Haskell for execution of (certified) algorithms [17, 18]. In this work, enumerated types and sum types are defined using Haskell-like notation; for example, optionT=defNoneSome(t:T)option\ T\stackrel{{\scriptstyle{\rm def}}}{{=}}None\mid Some\ (t:T). Record types are of the form {l1:T1,,ln:Tn}\left\{l_{1}:T_{1},\ldots,l_{n}:T_{n}\right\}, whereas their elements are of the form {t1,,tn}\{t_{1},\ldots,t_{n}\}. Field selection is written as r.lir.l_{i}. We also use {T}\{T\} to denote the set of elements of type TT. Finally, the symbol ×\times defines tuples, and natnat is the datatype of natural numbers. We omit Coq code for reasons of clarity; this code is available in [19].

3.1 Model states

The Android security model we have developed has been formalized as an abstract state machine. In this model, states (𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳\mathsf{AndroidST}) are modelled as 13-tuples that store dynamic data about the system such as the installed applications and their current permissions, as well as static data like the declared manifest of each installed app. A complete formal definition is given in Figure 1.

Auxiliary definitions𝖮𝗉𝖳𝗒::=read|write|rw𝖯𝖾𝗋𝗆𝖫𝗏𝗅::=Dangerous|Normal|Signature|Signature/System𝖯𝖾𝗋𝗆::=𝖯𝖾𝗋𝗆𝖨𝖽×option𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉×𝖯𝖾𝗋𝗆𝖫𝗏𝗅𝖢𝗈𝗆𝗉𝖨𝗇𝗌𝗍𝖺𝗇𝖼𝖾::=𝗂𝖢𝗈𝗆𝗉×𝖢𝗈𝗆𝗉𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍::={𝖢𝗈𝗆𝗉}×optionnat×optionnat×{𝖯𝖾𝗋𝗆𝖨𝖽}×{𝖯𝖾𝗋𝗆}×option𝖯𝖾𝗋𝗆𝖨𝖽State components𝖨𝗇𝗌𝗍𝖠𝗉𝗉𝗌::={𝖠𝗉𝗉𝖨𝖽}𝖵𝖾𝗋𝗂𝖿𝗂𝖾𝖽𝖠𝗉𝗉𝗌::={𝖠𝗉𝗉𝖨𝖽}𝖠𝗉𝗉𝖯𝖲::={𝖠𝗉𝗉𝖨𝖽×𝖯𝖾𝗋𝗆𝖨𝖽}𝖯𝖾𝗋𝗆𝗌𝖦𝗋::={𝖠𝗉𝗉𝖨𝖽×𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉}𝖢𝗈𝗆𝗉𝖨𝗇𝗌𝖱𝗎𝗇::={𝖢𝗈𝗆𝗉𝖨𝗇𝗌𝗍𝖺𝗇𝖼𝖾}𝖣𝖾𝗅𝖯𝖯𝖾𝗋𝗆𝗌::={𝖠𝗉𝗉𝖨𝖽×𝖢𝗈𝗇𝗍𝖯𝗋𝗈𝗏×𝖴𝗋𝗂×𝖮𝗉𝖳𝗒}𝖣𝖾𝗅𝖳𝖯𝖾𝗋𝗆𝗌::={𝗂𝖢𝗈𝗆𝗉×𝖢𝗈𝗇𝗍𝖯𝗋𝗈𝗏×𝖴𝗋𝗂×𝖮𝗉𝖳𝗒}𝖠𝖱𝖵𝖲::={𝖠𝗉𝗉𝖨𝖽×𝖱𝖾𝗌×𝖵𝖺𝗅}𝖨𝗇𝗍𝖾𝗇𝗍𝗌::={𝗂𝖢𝗈𝗆𝗉×𝖨𝗇𝗍𝖾𝗇𝗍}𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍𝗌::={𝖠𝗉𝗉𝖨𝖽×𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍}𝖢𝖾𝗋𝗍𝗌::={𝖠𝗉𝗉𝖨𝖽×𝖢𝖾𝗋𝗍}𝖠𝗉𝗉𝖣𝖾𝖿𝖯𝖲::={𝖠𝗉𝗉𝖨𝖽×𝖯𝖾𝗋𝗆}𝖲𝗒𝗌𝖨𝗆𝖺𝗀𝖾::={𝖲𝗒𝗌𝖨𝗆𝗀𝖠𝗉𝗉}𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳::=𝖨𝗇𝗌𝗍𝖠𝗉𝗉𝗌×𝖵𝖾𝗋𝗂𝖿𝗂𝖾𝖽𝖠𝗉𝗉𝗌×𝖯𝖾𝗋𝗆𝗌𝖦𝗋×𝖠𝗉𝗉𝖯𝖲×𝖢𝗈𝗆𝗉𝖨𝗇𝗌𝖱𝗎𝗇×𝖣𝖾𝗅𝖯𝖯𝖾𝗋𝗆𝗌×𝖣𝖾𝗅𝖳𝖯𝖾𝗋𝗆𝗌×𝖠𝖱𝖵𝖲×𝖨𝗇𝗍𝖾𝗇𝗍𝗌×𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍𝗌×𝖢𝖾𝗋𝗍𝗌×𝖠𝗉𝗉𝖣𝖾𝖿𝖯𝖲×𝖲𝗒𝗌𝖨𝗆𝖺𝗀𝖾\begin{array}[t]{l@{\,}l@{\,\,}l}\textbf{Auxiliary definitions}\\ \mathsf{OpTy}&::=&read\;|\;write\;|\;rw\\ \mathsf{PermLvl}&::=&Dangerous\;|\;Normal\;|\;Signature\;|\;Signature/System\\ \mathsf{Perm}&::=&\mathsf{PermId}\times option~{}\mathsf{PermGroup}\times\mathsf{PermLvl}\\ \mathsf{CompInstance}&::=&\mathsf{iComp}\times\mathsf{Comp}\\ \mathsf{Manifest}&::=&\{\mathsf{Comp}\}\times option~{}nat\times option~{}nat~{}\times\{\mathsf{PermId}\}\times\{\mathsf{Perm}\}\times option~{}\mathsf{PermId}\\ \\ \textbf{State components}\\ \mathsf{InstApps}&::=&\{\mathsf{AppId}\}\\ \mathsf{VerifiedApps}&::=&\{\mathsf{AppId}\}\\ \mathsf{AppPS}&::=&\{\mathsf{AppId}\times\mathsf{PermId}\}\\ \mathsf{PermsGr}&::=&\{\mathsf{AppId}\times\mathsf{PermGroup}\}\\ \mathsf{CompInsRun}&::=&\{\mathsf{CompInstance}\}\\ \mathsf{DelPPerms}&::=&\{\mathsf{AppId}\times\mathsf{ContProv}\times\mathsf{Uri}\times\mathsf{OpTy}\}\\ \mathsf{DelTPerms}&::=&\{\mathsf{iComp}\times\mathsf{ContProv}\times\mathsf{Uri}\times\mathsf{OpTy}\}\\ \mathsf{ARVS}&::=&\{\mathsf{AppId}\times\mathsf{Res}\times\mathsf{Val}\}\\ \mathsf{Intents}&::=&\{\mathsf{iComp}\times\mathsf{Intent}\}\\ \mathsf{Manifests}&::=&\{\mathsf{AppId}\times\mathsf{Manifest}\}\\ \mathsf{Certs}&::=&\{\mathsf{AppId}\times\mathsf{Cert}\}\\ \mathsf{AppDefPS}&::=&\{\mathsf{AppId}\times\mathsf{Perm}\}\\ \mathsf{SysImage}&::=&\{\mathsf{SysImgApp}\}\\[3.01389pt] \mathsf{AndroidST}&::=&\mathsf{InstApps}\times\mathsf{VerifiedApps}\times\mathsf{PermsGr}\times\mathsf{AppPS}\times\mathsf{CompInsRun}\times\mathsf{DelPPerms}~{}\times\\ &&\mathsf{DelTPerms}\ \times\mathsf{ARVS}\times\mathsf{Intents}~{}\times\mathsf{Manifests}\times\mathsf{Certs}\times\mathsf{AppDefPS}\times\mathsf{SysImage}\\ \end{array}

Figure 1: Android state

The type 𝖯𝖾𝗋𝗆𝖨𝖽\mathsf{PermId} represents the set of permissions identifiers; 𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉\mathsf{PermGroup}, the set of permission groups identifiers; 𝖢𝗈𝗆𝗉\mathsf{Comp}, the application components whose code will run on the system; 𝖠𝗉𝗉𝖨𝖽\mathsf{AppId} represents the set of application identifiers; 𝗂𝖢𝗈𝗆𝗉\mathsf{iComp} is the set of identifiers of running instances of application components; 𝖢𝗈𝗇𝗍𝖯𝗋𝗈𝗏\mathsf{ContProv} is a subset of 𝖢𝗈𝗆𝗉\mathsf{Comp}, a special type of component that allows sharing resources among different applications; a member of the type 𝖴𝗋𝗂\mathsf{Uri} is a particular URI (uniform resources identifier); the type 𝖱𝖾𝗌\mathsf{Res} represents the set of resources an application can have (through its contentproviderscontent~{}providers, members of 𝖢𝗈𝗇𝗍𝖯𝗋𝗈𝗏\mathsf{ContProv}); the type 𝖵𝖺𝗅\mathsf{Val} is the set of possible values that can be written on resources; an intent –i.e. a member of type 𝖨𝗇𝗍𝖾𝗇𝗍\mathsf{Intent}– represents the intention of a running component instance to start or communicate with other applications; a member of 𝖲𝗒𝗌𝖨𝗆𝗀𝖠𝗉𝗉\mathsf{SysImgApp} is a special kind of applications which are deployed along with the OS itself and has certain privileges, like being impossible to uninstall.

The first component of the state records the identifiers (𝖠𝗉𝗉𝖨𝖽\mathsf{AppId}) of the applications installed by the user. The second component is a subset of the first one, and represents those applications that are considered to be old but have already been verified, also by the user. The third component keeps track of the permissions granted to every application present in the system, including the ones preinstalled on the system. Similarly, the next component holds the information about what permission groups have already been authorized by the user on each app. The fifth component of the state stores the set of running component instances (𝖢𝗈𝗆𝗉𝖨𝗇𝗌𝗍𝖺𝗇𝖼𝖾\mathsf{CompInstance}), while the components 𝖣𝖾𝗅𝖯𝖯𝖾𝗋𝗆𝗌\mathsf{DelPPerms} and 𝖣𝖾𝗅𝖳𝖯𝖾𝗋𝗆𝗌\mathsf{DelTPerms} store the information concerning permanent and temporary permissions delegations, respectively333A permanent delegated permission represents that an app has delegated permission to perform an operation on the resource identified by an URI. A temporary delegated permission refers to a permission that has been delegated to a component instance.. The eighth and ninth components of the state store respectively the values (𝖵𝖺𝗅\mathsf{Val}) of resources (𝖱𝖾𝗌\mathsf{Res}) of applications and the set of intents (𝖨𝗇𝗍𝖾𝗇𝗍\mathsf{Intent}) sent by running instances of components (𝗂𝖢𝗈𝗆𝗉\mathsf{iComp}) not yet processed. The four last components of the state record information that represents the manifests of the applications installed by the user, the certificates (𝖢𝖾𝗋𝗍\mathsf{Cert}) with which they were signed and the set of permissions they define. The last component of the state stores the set of (native) applications installed in the Android system image, information that is relevant when granting permissions of level Signature/SystemSignature/System.

A manifest (𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍\mathsf{Manifest}) is modelled as a 6-tuple that respectively declare application components (set of components, of type 𝖢𝗈𝗆𝗉\mathsf{Comp}, included in the application); optionally, the minimum version of the Android SDK required to run the application; optionally, the version of the Android SDK targeted on development; the set of permissions it may need to run at its maximum capability; the set of permissions it declares; and the permission required to interact with its components, if any. Application components are all denoted by a component identifier. A content provider (𝖢𝗈𝗇𝗍𝖯𝗋𝗈𝗏\mathsf{ContProv}), in addition, encompasses a mapping to the managed resources from the URIs assigned to them for external access. While the components constitute the static building blocks of an application, all runtime operations are initiated by component instances, which are represented in our model as members of an abstract type.

Valid states

The states defined this way include some cases that are not relevant with the model we are trying to analyze. For example, we don’t want a state were a preinstalled application and one installed by the user have the same identifier. In order to prevent this inconsistencies, we define a notion of valid state that captures several well-formedness conditions. It is formally defined as a predicate valid_state on the elements of type 𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳\mathsf{AndroidST}. This predicate holds on a state ss if the following conditions are met:

  • all the components both in installed applications and in system applications have different identifiers;

  • no component belongs to two different applications present in the device;

  • no running component is an instance of a content provider;

  • every temporally delegated permission has been granted to a currently running component and over a content provider present in the system;

  • every running component belongs to an application present in the system;

  • every application that sets a value for a resource is present in the system;

  • the domains of the partial functions 𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍𝗌\mathsf{Manifests}, 𝖢𝖾𝗋𝗍𝗌\mathsf{Certs} and 𝖠𝗉𝗉𝖣𝖾𝖿𝖯𝖲\mathsf{AppDefPS} are exactly the identifiers of the user installed applications;

  • the domains of the partial functions 𝖠𝗉𝗉𝖯𝖲\mathsf{AppPS} and 𝖯𝖾𝗋𝗆𝗌𝖦𝗋\mathsf{PermsGr} are exactly the identifiers of the applications in the system, both those installed by the users and the system applications;

  • every installed application has an identifier different to those of the system applications, whose identifiers differ as well;

  • all the permissions defined by applications have different identifiers;

  • every partial function is indeed a function, that is, their domains don’t have repeated elements;

  • every individually granted permission is present in the system; and

  • all the sent intents have different identifiers.

All these safety properties have a straightforward interpretation in our model. The full formal definition of the predicate is available in [19].

3.2 Action semantics

We modelled the different functionalities provided by the Android security system as a set of actions (of type 𝖠𝖼𝗍𝗂𝗈𝗇\mathsf{Action}) that determine how the system is able to transition from one state to another. Table 1 summarises the actions specified in our previous model that remained mostly the same since the new features didn’t affect them whereas Table 2 groups those that are new or that suffered a big semantic change.

𝚒𝚗𝚜𝚝𝚊𝚕𝚕appmclRes\mathtt{install}~{}app~{}m~{}c~{}lRes Install application with id appapp, whose manifest is mm, is signed with certificate cc and its resources list is lReslRes.
𝚞𝚗𝚒𝚗𝚜𝚝𝚊𝚕𝚕app\mathtt{uninstall}~{}app Uninstall the application with id appapp.
𝚛𝚎𝚊𝚍iccpu\mathtt{read}~{}ic~{}cp~{}u The running comp. icic reads the resource corresponding to URI uu from content provider cpcp.
𝚠𝚛𝚒𝚝𝚎iccpuval\mathtt{write}~{}ic~{}cp~{}u~{}val The running comp. icic writes value valval on the resource corresponding to URI uu from content provider cpcp.
𝚜𝚝𝚊𝚛𝚝𝙰𝚌𝚝𝚒𝚟𝚒𝚝𝚢iic\mathtt{startActivity}~{}i~{}ic The running comp. icic asks to start an activity specified by the intent ii.
𝚜𝚝𝚊𝚛𝚝𝙰𝚌𝚝𝚒𝚟𝚒𝚝𝚢𝚁𝚎𝚜inic\mathtt{startActivityRes}~{}i~{}n~{}ic The running comp. icic asks to start an activity specified by the intent ii, and expects as return a token nn.
𝚜𝚝𝚊𝚛𝚝𝚂𝚎𝚛𝚟𝚒𝚌𝚎iic\mathtt{startService}~{}i~{}ic The running comp. icic asks to start a service specified by the intent ii.
𝚜𝚎𝚗𝚍𝙱𝚛𝚘𝚊𝚍𝚌𝚊𝚜𝚝iicp\mathtt{sendBroadcast}~{}i~{}ic~{}p The running comp. icic sends the intent ii as broadcast, specifying that only those components who have the permission pp can receive it.
𝚜𝚎𝚗𝚍𝙾𝚛𝚍𝙱𝚛𝚘𝚊𝚍𝚌𝚊𝚜𝚝iicp\mathtt{sendOrdBroadcast}~{}i~{}ic~{}p The running comp. icic sends the intent ii as an ordered broadcast, specifying that only those components who have the permission pp can receive it.
𝚜𝚎𝚗𝚍𝚂𝙱𝚛𝚘𝚊𝚍𝚌𝚊𝚜𝚝iic\mathtt{sendSBroadcast}~{}i~{}ic The running comp. icic sends the intent ii as a sticky broadcast.
𝚛𝚎𝚜𝚘𝚕𝚟𝚎𝙸𝚗𝚝𝚎𝚗𝚝iapp\mathtt{resolveIntent}~{}i~{}app Application appapp makes the intent ii explicit.
𝚜𝚝𝚘𝚙ic\mathtt{stop}~{}ic The running comp. icic finishes its execution.
𝚐𝚛𝚊𝚗𝚝𝙿iccpappupt\mathtt{grantP}~{}ic~{}cp~{}app~{}u~{}pt The running comp. icic delegates permanent permissions to application appapp. This delegation enables appapp to perform operation ptpt on the resource assigned to URI uu from content provider cpcp.
𝚛𝚎𝚟𝚘𝚔𝚎𝙳𝚎𝚕iccpupt\mathtt{revokeDel}~{}ic~{}cp~{}u~{}pt The running comp. icic revokes delegated permissions on URI uu from content provider cpcp to perform operation ptpt.
𝚌𝚊𝚕𝚕icsac\mathtt{call}~{}ic~{}sac The running comp. icic makes the API call sacsac.
Table 1: Legacy actions
𝚐𝚛𝚊𝚗𝚝papp\mathtt{grant}~{}p~{}app Grant the permission pp to the application appapp with user confirmation.
𝚐𝚛𝚊𝚗𝚝𝙰𝚞𝚝𝚘papp\mathtt{grantAuto}~{}p~{}app Grant automatically the permission pp to the application appapp (without user confirmation).
𝚛𝚎𝚟𝚘𝚔𝚎papp\mathtt{revoke}~{}p~{}app Remove an ungrouped permission pp from the application appapp.
𝚛𝚎𝚟𝚘𝚔𝚎𝙿𝚎𝚛𝚖𝙶𝚛𝚘𝚞𝚙gapp\mathtt{revokePermGroup}~{}g~{}app Remove the every permission of group gg from the application appapp.
𝚑𝚊𝚜𝙿𝚎𝚛𝚖𝚒𝚜𝚜𝚒𝚘𝚗papp\mathtt{hasPermission}~{}p~{}app Check if the application appapp has the permission pp.
𝚛𝚎𝚌𝚎𝚒𝚟𝚎𝙸𝚗𝚝𝚎𝚗𝚝iicapp\mathtt{receiveIntent}~{}i~{}ic~{}app Application appapp receives the intent ii, sent by the running comp. icic.
𝚟𝚎𝚛𝚒𝚏𝚢𝙾𝚕𝚍𝙰𝚙𝚙app\mathtt{verifyOldApp}~{}app Application appapp granted permissions are verified by the user
Table 2: New or modified actions

The behaviour of each action is specified in terms of a precondition (Pre:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳𝖠𝖼𝗍𝗂𝗈𝗇PropPre:\mathsf{AndroidST}\rightarrow\mathsf{Action}\rightarrow Prop) and a postcondition (Post:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳𝖠𝖼𝗍𝗂𝗈𝗇𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳PropPost:\mathsf{AndroidST}\rightarrow\mathsf{Action}\rightarrow\mathsf{AndroidST}\rightarrow Prop). For instance, the axiomatic semantics of the new feature about automatic granting of permissions grantAuto is given by:

Pre(s,grantAutopapp)=def(m:𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍,m=getManifestForApp(app,s)getPermissionId(p)(usem))(isSystemPermpusrDefPermp)pgrantedPerms(app,s)permLevel(p)=dangerous(g:𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉,getPermissionGroup(p)=SomegggetAuthorizedGroups(app,s))Post(s,grantAutopapp,s)=defgrantPerm(app,p,s,s)sameOtherFieldsOnGrantAuto(s,s)\begin{array}[]{l}\quad\quad Pre(s,\texttt{grantAuto}\ p\ app)\stackrel{{\scriptstyle{\rm def}}}{{=}}\\ \quad\quad\quad\quad(\exists m:\mathsf{Manifest},\ m=getManifestForApp(app,s)\\ \quad\quad\quad\quad\quad\quad\land\ getPermissionId(p)\in(use\ m))\ \land\\ \quad\quad\quad\quad(isSystemPerm\ p\ \lor usrDefPerm\ p)\ \land\\ \quad\quad\quad\quad p\ \notin grantedPerms(app,s)\ \land\\ \quad\quad\quad\quad permLevel(p)\ =dangerous\ \land\\ \quad\quad\quad\quad(\exists g:\mathsf{PermGroup},\ getPermissionGroup(p)=Some\ g\\ \quad\quad\quad\quad\quad\quad\land\ g\in getAuthorizedGroups(app,s))\\ \quad\quad Post(s,\texttt{grantAuto}\ p\ app,s^{\prime})\stackrel{{\scriptstyle{\rm def}}}{{=}}\\ \quad\quad\quad\quad grantPerm(app,p,s,s^{\prime})\ \land\\ \quad\quad\quad\quad sameOtherFieldsOnGrantAuto(s,s^{\prime})\end{array}

The precondition establishes several conditions that must be fulfilled before this action is able to transition. The first one requires that the permission pp is listed on the application’s manifest (and this manifest, of course, is required to exist). Regarding the permission, it’s also required that its defined either by the user or the system, that its level is dangerousdangerous and that it has not been already granted to appapp. Up to this point, the precondition of grantAutograntAuto is exactly the same than the one of grantgrant. The main difference is established by the following condition: the permission at issue should belong to a group gg and the system should know that the user had previously authorized that group for automatic granting.

The postcondition of grantAutopa\texttt{grantAuto}\ p\ a requires that for an initial state ss and a final state ss^{\prime}, the individual permission pp is granted to application appapp. This condition is enforced by the grantPermapss\texttt{grantPerm}\ a\ p\ s\ s^{\prime} predicate which only alters the state in component that maps applications with their current dangerous permissions. Every other component of the state remains the same.

3.3 Executions

Whenever the system attempts to execute an action aa over a valid state ss, there are two possible outcomes. If the precondition holds, the system will transition to another state ss^{\prime} where the postcondition of aa is established; but if the precondition is not satisfied on ss, then the state remains unchanged and the system answers with an error message determined by the relation ErrorMsgErrorMsg444Given a state ss, an action aa and an error code ecec, 𝐸𝑟𝑟𝑜𝑟𝑀𝑠𝑔(s,a,ec)\mathit{ErrorMsg}(s,a,ec) holds iff errorecerror~{}ec is an acceptable response when the execution of aa is requested on state ss..

Formally, the possible answers of the system are defined by the type

Response=defok|error(ec:ErrorCode)\textit{Response}\stackrel{{\scriptstyle{\rm def}}}{{=}}ok\ |\ error\ (ec:ErrorCode)

and the executions can be specified with this operational semantics:

\inference[]valid_state(s)Pre(s,a)Post(s,a,s)s⸦a/ok→s\inference[]valid_state(s)ErrorMsg(s,a,ec)s⸦a/error(ec)→s\begin{array}[]{c}\inference[]{$$valid\_state(s)$$\hskip 5.69046pt$$Pre(s,a)$$\hskip 5.69046pt$$Post(s,a,s^{\prime})$$}{$$s\mathbin{\lower 1.89444pt\hbox{$\lhook\joinrel\xrightarrow{a/ok}$}}s^{\prime}$$}\hskip 14.22636pt\inference[]{$$valid\_state(s)$$\hskip 5.69046pt$$ErrorMsg(s,a,ec)$$}{$$s\mathbin{\lower 1.89444pt\hbox{$\lhook\joinrel\xrightarrow{a/error(ec)}$}}s$$}\end{array}

One-step execution with error management preserves valid states.

Lemma 1 (Validity is invariant)


(ss:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(a:𝖠𝖼𝗍𝗂𝗈𝗇)(r:Response),s⸦a/r→svalid_state(s)\begin{array}[]{l}\forall\ (s\ s^{\prime}:\mathsf{AndroidST})(a:\mathsf{Action})(r:Response),s\mathbin{\lower 1.89444pt\hbox{$\lhook\joinrel\xrightarrow{a/r}$}}s^{\prime}\rightarrow valid\_state(s^{\prime})\end{array}

The property is proved by case analysis on aa, for each condition in valid_state, using several auxiliary lemmas [19].

System state invariants, such as state validity, are useful to analyze other relevant properties of the model. In particular, the results presented in this work are obtained from valid states of the system.

3.4 Reasoning over the specified model

In this section we present and discuss some properties about the Android 10 security framework. We focus on safety-related properties about the changes introduced on the later versions of Android (mainly Oreo and 10) rather than on security issues. Nevertheless, we also found potentially dangerous behaviours that may not be considered in the informal documentation of the platform and we formally reasoned about them as well. The full formal definition of these properties can be found in [19], along with the corresponding proofs.

On Table 3 we introduce helper functions and predicates used to define the properties that will follow.

Function/Predicate Description
appHasPermission(app,p,s)appHasPermission(app,p,s) holds iff appapp is considered to have permission pp on state ss.
canGrant(cp,u,s)canGrant(cp,u,s) holds iff the content provider cpcp allows the delegation of permissions over the resource at URI uu on state ss.
𝑐𝑎𝑛𝑆𝑡𝑎𝑟𝑡(c,c,s)\mathit{\mathit{canStart}}(c^{\prime},c,s) holds if the app containing component cc^{\prime} (installed in ss) has the required permissions to create a new running instance of cc.
cmpProtectedByPerm(c)cmpProtectedByPerm(c) returns the permission by which the component cc is protected.
componentIsExported(c)componentIsExported(c) holds iff the component cc is exported and can be accessed from other applications.
existsRes(cp,u,s)existsRes(cp,u,s) holds iff the URI uu belongs to the content provider cpcp on ss.
getAppFromCmp(c,s)getAppFromCmp(c,s) given a component cc on ss, returns the app to which it belongs.
getAppRequestedPerms(m)getAppRequestedPerms(m) given the manifest mm of an app, returns the set of permissions it uses.
getDefPermsApp(app,s)getDefPermsApp(app,s) returns the set of permissions defined by appapp on state ss.
getGrantedPermsApp(app,s)getGrantedPermsApp(app,s) returns the set of indvidual permissions granted to appapp on ss.
getAuthorizedGroups(app,s)getAuthorizedGroups(app,s) returns the set of permission groups that have been authorized for automatic granting for appapp on ss.
getInstalledApps(s)getInstalledApps(s) returns the set of identifiers of the applications installed on ss.
getManifestForApp(app,s)getManifestForApp(app,s) returns the manifest of application appapp on state ss.
getPermissionId(p)getPermissionId(p) returns the identifier of permission pp.
getPermissionLevel(p)getPermissionLevel(p) returns the permission level of permission pp.
getPermissionGroup(p)getPermissionGroup(p) returns SomegSome~{}g if the permission pp is grouped or NoneNone if not.
getRunningComponents(s)getRunningComponents(s) returns the set of pairs consisting of a running instance id, and its associated component currently running on state ss.
inApp(c,app,s)inApp(c,app,s) holds iff the component cc belongs to application appapp on state ss.
permissionRequiredRead(c)permissionRequiredRead(c) returns the permission required for reading the component.
permSACs(p,sac)permSACs(p,sac) holds iff permission pp is required for performing the system call sacsac (of type SACallSACall).
oldAppNotVerified(a,s)oldAppNotVerified(a,s) holds iff the application aa is considered old and the user hasn’t verified it in state ss.
Table 3: Helper functions and predicates

The first property that we proved establishes a safety condition about the automatic granting of grouped permissions. It states that the system is not able to transition with this action unless the group of the permission involved is already authorized.

Property 1 (Automatic grant only possible on authorized groups)


(s,s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(p:𝖯𝖾𝗋𝗆)(g:𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉)(app:𝖠𝗉𝗉𝖨𝖽),\forall(s,s^{\prime}:\mathsf{AndroidST})(p:\mathsf{Perm})(g:\mathsf{PermGroup})(app:\mathsf{AppId}),
getPermissionLevel(p)=dangerousgetPermissionGroup(p)=SomegggetAuthorizedGroups(app)¬s⸦grantAutopapp/ok→sgetPermissionLevel(p)=dangerous\land getPermissionGroup(p)=Some\ g\land\\ g\notin getAuthorizedGroups(app)\rightarrow\ \neg s\mathbin{\lower 2.13124pt\hbox{$\lhook\joinrel\xrightarrow{\texttt{grantAuto}~{}p~{}app/ok}$}}s^{\prime}

Android’s permission system ensures that an automatic granting can only occur on permissions that belong to authorized groups.

However, a few questions arise when trying to formally describe the situations in which a group is authorized. The following property formalizes an unclear behaviour: there’s at least one valid state where the system can automatically grant a grouped permission to an app even though that the application has no other permission of the same group granted at that moment. This means that an application can have a group authorized for automatic granting via a permission that no longer exist. This is not necessarily a security flaw. It may be a design principle to avoid asking the user to authorize the same group too many times, but the situation is not clear nor disambiguated in the official documentation.

Property 2 (Auto-granting permission)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(p:𝖯𝖾𝗋𝗆)(g:𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉)(app:𝖠𝗉𝗉𝖨𝖽),\exists(s:\mathsf{AndroidST})(p:\mathsf{Perm})(g:\mathsf{PermGroup})(app:\mathsf{AppId}), valid_state(s)getPermissionLevel(p)=dangerousgetPermissionGroup(p)=Somegvalid\_state(s)\land\\ getPermissionLevel(p)=dangerous~{}\land getPermissionGroup(p)=Some\ g\land\\ ¬((p:𝖯𝖾𝗋𝗆),pgetGrantedPermsApp(app,s)\neg(\exists(p^{\prime}:\mathsf{Perm}),p^{\prime}\in getGrantedPermsApp(app,s)~{}\land
getPermissionGroup(p)=Someg)Pre(s,grantAutopa)getPermissionGroup(p^{\prime})=Some\ g)\land Pre(s,grantAuto~{}p~{}a)\\ \\ System can automatically grant a permission even though there is currently no other permission of that group granted to the app.

The next property formalizes the situation described in Section 2.2 about normal and dangerous permissions sharing a group. Once again, the lack of a strict documentation about the platform can conduce to ambiguous cases or even to accept a dangerous behaviour as this one.

Property 3 (Dangerous permission automatically granted)


(s,s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(a:𝖠𝗉𝗉𝖨𝖽)(m:𝖬𝖺𝗇𝗂𝖿𝖾𝗌𝗍)(c:𝖢𝖾𝗋𝗍)(resources:list𝖱𝖾𝗌)(g:𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉)(pDangpNorm:𝖯𝖾𝗋𝗆),s⸦installamcresources/ok→s\forall(s,s^{\prime}:\mathsf{AndroidST})~{}(a:\mathsf{AppId})~{}(m:\mathsf{Manifest})~{}(c:\mathsf{Cert})~{}(resources:list~{}\mathsf{Res})~{}(g:\mathsf{PermGroup})\\ (pDang~{}pNorm:\mathsf{Perm}),s\mathbin{\lower 2.13124pt\hbox{$\lhook\joinrel\xrightarrow{\texttt{install}~{}a~{}m~{}c~{}resources/ok}$}}s^{\prime}\rightarrow
getPermissionLevel(pDang)=dangerousgetPermissionGroup(pDang)=SomeggetPermissionLevel(pNorm)=normalgetPermissionGroup(pNorm)=Someg{pDang,pNorm}getAppRequestedPerms(m)Pre(s,grantAutopDanga)getPermissionLevel(pDang)=dangerous~{}\rightarrow\\ getPermissionGroup(pDang)=Some\ g\rightarrow\\ getPermissionLevel(pNorm)=normal~{}\rightarrow\\ getPermissionGroup(pNorm)=Some\ g\rightarrow\\ \{pDang,~{}pNorm\}\subseteq getAppRequestedPerms(m)\rightarrow\\ Pre(s^{\prime},grantAuto~{}pDang~{}a)

An application that uses a normal and a dangerous permission of the same group, can obtain the dangerous one automatically after being installed.

Users are able to revoke permissions at runtime. However, the UI does not allow to revoke grouped permissions individually, the complete group should be invalidated. Thus, we proved that whenever a user revokes a permission group from an application, every individual permission that belongs to that group is revoked.

Property 4 (Revoking group revokes grouped individual permissions)


(s,s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(g:𝖯𝖾𝗋𝗆𝖦𝗋𝗈𝗎𝗉)(app:𝖠𝗉𝗉𝖨𝖽),\forall(s,s^{\prime}:\mathsf{AndroidST})~{}(g:\mathsf{PermGroup})~{}(app:\mathsf{AppId}),
valid_state(s)s⸦revokePermGroupgapp/ok→svalid\_state(s)\rightarrow s\mathbin{\lower 2.13124pt\hbox{$\lhook\joinrel\xrightarrow{\texttt{revokePermGroup}~{}g~{}app/ok}$}}s^{\prime}\rightarrow
¬((p:𝖯𝖾𝗋𝗆),pgetGrantedPermsApp(app,s)getPermissionGroup(p)=Someg)\neg(\exists(p:\mathsf{Perm}),p\in getGrantedPermsApp(app,s^{\prime})~{}\land getPermissionGroup(p)=Some\ g)\\ \\ System can automatically grant a permission even though there is currently no other permission of that group granted to the app.

The following property reasons about another change mentioned in Section 2.2. It reasons about a good behaviour about the unverified legacy applications.

Property 5 (Unverified old app cannot receive intents)


(s,s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(i:𝖨𝗇𝗍𝖾𝗇𝗍)(ic:𝗂𝖢𝗈𝗆𝗉)(app:𝖠𝗉𝗉𝖨𝖽),\forall(s,s^{\prime}:\mathsf{AndroidST})~{}(i:\mathsf{Intent})~{}(ic:\mathsf{iComp})~{}(app:\mathsf{AppId}),
valid_state(s)oldAppNotVerified(app,s)valid\_state(s)\rightarrow oldAppNotVerified(app,s)\rightarrow
¬s⸦receiveIntentiicapp/ok→s\neg s\mathbin{\lower 2.13124pt\hbox{$\lhook\joinrel\xrightarrow{\texttt{receiveIntent}~{}i~{}ic~{}app/ok}$}}s^{\prime}

An old application that hasn’t been verified by the user yet cannot receive intents, meaning that it can’t start activities as well.

Finally, we include here a property that holds since version 6 of Android. Any application that wants to send information through the network must have the permission 𝖨𝖭𝖳𝖤𝖱𝖭𝖤𝖳\mathsf{INTERNET}, but since this permission is of level normalnormal, the application just needs to declare it as used in its manifest. This will give access to the network in an implicit and irrevocable way. Once again, this has been criticized due to the potential information leakage it allows. The following property formally generalizes this situation and embodies a reasonable argument to roll back this security issue introduced in Android Marshmallow.

Property 6 (Internet access implicitly and irrevocably allowed)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(sac:SACall)(c:𝖢𝗈𝗆𝗉)(ic:𝗂𝖢𝗈𝗆𝗉)(p:𝖯𝖾𝗋𝗆),valid_state(s)permSAC(p,sac)getPermissionLevel(p)=normalgetPermissionId(p)getAppRequestedPerms(getManifestForApp(getAppFromCmp(c,s),s))(ic,c)getRunningComponents(s)s⸦callicsac/ok→s\forall(s:\mathsf{AndroidST})(sac:SACall)(c:\mathsf{Comp})(ic:\mathsf{iComp})(p:\mathsf{Perm}),\\ valid\_state(s)\rightarrow permSAC(p,sac)\rightarrow\\ getPermissionLevel(p)=normal\rightarrow getPermissionId(p)\in\\ getAppRequestedPerms(getManifestForApp(getAppFromCmp(c,s),s))\rightarrow\\ (ic,c)\in getRunningComponents(s)\rightarrow s\mathbin{\lower 2.13124pt\hbox{$\lhook\joinrel\xrightarrow{\texttt{call}~{}ic~{}sac/ok}$}}s

If the execution of an Android API call only requires permissions of level normalnormal, it is enough for an application to list them as used on its manifest file to be allowed to perform such call.

4 A certified reference validation mechanism

The implementation we developed in our previous model consisted in a set of Coq functions such that for every action in our axiomatic specification there exists a function which stands for it. In this work we kept this approach, updating those functions for which its axiomatic counterpart changed and adding new ones for the new actions verifyOldApp and grantAuto.

Functions that implement actions are basically state transformers. Its definition follows this pattern: first, it is checked whether the precondition of the action is satisfied in state ss, and then, if that is the case, another function is called to achieve a state ss^{\prime} where the postcondition of the action holds. Otherwise, the state ss is returned unchanged along with an appropriate response specifying an error code which describes the failure. More formally, the returned value has type Result=def{resp:Response,st:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳}Result\stackrel{{\scriptstyle{\rm def}}}{{=}}\{resp\ :\ Response,st\ :\ \mathsf{AndroidST}\}. In Figure 2 we present, as an example, the function that implements the execution of the grant action. The Coq code of this function, together with that of the remaining ones, can be found in [19]555We omit here the formal definition of these functions due to space constraints.. The function grant_pregrant\_pre is defined as the nested validation of each of the properties of the precondition, specifying which error to throw when one of them doesn’t hold. In general, every <action>_pre\texttt{<action>}\_pre function is defined this way. The function grant_postgrant\_post implements the expected behaviour of the grantgrant action: the permission perm is prepended to the list666We implement the sets in the model with lists of Coq. of given permissions of the application app and, if that permission is grouped, that grouped is also added to the list of permissions groups authorized by the user on that application.

Definitiongrant_safe(perm,app,s):Result:=matchgrant_pre(perm,app,s)with|Someec{𝑒𝑟𝑟𝑜𝑟(ec),s}|None{ok,grant_post(perm,app,s)}end.\begin{array}[]{l}\textbf{Definition}\ grant\_safe(perm,app,s)\ :Result\ :=\\ \quad\textbf{match}\ grant\_pre(perm,app,s)\ \textbf{with}\\ \quad\hskip 28.45274pt|\ Some\ ec\ \Rightarrow\ \{\mbox{$\mathit{error}(ec)$},s\}\\ \quad\hskip 28.45274pt|\ None\ \Rightarrow\ \{ok,grant\_post(perm,app,s)\}\\ \quad\ \textbf{end}.\\ \end{array}
Figure 2: The function that implements the grant action

Step

All of these functions are grouped into a step function, which basically acts as an action dispatcher777Mechanism to trigger actions, on a state, according to the type of event considered.. Figure 3 show the structure of this function.

Definitionstep(s,a):=matchawith||grantpermappgrant_safe(perm,app,s):Result:=|end.\begin{array}[]{l}\textbf{Definition}\ step(s,a)\ :=\\ \quad\textbf{match}\ a\ \textbf{with}\\ \quad\hskip 28.45274pt|\ \ldots\Rightarrow\ \ldots\\ \quad\hskip 28.45274pt|\ \texttt{grant}\ perm\ app\ \Rightarrow\ grant\_safe(perm,app,s)\ :Result\ :=\\ \quad\hskip 28.45274pt|\ \ldots\Rightarrow\ \ldots\\ \quad\ \textbf{end}.\end{array}
Figure 3: Structure of the step function

Traces

We have modeled the execution of the permission validation mechanism during a session of the system as a function that implements the execution of a list of actions starting in an initial system state. The output of the execution, a trace, is the corresponding sequence of states.

Functiontrace(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(actions:list𝖠𝖼𝗍𝗂𝗈𝗇):list𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳:=matchactionswith|nilnil|action::restlets:=(stepsaction).stins::tracesrestend.\begin{array}[]{l}\textbf{Function}\ trace\ (s:\mathsf{AndroidST})\ (actions:list\ \mathsf{Action})\ :\ list\ \mathsf{AndroidST}\ :=\\ \quad\textbf{match}\ actions\ \textbf{with}\\ \quad\hskip 28.45274pt|\ nil\ \Rightarrow\ nil\\ \quad\hskip 28.45274pt|\ action::rest\ \Rightarrow\ \textbf{let}\ s^{\prime}\ :=\ (step\ s\ action).st\ \textbf{in}\ s^{\prime}::trace\ s^{\prime}\ rest\\ \quad\textbf{end.}\end{array}

4.1 Correctness of the implementation

We proceed now to outline the proof that our functional implementation of the security mechanisms of Android correctly implements the axiomatic model. This property has been formally stated as the following correctness theorem which in turn was verified using Coq [19].

Theorem 4.1 (Correctness of the reference validation mechanism)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(a:𝖠𝖼𝗍𝗂𝗈𝗇),𝑣𝑎𝑙𝑖𝑑_𝑠𝑡𝑎𝑡𝑒(s)s⸦a/step(s,a).resp→𝑠𝑡𝑒𝑝(s,a).st\begin{array}[t]{l}\forall\ (s:\mathsf{AndroidST})\ (a:\mathsf{Action}),\mbox{$\mathit{valid\_state}(s)$}\rightarrow\ s\mathbin{\lower 1.89444pt\hbox{$\lhook\joinrel\xrightarrow{a/step(s,a).resp}$}}\mbox{$\mathit{step}(s,a)$}.st\\ \end{array}

The proof of this theorem starts by performing a case analysis on the (decidable) predicate Pre(s,a)Pre(s,a). Then, in case that the predicate holds, we apply Lemma 2; otherwise we continue by applying Lemma 3.

Lemma 2 (Correctness of valid execution)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(a:𝖠𝖼𝗍𝗂𝗈𝗇),𝑣𝑎𝑙𝑖𝑑_𝑠𝑡𝑎𝑡𝑒(s)Pre(s,a)s⸦a/ok→𝑠𝑡𝑒𝑝(s,a).st𝑠𝑡𝑒𝑝(s,a).resp=ok\begin{array}[t]{l}\forall\ (s:\mathsf{AndroidST})\ (a:\mathsf{Action}),\mbox{$\mathit{valid\_state}(s)$}\rightarrow\ Pre(s,a)\ \rightarrow\\ s\mathbin{\lower 1.89444pt\hbox{$\lhook\joinrel\xrightarrow{a/ok}$}}\mbox{$\mathit{step}(s,a)$}.st\ \wedge\ \mbox{$\mathit{step}(s,a)$}.resp=ok\\ \end{array}

Lemma 3 (Correctness of error execution)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(a:𝖠𝖼𝗍𝗂𝗈𝗇),𝑣𝑎𝑙𝑖𝑑_𝑠𝑡𝑎𝑡𝑒(s)¬Pre(s,a)(ec:ErrorCode),𝑠𝑡𝑒𝑝(s,a).st=s𝑠𝑡𝑒𝑝(s,a).resp=error(ec)ErrorMsg(s,a,ec)\begin{array}[t]{l}\forall\ (s:\mathsf{AndroidST})\ (a:\mathsf{Action}),\mbox{$\mathit{valid\_state}(s)$}\rightarrow\ \neg Pre(s,a)\rightarrow\ \exists\ (ec:ErrorCode),\\ \mbox{$\mathit{step}(s,a)$}.st=s\wedge\mbox{$\mathit{step}(s,a)$}.resp=error(ec)\wedge ErrorMsg(s,a,ec)\\ \end{array}

The proof of this lemmas proceeds by applying functional induction on 𝑠𝑡𝑒𝑝(s,a)\mathit{step}(s,a). Then, in Lemma 2, the proof continues by applying the corresponding subproof of soundness of the function that implements each action; whereas in Lemma 3, a subproof about the existence of a proper error code is provided.

4.2 Reasoning over the certified reference validation mechanism

In this section we present several security properties we have stated and proved about the function tracetrace defined in Section 4.

The first property states that in Android 10, if an application that is considered to be old (as we defined in Section 2.2) is able to run, then it has been verified and validated by the user previously.

Property 7 (Old applications must be verified)


(initState,lastState:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(app:AppId)(l:list𝖠𝖼𝗍𝗂𝗈𝗇)\forall(initState,lastState:\mathsf{AndroidST})(app:AppId)(l:list\ \mathsf{Action}),
valid_state(initState)appgetInstalledApps(initState)oldAppNotVerified(a,initState)canRun(a,lastState)last(trace(initState,l),initState)=lastStateuninstallapplverifyOldAppapplvalid\_state(initState)\rightarrow app\in getInstalledApps(initState)\rightarrow\\ oldAppNotVerified(a,initState)\rightarrow canRun(a,lastState)\rightarrow\\ last(trace(initState,l),initState)=lastState\rightarrow\\ \texttt{uninstall}~{}app\notin l\rightarrow\texttt{verifyOldApp}~{}app\in l

The only way for an old application to be able to execute is if the user verified it.

The next property establishes that for an application to have any dangerous permission (grouped or ungrouped) it must be explicitly granted to it, either by the user or automatically by the system.

Property 8 (Dangerous permissions must be explicitly granted)


(initState,lastState:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(app:AppId)(p:𝖯𝖾𝗋𝗆)(l:list𝖠𝖼𝗍𝗂𝗈𝗇)\forall(initState,lastState:\mathsf{AndroidST})(app:AppId)(p:\mathsf{Perm})(l:list\ \mathsf{Action}),
valid_state(initState)appgetInstalledApps(initState)valid\_state(initState)\rightarrow app\in getInstalledApps(initState)\rightarrow
getPermissionLevel(p)=dangerouspermissionIsGrouped(p)=NonegetPermissionLevel(p)=dangerous\rightarrow permissionIsGrouped(p)=None\rightarrow
appHasPermission(app,p,lastState)appHasPermission(app,p,lastState)\rightarrow
¬appHasPermission(app,p,initState)uninstallappl\neg appHasPermission(app,p,initState)\rightarrow\texttt{uninstall}~{}app\notin l\rightarrow
last(trace(initState,l),initState)=lastState(grantpappllast(trace(initState,l),initState)=lastState\rightarrow(\texttt{grant}~{}p~{}app\in l~{}\lor~{}
grantAutopappl)\texttt{grantAuto}~{}p~{}app\in l)

The only way for an application to get a permission is if the user authorized it, or if the user authorized a group and the system is able to automatically grant it.

The following property formally states that if an application used to have a permission that was later revoked, only re-granting it will allow the application to have it again.

Property 9 (Revoked permissions must be regranted)


(initState,sndState,lastState:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(app:𝖠𝗉𝗉𝖨𝖽)(p:𝖯𝖾𝗋𝗆)(l:list𝖠𝖼𝗍𝗂𝗈𝗇)\forall(initState,sndState,lastState:\mathsf{AndroidST})(app:\mathsf{AppId})(p:\mathsf{Perm})(l:list~{}\mathsf{Action}),
valid_state(initState)getPermissionLevel(p)=dangerousvalid\_state(initState)\rightarrow getPermissionLevel(p)=dangerous\rightarrow
pgetDefPermsForApp(app,initState)p\notin getDefPermsForApp(app,initState)\rightarrow
step(initState,revokepapp).st=sndStatestep(initState,\texttt{revoke}~{}p~{}app).st=sndState\rightarrow
step(initState,revokepapp)).resp=okuninstallapplgrantpapplgrantAutopapplstep(initState,\texttt{revoke}~{}p~{}app)).resp=ok\rightarrow\\ \texttt{uninstall}~{}app\notin l\rightarrow\texttt{grant}~{}p~{}app\notin l\rightarrow\texttt{grantAuto}~{}p~{}app\notin l\rightarrow
last(trace(sndState,l),sndState)=lastStatelast(trace(sndState,l),sndState)=lastState\rightarrow
¬appHasPermission(app,p,lastState)\neg appHasPermission(app,p,lastState)

If a permission is revoked from an application, only regranting it will allow the application to have it again.

Whenever an application appapp receives a READ/WRITE permission permperm, it also receives the right to delegate this permission to another application, say appapp^{\prime}, to access that same resource on its behalf. However, if permperm is later revoked from application appapp, there’s a chance that appapp^{\prime} still has access to that resource, since delegated permissions are not recursively revoked. The following property formalizes this situation and is a proof that the current specification allows a behavior which is arguably against the user’s will.

Property 10 (Delegated permissions are not recursively revoked)


(s:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(p:𝖯𝖾𝗋𝗆)(app,app:𝖠𝗉𝗉𝖨𝖽)(ic,ic:𝗂𝖢𝗈𝗆𝗉)(c,c:𝖢𝗈𝗆𝗉)(u:𝖴𝗋𝗂)(cp:CProvider),\forall(s:\mathsf{AndroidST})(p:\mathsf{Perm})(app,app^{\prime}:\mathsf{AppId})(ic,ic^{\prime}:\mathsf{iComp})(c,c^{\prime}:\mathsf{Comp})(u:\mathsf{Uri})(cp:CProvider),
valid_state(s)step(s,grantpapp).resp=okvalid\_state(s)\rightarrow step(s,\texttt{grant}~{}p~{}app).resp=ok\rightarrow
getAppFromCmp(c,s)=appgetAppFromCmp(c,s)=appgetAppFromCmp(c,s)=app\rightarrow getAppFromCmp(c^{\prime},s)=app^{\prime}\rightarrow
(ic,c)getRunningComponents(s)(ic,c)getRunningComponents(s)(ic,c)\in getRunningComponents(s)\rightarrow(ic^{\prime},c^{\prime})\in getRunningComponents(s)\rightarrow
canGrant(cp,u,s)existsRes(cp,u,s)componentIsExported(cp)canGrant(cp,u,s)\rightarrow existsRes(cp,u,s)\rightarrow componentIsExported(cp)\rightarrow
permissionRequiredRead(cp)=SomeppermissionRequiredRead(cp)=Some~{}p\rightarrow
𝗅𝖾𝗍opsResult:=trace(s,[grantpapp,grantPiccpappuRead\mathsf{let}~{}opsResult:=trace(s,\texttt{[}\texttt{grant}~{}p~{}app,\texttt{grantP}~{}ic~{}cp~{}app^{\prime}~{}u~{}Read,
revokepapp]𝗂𝗇\texttt{revoke}~{}p~{}app\texttt{]}~{}\mathsf{in} step(last(opsResult,s),readiccpu).resp=okstep(last(opsResult,s),\texttt{read}~{}ic^{\prime}~{}cp~{}u).resp=ok

In Android 6 if a permission pp is revoked for an application appapp not necessarily shall it be revoked for the applications to which appapp delegated pp.

The purpose of this last property is to show that with runtime permissions introduced after Android 6, certain assertions on which a developer could rely in previous versions do not hold. For example, a running component may have the right of starting another one on a certain state, but may not be able to do so at a later time, even though no involved application was uninstalled. The property still holds on the latest version of Android.

Property 11 (The right to start an external component is revocable)


(initState:𝖠𝗇𝖽𝗋𝗈𝗂𝖽𝖲𝖳)(l:list𝖠𝖼𝗍𝗂𝗈𝗇)(app,app:𝖠𝗉𝗉𝖨𝖽)(c:𝖢𝗈𝗆𝗉)(act:𝖠𝖼𝗍𝗂𝗏𝗂𝗍𝗒)(p:𝖯𝖾𝗋𝗆)\forall(initState:\mathsf{AndroidST})(l:list\mathsf{Action})(app,app^{\prime}:\mathsf{AppId})(c:\mathsf{Comp})(act:\mathsf{Activity})(p:\mathsf{Perm}),
valid_state(initState)getPermissionLevel(p)=dangerousvalid\_state(initState)\rightarrow\\ getPermissionLevel(p)=dangerous\rightarrow permissionIsGrouped(p)=NoneappapppermissionIsGrouped(p)=None\rightarrow\\ app\neq app^{\prime}\rightarrow pgetDefPermsApp(app,initState)inApp(c,app,initState)p\notin getDefPermsApp(app,initState)\rightarrow inApp(c,app,initState)\rightarrow
inApp(act,app,initState)cmpProtectedByPerm(act)=SomepinApp(act,app^{\prime},initState)\rightarrow cmpProtectedByPerm(act)=Some~{}p\rightarrow
canStart(c,act,initState)(l:list𝖠𝖼𝗍𝗂𝗈𝗇),uninstallapplcanStart(c,act,initState)\rightarrow\exists(l:list\ \mathsf{Action}),\texttt{uninstall}~{}app\notin l\ \land
uninstallappl¬canStart(c,act,last(trace(initState,l),initState))\texttt{uninstall}~{}app^{\prime}\notin l\land\neg canStart(c,act,last(trace(initState,l),initState))

A running component may have the right of starting another one on a certain state, but may not be able to do so at a later time.

5 Related work

Several analyses have been carried out concerning the security of the Android permission system. Plenty of them [11, 29, 13, 28, 22, 5] implement a static analysis tool that is capable of detecting overprivileges and unwanted information flow on a set of applications. This pragmatic approach may be helpful for Android users to keep their private information secure, but no properties about the system can be established. Recently, Mayrhofer et al. [21] described the Android security platform and documented the complex threat model and ecosystem it needs to operate, but no formal analysis was performed in it.

Few works study the aspects of the permission enforcing framework in a formal way. In particular, Shin et al. [24, 25] developed using Coq a framework that represents the Android permission system, similarly to what we did. Although, that work does not consider the different types of components, the interaction between a running instance and the system, the R/W operation on a content provider, the semantics of the permission delegation mechanism. Also, their work is based on an older version of the platform and some novel aspects, like the management of runtime permissions or the verification of legacy applications, are not included. Similarly, Bagheri et al. [6] formalized Android permission protocol using Alloy [15]. The analyses performed, however, was based on the ability to automatically find counterexamples provided by the Alloy framework, which the authors claim to be tremendously helpful for identifying vulnerabilities. A Coq-based approach like ours, requires more human effort to identify a flaw but provides stronger guarantees on security and safety properties. Another formal work on Android is CrashSafe [16], where the authors formalized in Coq the inter-component communication mechanism and proved its safety with regard to failures (or crashes). This work, similarly to ours, focus on safety properties rather than security ones.

On the other hand, many works have addressed the problem of relating inductively defined relations and executable functions. In particular, Tollitte et al. [27] show how to extract a functional implementation from an inductive specification in Coq, and [9] exhibits a similar approach for Isabelle. Earlier, alternative approaches such as [7, 8] aim to provide reasoning principles for executable specifications. In [12], the verification of properties of imperative programs is performed using techniques based on the specialization of constrained logic programs. In this work we are able to develop independently the specification of the reference monitor and the implementation of the validation mechanism, considering that Coq provides a reasoning framework based on higher order logic to perform proofs of specifications and programs and a functional programming language. Other approaches could be considered to develop the formalization. For instance, a logical approach like the one used in [12]. However, a logical approach does not allow us to have the same functionalities in a unified formal environment.

Specifically, in this work we present a model of a reference monitor and demonstrate properties which shall hold for every correct implementation of the model. Then, we have developed a functional implementation in Coq of the reference validation mechanism and proved its correctness with respect to the specified reference monitor. Applying the program extraction mechanism provided by Coq we have also derived a certified Haskell prototype of the reference validation mechanism, which can be used to conduct verification activities on actual real implementations of the platform. The results presented in this paper extend the ones reported in [10, 20]. We have enriched the model presented in [10, 20] so as to consider the changes introduced in Android permission system by version Nougat, Oreo, Pie and 10.

6 Final remarks

We have enhanced the formal specification considered in our previous work [10] with the new features concerning the permission system that have been added during the later releases of Android. With a conservative approach, we first analyzed the validity of the already formulated properties and then established new ones about the novel changes; summing up a total of 14 valid properties, without including the auxiliary lemmas that have been separated just for modularization. Among these properties we included several that aim to highlight how formal methods help to disambiguate unclear behaviours that may be inferred from an informal specification. For instance, we found a potentially dangerous situation in which an application can gain access to every dangerous permission that shares group with a normal one, without explicit consent of the user (see Property 3). This scenario fits the model (informally) described in the official documentation of the platform.

We also enriched our previous functional implementation of the reference validation mechanism with these new characteristics and updated its correctness proof. As consequence, the derived Haskell prototype obtained using the program extraction mechanism provided by the proof assistant, has been updated as well. The full certified code is available in [19].

One important goal of our work is to keep our formalization up to date with the later versions of Android in order to constitute a reliable framework for reasoning about its permission system. We aim to help to increase the confidence on Android’s security mechanisms by providing certified guarantees about the enforcement of this measures. The use of idealized models and certified prototypes is a good step forward but no doubt the definitive step is to be able to provide similar guarantees concerning actual implementations of the platform. The formal development is about 23k LOC of Coq, including proofs.

On September 8th 2020, Android 11 was released. This update includes features that continue increasing the security of the device, such as auto-resetting permissions from unused applications or one-time permissions for the most sensitive resources, like the microphone or camera. A one time permission is basically a permission as we described in Section 2 but it only holds for a short period of time, determined by the behaviour of the app and the user. In future work, we intend to add this features to our model.

References

  • [1] J. P. Anderson. Computer Security technology planning study. Technical report, Deputy for Command and Management System, USA, 1972.
  • [2] Android Developers. Application Fundamentals. Available at: http://developer.android.com/guide/components/fundamentals.html. Last access: Oct. 2020.
  • [3] Android Developers. Permissions. Available at: http://developer.android.com/guide/topics/security/permissions.html. Last access: Oct. 2020.
  • [4] Android Developers. Protection levels. Available at: https://developer.android.com/guide/topics/permissions/. Last access: Oct. 2020.
  • [5] H. Bagheri, A. Sadeghi, J. Garcia, and S. Malek. Covert: Compositional analysis of android inter-app permission leakage. IEEE Transactions on Software Engineering, 41(9):866–886, Sep. 2015.
  • [6] Hamid Bagheri, Eunsuk Kang, Sam Malek, and Daniel Jackson. A formal approach for detection of security flaws in the android permission system. Formal Aspects of Computing, 30, 11 2017.
  • [7] A. Balaa and Y. Bertot. Fix-point equations for well-founded recursion in type theory. In M. Aagaard and J. Harrison, editors, TPHOLs, volume 1869 of LNCS, pages 1–16. Springer, 2000.
  • [8] G. Barthe, J. Forest, D. Pichardie, and V. Rusu. Defining and reasoning about recursive functions: A practical tool for the coq proof assistant. In M. Hagiya and P. Wadler, editors, FLOPS, volume 3945 of LNCS, pages 114–129. Springer, 2006.
  • [9] Stefan Berghofer, Lukas Bulwahn, and Florian Haftmann. Turning inductive into equational specifications. In S. Berghofer, T. Nipkow, C. Urban, and M. Wenzel, editors, TPHOLs, volume 5674 of LNCS, pages 131–146. Springer, 2009.
  • [10] Gustavo Betarte, Juan Campo, Felipe Gorostiaga, and Carlos Luna. A Certified Reference Validation Mechanism for the Permission Model of Android: 27th International Symposium, LOPSTR 2017, Namur, Belgium, October 10-12, 2017, Revised Selected Papers. 07 2018.
  • [11] P. Chester, C. Jones, M. Wiem Mkaouer, and D. E. Krutz. M-perm: A lightweight detector for android permission gaps. In 2017 IEEE/ACM 4th International Conference on Mobile Software Engineering and Systems (MOBILESoft), pages 217–218, May 2017.
  • [12] E. De Angelis, F. Fioravanti, A. Pettorossi, and M. Proietti. Program verification via iterated specialization. Sci. Comput. Program., 95:149–175, 2014.
  • [13] Michael Gordon, Kim deokhwan, Jeff Perkins, Limei Gilham, Nguyen Nguyen, and Martin Rinard. Information-flow analysis of android applications in droidsafe. 01 2015.
  • [14] International Data Corporation (IDC). Smartphone market share. Technical report, International Data Corporation (IDC), 2020.
  • [15] Daniel Jackson. Software Abstractions: Logic, Language, and Analysis. The MIT Press, 2012.
  • [16] Wilayat Khan, Habib Ullah, Aakash Ahmad, Khalid Sultan, Abdullah Alzahrani, Sultan Khan, Mohammad Alhumaid, and Sultan Abdulaziz. Crashsafe: a formal model for proving crash-safety of android applications. Human-centric Computing and Information Sciences, 8, 12 2018.
  • [17] P. Letouzey. Programmation fonctionnelle certifiée – L’extraction de programmes dans l’assistant Coq. PhD thesis, Université Paris-Sud, July 2004.
  • [18] Pierre Letouzey. A New Extraction for Coq. In Proceedings of TYPES’02, volume 2646 of LNCS, 2003.
  • [19] Guido De Luca and Carlos Luna. Formal verification of the security model of Android 10: Coq code. Available at: https://www.fing.edu.uy/~cluna/Android10-Coq.zip. Last access: Oct. 2020.
  • [20] Carlos Luna, Gustavo Betarte, Juan Diego Campo, Camila Sanz, Maximiliano Cristiá, and Felipe Gorostiaga. A formal approach for the verification of the permission-based security model of android. CLEI Electron. J., 21(2), 2018.
  • [21] René Mayrhofer, Jeffrey Vander Stoep, Chad Brubaker, and Nick Kralevich. The android platform security model. CoRR, abs/1904.05572, 2019.
  • [22] Damien Octeau, Daniel Luchaup, Matthew Dering, Somesh Jha, and Patrick McDaniel. Composite constant propagation: Application to android inter-component communication analysis. In Proceedings of the 37th International Conference on Software Engineering - Volume 1, ICSE ’15, pages 77–88, Piscataway, NJ, USA, 2015. IEEE Press.
  • [23] Open Handset Alliance. Android project. Available at: //source.android.com/. Last access: Oct. 2020.
  • [24] W. Shin, S. Kiyomoto, K. Fukushima, and T. Tanaka. A formal model to analyze the permission authorization and enforcement in the android framework. In SocialCom’10, pages 944–951, Washington, DC, USA, 2010. IEEE Computer Society.
  • [25] W. Shin, S. Kiyomoto, K. Fukushima, and T. Tanaka. A frst step towards automated permission-enforcement analysis of the android framework. In SAM 2010, pages 323–329. CSREA Press, 2010.
  • [26] The Coq Team. The Coq Proof Assistant Reference Manual – Version V8.12.0, 2020.
  • [27] P.-N. Tollitte, D. Delahaye, and C. Dubois. Producing certified functional code from inductive specifications. In Chris Hawblitzel and Dale Miller, editors, CPP, volume 7679 of LNCS, pages 76–91. Springer, 2012.
  • [28] Fengguo Wei, Sankardas Roy, Xinming Ou, and Robby. Amandroid: A precise and general inter-component data flow analysis framework for security vetting of android apps. ACM Transactions on Privacy and Security, 21:1–32, 04 2018.
  • [29] S. Wu and J. Liu. Overprivileged permission detection for android applications. In ICC 2019 - 2019 IEEE International Conference on Communications (ICC), pages 1–6, May 2019.