See Application Layout for more details of how store and built-in application bundles are arranged.
Assumptions
- Store application bundles are arranged according to the Application Layout.
- Built-in application bundles are arranged according to the Application Layout.
- Platform upgrades are somewhat frequent, although not as frequent as store application bundle installation, upgrade or removal.
- Rollbacks are supported, but are relatively infrequent.
Requirements
Application bundles
Suppose com.example.BuiltInApp
is a built-in application
bundle. A
platform update from version 42 to
version 43 results in BuiltInApp being updated. Later, the user requests
a system rollback. It is possible that the version of BuiltInApp in
platform v43 has migrated user files to a format not understood by the
version in platform v42, so we must roll back the user data.
- During upgrade, the platform must take a snapshot of the data stored on behalf of BuiltInApp in platform v42. The upgraded system v43 must have a separate read/write data area for BuiltInApp, mounted in the same place and starting from the same state as that snapshot. (System Updates & Rollback design, §6.3; Applications design, §4.2.2)
- During rollback, the platform must discard the data stored by the version of BuiltInApp that was present in platform v43, replacing it with the data stored by the version of BuiltInApp that was present in platform v42 (System Updates & Rollback, §6.3; Applications, §4.2.4), with the exception that cached files may be deleted instead of being rolled back.
- Because built-in applications are upgraded and rolled back as part of the platform, it is not necessary to support rolling back built in applications’ data individually; in other words, it would be acceptable to have a single snapshot that contains the data for all built-in applications together.
- Because we have assumed that upgrades and rollbacks will not be very frequent, it is acceptable for performing an upgrade or rollback involving n built-in application bundles to take O(n) operations; in other words, it would also be acceptable to have a snapshot per built-in application even though it is not necessary.
Suppose net.example.ThirdPartyApp
is a store application
bundle that was
installed before the upgrade described above.
- During upgrade, under certain circumstances (if the platform API level increased between platform v42 and v43), the platform must take a snapshot of ThirdPartyApp and its data. (System Updates & Rollback, §6.4)
- During rollback, under certain circumstances, the platform must restore that snapshot. (System Updates & Rollback, §6.4)
Platform services
Some platform services store configuration, state and/or cached files outside the scope of a particular application bundle. There are various use-cases for how these interact with upgrades and rollbacks.
System-level components may store configuration and state that is valid for the system as a whole, independent of users. For example, if ConnMan is configured to provide a wireless hotspot in the car, the SSID and password should be preserved during upgrades, but rolled back during rollbacks.
- There must be a storage location for user-independent system configuration and state, which has upgrade/rollback behaviour similar to a built-in application: upgrades preserve it, but rollbacks roll it back.
- The Applications design calls for
/var/lib
to have this behaviour. (Applications design, §3.2)
User-level platform components may store configuration and state on a per-user basis, independent of any particular application bundle. For example, the Evolution data server stores address book and calendar data for a particular user.
- There should be a storage location for user-specific platform-level configuration and state, which again has upgrade/rollback behaviour similar to a built-in application: upgrades preserve it, but rollbacks roll it back.
System-level components may store configuration and state that is only
valid for a particular operating system image. For example, the state of
the dpkg
and apt
package databases is invalidated by platform
upgrades.
- There should be a storage location for user-independent system configuration and state that is tied to a particular operating system image.
- We anticipate that this will only be needed in special cases (such as apt), so this may be a special case that is only available to specific components.
- We do not anticipate that a similar feature will be needed for per-user configuration and state.
Certain system-level components may store configuration and state that
is valid for the system as a whole, and must be preserved across
upgrades and rollbacks. For example, the list of blacklisted platform
upgrades (System Updates & Rollback, §3.1) should be preserved and
extended after a rollback. It would also be sensible to avoid
/var/cache
and /var/log
participating in snapshots. (Applications
design, §3.2)
- There must be a storage location for system configuration and state that survive rollbacks. Platform components must be careful to use extensible formats with robust parsers for anything in this location, since it may have been written by a newer version of the same software.
- The Applications design calls for
/var
to have this behaviour. (Applications design, §3.2) /var/cache
must be cleaned during system rollback. (Applications design, §3.2)/var/log
must not be cleaned during system rollback, since it is likely to be key to analyzing why a rollback was required. (Applications design, §3.2)
We anticipate that large media files should be stored in shared space
(as of September 2015, /home/shared
). It would not be appropriate to
carry out snapshots or rollback for these files.
- There must be a storage location that is not subject to snapshot and rollback. Large media files should be stored there.
- User-level components may write other data to this location, with the same caveats as for system-level non-rollback data. (Applications design, §4.1.5)
System- and user-level components may have cached files that are unimportant and may be deleted. For example, Tracker stores a database of media files per user. This is non-critical and can be rebuilt if necessary, at some performance penalty.
Application bundles that extend the platform
Certain application bundles provide extensions for the operating system. ‘’(System Updates & Rollback, §6.2; Applications, §4.3).
- See the Applications design document for details of the requirements in this area.
Developer considerations
Mounting btrfs subvolumes can lead to difficulties with debugging and documenting the system architecture: it is non-obvious which physical locations (subvolumes) correspond to which logical locations (mounts).
To make the system more debuggable, we recommend that the root of each
underlying btrfs volume has a standard mount path, for example /System
and /General
. These could either be mounted at boot time, or left
unmounted but configured as noauto
in /etc/fstab
so that they can be
mounted for debugging.
Production code should not normally use these locations, although the mount management service may use them if desired.
This would facilitate references to physical locations as, for example,
/System/root_1/usr
or /General/apertis_extensions
in developer
documentation.
Security considerations
If ordinary user processes can access an outdated setuid binary that has an exploitable security vulnerability, then they may be able to escalate privileges using the vulnerability, even if the latest version of the corresponding binary has been fixed.
As a result, old snapshots should be mounted below a directory that is
not accessible by ordinary user processes. We recommend that when the
root of a btrfs volume is mounted, for example at /System
and
/General
, it should be owned by root, with rwx------
permissions.
Similarly, AppArmor rules should be configured so that those mount points can only be accessed by the snapshot/subvolume manager (Ribchester) and by unconfined processes.
Implementation as of September 2015
Logical layout
Directories that are a mount point for a separate subvolume are emphasized in this diagram. See Physical layout, below, for how they are actually arranged on-disk.
- /
- Applications
- com.example.BuiltInApp
- (variable data as described in Application Layout)
- com.example.StoreApp
- (static data as described in Application Layout)
- (variable data as described in Application Layout)
- com.example.BuiltInApp
- bin (early-boot programs)
- boot (kernel and initramfs files)
- dev (virtual filesystem for device nodes)
- etc (system configuration)
- home
- shared (shared files for all users)
- user (personal files for user named “user”)
- lib (early-boot libraries)
- media (transient mount points for removable devices)
- user (removable devices for user named “user”)
- USBSTICK (a USB drive with a label)
- 1234_5678 (a USB drive with a serial number)
- user (removable devices for user named “user”)
- mnt (empty, not used on Apertis)
- opt (empty, not used on Apertis)
- proc (virtual filesystem for process information)
- root -> var/root (sysadmin’s home directory, should not be used on Apertis)
- run (transient runtime data for the system)
- dbus (contains the system-level D-Bus socket)
- user (parent directory for users’ runtime data areas)
- 1000 (transient runtime data for uid 1000)
- sbin (early-boot programs)
- srv (not used by Apertis)
- sys (virtual filesystems for system information)
- tmp (temporary directory for all users, avoid using it)
- usr (static data and programs)
- Applications
- com.example.BuiltInApp
- (static data as described in Application Layout)
- com.example.BuiltInApp
- bin (platform programs)
- lib (platform libraries and data)
- share (platform data)
- arm-linux-gnueabihf etc. (platform libraries with “multiarch” support)
- Applications
- var (variable platform data)
- cache (system-wide caches)
- lib (assorted variable platform data)
- MILDENHALL_extensions (platform plugins installed by applications) (should be called apertis_extensions)
- Services (FIXME: document this)
- …
- Applications
Where not otherwise stated, directories have the same purpose as their equivalent in Debian.
Root filesystem
The root directory is mounted read-only. Its subdirectories /bin, /boot, /lib, /usr and so on contain the static files of the Apertis platform.
Either the system_1 or system_2 subvolume from the system partition is mounted here, whichever one is currently in use.
/Applications
The applications subvolume on the general partition is mounted at /Applications.
/Applications/(store app bundle)
Store applications are installed in a subdirectory of /Applications named after their bundle ID.
The current applications/System/Application-Subvolumes/(bundle ID) subvolume from the general partition is mounted here.
/Applications/(built-in app bundle)
Built-in application bundles’ program files are stored in subdirectories of /usr/Applications, but that location is read-only, so their read/write data is stored in a corresponding subdirectory of /Applications.
The current applications/System/Application-Subvolumes/(bundle ID) subvolume from the general partition is mounted here.
/etc
/etc is physically stored on the root directory, but is remounted to be read/write. It holds basic system configuration.
/home
The home subvolume from the general partition is mounted here. One subdirectory per user contains user-specific but non-app-specific data.
/home/shared
The shared subdirectory of /home contains files available to all users.
/usr/Applications
/usr/Applications is an Apertis-specific subdirectory of /usr. It contains built-in application bundles, each in its own directory.
/var
/var is physically stored on the root directory, but is remounted to be read/write. It holds the mutable state of the system.
/var/lib/MILDENHALL_extensions
The applications/System/System-Subvolumes/var/lib/MILDENHALL_extensions subvolume from the general partition is mounted here.
/var/lib/Services
The applications/System/System-Subvolumes/var/lib/Services subvolume from the general partition is mounted here.
Physical layout
There are two major partitions.
System partition
The system partition contains the Apertis platform.
Mount points (locations where other filesystems will be mounted) are physically empty directories.
Subvolumes are shown in bold here.
- (system partition)
- system_1
- Applications
- bin
- boot
- …
- Applications
- system_2
- Applications
- bin
- boot
- …
- Applications
- system_1
General partition
The general partition contains store application bundles and user data.
Again, subvolumes are shown in bold here.
- (general partition)
- applications
- System
- Application-Subvolumes
- com.example.BuiltInApp
- com.example.StoreApp
- Snapshots
- System-Subvolumes
- var
- lib
- MILDENHALL_extensions
- Services
- lib
- var
- com.example.BuiltInApp (empty directory to use as a mount point)
- com.example.StoreApp (empty directory to use as a mount point)
- home
- shared
- user
- applications
Differences between this setup and the design documents
The Applications design document calls for /var and /var/lib to be separate, with /var read/write and not participating in rollbacks, while /var/lib does participate in rollbacks. (§7 “Application Storage”
The Applications design document calls for the directory shared by all
users to be /home/_Shared
.
The Applications design document calls for the application subvolumes to have version-dependent names.
The Applications design document documents a more complex directory
hierarchy with Application/Bundle/{bin,lib,...}
, User Storage/$user
and Everyone Storage
instead of {bin,lib,...}
, users/$uid
and
{cache,config,data}
inside an application bundle’s data directory.
The Applications design document calls for the general partition to be
mounted at /General
.
The System Updates & Rollback design document calls for separate home
,
var
and Applications
subvolumes within the general partition, with
var
mounted at /var
.
Many system-wide files such as /Applications
are currently owned by
the user named “user
”, which prevents correct multi-user behaviour. We
recommend having a strict division between system files
(user-independent and only written by root or other system uids), shared
files (user-independent but written by all users), and user-dependent
files.
The /var/lib/Services
directory is not present in the design
documents. Its interaction with rollback is not clear. We recommend
clarifying the desired interaction with rollback and multi-user, and
revisiting this part of the design.
Recommendations
This section is incomplete.
Design principles
When choosing where files are to be situated, we recommend answering these questions as a guide:
- Is the file intended to be read by system uids, or by a single user, or by multiple users?
- Is the file intended to be written by nobody (read-only data), by system uids, or by a single user, or by multiple users?
- Is the file intended to be read by platform components, by a single application bundle, and/or by all application bundles?
- Is the file intended to be written by platform components, by a single application bundle, and/or by multiple application bundles?
- If the file is not read-only, which category does it most closely fit: configuration, cache, or valuable data? To choose between these, consider what the user-visible impact would be for deleting the file. If the user would be angry to have lost something that they created, then the file was valuable data; if the user would be at annoyed that some settings/preferences had returned to their default values, then the file was configuration; and if the user would not notice the difference (except for perhaps a performance impact), it was cache.
- If the application or platform is rolled back from version 2 to version 1, is the file expected to be kept intact at its version-2 state, rolled back to its version-1 state, or deleted?
Logical layout
We recommend that mount points for the system and general partitions are
reserved at /System
and /General
respectively. The top-level
directory of each partition should be owned by root and have permissions
rwx------
(see Security
considerations).
Ribchester or another platform component may mount those locations, if
they are required to be mounted in order to make platform components
work as desired. If not, we recommend that they are listed in
/etc/fstab
with the noauto
flag, so that they are not mounted by
default but developers can easily mount them for debugging.
Physical layout
This section is written with the assumption that the root directories of
the system and general partitions are available at /System
and
/General
respectively.
The current layout of the system partition, with two subvolumes
/System/root_1
and /System/root_2
, is suitable and should be kept.
/General/applications
should not be mounted on /Applications
.
Instead, we recommend that /Applications
should be a tmpfs (in-memory
file system), which should be populated with empty directories to act as
mount points for application bundles. All directories in that tmpfs
should be owned by root, with the standard permissions (rwxr-xr-x).
All subdirectories and subvolumes that are not specific to a particular
application bundle, such as /General/applications/System
, should be
moved from /General/applications
into /General
.
References
- Applications design document (v0.5.4 used)
- Multimedia design document (v0.5.4 used)
- Security design document (v1.1.3 used)
- System Update & Rollback design document (v1.6.2 used)