Bug 1574418 - Cannot redirect output of command chronyc to a file
Summary: Cannot redirect output of command chronyc to a file
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: selinux-policy
Version: 7.5
Hardware: All
OS: Linux
medium
medium
Target Milestone: rc
: ---
Assignee: Lukas Vrabec
QA Contact: Milos Malik
URL:
Whiteboard:
: 1575002 1577057 (view as bug list)
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-05-03 09:22 UTC by Renaud Métrich
Modified: 2019-04-29 09:15 UTC (History)
16 users (show)

Fixed In Version: selinux-policy-3.13.1-199.el7
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2018-10-30 10:03:50 UTC
Target Upstream Version:


Attachments (Terms of Use)


Links
System ID Priority Status Summary Last Updated
Red Hat Knowledge Base (Solution) 3432501 None None None 2018-05-04 09:23:35 UTC
Red Hat Product Errata RHBA-2018:3111 None None None 2018-10-30 10:04:28 UTC

Description Renaud Métrich 2018-05-03 09:22:02 UTC
Description of problem:

On RHEL7.5, chronyc is confined. This causes a AVC denied to be issued when trying to redirect the output of the command:

# chronyc -n tracking > /var/lib/test; echo $?
1

# ausearch -ts recent -m avc
----
time->Thu May  3 10:03:46 2018
type=PROCTITLE msg=audit(1525334626.324:225): proctitle=6368726F6E7963002D6E00747261636B696E67
type=SYSCALL msg=audit(1525334626.324:225): arch=c000003e syscall=59 success=yes exit=0 a0=ec8af0 a1=f84300 a2=f81110 a3=7ffd006382a0 items=0 ppid=1540 pid=25627 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="chronyc" exe="/usr/bin/chronyc" subj=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1525334626.324:225): avc:  denied  { write } for  pid=25627 comm="chronyc" path="/var/lib/test" dev="dm-0" ino=33631503 scontext=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file

When redirecting to /var/log, the command silently fails, with no AVC being displayed:

# chronyc -n tracking > /var/log/test; echo $?
1


Version-Release number of selected component (if applicable):

chrony-3.2-2.el7.x86_64


How reproducible:

Always


Steps to Reproduce: see above

Additional info:

Workaround is to pipe the output instead:

# chronyc -n tracking | cat > /var/log/test; echo $?
0

Comment 3 Miroslav Lichvar 2018-05-03 10:10:31 UTC
FWIW, a similar issue was fixed in bug #1530525.

Comment 4 Milos Malik 2018-05-03 19:04:28 UTC
The chronyc program is confined:

# matchpathcon `which chronyc`
/usr/bin/chronyc	system_u:object_r:chronyc_exec_t:s0
#

and if root (unconfined_t user) executes the program, the newly created process transitions into a different context:

# sesearch -s unconfined_t -t chronyc_exec_t -T
Found 1 semantic te rules:
   type_transition unconfined_t chronyc_exec_t : process chronyc_t; 
#

Unfortunately, the process running under chronyc_t is not able to write to a /var/lib/test file even if it exists:

# matchpathcon /var/lib/test
/var/lib/test	system_u:object_r:var_lib_t:s0
# sesearch -s chronyc_t -t var_lib_t -c file -A

# sesearch -s chronyc_t -t var_lib_t -T

#

That's the reason why we see following SELinux denial in enforcing mode:

