Bug 1227092

Summary: network/boinc-client: Add WorkingDirectory= to unit file (and other possible unit file enhancements)
Product: [openSUSE] openSUSE.org Reporter: Muzhi Tian <timuzhti>
Component: 3rd party softwareAssignee: Christian Wittmer <chris>
Status: CONFIRMED --- QA Contact: E-mail List <screening-team-bugs>
Severity: Enhancement    
Priority: P5 - None CC: aaronpuchert, Sascha.Manns, timuzhti
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: openSUSE Tumbleweed   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Muzhi Tian 2024-06-26 14:24:13 UTC
This is a pretty minor issue but without WorkingDirectory= set, the ExecStop= command (/usr/bin/boinccmd --quit) does not actually function because it can't find the gui_rpc_auth.cfg file. This causes the unit to report failure every time it's stopped.

According to documentation, boinccmd checks three places for the password (it doesn't have a --datadir option). Changing the working directory to either /var/lib/boinc or ~ (which is the same thing by default) seems to be the easiest way to resolve this, since /etc/boinc-client/ and /var/lib/boinc-client are not used by default.

I'm not really sure which of the two options would be better. Using the home directory of the boinc user would probably make it easier to reconfigure to another directory, but I'm not sure that's worth it. It might be even better to somehow pull $BOINC_BOINC_DIR into WorkingDirectory= but systemd doesn't seem to support this.

Another quirk uncovered looking at the logs is that systemd apparently interprets /lockfile as part of the variable name, sample log message as follows:

(rm): boinc-client.service: Invalid environment variable name evaluates to an empty string: BOINC_BOINC_DIR/lockfile

This can be avoided by wrapping the variable name in braces, ExecStopPost=/bin/rm -f ${BOINC_BOINC_DIR}/lockfile though I'm not sure if this is actually a systemd issue.

Finally, the upstream unit file at https://github.com/BOINC/boinc/blob/master/client/scripts/boinc-client.service.in includes a couple of systemd hardening options. Some of these are off by default because Atlas requires setuid root, but the three options limiting the read/write access of the unit to the boinc directory only might be worthwhile.

ProtectSystem=full
ProtectControlGroups=true
ReadWritePaths=-/var/lib/boinc -/etc/boinc-client
Comment 1 Christian Wittmer 2024-06-27 11:43:58 UTC
work in progress
Comment 2 Christian Wittmer 2024-06-27 12:00:59 UTC
(In reply to Muzhi Tian from comment #0)
> This is a pretty minor issue but without WorkingDirectory= set, the
> ExecStop= command (/usr/bin/boinccmd --quit) does not actually function
> because it can't find the gui_rpc_auth.cfg file. This causes the unit to
> report failure every time it's stopped.
> 
> According to documentation, boinccmd checks three places for the password
> (it doesn't have a --datadir option). Changing the working directory to
> either /var/lib/boinc or ~ (which is the same thing by default) seems to be
> the easiest way to resolve this, since /etc/boinc-client/ and
> /var/lib/boinc-client are not used by default.
> 
> I'm not really sure which of the two options would be better. Using the home
> directory of the boinc user would probably make it easier to reconfigure to
> another directory, but I'm not sure that's worth it. It might be even better
> to somehow pull $BOINC_BOINC_DIR into WorkingDirectory= but systemd doesn't
> seem to support this.
> 
> Another quirk uncovered looking at the logs is that systemd apparently
> interprets /lockfile as part of the variable name, sample log message as
> follows:
> 
> (rm): boinc-client.service: Invalid environment variable name evaluates to
> an empty string: BOINC_BOINC_DIR/lockfile
> 
> This can be avoided by wrapping the variable name in braces,
> ExecStopPost=/bin/rm -f ${BOINC_BOINC_DIR}/lockfile though I'm not sure if
> this is actually a systemd issue.
> 
> Finally, the upstream unit file at
> https://github.com/BOINC/boinc/blob/master/client/scripts/boinc-client.
> service.in includes a couple of systemd hardening options. Some of these are
> off by default because Atlas requires setuid root, but the three options
> limiting the read/write access of the unit to the boinc directory only might
> be worthwhile.
> 
> ProtectSystem=full
> ProtectControlGroups=true
> ReadWritePaths=-/var/lib/boinc -/etc/boinc-client

Hi,

you have a project in OBS here: https://build.opensuse.org/package/show/home:timuzhti/boinc-client

Why didn't you just fix it and created a submit request ?
Comment 3 Muzhi Tian 2024-06-27 14:06:24 UTC
Ah, to be honest the main reason I didn't submit it as a request was because I wasn't sure if I should bundle it all together or if there's any preference between hardcoded vs ~ as the workdir. I've put something with all of my suggested changes as https://build.opensuse.org/request/show/1183583 if there's no strong opinion one way or the other on that.
Comment 4 Muzhi Tian 2024-06-27 14:22:54 UTC
Ah, I see you've already made the changes as well. One of the issues I encountered was that I couldn't figure out how to get systemd to read the variable $BOINC_BOINC_DIR when set as a path in the unit file. I kept on getting "WorkingDirectory= path is not absolute: $BOINC_BOINC_DIR".

Wasn't sure if there was a way to do it, but I guess it might have been easier to just make the request and then explain it if anyone asks? Sorry for the extra work :/
Comment 5 OBSbugzilla Bot 2024-07-01 18:35:03 UTC
This is an autogenerated message for OBS integration:
This bug (1227092) was mentioned in
https://build.opensuse.org/request/show/1184357 Factory / boinc-client
Comment 6 Aaron Puchert 2024-07-06 23:29:23 UTC
My proposal to fix this would be to get rid of BOINC_BOINC_USR, BOINC_BOINC_GRP, and BOINC_BOINC_DIR in /etc/sysconfig/boinc-client, because we cannot use environment variables outside of commands in systemd unit files. Let's just hardcode the defaults including WorkingDirectory=/var/lib/boinc, and let users override them via drop-in configuration files.

Then we can drop --dir from from ExecStart, because it will just start in the working directory if the option isn't specified, and write "ExecStopPost=/bin/rm -f lockfile", using a relative path from the working directory.

I don't see any way to use the working directory for ReadWritePaths though. If we want to keep it, users would have to override it together with WorkingDirectory.

For the remaining environment variable, we can do

    ExecStart=/bin/sh -c "exec /usr/bin/boinc $BOINC_BOINC_OPTS"

The "exec" should ensure that the shell doesn't stay around.
Comment 7 Aaron Puchert 2024-07-07 20:53:48 UTC
(In reply to Aaron Puchert from comment #6)
> For the remaining environment variable, we can do
> 
>     ExecStart=/bin/sh -c "exec /usr/bin/boinc $BOINC_BOINC_OPTS"
> 
> The "exec" should ensure that the shell doesn't stay around.

Or just get rid of the sysconfig file entirely. Overriding ExecStart, should additional options be desired, is also possible via drop-in configuration.

This wouldn't even be a breaking change, as none of these options properly worked before. (That is, they might have worked prior to the switch to systemd.)
Comment 8 OBSbugzilla Bot 2024-07-12 05:55:03 UTC
This is an autogenerated message for OBS integration:
This bug (1227092) was mentioned in
https://build.opensuse.org/request/show/1186996 Factory / boinc-client