Discretionary Access Control (DAC)

Filesystem objects and services added to the build frequently need separate,
unique IDs, known as Android IDs (AIDs). Currently, many resources such as
files and services use core (Android-defined) AIDs unnecessarily; in many
cases you can use OEM (OEM-defined) AIDs instead.

Earlier versions of Android (Android 7.x and lower) extended the AIDs
mechanism using a device-specific android_filesystem_config.h
file to specify filesystem capabilities and/or custom OEM AIDs. However, this
system was unintuitive as it did not support using nice names for OEM AIDs,
requiring you to specify the raw numeric for user and group fields without a
way to associate a friendly name with the numeric AID.

Newer versions of Android (Android 8.0 and higher) support a new method for
extending filesystem capabilities. This new method has support for the
following:

Generation of a custom OEM AID header that can be used in source files as
needed.

Association of a friendly name with the actual OEM AID value. Supports
non-numeric string arguments for user and group, i.e. "foo" instead of
"2901".

Additional improvements include the removal of the android_ids[]
array from
system/core/include/private/android_filesystem_config.h. This
array now exists in Bionic as a fully private generated array, with
accessors via getpwnam() and getgrnam(). (This has
the side effect of producing stable binaries as core AIDs are modified.) For
tooling and a README file with more details, refer to
build/make/tools/fs_config.

Adding Android IDs (AIDs)

Android 8.0 removed the android_ids[] array from the Android
Open Source Project (AOSP). All AID-friendly names are instead generated from
the system/core/include/private/android_filesystem_config.h
header file when generating the Bionic android_ids[] array. Any
define matching AID_* is picked up by the tooling
and * becomes the lowercase name.

For example, in private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Becomes:

Friendly name: system

uid: 1000

gid: 1000

To add a new AOSP core AID, simply add the #define to the
android_filesystem_config.h header file. The AID will be
generated at build and made available to interfaces that use user and group
arguments. The tooling validates the new AID is not within the APP or OEM
ranges; it also respects changes to those ranges and should automatically
reconfigure on changes or new OEM-reserved ranges.

Configuring AIDs

To enable the new AIDs mechanism, set TARGET_FS_CONFIG_GEN in the
BoardConfig.mk file. This variable holds a list of configuration
files, enabling you to append files as needed.

Caution: Don't use TARGET_FS_CONFIG_GEN with the
older TARGET_ANDROID_FILESYSTEM_CONFIG_H method from older
Android releases! You will get an error.

By convention, configuration files use the name config.fs, but in
practice you can use any name. config.fs files are in the
Python
ConfigParser ini format and include a caps section (for configuring file
system capabilities) and an AIDs section (for configuring OEM AIDs).

Configuring the caps section

Note:Ambient
capabilities are the preferred mechanism for setting capabilities for
services launched by init (this method keeps all aspects for the
service configuration in a single .rc file). We recommend using
ambient capabilities for these services instead of configuring file system
capabilities using the caps section in config.fs files. When
setting capabilities for services not launched by
init, continue to configure file system capabilities
using fs_config.c.

The caps section supports setting
file
system capabilities on filesystem objects within the build (the filesystem
itself must also support this functionality).

Because running a stable service as root in Android causes a
Compatibility Test Suite (CTS)
failure, previous requirements for retaining a capability while running a
process or service involved setting up capabilities then using
setuid/setgid to a proper AID to run. With caps, you
can skip these requirements and have the kernel do it for you. When control is
handed to main(), your process already has the capabilities it
needs so your service can use a non-root user and group (this is the preferred
way for starting privileged services).

The caps section uses the following syntax:

Section

Value

Definition

[path]

The filesystem path to configure. A path ending in / is considered a dir,
else it's a file.

It is an error to specify multiple sections with the same
[path] in different files. In Python versions <= 3.2, the
same file may contain sections that override the previous section; in Python
3.2, it's set to strict mode.

mode

Octal file mode

A valid octal file mode of at least 3 digits. If 3 is specified, it is
prefixed with a 0, else mode is used as is.

user

AID_<user>

Either the C define for a valid AID or the friendly name
(e.g. both AID_RADIO and radio are acceptable). To
define a custom AID, see Configuring
the AID section.

group

AID_<group>

Same as user.

caps

cap*

The name as declared in
system/core/include/private/android_filesystem_capability.h
without the leading CAP_. Mixed case allowed. Caps can also be
the raw:

Configuring the AID section

The AID section contains OEM AIDs and uses the following syntax:

Section

Value

Definition

[AID_<name>]

The <name> can contain characters in the set
uppercase, numbers, and underscores. The lowercase version is used as the
friendly name. The generated header file for code inclusion uses the exact
AID_<name>.

It is an error to specify multiple sections with the same
AID_<name> (case insensitive with the same constraints as
[path]).

<name> must begin with a partition name to ensure
that it does not conflict with different sources.

value

<number>

A valid C style number string (hex, octal, binary and decimal).

It is an error to specify multiple sections with the same value option.

Value options must be specified in the range corresponding to the partition
used in <name>. The list of valid partitions and their corresponding
ranges is defined in system/core/include/private/android_filesystem_config.h.
The options are:

Usage examples

The following examples detail how to define and use an OEM AID and how to
enable filesystem capabilities. OEM AID names
([AID_name]) must begin with a
partition name such as "vendor_" to ensure they do not conflict with future
AOSP names or other partitions.

Defining OEM AID names

