Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 717128 - sys-apps/man-db's daily cron job possibly abuses su; causes log warnings
Summary: sys-apps/man-db's daily cron job possibly abuses su; causes log warnings
Status: UNCONFIRMED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Gentoo's Team for Core System packages
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-04-11 18:28 UTC by Erik Quaeghebeur
Modified: 2024-12-09 16:12 UTC (History)
6 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Erik Quaeghebeur 2020-04-11 18:28:41 UTC
In my logs, I got warnings about systemd failing to open certain files. (See log excerpt in Additional Information below.) After some investigation, it seems these appear because in /etc/cron.daily/man-db we have

  exec su man -s /bin/sh -c 'nice mandb --quiet' 2>/dev/null

So man-db is su'ing to the user ‘man’, which results in (unnecessarily) logging in this user.

After looking around on the web, I stumbled upon the webpage

  http://jdebp.eu./FGA/dont-abuse-su-for-dropping-privileges.html

that seems applicable here. (I may be mistaken.)

Reproducible: Always

Steps to Reproduce:
1. use systemd
2. install man-db

Actual Results:  
‘Failed to open’ warnings in logs, caused by man-db su'ing to the user ‘man’.

Expected Results:  
No such warnings and man-db not su'ing (logging in the ‘man’ user).

systemd[1]: Starting systemd-cron daily script service...
systemd[1]: Condition check resulted in systemd-cron hourly script service being skipped.
systemd[1]: Reached target systemd-cron hourly target.
systemd[1]: Stopped target systemd-cron hourly target.
su[576833]: Successful su for man by root
su[576833]: + ??? root:man
su[576833]: pam_unix(su:session): session opened for user man by (uid=0)
systemd[1]: Created slice User Slice of UID 13.
systemd[1]: Starting User Runtime Directory /run/user/13...
systemd-logind[102]: New session c13 of user man.
systemd[1]: Started User Runtime Directory /run/user/13.
systemd[1]: Starting User Manager for UID 13...
systemd[576835]: pam_unix(systemd-user:session): session opened for user man by (uid=0)
systemd[576835]: Failed to open "/dev/null/.config/systemd/user.control", ignoring: Not a directory
systemd[576835]: Failed to open "/dev/null/.config/systemd/user", ignoring: Not a directory
systemd[576835]: Failed to open "/dev/null/.local/share/systemd/user", ignoring: Not a directory
systemd[576835]: Reached target Paths.
systemd[576835]: Reached target Sockets.
systemd[576835]: Reached target Timers.
systemd[576835]: Reached target Basic System.
systemd[1]: Started User Manager for UID 13.
systemd[1]: Started Session c13 of user man.
systemd[576835]: Reached target Main User Target.
systemd[576835]: Startup finished in 110ms.
su[576833]: pam_unix(su:session): session closed for user man
systemd[1]: session-c13.scope: Succeeded.
systemd-logind[102]: Session c13 logged out. Waiting for processes to exit.
systemd-logind[102]: Removed session c13.
systemd[1]: Stopping User Manager for UID 13...
systemd[576835]: Stopped target Main User Target.
systemd[576835]: Stopped target Basic System.
systemd[576835]: Stopped target Paths.
systemd[576835]: Stopped target Sockets.
systemd[576835]: Reached target Shutdown.
systemd[576835]: Stopped target Timers.
systemd[576835]: systemd-exit.service: Succeeded.
systemd[576835]: Started Exit the Session.
systemd[576835]: Reached target Exit the Session.
systemd[1]: user@13.service: Succeeded.
systemd[1]: Stopped User Manager for UID 13.
systemd[1]: Stopping User Runtime Directory /run/user/13...
systemd[656]: run-user-13.mount: Succeeded.
systemd[1]: run-user-13.mount: Succeeded.
systemd[1]: user-runtime-dir@13.service: Succeeded.
systemd[1]: Stopped User Runtime Directory /run/user/13.
systemd[1]: Removed slice User Slice of UID 13.
systemd[1]: user-13.slice: Consumed 1.009s CPU time.
systemd[1]: cron-daily.service: Succeeded.
systemd[1]: Started systemd-cron daily script service.
systemd[1]: cron-daily.service: Consumed 1.017s CPU time.
systemd[1]: Reached target systemd-cron daily target.
systemd[1]: Stopped target systemd-cron daily target.
Comment 1 Lars Wendler (Polynomial-C) (RETIRED) gentoo-dev 2020-04-11 18:49:28 UTC
CCing mjo as he might add some valuable input here...
Comment 2 Michael Orlitzky gentoo-dev 2020-04-11 19:23:06 UTC
I agree the "su" is pretty ugly here, but I have some excuses. First, the job would otherwise be run as root, so the "su adds privileges thing" doesn't apply in this case. You're a lot safer with the error messages. Second, this is a @system package with few dependencies, and a cron job that has to work with all of Gentoo's cron implementations.