# ausearch -m avc -i
----
type=PROCTITLE msg=audit(05/03/2018 14:43:12.587:282) : proctitle=chronyc -n tracking 
type=PATH msg=audit(05/03/2018 14:43:12.587:282) : item=1 name=/lib64/ld-linux-x86-64.so.2 inode=6342393 dev=fd:01 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:ld_so_t:s0 objtype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 
type=PATH msg=audit(05/03/2018 14:43:12.587:282) : item=0 name=/usr/bin/chronyc inode=4407177 dev=fd:01 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:chronyc_exec_t:s0 objtype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 
type=CWD msg=audit(05/03/2018 14:43:12.587:282) :  cwd=/root 
type=EXECVE msg=audit(05/03/2018 14:43:12.587:282) : argc=3 a0=chronyc a1=-n a2=tracking 
type=SYSCALL msg=audit(05/03/2018 14:43:12.587:282) : arch=x86_64 syscall=execve success=yes exit=0 a0=0x71a820 a1=0x71ebc0 a2=0x71e5b0 a3=0x7ffe5561bda0 items=2 ppid=11286 pid=27113 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=2 comm=chronyc exe=/usr/bin/chronyc subj=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 key=(null) 
type=AVC msg=audit(05/03/2018 14:43:12.587:282) : avc:  denied  { write } for  pid=27113 comm=chronyc path=/var/lib/test dev="vda1" ino=3051479 scontext=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file 
----

Comment 5 Milos Malik 2018-05-03 19:18:06 UTC
If chronyc output is redirected (just 1 '>') to /var/log/test then the situation is similar:

# matchpathcon /var/log/test
/var/log/test	system_u:object_r:var_log_t:s0
# sesearch -s chronyc_t -t var_log_t -c file -A
Found 2 semantic av rules:
   allow application_domain_type logfile : file { ioctl getattr lock append } ; 
   allow systemprocess logfile : file { ioctl getattr lock append } ; 

# sesearch -s chronyc_t -t var_log_t -T

#

There is no allow rule which would allow the chronyc process to write to the file, but no SELinux denial appears, because there is a dontaudit rule, which prevents the SELinux denial from being reported:

# sesearch -s chronyc_t -t var_log_t -c file -D
Found 1 semantic av rules:
   dontaudit systemprocess var_log_t : file { ioctl read write getattr lock append } ; 
#

If we disable dontaudit rules using:

# semodule -DB
#

then the SELinux denial appears as expected:
----
type=PROCTITLE msg=audit(05/03/2018 15:08:31.126:292) : proctitle=chronyc tracking 
type=PATH msg=audit(05/03/2018 15:08:31.126:292) : item=1 name=/lib64/ld-linux-x86-64.so.2 inode=6342393 dev=fd:01 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:ld_so_t:s0 objtype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 
type=PATH msg=audit(05/03/2018 15:08:31.126:292) : item=0 name=/usr/bin/chronyc inode=4407177 dev=fd:01 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:chronyc_exec_t:s0 objtype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 
type=CWD msg=audit(05/03/2018 15:08:31.126:292) :  cwd=/root 
type=EXECVE msg=audit(05/03/2018 15:08:31.126:292) : argc=2 a0=chronyc a1=tracking 
type=SYSCALL msg=audit(05/03/2018 15:08:31.126:292) : arch=x86_64 syscall=execve success=yes exit=0 a0=0x7208d0 a1=0x720fe0 a2=0x71e5b0 a3=0x7ffe5561bda0 items=2 ppid=11286 pid=27178 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=2 comm=chronyc exe=/usr/bin/chronyc subj=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 key=(null) 
type=AVC msg=audit(05/03/2018 15:08:31.126:292) : avc:  denied  { write } for  pid=27178 comm=chronyc path=/var/log/test dev="vda1" ino=7332065 scontext=unconfined_u:unconfined_r:chronyc_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file 
----

Comment 6 Milos Malik 2018-05-03 19:23:12 UTC
If we use append ('>>') when redirecting the chronyc output, then the situation is different, because there is at least 1 allow rule which allows the process running as chronyc_t to append to /var/log/test:

# sesearch -s chronyc_t -t var_log_t -c file -p append -A 
Found 2 semantic av rules:
   allow application_domain_type logfile : file { ioctl getattr lock append } ; 
   allow systemprocess logfile : file { ioctl getattr lock append } ; 
#

