Ubuntu logo

Developer

Security policy for click packages

AppArmor Policy for Click packages v1.0

Introduction

Application Confinement defines the implementation for confining applications in Ubuntu. This page gets into the specifics of the permissions policy which should be helpful for both Ubuntu system and app developers.

AppArmor policy for click packages is essentially based on templates and policy groups. The developer specifies the template to use based on the type of application being developed, and then specifies any additional accesses via policy groups. Templates are organized by vendor (eg, ubuntu) and version (eg, 1.0).

Trust Model

Part of understanding the application confinement permissions is knowing about the the trust model. Ubuntu’s trust model is in essence:

  • Untrusted by the OS: AppStore apps run in a restricted sandbox as defined in Application Confinement. Reviews of apps can be shallow, but as a result AppStore apps are considered untrusted. Untrusted applications:
    • can freely access their own data
    • cannot access other applications’ data
    • cannot access user data
    • cannot access privileged portions of the OS
    • cannot access privileged APIs, such as Telephony
    • may access sensitive APIs with user permission, such as Location or Online Accounts.
    • are not typically supported by Ubuntu or Canonical
  • Trusted by the OS: software installed as part of the base OS or part of the Ubuntu archive are considered trusted by the OS. These applications typically do not run under confinement. User applications trusted by the OS:
    • can typically access any resources or data available within the user’s session
    • have limited access to system services and data as defined by the OS (ie, traditional filesystem permissions, PolicyKit, etc)
    • are supported by Ubuntu and/or Canonical and may receive security and high impact bug fixes based on the software’s support status.

Importantly, permission to access sensitive data by AppStore apps is typically granted or denied at the time of access (caching the result for later use as appropriate), so users have a context for the access being requested. This provides better usability and less confusion overall.

Policy templates

The supported templates can be found by using the aa-easyprof command:

$ aa-easyprof --policy-vendor=ubuntu --policy-version=1.0 --list-templates
default
ubuntu-sdk
ubuntu-webapp
unconfined

You can see the contents of a template with:

$ aa-easyprof --policy-vendor=ubuntu --policy-version=1.0 --show-template --template=ubuntu-sdk
#
# Example usage for an ubuntu-sdk app 'appname'
# $ aa-easyprof --template=ubuntu-sdk \
#               --profile-name=com.example.appname \
#               -p networking \
#               --template-var="@{APP_PKGNAME}=appname" \
#               --template-var="@{APP_VERSION}=0.1" \
#               "/usr/share/appname/**"
#
###ENDUSAGE###
# vim:syntax=apparmor

#include <tunables/global>
...

Usage

  • ubuntu-sdk: this is the default template if unspecified. This template is appropriate for Ubuntu SDK native, HTML5 and PhoneGap (Cordova) apps. default is a symlink to ubuntu-sdk
  • ubuntu-webapp: a specialized template for use by the Ubuntu Webapps platform
  • unconfined: provides no restrictions on the app. This template is reserved for applications that are explicitly trusted and should not be used by developers.

Various behaviors and APIs are automatically allowed in the Ubuntu templates:

  • Normal operation within the Unity shell
  • Use of QML app Toolbars
  • Communicating with the on screen keyboard (OSK)
  • Use of the accessbility bus
  • Use of the URL dispatcher
    • QML: Qt.openUrlExternally()
    • Note: underlying libraries must be present for Qt.openUrlExternally() to work with the URL Dispatcher, otherwise access will be denied.
  • HUD
    • QML: qtdeclarative5-hud1.0
    • import Ubuntu.Unity.Action 1.0 as UnityActions
  • LocalStorage
    • QML: qtdeclarative5-localstorage-plugin
    • import QtQuick.LocalStorage 2.0
  • U1db
    • QML: qtdeclarative5-u1db1.0
    • import U1db 1.0
    • Note: needs ‘networking’ policy group
  • Webview
    • QML: libqt5webkit5-qmlwebkitplugin
    • import QtWebKit 3.0
    • Note: developers should use Oxide in future versions of the SDK
  • Read access to the install directory and all its files and subdirectories
  • Write access based on the XDG basedir specification (see below)

