blob: 6bbd08ccd94a7cc99d156a1971064717aed4b1fb [file] [log] [blame] [view] [edit]
# tmpfiles.d Configuration Files
These `.conf` files define filesystem operations that are needed to set up
paths. This is commonly creating specific files and directories with specific
permissions and ownership before running a system daemon. For example an
upstart job with:
```bash
pre-start script
mkdir -p /run/dbus
chown messagebus:messagebus /run/dbus
mkdir -p /var/lib/dbus
end script
```
Can be replaced with a `tmpfiles.d` file with:
```bash
d= /run/dbus 0755 messagebus messagebus
d= /var/lib/dbus 0755 root root
```
See the [upstream documentation] for the configuration file format. On Chrome OS
the `=` is used to remove a path if it has the wrong type (FIFO vs.
directory vs. file vs. etc.) instead of failing with an error.
This configuration will take care of creating the listed paths with the correct
type, ownership, permissions, and SELinux labels. If the path already exists
with the wrong ownership or permissions they will be changed to match the
configuration with some caveats (see the note below). Remember the root-fs is
read-only and uses verity for integrity checking so you cannot create or change
paths on it without building a new image. Also, tmpfiles.d checks to make sure
symlinks in the parent directories paths do not cross from lower privilege to
higher privilege.
***note
**Note:**
If the parent directory is not owned by root and a sub path is owned
by a different user, it is treated as an unsafe transition. Currently, an unsafe
transition in a configured path will cause tmpfiles.d to fail with an error and
chromeos_startup will trigger a cleanup of the stateful partition.
***
The preferred location of these config files in the source tree is a
subdirectory of the parent project named `tmpfiles.d`.
## When not to use tmpfiles.d
Not all paths should be used with the tmpfiles.d mechanism.
For device-related paths under `/dev` and `/sys`, use udev rules instead to
set ownership & permissions. These react well according to when the kernel
finishes initialization and avoid race conditions with userland.
## Configuration application timing
There are three primary ways to apply a tmpfiles.d configuration on Chrome OS.
1. As part of the early system start-up.
2. By using a tmpfiles stanza in an upstart job.
3. By calling systemd-tmpfiles directly on a configuration.
Note that these are not mutually exclusive, so different combinations can be
used if appropriate.
### Early startup
Configurations intended to be applied from startup should have the `.conf`
extension and be installed to `/usr/lib/tmpfiles.d` using `dotmpfiles` or
`newtmpfiles` from [tmpfiles.eclass]. The `--boot` flag is supplied here so
configuration entries with the `!` action will be applied.
[pre-startup.conf] applies configurations for the following path prefixes:
* `/dev`
* `/proc`
* `/run`
`/sys` can be added, but care needs to be taken because some subpaths are
mounted at a later time like cgroups.
After [pre-startup.conf] finishes, [chromeos_startup] is executed, which covers
the following path prefixes:
* `/home`
* `/media`
* `/mnt/stateful_partition`
* `/var`
Additional path prefixes can be added as needed, but care needs to be taking to
make sure the parent paths are mounted before applying the configuration.
### Upstart job pre-start
Adding a tmpfiles stanza to an upstart config applies the config before running
the pre-start stanza. This does not prevent the config from also being applied
at early boot.
Some reasons you might want a tmpfiles stanza are for paths created dynamically,
or to reduce the risk of a compromise persisting between user-sessions (without
a reboot).
Here is an excerpt from [vm_concierge.conf] with an example:
```
start on start-user-session
stop on stopping ui
respawn
expect daemon
tmpfiles /usr/lib/tmpfiles.d/arcvm.conf /usr/lib/tmpfiles.d/vm_tools.conf
```
The Chrome OS upstart patch that adds the tmpfiles stanza does not set the
`--boot` flag so configuration entries with the `!` action will not be applied.
### On demand
Configurations that can not be applied in early boot should be installed to
`/usr/lib/tmpfiles.d/on-demand` using `doins` or `newins`. These need either:
* A tmpfiles stanza to the appropriate upstart config as shown in the previous
section
* A direct call to systemd-tmpfiles. Here is an example:
```
systemd-tmpfiles --create --remove --clean <absolute path to your-tmpfiles-d.conf>
```
***note
**Note:**
You may not need all the options `--create`, `--remove`, or `--clean` depending
on the actions being applied. See the [upstream documentation] for more details.
***
One reason why this might be necessary is the cases a tmpfiles.d configuration
has a path inside a mount that is created on demand.
## Testing
Currently, an error in a tmpfiles.d config installed to /usr/lib/tmpfiles.d will
result in a stateful repair boot-loop. To avoid this when testing, copy your
config file to a different path and invoke it manually (or from an upstart job)
with:
```sh
/usr/bin/systemd-tmpfiles --boot --create --remove --clean <absolute path to your-tmpfiles-d.conf>
```
Generally, no errors are printed on success. If extra verbosity is desired, use:
```sh
export SYSTEMD_LOG_LEVEL=debug
```
## Troubleshooting and Common Obstacles
For tmpfiles.d configurations applied at startup, errors cause a clobber of
the stateful partition. Warnings and errors are logged to `/run/tmpfiles.log`
because the system log is set up after [chromeos_startup] executes and writes to
the stateful partition which may be clobbered. The [clobber_state_collector]
crash collector preserves this log across stateful_partition clobbers and writes
it to `/var/spool/crash` which can be checked when troubleshooting.
Warnings do not result in the stateful_partition being clobbered and the
[collect-early-logs] upstart job applies the contents of `/run/tmpfiles.log` to
the system log once it is available. These entries are prefixed with
"tmpfiles.d".
Here are some common errors with known resolutions.
### Paths Missing SELinux File Context Entries
If you see errors that resemble something like:
```
Failed to determine SELinux security context for /run/rsyslogd: Resource temporarily unavailable
Failed to create directory or subvolume "/run/rsyslogd": Resource temporarily unavailable
Failed to determine SELinux security context for /var/log/bluetooth.log: Resource temporarily unavailable
Unable to fix SELinux security context of /var/log/bluetooth.log (/var/log/bluetooth.log): Resource temporarily unavailable
```
The problem is usually missing SELinux file context entries. This occurs because
tmpfiles.d tries to restore the SELinux labels of the path. The restore
operation depends on having a file context entry. In some cases the path may
already have an existing label applied through a context transition policy rule,
but without the file context entry tmpfiles.d will still fail.
Here are example entries to resolve the above errors from
[chromeos_file_contexts]:
```
/run/rsyslogd u:object_r:cros_run_rsyslogd:s0
/var/log/bluetooth.log u:object_r:cros_var_log_bluetooth:s0
```
*** note
**Note:** the context label (e.g. `cros_var_log_bluetooth`) needs to be defined.
Most are located in [file.te].
***
More information about defining the SELinux policy can be found in the
[SELinux documentation].
[chromeos_file_contexts]: /sepolicy/file_contexts/chromeos_file_contexts
[chromeos_startup]: /init/chromeos_startup
[clobber_state_collector]: /crash-reporter/clobber_state_collector.cc
[collect-early-logs]: /init/upstart/collect-early-logs.conf
[file.te]: /sepolicy/policy/base/file.te
[pre-startup.conf]: /init/upstart/pre-startup.conf
[SELinux documentation]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/security/selinux.md
[tmpfiles.eclass]: https://chromium.googlesource.com/chromiumos/overlays/portage-stable/+/HEAD/eclass/tmpfiles.eclass
[upstream documentation]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
[vm_concierge.conf]: /vm_tools/init/vm_concierge.conf