0

I am working on a service to capture device-mapper dm-verity uevent. However, I am not able to figure out why the service is able to be triggered but fails to run my logger script.

I have the following rules (/etc/udev/rules.d/dm-verity.rules) based on this discussion (newline added for readability):

KERNEL=="dm-[0-9]*", \ ACTION=="change", \ SUBSYSTEM=="block", \ ENV{DM_VERITY_ERR_BLOCK_NR}!="", \ TAG+="systemd", \ ENV{SYSTEMD_WANTS}+="dm-verity.service" 

I have the following service (/etc/systemd/system/dm-verity.service):

[Unit] Description=dm-verity uevent logger [Service] Type=forking ExecStart=/usr/bin/dm-verity_log_error.sh 

I have the following script (/usr/bin/dm-verity_log_error.sh):

#!/bin/bash echo "dm-verity occurs" | my-logger-adaptor exit 0 

I can confirm from journal that the dm-verity.rules and dm-verity.service is triggered, however, it fails when it tries to execute dm-verity_log_error.sh. Journal log snippet as follows.

systemd[1]: dm-verity.service: About to execute: /bin/bash -c /usr/bin/dm-verity_log_error.sh systemd[1]: dm-verity.service: Forked /bin/bash as 19823 systemd[19823]: dm-verity.service: Kernel keyring not supported, ignoring. systemd[19823]: dm-verity.service: Executing: /bin/bash -c /usr/bin/dm-verity_log_error.sh systemd[1]: dm-verity.service: Changed dead -> start systemd[1]: Starting dm-verity uevent logger systemd[1]: dm-verity.service: cgroup is empty audit[19823]: ANOM_ABEND auid=4294967295 uid=0 gid=0 ses=4294967295 pid=19823 comm="bash" exe="/bin/bash.bash" sig=11 res=1 systemd[1]: Received SIGCHLD from PID 19823 (bash). systemd[1]: Child 19823 (bash) died (code=killed, status=11/SEGV) systemd[1]: dm-verity.service: Child 19823 belongs to dm-verity.service. systemd[1]: dm-verity.service: Main process exited, code=killed, status=11/SEGV systemd[1]: dm-verity.service: Failed with result 'signal'. systemd[1]: dm-verity.service: Changed start -> failed systemd[1]: dm-verity.service: Job dm-verity.service/start finished, result=failed systemd[1]: Failed to start dm-verity uevent logger 

From the logs, it seem like there is an error when executing the bash shell to run the script (code=killed, status=11/SEGV) but I am not quite sure the cause of it. Any pointer to some documents or possible solutions on the problem?

My thoughts on what might be the cause:

  1. Maybe it is because of systemd.exec executing the command in sandbox environment so that the bash shell does not has all of the necessary environment (reference 1
  2. Maybe I invoke dm-verity_log_error.sh incorrectly in ExecStart= attribute field. Starting the service with systemctl start dm-verity.service is successful. I did some other test with ExecStart=/bin/ls and it can also run successfully when triggered by the rules.
  3. Maybe dm-verity_log_error.sh did run, but ends too quickly. However, I am not sure if the main process in the journal is referring to the dm-verity.service that finished or referring to the ``dm-verity_log_error.sh` script itself.

I have tried to search for similar problem online but have not find one quite that match my problem. Maybe I am using the wrong keyword to search. I have read the following reference so far:

I am using a development board running Yocto 2.6, and systemd 239.

6
  • Have you tried adding the full path to my-logger-adaptor in the shell script? Commented Nov 19, 2024 at 16:35
  • What happens if you systemctl start the service manually? The problem seems to be completely unrelated to udev, as your process is not run within the udev environment, nor even run by udev directly at all. Commented Nov 20, 2024 at 6:01
  • @Popup yes, unfortunately it also produce the same error when using with full path Commented Nov 20, 2024 at 6:26
  • @grawity when using systemctl start to manually start the service, the script can execute successfully. I agree that the issue seems to be unrelated with udev. I am thinking maybe it has to do with how the script or shell is invoked from the ExecStart= directive. I wonder if the service triggered by udev rules runs under different environment compared to the one run manually with systemctl start. Commented Nov 20, 2024 at 6:30
  • Are you using SELinux? (try getenforce to find out.) Commented Nov 20, 2024 at 12:14

1 Answer 1

0

I believe the issue is due to Type=forking in the systemd service. Based on documentation, what you need is Type=oneshot.

Here's a quote from the documentation for both:

  • If set to forking, the manager will consider the unit started immediately after the binary that forked off by the manager exits. The use of this type is discouraged, use notify, notify-reload, or dbus instead.

    It is expected that the process configured with ExecStart= will call fork() as part of its start-up. The parent process is expected to exit when start-up is complete and all communication channels are set up. The child continues to run as the main service process, and the service manager will consider the unit started when the parent process exits. This is the behavior of traditional UNIX services.

  • Behavior of oneshot is similar to simple; however, the service manager will consider the unit up after the main process exits. It will then start follow-up units. RemainAfterExit= is particularly useful for this type of service. Type=oneshot is the implied default if neither Type= nor ExecStart= are specified. Note that if this option is used without RemainAfterExit= the service will never enter active unit state, but will directly transition from activating to deactivating or dead, since no process is configured that shall run continuously. In particular this means that after a service of this type ran (and which has RemainAfterExit= not set) it will not show up as started afterwards, but as dead.

In addition, given the simplicity of your script, I'd consider getting rid of it and planting the command directly in the service, like so:

[Unit] Description=dm-verity uevent logger [Service] Type=oneshot ExecStart=echo "dm-verity occurs" | my-logger-adaptor 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.