Policy groups

The supported policy groups can be seen with:

$ aa-easyprof --policy-vendor=ubuntu --policy-version=1.0 --list-policy-groups
accounts
audio
calendar
camera
connectivity
contacts
content_exchange
content_exchange_source
friends
history
location
microphone
music_files
music_files_read
networking
picture_files
picture_files_read
sensors
usermetrics
video
video_files
video_files_read

You can see the contents of policy groups by running this command (on a Ubuntu 13.10 system):

$ aa-easyprof --policy-vendor=ubuntu --policy-version=1.0 --show-policy-group --policy-groups=audio,networking
# Description: Can play audio
# Usage: common
...
# Description: Can access the network
# Usage: common

Policy groups fall into different usage categories

  • common: policy groups available for use by any app
  • reserved: policy groups available for specialized applications. Use of these will result in the application being redflagged

Other categories may be added in a future version of the policy.

Usage

Policy groups have been tested to work with QML APIs, but apps may use any API that complies with the defined policy. APIs listed should not be considered exhaustive.

Common

  • audio: Can play audio
    • QML: qtdeclarative5-qtmultimedia-plugin
    • import QtMultimedia 5.0
    • Other APIs: anything that uses pulseaudio, like gstreamer. Direct access to hardware is not allowed
  • camera: Can access the camera(s)
    • QML: qtdeclarative5-qtmultimedia-plugin
    • import QtMultimedia 5.0
  • connectivity: Can access coarse network connectivity information
    • QML: qtdeclarative5-systeminfo-plugin
    • import QtSystemInfo 5.0
    • Other APIs: Qt5 QHostAddress and QNetworkInterface
  • content_exchange: Can request/import data from other applications
    • QML: qtdeclarative5-ubuntu-content0.1
    • import Ubuntu.Content 0.1
  • content_exchange_source: Can provide/export data to other applications
    • QML: qtdeclarative5-ubuntu-content0.1
    • import Ubuntu.Content 0.1
  • location: Can access Location
    • QML: qtdeclarative5-qtlocation-plugin
    • import QtLocation 5.0
  • microphone: Can access the microphone
    • QML: no QML for audio-only recording in Qt5
    • Qt5 QAudioRecorder
    • Other APIs: anything that uses pulseaudio, like gstreamer. Direct access to hardware is not allowed
  • networking: Can access the network
    • QML: QtWebKit (QtOxide in 14.04) or anything that can fetch web content, like qtdeclarative5-xmllistmodel-plugin
    • Note: also provides access to the Ubuntu Download Service
  • sensors: Can access the sensors
    • QML: qtdeclarative5-qtsensors-plugin (uses qtubuntu-sensors)
    • import QtSensors 5.0
    • Note: policy pending due to LP: #1227116
  • usermetrics: Can use UserMetrics to update the InfoGraphic
    • QML: qtdeclarative5-usermetrics0.1
    • import UserMetrics 0.1
  • video: Can play video
    • QML: qtdeclarative5-qtmultimedia-plugin
    • import QtMultimedia 5.0

Reserved