# chronyc tracking >> /var/log/test
# ls -Z /var/log/test
-rw-r--r--. root root unconfined_u:object_r:var_log_t:s0 /var/log/test
# cat /var/log/test
Reference ID    : 00000000 ()
Stratum         : 0
Ref time (UTC)  : Thu Jan 01 00:00:00 1970
System time     : 0.000000000 seconds fast of NTP time
Last offset     : +0.000000000 seconds
RMS offset      : 0.000000000 seconds
Frequency       : 0.000 ppm slow
Residual freq   : +0.000 ppm
Skew            : 0.000 ppm
Root delay      : 1.000000000 seconds
Root dispersion : 1.000000000 seconds
Update interval : 0.0 seconds
Leap status     : Not synchronised
# 

and there is no SELinux denial logged.

Comment 7 Milos Malik 2018-05-03 19:33:44 UTC
Using the cat command together with chronyc:

# chronyc -n tracking | cat > /var/log/test

also leads to a successful write access to /var/log/test file, because the cat process runs as unconfined_t:

# cat -
^Z
[1]+  Stopped                 cat -
# ps -efZ | grep cat
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 27210 11286  0 15:27 pts/0 00:00:00 cat -
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 27212 11286  0 15:27 pts/0 00:00:00 grep --color=auto cat
#

and a chronyc_t process can provide data to an unconfined_t process:

# sesearch -s chronyc_t -t unconfined_t -c fd -A
Found 4 semantic av rules:
   allow systemprocess initrc_transition_domain : fd use ; 
   allow chronyc_t unconfined_t : fd use ; 
   allow domain unconfined_t : fd use ; 
   allow domain domain : fd use ; 
# sesearch -s chronyc_t -t unconfined_t -c fifo_file -A
Found 4 semantic av rules:
   allow application_domain_type userdomain : fifo_file { ioctl read write getattr lock append } ; 
   allow domain rpm_transition_domain : fifo_file { ioctl read write getattr lock append } ; 
   allow systemprocess initrc_transition_domain : fifo_file { ioctl read write getattr lock append } ; 
   allow chronyc_t unconfined_t : fifo_file { ioctl read write getattr lock append } ; 
#

and an unconfined_t process can write to /var/log/test file:

# sesearch -s unconfined_t -t var_log_t -c file -p write -A
Found 1 semantic av rules:
   allow files_unconfined_type file_type : file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton execute_no_trans open audit_access } ; 
#

I hope the explanation is correct and I didn't forget to mention any important step.

Comment 8 Troels Arvin 2018-05-06 20:46:40 UTC
In the Check_MK agent, the following was done to work around this issue:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commitdiff;h=4e56d264c8d85278c37a3bbb6bc334475141b13e

Comment 9 Lukas Vrabec 2018-05-18 16:46:04 UTC
*** Bug 1575002 has been marked as a duplicate of this bug. ***

Comment 10 Lukas Vrabec 2018-05-20 22:34:16 UTC
*** Bug 1577057 has been marked as a duplicate of this bug. ***

Comment 12 Nelson 2018-08-23 13:36:20 UTC
We have seen this in the past with some other bugs. when you run chronyc sources " or any of the other options" you will get no output to the terminal "tty." We have found that if you just add "| cat" it will output it to the terminal.

example
chronyc tracking
-returns nothing

chronyc tracking |cat 
- will output the information to the terminal

Reason for this is SELinux, by piping it to cat strips away the selinux and will allow you to display it to the screen. Once the people at Red Hat make a patch for selinux it should work find and output to the terminal correctly.

I hope this helps the other people who reported this bug and your thread was merge here.

Comment 17 Milos Malik 2018-09-24 16:47:15 UTC
If following rule was present in selinux-policy then chronyc would be allowed to write to any file labeled var_lib_t:

allow chronyc_t var_lib_t : file { write };

If following rule was present in selinux-policy then chronyc would be allowed to write to any file labeled var_log_t:

allow chronyc_t var_log_t : file { write };

There are dedicated directories like /var/lib/chrony and /var/log/chrony where chronyc can write to, because files in them usually inherit their label.

Because there is the "| cat" workaround and because these rules would weaken the chronyc confinement, we decided not to add them the selinux-policy.

Comment 22 errata-xmlrpc 2018-10-30 10:03:50 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2018:3111


Note You need to log in before you can comment on or make changes to this bug.