To define an OEM AID, create a config.fs file and set
the AID value. For example, in device/x/y/config.fs, set the
following:

[AID_VENDOR_FOO]
value: 2900

After creating the file, set the TARGET_FS_CONFIG_GEN variable
and point to it in BoardConfig.mk. For example, in
device/x/y/BoardConfig.mk, set the following:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

Your custom AID can now be consumed by the system at large on a new build.

Using OEM AIDs

To use an OEM AID, in your C code, add #include
"generated_oem_aid.h" and start using the declared identifiers. For
example, in my_file.c, add the following:

Because the internal mapping from friendly name to uid is performed by
/vendor/etc/passwd and /vendor/etc/group, the vendor
partition must be mounted.

Associating friendly names

Android 9 includes support for associating a
friendly name with the actual OEM AID value. You can use non-numeric string
arguments for user and group, i.e. "vendor_foo" instead of
"2901".

Converting from AID to friendly names

For
OEM AIDs, Android 8.x required the use of
oem_#### with getpwnam and similar functions, as
well in places that handle lookups via getpwnam (such as
init scripts). In Android 9, you can
use the getpwnam and getgrnam friends in Bionic for
converting from Android IDs (AIDs) to friendly names and vice versa.

Using file system capabilities

To enable filesystem capabilities, create a caps section in the
config.fs file. For example, in
device/x/y/config.fs, add the following section:

Note: The nice names vendor_foo
and system could be used here as well.

After creating the file, set the TARGET_FS_CONFIG_GEN to point to
that file in BoardConfig.mk. For example, in
device/x/y/BoardConfig.mk, set the following:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

When service vendor_foo is executed, it starts
with capabilities CAP_SYS_ADMIN and CAP_SYS_NICE
without setuid and setgid calls. In addition, the
vendor_foo service's SELinux policy no longer
needs capability setuid and setgid and can be
deleted.

Configuring overrides (Android 6.x-7.x)

Android 6.0 relocated fs_config and associated structure
definitions
(system/core/include/private/android_filesystem_config.h) to
system/core/libcutils/fs_config.c where they could be updated or
overridden by binary files installed in
/system/etc/fs_config_dirs and
/system/etc/fs_config_files. Using separate matching and parsing
rules for directories and files (which could use additional glob expressions)
enabled Android to handle directories and files in two different tables.
Structure definitions in system/core/libcutils/fs_config.c not
only allowed runtime reading of directories and files, but the host could use
the same files during build time to construct filesystem images as
${OUT}/system/etc/fs_config_dirs and
${OUT}/system/etc/fs_config_files.

While the override method of extending the filesystem has been superseded by
the modular config system introduced in Android 8.0, you can still use the old
method if desired. The following sections detail how to generate and include
override files and configure the filesystem.

Generating override files

You can generate the aligned binary files
/system/etc/fs_config_dirs and
/system/etc/fs_config_files using the
fs_config_generate tool in build/tools/fs_config. The
tool uses a libcutils library function
(fs_config_generate()) to manage DAC requirements into a buffer
and defines rules for an include file to institutionalize the DAC rules.

To use, create an include file in
device/vendor/device/android_filesystem_config.h
that acts as the override. The file must use the
structure fs_path_config format defined in
system/core/include/private/android_filesystem_config.h with the
following structure initializations for directory and file symbols:

For directories, use android_device_dirs[].

For files, use android_device_files[].

When not using android_device_dirs[] and
android_device_files[], you can define
NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS and
NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (see the
example below). You can also specify the override
file using TARGET_ANDROID_FILESYSTEM_CONFIG_H in the board
configuration, with an enforced basename of
android_filesystem_config.h.

Including override files

To include files, ensure that PRODUCT_PACKAGES includes
fs_config_dirs and/or fs_config_files so it can
install them to /system/etc/fs_config_dirs and
/system/etc/fs_config_files, respectively. The build system
searches for custom android_filesystem_config.h in
$(TARGET_DEVICE_DIR), where BoardConfig.mk exists.
If this file exists elsewhere, set board config variable
TARGET_ANDROID_FILESYSTEM_CONFIG_H to point to that location.

Override example

This example shows a patch for overriding the system/bin/glgps
daemon to add wake lock support in the
device/vendor/device directory. Keep the
following in mind:

Each structure entry is the mode, uid, gid, capabilities, and the name.
system/core/include/private/android_filesystem_config.h is
included automatically to provide the manifest #defines
(AID_ROOT, AID_SHELL,
CAP_BLOCK_SUSPEND).

The android_device_files[] section includes an action to
suppress access to system/etc/fs_config_dirs when unspecified,
which serves as an additional DAC protection for lack of content for directory
overrides. However, this is weak protection; if someone has control over
/system, they can typically do anything they want.

Migrating filesystems from earlier releases

When migrating filesystems from Android 5.x and earlier, keep in mind that
Android 6.x

Removes some includes, structures, and inline definitions.

Requires a reference to libcutils instead of running directly
from system/core/include/private/android_filesystem_config.h.
Device manufacturer private executables that depend on
system/code/include/private_filesystem_config.h for the file or
directory structures or fs_config must add libcutils
library dependencies.

Requires device manufacturer private branch copies of the
system/core/include/private/android_filesystem_config.h with
extra content on existing targets to move to
device/vendor/device/android_filesystem_config.h.

Reserves the right to apply SELinux Mandatory Access Controls (MAC) to
configuration files on the target system, implementations that include custom
target executables using fs_config() must ensure access.

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.