Home / Alt manpages / systemd-binfmt.service(8)

  • systemd-binfmt.service(8)
  • Admin command
  • linux

Register and Troubleshoot Linux Binary Handlers with systemd-binfmt

You will inspect the binary-format handlers that systemd has registered, understand which binfmt.d file wins, and add or remove a handler without losing track of the kernel state. The examples match systemd 255.4 on Ubuntu, package version 255.4-1ubuntu8.17, installed on the machine used for this guide.

Allow about fifteen minutes. You need a shell and a working systemd installation. Reading configuration is unprivileged; writing under /etc/binfmt.d, restarting the service, and unregistering handlers require elevated privileges. The last operation is destructive, so it is called out separately.

1. Confirm the installed tool

The service uses the helper at /usr/lib/systemd/systemd-binfmt. Check the version and available options before copying a command into a script:

$ /usr/lib/systemd/systemd-binfmt --version
systemd 255 (255.4-1ubuntu8.17)

$ /usr/lib/systemd/systemd-binfmt --help
systemd-binfmt [OPTIONS...] [CONFIGURATION FILE...]
...
     --cat-config       Show configuration files
     --tldr             Show non-comment parts of configuration
     --no-pager         Do not pipe output into a pager
     --unregister       Unregister all existing entries

The exact feature list can vary with the systemd release. In this release, --unregister exists and has been available since systemd 246. Do not use it as a routine reload command: it removes every currently registered entry.

2. See the effective configuration

Start with the read-only view. --cat-config prints each file and its filename; --tldr omits blank lines and comments:

$ /usr/lib/systemd/systemd-binfmt --no-pager --tldr
# /usr/lib/binfmt.d/llvm-18-runtime.binfmt.conf
:llvm-18-runtime.binfmt:M::BC::/usr/bin/lli-18:

# /usr/lib/binfmt.d/llvm-20-runtime.binfmt.conf
:llvm-20-runtime.binfmt:M::BC::/usr/bin/lli-20:

# /usr/lib/binfmt.d/python3.12.conf
:python3.12:M::\xcb\x0d\x0d\x0a::/usr/bin/python3.12:

Your output depends on installed packages. The entries are kernel binfmt_misc rules, not shell aliases. A magic rule matches bytes at an offset in a file and invokes the named interpreter. The kernel documentation describes the full registration shape as :name:type:offset:magic:mask:interpreter:flags; the separator can be changed when the rule needs a literal colon.

Checkpoint: compare this output with the live kernel directory:

$ ls -l /proc/sys/fs/binfmt_misc
$ cat /proc/sys/fs/binfmt_misc/status

Registered names such as python3.12 should have corresponding files. An empty or missing directory usually means the kernel interface is not mounted or available. Do not write to register by hand while diagnosing a systemd-managed setup.

3. Understand which file wins

Configuration files must end in .conf. systemd reads administrator files from /etc/binfmt.d, runtime files from /run/binfmt.d, and package or local files from /usr/lib/binfmt.d or /usr/local/lib/binfmt.d. Higher-priority directories override a file with the same filename. The files are then sorted by filename across the directories, so a later lexicographic name can change an individual setting.

For example, a vendor file named 50-example.conf can be replaced completely by an /etc/binfmt.d/50-example.conf file. To add a later rule without replacing the vendor file, use a later name such as 90-local-example.conf. The recommended two-digit prefix makes this ordering visible during review.

Blank lines and lines beginning with # or ; are comments. Those characters therefore cannot be used as a rule's field separator. Keep comments outside the registration line.

4. Add a local rule deliberately

Use a real interpreter path and a rule designed for the file format you intend to run. This is a template, not a safe claim that the placeholder interpreter exists:

# /etc/binfmt.d/90-example.conf
:example:M::MAGIC::/absolute/path/to/trusted-interpreter:

The M means magic-byte matching. The name is example, MAGIC is the byte sequence, and the final path is the interpreter. The kernel can execute this handler whenever a file matches, so a wrong or untrusted interpreter is a security decision, not a harmless test.

Create the file with your normal administrative editor, then inspect it before applying it:

$ sudoedit /etc/binfmt.d/90-example.conf
$ sudo /usr/lib/systemd/systemd-binfmt --no-pager --cat-config | sed -n '/90-example.conf/,+2p'

Do not use a broad shell redirection with an unquoted path or user-supplied rule. Keep the file mode ordinary for configuration, and confirm that the interpreter is an absolute, executable file owned and maintained by the system administrator.

5. Apply and verify the change

After editing a persistent file, restart the service during a suitable maintenance window. This changes kernel execution behaviour for matching files:

$ sudo systemctl restart systemd-binfmt.service
$ systemctl is-active systemd-binfmt.service
active
$ ls -l /proc/sys/fs/binfmt_misc/example

The service is normally a static unit, so is-enabled may print static even when is-active prints active. That is not a failure. If the restart fails, read the unit log and remove or correct the new file, then restart again:

$ journalctl -u systemd-binfmt.service -b --no-pager
$ sudoedit /etc/binfmt.d/90-example.conf
$ sudo systemctl restart systemd-binfmt.service

Keep the old configuration until a representative file has been executed successfully. A matching rule can affect ordinary command launches, and a handler that exits unexpectedly can make the original program appear broken.

6. Override or remove a vendor rule

To disable a packaged configuration file, place a symlink with the same filename in /etc/binfmt.d pointing to /dev/null. Resolve the exact vendor filename first:

$ find /usr/lib/binfmt.d /usr/local/lib/binfmt.d -maxdepth 1 -type f -name '*.conf' -printf '%f\n' | sort
$ sudo ln -s /dev/null /etc/binfmt.d/EXACT-VENDOR-FILENAME.conf
$ sudo systemctl restart systemd-binfmt.service

Replace EXACT-VENDOR-FILENAME.conf with the filename you actually found. Do not create a guessed link. If the configuration was included in an initrd, the manpage requires regenerating that initrd as a separate, distribution-specific operation.

To undo the local override, remove only the symlink you created, then restart the service:

$ test -L /etc/binfmt.d/EXACT-VENDOR-FILENAME.conf
$ sudo rm /etc/binfmt.d/EXACT-VENDOR-FILENAME.conf
$ sudo systemctl restart systemd-binfmt.service

The rm command is irreversible for that directory entry. The vendor file is not removed, but check the target with test -L first so you do not delete a real administrator file.

7. Treat unregister as an emergency operation

--unregister unregisters all currently registered binary formats, including entries that did not come from the files you are editing. It requires the privilege needed to change the kernel interface and can disrupt unrelated applications. Use it only with a documented recovery plan:

$ sudo /usr/lib/systemd/systemd-binfmt --unregister
$ sudo systemctl restart systemd-binfmt.service
$ /usr/lib/systemd/systemd-binfmt --no-pager --tldr

The restart re-registers the configured rules, but it cannot restore an entry that was registered by another mechanism or a configuration file you have removed. Prefer correcting binfmt.d and restarting the service when the problem is a bad local rule.

Done means

  • You confirmed the installed systemd version and inspected the effective rules with --tldr.
  • You checked both configuration precedence and the live /proc/sys/fs/binfmt_misc entries.
  • Any new rule uses a reviewed absolute interpreter path and a deliberate filename order.
  • You verified the service state after applying a change and kept a recovery edit ready.
  • You did not use --unregister unless clearing every handler was explicitly required.