As noted, use of these is reserved for specialized apps only. They are listed here for completeness.

  • accounts: Can use Online Accounts
    • QML: qtdeclarative5-accounts-plugin
    • import Ubuntu.OnlineAccounts 0.1
    • Note: Not permitted by untrusted apps. Will move to common once LP: #1230091 is implemented
  • calendar: Can access the user’s calendar(s)
    • QML: qtdeclarative5-qtorganizer-plugin (uses qtorganizer5-eds)
    • import QtOrganizer 5.0 and use manager: "eds"
    • Note: Not permitted by untrusted apps. Will move to common once LP: #1227824 is implemented
  • contacts: Can access the user’s contacts
    • QML: qtdeclarative5-ubuntu-contacts0.1
    • import Ubuntu.Contacts 0.1
    • Note: Not permitted by untrusted apps. Will move to common once LP: #1227821 is implemented
  • friends: Can use Friends social network service
    • QML: qtdeclarative5-friends-plugin/qtdeclarative5-friends0.2
    • import Friends 0.2 (also needs accounts policy group (see above)
    • Note: Not permitted by untrusted apps. Will move to common once LP: #1231737 is implemented
  • history: Can access the history-service (SMS and call logs)
    • QML: qtdeclarative5-ubuntu-history0.1
    • import Ubuntu.History 0.1
    • Note: Not permitted by untrusted apps.
  • music_files: Can read and write to music files
    • Note: Developers should typically use the content_exchange policy group and API to access music files instead
  • music_files_read: Can read all music files
    • Note: Developers should typically use the content_exchange policy group and API to access music files instead
  • picture_files: Can read and write to picture files
    • Note: Developers should typically use the content_exchange policy group and API to access picture files instead
  • picture_files_read: Can read all picture files
    • Note: Developers should typically use the content_exchange policy group and API to access picture files instead
  • video_files: Can read and write to video files
    • Note: Developers should typically use the content_exchange policy group and API to access video files instead
  • video_files_read: Can read all video files
    • Note: Developers should typically use the content_exchange policy group and API to access video files instead

Removed

Previous iterations of the v1.0 policy defined the following policy groups:

  • bluetooth: Can access bluetooth devices
    • QML: qtdeclarative5-qtbluetooth-plugin (unusable with Qt5 on Ubuntu 13.10)
  • nfc: Can access NFC (Near Field Communications) device
    • QML: qtdeclarative5-qtnfc-plugin (unusable with Qt5 on Ubuntu 13.10)

These may be added in a later version of the policy.

Runtime Environment

ApplicationConfinement defines the application environment fully, but the following provides what developers should need.

The following environment variables are set:

  • UBUNTU_APPLICATION_ISOLATION=1: convenience variable
  • APP_ID: the application ID as used by the system. Provided for convenience
  • XDG_CACHE_HOME: set to $HOME/.cache
  • XDG_CONFIG_HOME: set to $HOME/.config
  • XDG_DATA_HOME: set to $HOME/.local/share
  • XDG_RUNTIME_DIR: set to /run/user/$UID
  • TMPDIR: set to application specific path under XDG_RUNTIME_DIR. Note: standard libraries should all honor TMPDIR
  • PWD: a chdir() to the installation directory is performed prior to launching the app

The application will have read/write access files in the standard XDG base directories. Specifically:

  • XDG_CACHE_HOME/<APP_PKGNAME>
  • XDG_CONFIG_HOME/<APP_PKGNAME>
  • XDG_DATA_HOME/<APP_PKGNAME>
  • XDG_RUNTIME_DIR/confined/<APP_PKGNAME>

where <APP_PKGNAME> is what is used in the “name” field of the click manifest. Eg, if the click manifest has this:

$ cat ./manifest.json
{
  "name": "com.ubuntu.developer.you.yourapp",
  ...
}

then the app will have read/write access to these directories and any files or subdirectories under them:

  • XDG_CACHE_HOME/com.ubuntu.developer.you.yourapp
  • XDG_CONFIG_HOME/com.ubuntu.developer.you.yourapp
  • XDG_DATA_HOME/com.ubuntu.developer.you.yourapp
  • XDG_RUNTIME_DIR/confined/com.ubuntu.developer.you.yourapp

QML applications will use the correct location (once LP: #1231863 is fixed) as long as they set applicationName in the MainView to be the same as what is in the click manifest file for name. Eg:

$ cat ./yourapp.qml
...
MainView {
    ...
    // Note! applicationName must match the click manifest
    applicationName: "com.ubuntu.developer.you.yourapp"
    ...
}

Qt applications can find the values of the XDG directories by using the QStandardPaths API as well as QCoreApplication::applicationName.

Alternatively, the APP_PKGNAME can be programmaticly found by parsing the APP_ID (it is everything before the first underscore) and combing it with the desired XDG dir. Example pseudocode:

APP_PKGNAME = APP_ID.split('_')[0]
my_writable_dir = os.environ['XDG_DATA_HOME'] + APP_PKGNAME

IMPORTANT: an app that chooses to ignore, change or otherwise not adhere to anything in the runtime environment will be blocked by application confinement.