Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-16104

[rhel-9] AVCs when confined user tries to sudo while sudo-io is configured

    • selinux-policy-38.1.41-1.el9
    • None
    • Important
    • 1
    • rhel-sst-security-selinux
    • ssg_security
    • 20
    • None
    • QE ack
    • False
    • Hide

      None

      Show
      None
    • Yes
    • Red Hat Enterprise Linux
    • CY24Q2
    • Hide

      A user derived from sysadm_u (SELinux user defined by default) can successfully run the dmidecode command via sudo with the input/output logging enabled. No SELinux denials are triggered during the run.

      Show
      A user derived from sysadm_u (SELinux user defined by default) can successfully run the dmidecode command via sudo with the input/output logging enabled. No SELinux denials are triggered during the run.
    • Pass
    • Automated
    • Bug Fix
    • Hide
      .SELinux policy adds rules for `sysadm_r` users to define input/output log directory through `sudo`

      Previously, the SELinux policy did not contain rules to allow confined administrators to run any command to specify the input/output log directory by using `sudo` when the `iolog_dir` option was defined in the `sudo` configuration. As a consequence, confined administrators in the `sysadm_r` role could not execute commands by using `sudo` with the `iolog_dir` option. This update adds a rule to the SELinux policy, and as a result, `sysadm_r` users can execute commands by using `sudo` with `iolog_dir`.
      Show
      .SELinux policy adds rules for `sysadm_r` users to define input/output log directory through `sudo` Previously, the SELinux policy did not contain rules to allow confined administrators to run any command to specify the input/output log directory by using `sudo` when the `iolog_dir` option was defined in the `sudo` configuration. As a consequence, confined administrators in the `sysadm_r` role could not execute commands by using `sudo` with the `iolog_dir` option. This update adds a rule to the SELinux policy, and as a result, `sysadm_r` users can execute commands by using `sudo` with `iolog_dir`.
    • Done
    • None

      Reproducer

      Have a user mapped to sysadm_u and able to sudo

      [root@vm-sudo9 ~]# useradd -Z sysadm_u -G wheel sysadm
      [root@vm-sudo9 ~]# echo redhat | passwd --stdin sysadm
      [root@vm-sudo9 ~]# semanage boolean -m --on ssh_sysadm_login
      

      Enable sudo-io input+output logging

      Defaults log_output
      Defaults log_input
      Defaults iolog_dir=/var/log/sudo-io
      

      Make sure `/var/log/sudo-io` doesn't exist yet.


      Issue 1

      [sysadm@vm-sudo9 ~]$ sudo dmidecode
      sudo: unable to open /var: Permission denied
      [sysadm@vm-sudo9 ~]$
      

      Trigger condition

      ALWAYS

      AVCs

      type=PROCTITLE msg=audit(11/09/2023 08:46:34.833:368) : proctitle=sudo dmidecode 
      type=SYSCALL msg=audit(11/09/2023 08:46:34.833:368) : arch=x86_64 syscall=openat success=no exit=EACCES(Permission denied) a0=AT_FDCWD a1=0x7fff7f989ef0 a2=O_RDONLY|O_NONBLOCK a3=0x0 items=0 ppid=4561 pid=29408 auid=sysadm uid=sysadm gid=sysadm euid=root suid=root fsuid=root egid=root sgid=sysadm fsgid=root tty=pts1 ses=8 comm=sudo exe=/usr/bin/sudo subj=sysadm_u:sysadm_r:sysadm_sudo_t:s0-s0:c0.c1023 key=(null) 
      type=AVC msg=audit(11/09/2023 08:46:34.833:368) : avc:  denied  { read } for  pid=29408 comm=sudo name=var dev="dm-0" ino=33575046 scontext=sysadm_u:sysadm_r:sysadm_sudo_t:s0-s0:c0.c1023 tcontext=system_u:object_r:var_t:s0 tclass=dir permissive=0 
      

      Root cause: `sudo` cannot read `/var` directory.

      strace

      4692  [sysadm_u:sysadm_r:sysadm_sudo_t:s0-s0:c0.c1023] 08:31:01.799094 openat(AT_FDCWD</home/sysadm>, "/var" [system_u:object_r:var_t:s0], O_RDONLY|O_NONBLOCK) = -1 EACCES (Permission denied) <0.000070>
      

      Code location

      # stap -d /usr/libexec/sudo/sudoers.so -d /usr/bin/sudo --ldd -v -e 'probe syscall.openat { if (execname() != "sudo" || argstr !~ "\"/var\".*O_RDONLY.*") next; printf("%s(%s)\n", name, argstr); print_usyms(ubacktrace()) }'
      [...]
      openat(AT_FDCWD, "/var", O_RDONLY|O_NONBLOCK)
       0x7fb97a13e5db : open+0x5b/0x130 [/usr/lib64/libc.so.6]
       0x7fb97a37ac3d : sudo_mkdir_parents_v1+0xfd/0x380 [/usr/libexec/sudo/libsudo_util.so.0.0.0]
       0x7fb979fd143a : iolog_mkdirs.lto_priv.0+0x3aa/0x500 [/usr/libexec/sudo/sudoers.so]
       0x7fb979fd18a7 : iolog_nextid+0x67/0x3d0 [/usr/libexec/sudo/sudoers.so]
       0x7fb979f992ff : fill_seq.lto_priv.0+0x5f/0x140 [/usr/libexec/sudo/sudoers.so]
       0x7fb979fd4a3d : expand_iolog_path.constprop.0+0x1cd/0x2e0 [/usr/libexec/sudo/sudoers.so]
       0x7fb979fad1ae : format_iolog_path+0x10e/0x1a0 [/usr/libexec/sudo/sudoers.so]
       0x7fb979fb45be : sudoers_policy_main+0x1c1e/0x3390 [/usr/libexec/sudo/sudoers.so]
       0x7fb979fa29c7 : sudoers_policy_check+0xb7/0x1f0 [/usr/libexec/sudo/sudoers.so]
       0x5642c7171427 : main+0x717/0x28d0 [/usr/bin/sudo]
       0x7fb97a03feb0 : __libc_start_call_main+0x80/0xb0 [/usr/lib64/libc.so.6]
       0x7fb97a03ff60 : __libc_start_main@GLIBC_2.2.5+0x80/0x150 [/usr/lib64/libc.so.6]
       0x5642c7173605 : _start+0x25/0x30 [/usr/bin/sudo]
      

      Source code:

       49 bool
       50 sudo_mkdir_parents_v1(char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet)
       51 {
       :
       64 reopen:
       65         dfd = open(path, O_RDONLY|O_NONBLOCK);  <<<<< HERE
       66         if (dfd == -1) {
       67             if (errno != ENOENT) {
       68                 if (!quiet)
       69                     sudo_warn(U_("unable to open %s"), path);
       70                 goto bad;
       71             }
       72             if (mkdir(path, mode) == 0) {
       :
      

      Proposed fix (CIL format)

      (allow sudodomain var_t (dir (read)))
      

      Issue 2

      [sysadm@vm-sudo9 ~]$ sudo dmidecode
      sudo: unable to open /var: Permission denied
      sudo: /var/log/sudo-io/00/00/02: Permission denied
      sudo: error initializing I/O plugin sudoers_io
      

      Trigger condition

      `/var/log/sudo-io` exists but Proposed fix for Issue 1 not installed.

      Proposed fix

      Same as Proposed fix for Issue 1.


      Issue 3

      [sysadm@vm-sudo9 ~]$ sudo dmidecode
      --> NO OUTPUT
      [sysadm@vm-sudo9 ~]$
      
      [sysadm@vm-sudo9 ~]$ sudo -r sysadm_r dmidecode
      --> NO OUTPUT
      [sysadm@vm-sudo9 ~]$
      

      Trigger condition

      Using recommended configuration in `/etc/sudoers` (automatic role switching):

      %wheel  ALL=(ALL)       TYPE=sysadm_t ROLE=sysadm_r ALL
      

      or Using default configuration + explicitly specifying the role.

      AVCs

      type=PROCTITLE msg=audit(11/09/2023 09:07:26.866:408) : proctitle=/sbin/dmidecode 
      type=EXECVE msg=audit(11/09/2023 09:07:26.866:408) : argc=1 a0=/sbin/dmidecode 
      type=SYSCALL msg=audit(11/09/2023 09:07:26.866:408) : arch=x86_64 syscall=execve success=yes exit=0 a0=0x55992069a5c0 a1=0x7ffe6f400230 a2=0x7ffe6f400240 a3=0x0 items=0 ppid=29740 pid=29741 auid=sysadm uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=8 comm=dmidecode exe=/usr/sbin/dmidecode subj=sysadm_u:sysadm_r:dmidecode_t:s0-s0:c0.c1023 key=(null) 
      type=AVC msg=audit(11/09/2023 09:07:26.866:408) : avc:  denied  { read write } for  pid=29741 comm=dmidecode path=/dev/pts/2 dev="devpts" ino=5 scontext=sysadm_u:sysadm_r:dmidecode_t:s0-s0:c0.c1023 tcontext=sysadm_u:object_r:devpts_t:s0 tclass=chr_file permissive=0 
      type=AVC msg=audit(11/09/2023 09:07:26.866:408) : avc:  denied  { read write } for  pid=29741 comm=dmidecode path=/dev/pts/2 dev="devpts" ino=5 scontext=sysadm_u:sysadm_r:dmidecode_t:s0-s0:c0.c1023 tcontext=sysadm_u:object_r:devpts_t:s0 tclass=chr_file permissive=0 
      type=AVC msg=audit(11/09/2023 09:07:26.866:408) : avc:  denied  { read write } for  pid=29741 comm=dmidecode path=/dev/pts/2 dev="devpts" ino=5 scontext=sysadm_u:sysadm_r:dmidecode_t:s0-s0:c0.c1023 tcontext=sysadm_u:object_r:devpts_t:s0 tclass=chr_file permissive=0 
      type=AVC msg=audit(11/09/2023 09:07:26.866:408) : avc:  denied  { read write } for  pid=29741 comm=dmidecode path=/dev/pts/2 dev="devpts" ino=5 scontext=sysadm_u:sysadm_r:dmidecode_t:s0-s0:c0.c1023 tcontext=sysadm_u:object_r:devpts_t:s0 tclass=chr_file permissive=0 
      

      Root cause: `/dev/pts/2` mislabeled with `devpts_t` instead of `user_devpts_t`

      Why this works in "normal case"

      When not explicitly changing role, the command works.
      This is because this leads to having `dmidecode` execute in wrong context `sysadm_sudo_t`:

      29871 [sysadm_u:sysadm_r:sysadm_sudo_t:s0-s0:c0.c1023] 09:13:36.539520 execve("/sbin/dmidecode" [system_u:object_r:dmidecode_exec_t:s0], ["dmidecode"], ["HISTSIZE=10000", "HOSTNAME=vm-sudo9", "LANG=en_US.UTF-8", "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;37;41:su=37;41:sg=30"..., "TERM=xterm-256color", "MAIL=/var/spool/mail/sysadm", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "LOGNAME=root", "USER=root", "HOME=/root", "SHELL=/bin/bash", "SUDO_COMMAND=/sbin/dmidecode", "SUDO_USER=sysadm", "SUDO_UID=1000", "SUDO_GID=1000"] <unfinished ...>
       :
      29871 [sysadm_u:sysadm_r:sysadm_sudo_t:s0-s0:c0.c1023] 09:13:36.539793 <... execve resumed>) = 0 <0.000210>
      

      In such case, there is some allow rule:

      # sesearch -A -s sysadm_sudo_t -t devpts_t -c chr_file -p write
      allow sysadm_sudo_t devpts_t:chr_file { append ioctl lock open read setattr write };
      

      THIS IS WRONG: processes should never execute in `sysadm_sudo_t` context at all.
      This requires a proper fix in the policy.

      Code location

      # stap -g -d /usr/libexec/sudo/sudoers.so -d /usr/bin/sudo --ldd -v -e 'probe syscall.chown { if (execname() != "sudo" || argstr !~ "/dev/pts/") next; printf("%s(%s)\n", name, argstr); print_usyms(ubacktrace()); raise(%{SIGSTOP%}); mdelay(2000) }'
      [...]
      chown("/dev/pts/2", 0, 5)
       0x7feda7a3e99b : chown+0xb/0x30 [/usr/lib64/libc.so.6]
       0x558bbb95a54e : exec_pty.constprop.0+0x113e/0x2390 [/usr/bin/sudo]
       0x558bbb9511ec : run_command.constprop.0+0x11c/0x360 [/usr/bin/sudo]
       0x558bbb944424 : main+0x2714/0x28d0 [/usr/bin/sudo]
       0x7feda7a3feb0 : __libc_start_call_main+0x80/0xb0 [/usr/lib64/libc.so.6]
       0x7feda7a3ff60 : __libc_start_main@GLIBC_2.2.5+0x80/0x150 [/usr/lib64/libc.so.6]
       0x558bbb944605 : _start+0x25/0x30 [/usr/bin/sudo]
      
      # gdb /usr/bin/sudo <PID>
      [...]
      (gdb) bt
      #0  0x00007feda7a3e99b in chown () from /lib64/libc.so.6
      #1  0x0000558bbb95a54e in get_pty (leader=<optimized out>, follower=<optimized out>, name=<optimized out>, 
          namesz=4096, ttyuid=0) at ./get_pty.c:66
      #2  pty_setup (details=<optimized out>, tty=0x558bbcc8c764 "/dev/pts/1") at ./exec_pty.c:150
      #3  exec_pty.constprop.0 (cstat=0x7ffc71a12e50, details=<optimized out>) at ./exec_pty.c:1368
      #4  0x0000558bbb9511ec in sudo_execute (details=0x558bbb969600 <command_details.lto_priv>, cstat=0x7ffc71a12e50)
          at ./exec.c:402
      #5  run_command (details=0x558bbb969600 <command_details.lto_priv>) at ./sudo.c:977
      #6  0x0000558bbb944424 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at ./sudo.c:305
      

      Source code:

       54 bool
       55 get_pty(int *leader, int *follower, char *name, size_t namesz, uid_t ttyuid)
       56 {
       57     struct group *gr;
       58     gid_t ttygid = -1;
       59     bool ret = false;
       60     debug_decl(get_pty, SUDO_DEBUG_PTY);
       61 
       62     if ((gr = getgrnam("tty")) != NULL)
       63         ttygid = gr->gr_gid;
       64 
       65     if (openpty(leader, follower, name, NULL, NULL) == 0) {
       66         if (chown(name, ttyuid, ttygid) == 0)   <<<<< HERE
       67             ret = true;
       68     }
       69 
       70     debug_return_bool(ret);
       71 }
      

      We have `openpty()` return a PTY with unexpected context `devpts_t`.

      Proposed fix (TE format)

      policy_module(sudodomain_devpts_t, 1.0)
      gen_require(`
          type user_devpts_t;
          attribute sudodomain;
      ')
      term_create_pty(sudodomain, user_devpts_t)
      allow sudodomain user_devpts_t:chr_file { setattr rw_chr_file_perms };
      

      (Stolen from `policy/modules/system/userdomain.te` for `confined_admindomain`)

              rhn-support-zpytela Zdenek Pytela
              rhn-support-rmetrich Renaud Métrich
              Nikola Kňažeková Nikola Kňažeková (Inactive)
              Milos Malik Milos Malik
              Jan Fiala Jan Fiala
              Votes:
              0 Vote for this issue
              Watchers:
              12 Start watching this issue

                Created:
                Updated:
                Resolved: