Skip to content

Creating custom SELinux policies

Creating custom SELinux policies

Follow this procedure to create a custom SELinux policy for an AutoSD image using selcraft. Custom policies define fine-grained access rules for applications that communicate across partition boundaries or require permissions beyond the default targeted policy.

For background on when custom policies are needed, see Understanding SELinux policies in AutoSD images.

Prerequisites

Before you begin, verify that you have the following:

  • Podman installed. See the Podman installation guide for instructions.
  • Automotive Image Builder installed. See Installing Automotive Image Builder for instructions.
  • A manifest file (.aib.yml) for the target image.
  • createrepo_c installed for hosting the policy RPM in a local repository. Install with dnf install createrepo_c.
Create a custom policy with selcraft

The following steps use selcraft to generate a custom SELinux policy, package it as an RPM, and include it in an AIB image build. The example is based on the more complex demos/custom_selinux_policy/ demo in the sig-docs demos repository.

  1. Create a selcraft configuration file. Define the applications, IPC resources, and permissions in a YAML file named conf.yaml. The apps section lists binaries with their paths and whether they run in the QM partition. The ipc section defines shared resources. The permissions section grants specific access to each application.

    yaml schema_version: "1.0.0" info: name: "my-policy" version: "1.0.0" description: "Custom SELinux policy for my application" distro: "autosd10" apps: binaries: - name: "my-server" path: "/usr/bin/my-server" is_qm: false - name: "my-client" path: "/usr/bin/my-client" is_qm: true ipc: sockets: uds: - name: my-socket path: "/run/my-app/comm.socket" permissions: - app: my-server ipc: my-socket allow: - READ - WRITE - CREATE - app: my-client ipc: my-socket allow: - READ - WRITE

    For a complete example with multiple IPC types (Unix domain sockets and shared memory), see demos/custom_selinux_policy/selinux/conf.yaml.

  2. Build the selcraft container image. Create a Containerfile for selcraft named Containerfile.selcraft and then build the image:

    text --8<-- "demos/custom_selinux_policy/selinux/selcraft"

    Build the container:

    console $ podman build -t localhost/selcraft:latest -f Containerfile.selcraft .

  3. Generate the policy source. Run selcraft inside the container to produce the policy module and RPM build files:

    console $ podman run -v ./:/var/selcraft \ --security-opt label=type:unconfined_t \ localhost/selcraft:latest \ selcraft generate \ --config=/var/selcraft/selinux/conf.yaml \ --output-dir=/var/selcraft/selinux/out

    The --security-opt label=type:unconfined_t flag allows the container to access the mounted volume without SELinux restrictions on the build host.

  4. Build the policy RPM. Change to the output directory and compile the generated policy source into an installable RPM package:

    console $ make -C selinux/out container-build

  5. Create a local RPM repository. Create a directory for the repository:

    console $ mkdir -p /var/tmp/policy_repo/

    Copy the built RPM into it:

    console $ cp -rp selinux/out/rpmbuild/RPMS/noarch /var/tmp/policy_repo/

    Generate the repository metadata:

    console $ createrepo_c /var/tmp/policy_repo/noarch/

  6. Add the repository and policy RPM to the manifest. Configure the AIB manifest to use the local repository and install the policy package:

    yaml content: repos: - id: local-policy baseurl: file:///var/tmp/policy_repo/noarch/ rpms: - my-policy

    For a complete working manifest that integrates binary installation, systemd services, and QM configuration alongside the custom policy, see demos/custom_selinux_policy/custom_selinux_policy.aib.yml.

  7. Build the image. Run aib build to produce an image with the custom SELinux policy installed:

    console $ aib build \ --target qemu \ manifest.aib.yml \ localhost/my-image

Apply SELinux booleans by using the manifest

To override individual SELinux boolean values without creating a custom policy, use the selinux_booleans option under the image section of the manifest, as shown in the following example:

image:
  selinux_booleans:
    container_use_devices: true
    virt_sandbox_use_all_caps: false

Automotive Image Builder creates a systemd service that applies the specified booleans at boot time using setsebool.

Enforce SELinux settings with AIB policies

You can also enforce SELinux boolean settings across multiple builds using the AIB policy system (--policy flag). Policy files guarantee consistent SELinux configuration in production environments without requiring a custom policy RPM.

For instructions on creating and applying AIB policy files, see Understanding AIB build policies.

Key considerations for custom policies

Keep the following important points in mind when working with custom SELinux policies:

  • Custom policies extend the base targeted policy. They do not replace the default policy or its rules.
  • Test custom policies in permissive mode first by setting image.selinux_mode to permissive in the manifest. Review the audit log for denials before switching to enforcing mode.
  • Selcraft generates policies from a declarative YAML configuration, which avoids writing raw .te policy files. If required, you can manually inspect the generated policy source in the output directory.
  • The policy RPM must be hosted in a repository accessible to the build. For CI/CD pipelines, consider publishing the RPM to a shared internal repository rather than using a local file path.