/run/chrony missing - no privileged commands possible

Bug #1746444 reported by Christian Ehrhardt  on 2018-01-31
20
This bug affects 4 people
Affects Status Importance Assigned to Milestone
chrony (Debian)
Fix Released
Unknown
chrony (Ubuntu)
High
Christian Ehrhardt 

Bug Description

From logs:
chronyd[3443]: Could not change ownership of /run/chrony : Operation not permitted
chronyd[3443]: Could not access /run/chrony : No such file or directory
chronyd[3443]: Disabled command socket /run/chrony/chronyd.sock

Not sure if this is critical, but it should be checked.

Per chronyc this is for:
There are two ways chronyc can access chronyd. One is the Internet Protocol (IPv4 or IPv6) and the other is a Unix domain socket, which
is accessible locally by the root or chrony user. By default, chronyc first tries to connect to the Unix domain socket. The compiled-in
default path is /run/chrony/chronyd.sock. If that fails (e.g. because chronyc is running under a non-root user), it will try to connect
to 127.0.0.1 and then ::1.

Some commands are ONLY allowed via the socket connection OR if allowed per "cmdallow" so this should be important.

E.g. "clients" command is not authorized by default (and many more, but one to test).

Note: clients (as example) even fails if called as root.

Path is just not existing, if it exists as:

$ sudo ls -laF /run/chrony
total 0
drwxrwx--- 2 _chrony _chrony 40 Jan 31 08:48 ./

That is:
perm: 770
owner: _chrony:_chrony

Then things work on startup and creates:
srwxr-xr-x 1 _chrony _chrony 0 Jan 31 08:54 /run/chrony/chronyd.sock=

With that if a user that can not access the socket calls chronyc it is as before.
But if a user can (member of chrony group or as root) then it has the designed elevated permissions.

ubuntu@b-test-chrony:~$ sudo chronyc
chrony version 3.2
Copyright (C) 1997-2003, 2007, 2009-2017 Richard P. Curnow and others
chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and
you are welcome to redistribute it under certain conditions. See the
GNU General Public License version 2 for details.

chronyc> clients
Hostname NTP Drop Int IntL Last Cmd Drop Int Last
===============================================================================
localhost 0 0 - - - 2 0 2 5
chronyc> quit

Changed in chrony (Ubuntu):
status: New → Triaged
importance: Undecided → High

If only dir exists, but perms are wrong it is:
chronyd[3863]: Wrong permissions on /run/chrony
chronyd[3863]: Disabled command socket /run/chrony/chronyd.sock

Changed in chrony (Ubuntu):
assignee: nobody → ChristianEhrhardt (paelzer)
summary: - /run/chrony missing?
+ /run/chrony missing - no privileged commands possible

Arr - stupid me

Of course /run is tmpfs now.
So instead of a postinst fix we need a service change that makes it available.

Per [1] I found a better solution.

There is a defined entry for that in systemd, so it comes down to the even easier.

RuntimeDirectory=chrony
RuntimeDirectoryMode=0770

For user&group (which we need) we also need to set User & Group but that would affect ExecStart which would break it.

Via [2] and IRC discussion I found a way through that.
One can set user/group but ignore it for the execution.

User=_chrony
Group=_chrony
And add a ! at ExecStart

I'll check if the Priv/Protect settings are affected (They would be at ExecStart=+.

[1]: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
[2]: https://www.freedesktop.org/software/systemd/man/systemd.service.html

IRC from #systemd

[11:57] <cpaelzer> Hi, I'm *almost* happy with RuntimeDirectory and RuntimeDirectoryMode - I'd need to set user/group as well. doc says set User/Group, but that breaks the actual ExecStart :-/
[11:57] <cpaelzer> I'd almost need an inverse of PermissionsStartOnly
[11:58] <boucman_work> I don't know... using an unused tty/pty pair would have been my guess, but I never really understood how those worked, so I can't really tell you much
[11:58] <cpaelzer> any suggestions how that could be worked out (dir ownership without affecting the effective user the service is run)?
[11:59] <boucman_work> cpaelzer: I didn't understand what you are trying to do... can you rephrase ?
[11:59] <cpaelzer> I want a /run/dir to be created with a specific path (=RuntimeDirectory) mode (=RuntimeDirectoryMode) and woner (=???)
[12:00] <cpaelzer> for the owner I'm supposed to set User= Group= (and that works setting the dir up that way) but I do not want User/Group to affect ExecStart
[12:00] <cpaelzer> so I wonder how I'd best set ownership of that dir on service start
[12:01] <boucman_work> so you want your service run as root, but the dir created as another owner ?
[12:01] <cpaelzer> boucman_work: yes
[12:01] <boucman_work> did you try ExecStart=+ ? that might work
[12:01] <boucman_work> if not... i would abandon RuntimeDirectory and make stuff manually with ExecStartPre and ExecStopPost...
[12:02] <cpaelzer> ExecStart+= would make me loose PrivateTmp and such I think
[12:03] <boucman_work> hmm
[12:03] <cpaelzer> I can try ExecStartPre, just about every link I found on doing so with ExecStartPre pointed me to RuntimeDirectory
[12:03] <cpaelzer> but yeah, maybe my case is special and needs it via ExecStartPre :-/
[12:04] <boucman_work> yeah, RuntimeDirectory is cleaner in general, but in your particular case it can't help
[12:04] <boucman_work> i'd like to understand exactly how your app work, though... running as root but using directories owned by another user makes little sense to me...
[12:04] <boucman_work> is this an app that drops root privs at startup ?
[12:05] <cpaelzer> boucman_work: yes
[12:05] <cpaelzer> it drops and changes id later on by itself after some privileged early init
[12:06] <cpaelzer> boucman_work: could ExecStart=! be an option?
[12:06] <cpaelzer> just reading about that ...
[12:07] <boucman_work> ok, normally that sort of app should not use User= and Group= at all... so maybe do not use these directives and just do the chmod in ExecStartPre... worth trying
[12:10] <boucman_work> and yes, this seems to be what you want according to the documentation
[12:11] <cpaelzer> boucman_work: thanks, it really works - I now need to check if any of the PrivateTmp/Protect* features are affected
[12:11] <cpaelzer> but the dir creation works

This might in fact be a consequence of the recent apparmor profile.
[ +4,930997] audit: type=1400 audit(1517405671.243:26): apparmor="ALLOWED" operation="capable" profile="/usr/sbin/chronyd" pid=1883 comm="chronyd" capability=0 capname="chown"

I got to it as I found fedora creating this dir on demand but not via systemd.
Tracking that down got me this denial.

I got a fix in those and an ack by jdstrand.

Changed in chrony (Debian):
status: Unknown → New
Changed in chrony (Debian):
status: New → Fix Committed
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package chrony - 3.2-2ubuntu2

---------------
chrony (3.2-2ubuntu2) bionic; urgency=medium

  * d/control: use to nss instead of tomcrypt (in main) (LP: #1744072)
  * d/chrony.conf: use ubuntu ntp pool and server (LP: #1744664)
  * d/chrony.default, d/chrony.service: support /etc/default/chrony
    DAEMON_OPTS in systemd environment (LP: #1746081)
  * d/chrony.service: properly start after networking (LP: #1746458)
  * d/usr.sbin.chronyd: allow to create /run/chrony on demand (LP: #1746444)

 -- Christian Ehrhardt <email address hidden> Fri, 19 Jan 2018 09:45:38 +0100

Changed in chrony (Ubuntu):
status: Triaged → Fix Released
Changed in chrony (Debian):
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.