I initially proposed something smarter in bug #676044, but I wound up closing the bug when I realized that the sensible thing to do (just launch the cron job as the mandb user) relied on the nonstandard location /etc/cron.d. At the time, vixie-cron was still in the tree, and didn't support that. Good news: vixie-cron is gone. Maybe now all of our cron implementations support /etc/cron.d, and the solution in bug #676044 will make everyone happy.

For bonus points, you can pester QA to reverse their harmful policy on subdirectories of /var/cache (bug #692736), which would allow us to drop the tmpfiles entry that pointlessly recreates /var/cache/man and adjusts its permissions all the time. Most tmpfiles entries in Gentoo are vulnerable to their own root exploits,

  * https://github.com/OpenRC/opentmpfiles/issues/3
  * https://github.com/OpenRC/opentmpfiles/issues/4

so we're just shuffling them around. Otherwise:

  * We have daemontools in the tree, but I doubt we want to depend
    on it in a @system package to get the "setuidgid" executable mentioned
    in that article.
  * This is only happening on systemd, where I think a timer would do the
    same job.
Comment 3 Ionen Wolkens gentoo-dev 2020-04-11 20:00:14 UTC
Personally I use setpriv for it (doesn't depend on pam, set-bits, or init systems' personal run-as tools, and doesn't log), ...but... it'd incur a dependency on util-linux[caps] which is (currently) not enabled by default and also add a dependency on libcap-ng.

Perhaps not best but line I use looks like this:
setpriv --reuid man --regid man --inh-caps=-all --init-groups mandb --quiet

Just mentioning it anyway.
Comment 4 Erik Quaeghebeur 2020-04-11 21:57:32 UTC
(In reply to Michael Orlitzky from comment #2)
>   * This is only happening on systemd, where I think a timer would do the
>     same job.
Apparently, there are man-db.timer and man-db.service files included with man-db, and installed. (I tested it, and it seems to work.) However, the timer is not started and enabled upon emerging man-db. So to fix this bug, it seems to me that the following is the approach to take:

* add a systemd use flag
* if it is active
  - start and enable the man-db.timer
  - do not install the script in /etc/cron.daily

The reason for not installing the script on systemd systems is that there are packages that install scripts in the /etc/cron.* directories but do not have a corresponding systemd timer/service file yet (mlocate, for example). To make sure that those housekeeping activities are done, there is systemd-cron, which adds appropriate timers to run scripts in /etc/cron.* directories. (Effectively, it is a cron implementation based on systemd.)
Comment 5 Patrick McLean gentoo-dev 2020-04-12 02:45:12 UTC
(In reply to Michael Orlitzky from comment #2)
> I agree the "su" is pretty ugly here, but I have some excuses. First, the
> job would otherwise be run as root, so the "su adds privileges thing"
> doesn't apply in this case. You're a lot safer with the error messages.
> Second, this is a @system package with few dependencies, and a cron job that
> has to work with all of Gentoo's cron implementations.

"runuser" has been part of util-linux for some time now, and gives a clean way to drop privileges, only invoking PAM if it is asked to.
Comment 6 Mike Gilbert gentoo-dev 2020-04-12 03:58:38 UTC
My suggestion to systemd users is to disable the cron.daily script via chmod, and enable the systemd timer instead.

chmod -x /etc/cron.daily/man-db
systemctl enable man-db.timer

Modern versions of Portage will preserve the permissions on /etc/cron.daily/man-db via CONFIG_PROTECT.

Personally, I think non-essential cron scripts should be disabled by default as a distro policy.
Comment 7 Mike Gilbert gentoo-dev 2020-04-12 04:06:14 UTC
(In reply to Ionen Wolkens from comment #3)
> Personally I use setpriv for it (doesn't depend on pam, set-bits, or init
> systems' personal run-as tools, and doesn't log), ...but... it'd incur a
> dependency on util-linux[caps] which is (currently) not enabled by default
> and also add a dependency on libcap-ng.

Or the cron script could check to see if "setpriv" is installed, and fall back on "runuser" if it is missing.

setpriv is nice because it never invokes PAM. runuser will invoke PAM if enabled at build time.
Comment 8 Ionen Wolkens gentoo-dev 2020-04-12 06:15:52 UTC
(In reply to Mike Gilbert from comment #7)
> Or the cron script could check to see if "setpriv" is installed, and fall
> back on "runuser" if it is missing.
runuser won't even be available on a pam-less system as far as I'm aware, I have util-linux-2.35.1-r1 built with -pam and
	$ command -V runuser
	bash: command: runuser: not found

su is also technically optional, people could build with both shadow and util-linux with USE=-su

So there's really 0 tools that are certain to be there to launch as uid/gid as far as I'm aware unless adding a dependency check.
Comment 9 Ionen Wolkens gentoo-dev 2020-04-12 06:37:09 UTC
..but of course could also opt to fall back on simply not running mandb if nothing available, man pages still work, do lose whatis functionality or maybe more (for "me" lacking mandb hardly makes a difference, and I feel like a USE to disable those parts of mandb wouldn't hurt)
Comment 10 Erik Quaeghebeur 2020-04-12 14:24:56 UTC
(In reply to Mike Gilbert from comment #6)
> My suggestion to systemd users is to disable the cron.daily script via
> chmod, and enable the systemd timer instead.
Well, I think this is an alternative to not installing it when systemd is used. I do think a systemd use flag is preferable here and that the ebuild takes care of this (chmod'ing -x instead of deleting/not installing if that is preferable). There is no value in burdening users with this.

> Personally, I think non-essential cron scripts should be disabled by default
> as a distro policy.
Whatever the policy is, each ebuild installing such (enabled|disabled) cron scripts/systemd timers should ideally alert the user of the situation using a message after emerging.

(In reply to Ionen Wolkens from comment #9)
> ..but of course could also opt to fall back on simply not running mandb if
> nothing available, man pages still work, do lose whatis functionality or
> maybe more (for "me" lacking mandb hardly makes a difference, and I feel
> like a USE to disable those parts of mandb wouldn't hurt)
While I feel this bug is about the systemd situation (for which I have described my preferred solution above and earlier), my 2 cents after reading the other comments: For non-systemd systems, a use flag *enabling* the cron functionality which causes a dependency on runuser/setpriv/whatever to avoid any kludges in the script comes across as the most elegant solution. There are other packages that have a ‘cron’ use flag. (Whether that use flag is set by default is another matter. Negative use flags should be avoided, because that is confusing.)
Comment 11 Michael Orlitzky gentoo-dev 2020-04-14 14:33:17 UTC
(Off-topic:) Having a cross-platform way to drop privileges in @system would solve another major problem we have where some calls to "checkpath" in OpenRC init scripts are exploitable, specifically when checkpath is run in a user-controlled directory. The right solution to that is to drop privileges and do whatever it is you want to do rather than trying to hack around the insecurities while doing things as root. But the Gentoo base system should generally work on any POSIX system, not just linux, so we can't depend on e.g. util-linux if we want people to be able to run this stuff in a prefix on OSX for example.
Comment 12 Mike Gilbert gentoo-dev 2020-04-14 15:32:21 UTC
(In reply to Michael Orlitzky from comment #11)

Or you could extend checkpath to drop privileges itself. It shouldn't be much effort at all since checkpath is written in C and can call getpwnam() and setuid() directly. There should already be some code it can share with start-stop-daemon.
Comment 13 James Le Cuirot gentoo-dev 2022-01-07 10:42:56 UTC
I haven't dug into it but I think this script has suddenly stopped working for me because of the su. This simple test fails:

$ su man date
su: Authentication service cannot retrieve authentication info

Logs show:

Jan 07 10:39:38 [unix_chkpwd] could not obtain user info (man)
Jan 07 10:39:38 [su] FAILED SU (to man) root on pts/0

runuser works:

$ runuser -u man date
Fri  7 Jan 10:42:34 GMT 2022

I'm not doing anything special with PAM but it's probably PAM-related. I suggest trying runuser if that's available, and failing back to su. Whatever's broken here probably wouldn't affect a PAM-less system.
Comment 14 Michael Orlitzky gentoo-dev 2022-01-07 12:20:23 UTC
The very best solution here is for the QA team to respond to #692736 and then none of these gymnastics will be necessary. This is a self-inflicted problem.
Comment 15 Sam James archtester Gentoo Infrastructure gentoo-dev Security 2022-01-07 12:38:47 UTC
(In reply to James Le Cuirot from comment #13)
> I haven't dug into it but I think this script has suddenly stopped working
> for me because of the su. This simple test fails:
> 

Can you verify this isn't bug 829872? (Try pwck)
Comment 16 James Le Cuirot gentoo-dev 2022-01-07 13:00:04 UTC
(In reply to Sam James from comment #15)
> (In reply to James Le Cuirot from comment #13)
> > I haven't dug into it but I think this script has suddenly stopped working
> > for me because of the su. This simple test fails:
> > 
> 
> Can you verify this isn't bug 829872? (Try pwck)

Oh yep, missed that one, thanks. Still would be good to get this fixed though.
Comment 17 Richard H. 2022-02-19 10:59:03 UTC
(In reply to James Le Cuirot from comment #16)
> (In reply to Sam James from comment #15)
> > (In reply to James Le Cuirot from comment #13)
> > > I haven't dug into it but I think this script has suddenly stopped working
> > > for me because of the su. This simple test fails:
> > > 
> > 
> > Can you verify this isn't bug 829872? (Try pwck)
> 
> Oh yep, missed that one, thanks. Still would be good to get this fixed
> though.

I had the exact same problem on two boxes now, so something must be fishy there.
Nevertheless, pwconv could fix this issue for me as well.
Comment 18 Alexander Weber 2024-12-05 08:03:37 UTC
Found this bug that applies to my issue too.

On my selinux enabled server I get daily error message into audit log:

audit2why -i /var/log/audit/audit.log -e

#  scontext="system_u:system_r:system_cronjob_t" tcontext="system_u:object_r:shadow_t"
#  class="file" perms="read"
#  comm="unix_chkpwd" exe="" path=""
#  message="type=AVC msg=audit(1733367155.076:166): avc:  denied  { read } for
#   pid=15663 comm="unix_chkpwd" name="shadow" dev="nvme1n1p2" ino=40501642
#   scontext=system_u:system_r:system_cronjob_t
#   tcontext=system_u:object_r:shadow_t tclass=file permissive=0 "
allow system_cronjob_t shadow_t:file read;


I do not like to give all cron job scripts access to /etc/shadow
Comment 19 Alexander Weber 2024-12-09 14:45:49 UTC
EDIT: I changed to 
setpriv --reuid man --regid man --inh-caps=-all --init-groups mandb --quiet

proposed by Ionen Wolkens

The setpriv does not need access to shadow file, so it is a solution that can be used with selinux.


Tried runuser, but this tool try to access to to shadow file too.
Comment 20 Michael Orlitzky gentoo-dev 2024-12-09 16:12:22 UTC
It's lost in the noise now, but the solution to this should be pretty easy now that vixie-cron is dead: drop an entry in /etc/cron.d to run the job as the mandb user rather than as root. The only reason this was not done initially is because vixie-cron didn't support it.

Having systemd-tmpfiles recreate the permament directory /var/cache/man and fuck with its permissions on every reboot is still ridiculous (and dangerous), but it's not blocking a fix for su.