Bug 697775 - AVCs and sudoedit: mkstemps: Permission denied
Summary: AVCs and sudoedit: mkstemps: Permission denied
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 6
Classification: Red Hat
Component: sudo
Version: 6.1
Hardware: All
OS: Linux
high
high
Target Milestone: rc
: ---
Assignee: Daniel Kopeček
QA Contact: BaseOS QE Security Team
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2011-04-19 08:40 UTC by Milos Malik
Modified: 2012-11-05 15:32 UTC (History)
7 users (show)

Fixed In Version: sudo-1.7.4p5-8.el6
Doc Type: Bug Fix
Doc Text:
Cause: File manipulation done by sudoedit was performed under a wrong SELinux context. Consequence: Editing files using sudoedit was impossible when SELinux was in enforcing mode and if a SELinux context was specified by the sudoers rule allowing the user to use sudoedit. Fix: The code was modified in a way that allows a transition to the correct SELinux context and perform file manipulation under the correct SELinux context. Result: The user is able to edit files using sudoedit with SELinux set to enforcing mode.
Clone Of:
Environment:
Last Closed: 2012-06-20 14:18:29 UTC
Target Upstream Version:


Attachments (Terms of Use)
proposed patch (21.77 KB, patch)
2011-10-20 12:18 UTC, Daniel Kopeček
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2012:0905 0 normal SHIPPED_LIVE sudo bug fix update 2012-06-19 20:46:54 UTC

Description Milos Malik 2011-04-19 08:40:25 UTC
Description of problem:


Version-Release number of selected component (if applicable):
selinux-policy-minimum-3.7.19-85.el6.noarch
selinux-policy-doc-3.7.19-85.el6.noarch
selinux-policy-targeted-3.7.19-85.el6.noarch
selinux-policy-3.7.19-85.el6.noarch
selinux-policy-mls-3.7.19-85.el6.noarch

How reproducible:
always

Steps to Reproduce:
1) create an staff_u user
2) set a password for the user
3) allow the user to edit /etc/motd file via sudoedit
( echo "USERNAME ALL = (root) sudoedit /etc/motd" >> /etc/sudoers )
4) log in as the user (works in both SSH session and X session)
5) run "sudoedit /etc/motd" and you will see following:
[sudo] password for sudotester: 
sudoedit: mkstemps: Permission denied

Actual results:
----
time->Tue Apr 19 04:37:14 2011
type=SYSCALL msg=audit(1303202234.725:1265): arch=80000015 syscall=99 success=no exit=-13 a0=10020ed38c0 a1=fffddbf6688 a2=fffddbf65f8 a3=5355444f5f474944 items=0 ppid=6787 pid=6808 auid=501 uid=0 gid=503 euid=0 suid=0 fsuid=0 egid=503 sgid=503 fsgid=503 tty=pts2 ses=41 comm="sudoedit" exe="/usr/bin/sudoedit" subj=staff_u:staff_r:staff_sudo_t:s0 key=(null)
type=AVC msg=audit(1303202234.725:1265): avc:  denied  { getattr } for  pid=6808 comm="sudoedit" name="/" dev=devpts ino=1 scontext=staff_u:staff_r:staff_sudo_t:s0 tcontext=system_u:object_r:devpts_t:s0 tclass=filesystem
----
time->Tue Apr 19 04:37:15 2011
type=SYSCALL msg=audit(1303202235.017:1270): arch=80000015 syscall=5 success=no exit=-13 a0=10020eda7b0 a1=c2 a2=180 a3=df02dc items=0 ppid=6787 pid=6808 auid=501 uid=501 gid=503 euid=501 suid=0 fsuid=501 egid=503 sgid=503 fsgid=503 tty=pts2 ses=41 comm="sudoedit" exe="/usr/bin/sudoedit" subj=staff_u:staff_r:staff_sudo_t:s0 key=(null)
type=AVC msg=audit(1303202235.017:1270): avc:  denied  { write } for  pid=6808 comm="sudoedit" name="tmp" dev=dm-0 ino=917563 scontext=staff_u:staff_r:staff_sudo_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=dir
----

Expected results:
no AVCs

Comment 1 Milos Malik 2011-04-19 08:47:03 UTC
The result is: the user is not able to modify the file via sudoedit. "sudoedit /etc/motd" exits almost immediately after the password is given.

The same result is achievable when you use "sudo -e" instead of "sudoedit".

Comment 2 Milos Malik 2011-04-19 08:51:55 UTC
I played a little bit with EDITOR variable, but the issue still remains.

$ EDITOR=/usr/bin/modifier.sh sudoedit /etc/motd
[sudo] password for sudotester: 
sudoedit: mkstemps: Permission denied

$ cat /usr/bin/modifier.sh
#!/bin/bash
echo '# blahblah' >> $1

Comment 3 Daniel Walsh 2011-04-19 14:55:26 UTC
You need to change the type and role for the user to an admin role.

"USERNAME ALL = (root) ROLE=sysadm_r TYPE=sysadm_t sudoedit /etc/motd" >> /etc/sudoers

staff_t is not an admin, it is a user role that can transition to an admin role through sudo, but you need to transition via sudo or new role.

newrole -r sysadm_r
sudoedit /etc/motd 

Should have worked also, but I prefer to modify the sudo command.

Comment 4 Milos Malik 2011-04-19 15:12:04 UTC
# useradd -Z staff_u sudotester
# passwd sudotester
Changing password for user sudotester.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
# visudo 
# grep sudotester /etc/sudoers
sudotester ALL = (root) ROLE=sysadm_r TYPE=sysadm_t sudoedit /etc/motd
# 

[sudotester@localhost ~]$ id
uid=511(sudotester) gid=512(sudotester) groups=512(sudotester) context=staff_u:staff_r:staff_t:s0
[sudotester@localhost ~]$ newrole -r sysadm_r
Password: 
[sudotester@localhost ~]$ id
uid=511(sudotester) gid=512(sudotester) groups=512(sudotester) context=staff_u:sysadm_r:sysadm_t:s0
[sudotester@localhost ~]$ sudoedit /etc/motd 
[sudo] password for sudotester: 
sudoedit: mkstemps: Permission denied
[sudotester@localhost ~]$ echo $?
1

mkstemps still complains and I still see following AVCs:
----
time->Tue Apr 19 17:08:41 2011
type=SYSCALL msg=audit(1303225721.811:1462): arch=40000003 syscall=99 success=no exit=-13 a0=121dff0 a1=bfea8068 a2=f847cc a3=2 items=0 ppid=11836 pid=11868 auid=511 uid=0 gid=512 euid=0 suid=0 fsuid=0 egid=512 sgid=512 fsgid=512 tty=pts0 ses=72 comm="sudoedit" exe="/usr/bin/sudoedit" subj=staff_u:sysadm_r:sysadm_sudo_t:s0 key=(null)
type=AVC msg=audit(1303225721.811:1462): avc:  denied  { getattr } for  pid=11868 comm="sudoedit" name="/" dev=devpts ino=1 scontext=staff_u:sysadm_r:sysadm_sudo_t:s0 tcontext=system_u:object_r:devpts_t:s0 tclass=filesystem
----
time->Tue Apr 19 17:08:45 2011
type=SYSCALL msg=audit(1303225725.419:1466): arch=40000003 syscall=5 success=no exit=-13 a0=1224678 a1=c2 a2=180 a3=3c3759 items=0 ppid=11836 pid=11868 auid=511 uid=511 gid=512 euid=511 suid=0 fsuid=511 egid=512 sgid=512 fsgid=512 tty=pts0 ses=72 comm="sudoedit" exe="/usr/bin/sudoedit" subj=staff_u:sysadm_r:sysadm_sudo_t:s0 key=(null)
type=AVC msg=audit(1303225725.419:1466): avc:  denied  { write } for  pid=11868 comm="sudoedit" name="tmp" dev=dm-0 ino=47 scontext=staff_u:sysadm_r:sysadm_sudo_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=dir
----

Comment 5 Daniel Walsh 2011-04-19 15:27:17 UTC
Miroslav I think we need to add

	domain_auto_transition_pattern($1_sudo_t, sudo_exec_t, $3)

to sudo_role_template.

Milos if you add

policy_module(mysudo, 1.0)
gen_require(`
type sysadm_sudo_t, sudo_exec_t, sysadm_t;
')
domain_auto_transition_pattern(sysadm_sudo_t, sudo_exec_t, sysadm_t)


Does this work?

Comment 6 Milos Malik 2011-04-20 09:07:21 UTC
The module described in comment#5 did not help. I still see the same AVCs as in comment#4.

Comment 7 Miroslav Grepl 2011-04-20 10:50:01 UTC
The problem with 

"USERNAME ALL = (root) ROLE=sysadm_r TYPE=sysadm_t /usr/bin/sudoedit /etc/motd" 

or

newrole -r sysadm_r
sudoedit /etc/motd 


is we have the following transition

sysadm_t -> sudo_exec_t -> sysadm_sudo_t

Comment 8 Miroslav Grepl 2011-04-20 13:30:40 UTC
It works fine with 

type sysadm_sudo_tmp_t;
files_type(sysadm_sudo_tmp_t)

manage_files_pattern(sysadm_sudo_t, sysadm_sudo_tmp_t, sysadm_sudo_tmp_t)
files_tmp_filetrans(sysadm_sudo_t, sysadm_sudo_tmp_t, { file })

Comment 9 Miroslav Grepl 2011-04-20 13:55:14 UTC
One more avc msg

avc:  denied  { write } for  pid=32458 comm="sudoedit" name="motd" dev=dm-0 ino=132402 scontext=staff_u:sysadm_r:sysadm_sudo_t:s0 tcontext=system_u:object_r:etc_runtime_t:s0  tclass=file


Milos,
could you test it with a local policy which will have



type sysadm_sudo_tmp_t;
files_type(sysadm_sudo_tmp_t)

manage_files_pattern(sysadm_sudo_t, sysadm_sudo_tmp_t, sysadm_sudo_tmp_t)
files_tmp_filetrans(sysadm_sudo_t, sysadm_sudo_tmp_t, { file })

Comment 11 Milos Malik 2011-04-20 14:47:30 UTC
Following module solved my problem. I don't see any AVCs in enforcing mode when running the automated test.

policy_module(mypol2, 1.0)

gen_require(`
    type sysadm_sudo_t, sudo_exec_t, sysadm_t, etc_t, devpts_t;
')

type sysadm_sudo_tmp_t;
files_type(sysadm_sudo_tmp_t)

manage_files_pattern(sysadm_sudo_t, sysadm_sudo_tmp_t, sysadm_sudo_tmp_t)
files_tmp_filetrans(sysadm_sudo_t, sysadm_sudo_tmp_t, { file })

allow sysadm_sudo_t etc_t:file write;
allow sysadm_sudo_t devpts_t:filesystem getattr;

Comment 12 Daniel Walsh 2011-04-20 15:19:38 UTC
We need to make changes to the sudoedit code, perhaps some more SELinux inteligence.  We do not want to allow sudoedit to manage any file.

We want to have the editing context actually be syadm_t.

It looks from the AVC's as if sudoedit copies the file to /tmp and then when the user finishes editing it, copies the file over the existing file.

With this policy we have the editor running as sysadm_t which is what we want, but we want the portion of sudoedit that copies /tmp/motd over /etc/motd to be done as sysadm_t also, not as sysadm_sudo_t or staff_sudo_t.

I am reassigning for now to sudo to see if they can explain how sudoedit is working here.

I do not think we can get this done quickly and probably should move this bug to 6.2

Comment 15 Daniel Kopeček 2011-10-11 10:14:14 UTC
(In reply to comment #12)
> We need to make changes to the sudoedit code, perhaps some more SELinux
> inteligence.  We do not want to allow sudoedit to manage any file.

I see two options here:

 1. Use setcon() to change the domain from sudo_t to the requested one
    before doing anything to the files. This probably requires setcurrent & 
    dyntrans to be allowed.

 2. Create a helper (like sesh) which sudo could exec() in the right
    domain and the helper would do the file manipulation and execute the
    editor.

I guess the later option doesn't require modification of the policy since such a transition (exec based) is already allowed.

> We want to have the editing context actually be syadm_t.
>
> It looks from the AVC's as if sudoedit copies the file to /tmp and then when
> the user finishes editing it, copies the file over the existing file.

Yes, that is true. See below for a schematic view of how it works there.

> With this policy we have the editor running as sysadm_t which is what we want,
> but we want the portion of sudoedit that copies /tmp/motd over /etc/motd to be
> done as sysadm_t also, not as sysadm_sudo_t or staff_sudo_t.
> 
> I am reassigning for now to sudo to see if they can explain how sudoedit is
> working here.

Here's how it works in the sudoedit code:

source user = user executing sudo
target user = ...

1. make a copy
  - for each file do:
      seteuid(target user)
      open() + stat() original file
      seteuid(root)
      ... sanity checks ...
      seteuid(source user)
      mkstemp()
      seteuid(root)
      read()+write() (original->temp)
      close()
 
2. run the editor
  - here is all the selinux stuff performed:
    run_command() -> selinux_setup() -> fork()+selinux_execve()

3. replace the original files with the modified copies
  - for each temp file:
    seteuid(source user)
    open() + stat()
    seteuid(root)
    ... sanity & modification checks ...
    seteuid(target user)
    open() original file
    seteuid(root)
    read()+write() (temp->original)
    unlink() temp file
    close()

Comment 16 Miroslav Grepl 2011-10-11 11:20:21 UTC
Let's wait for Dan's comment.

The second solution could work. If I understand correctly.

Comment 17 Daniel Walsh 2011-10-11 15:38:55 UTC
I like the sesh idea so sudo execs sesh -c EDITOR /tmp/BLAH

Comment 18 Daniel Kopeček 2011-10-19 15:25:36 UTC
Things are more complicated than I thought with the second option. Sudo executes the $EDITOR under the source user. That's good for security, but not for what we are trying to do and I thing that it's actually wrong behavior if selinux is enabled and used (ROLE= and TYPE= set in sudoers), because the editor gets executed with the source uid + target domain, not target uid (runas) and target domain.

However, we can't just change this so that the editor gets executed as the target user, because then he could escape from it and do what he's not supposed to do under the target uid (usually 0).

I'll attach a patch which tries to solve at least the problem with moving the files to /tmp and back. Here is a short description of how it should look like with the patch applied:

1) Copy to /tmp
 - construct (from, to) pairs of strings where
    from = path to the original file
      to = tempnam("/tmp", ...) generated path
 - execute "sesh -e 0 from1 to1 from2 to2 ..." under the target domain
    here the "to#" files are opened with O_CREAT | O_EXCL, and if something
    fails, we'll abort the whole process
 - chown() the temp files to the source user

2) Run the editor (same as before)

3) Copy the files back
   almost the same as in 1) but sesh is executed with each pair reversed and
   the temp files are chowned() back to the target user before executing the
   sesh helper. Also -e is set to 1 to signal the other direction to sesh
   (needed for doing a proper cleanup).

We could generate the temporary files in the helper but then we would have to pass somehow the paths to the parent which executes the editor since we can't execute it from sesh (can't to seteuid() there...)

As this is way too complex (either way) and changes the behavior of sudo, I think it's a good idea not to include this in 6.2, but in 6.3 where a rebase from the 1.7.x to the 1.8.x branch is planned.

Comment 19 Daniel Kopeček 2011-10-20 12:18:57 UTC
Created attachment 529253 [details]
proposed patch

The attached patch changes the way sudo copies files to and from a temporary place for editing. With the patch applied, the copy operation is performed under the selinux domain specified in the sudoers file.

Comment 20 Daniel Kopeček 2011-10-20 12:21:20 UTC
There are still some AVCs. I guess we need to allow chown for the sesh process. It's needed to change the owner of the temporary file before and after editing.

----
time->Thu Oct 20 14:12:53 2011
type=USER_CMD msg=audit(1319112773.688:35249): user pid=18105 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='cwd="/home/sudotester" cmd=2F62696E2F7669202F6574632F6D6F7464 terminal=pts/1 res=success'
----
time->Thu Oct 20 14:12:53 2011
type=USER_ROLE_CHANGE msg=audit(1319112773.690:35250): user pid=18105 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='newrole: old-context=staff_u:staff_r:staff_t:s0 new-context=staff_u:sysadm_r:sysadm_t:s0: exe="/usr/bin/sudo" hostname=? addr=? terminal=pts/1 res=success'
----
time->Thu Oct 20 14:12:53 2011
type=USER_ROLE_CHANGE msg=audit(1319112773.691:35251): user pid=18106 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='newrole: old-context=staff_u:staff_r:staff_t:s0 new-context=staff_u:sysadm_r:sysadm_t:s0: exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'
----
time->Thu Oct 20 14:12:53 2011
type=USER_ROLE_CHANGE msg=audit(1319112773.731:35253): user pid=18107 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='newrole: old-context=staff_u:staff_r:staff_t:s0 new-context=staff_u:sysadm_r:sysadm_t:s0: exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'
----
time->Thu Oct 20 14:12:53 2011
type=SYSCALL msg=audit(1319112773.717:35252): arch=c000003e syscall=92 success=no exit=-1 a0=7f09891c64f0 a1=1f5 a2=1f5 a3=0 items=0 ppid=8927 pid=18105 auid=501 uid=0 gid=501 euid=0 suid=0 fsuid=0 egid=501 sgid=501 fsgid=501 tty=pts1 ses=6 comm="sudo" exe="/usr/bin/sudo" subj=staff_u:staff_r:staff_sudo_t:s0 key=(null)
type=AVC msg=audit(1319112773.717:35252): avc:  denied  { chown } for  pid=18105 comm="sudo" capability=0  scontext=staff_u:staff_r:staff_sudo_t:s0 tcontext=staff_u:staff_r:staff_sudo_t:s0 tclass=capability
----
time->Thu Oct 20 14:12:58 2011
type=USER_ROLE_CHANGE msg=audit(1319112778.915:35254): user pid=18105 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='newrole: old-context=staff_u:staff_r:staff_t:s0 new-context=staff_u:sysadm_r:sysadm_t:s0: exe="/usr/bin/sudo" hostname=? addr=? terminal=pts/1 res=success'
----
time->Thu Oct 20 14:12:58 2011
type=USER_ROLE_CHANGE msg=audit(1319112778.915:35256): user pid=18108 uid=0 auid=501 ses=6 subj=staff_u:staff_r:staff_sudo_t:s0 msg='newrole: old-context=staff_u:staff_r:staff_t:s0 new-context=staff_u:sysadm_r:sysadm_t:s0: exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'
----
time->Thu Oct 20 14:12:58 2011
type=SYSCALL msg=audit(1319112778.915:35255): arch=c000003e syscall=92 success=no exit=-1 a0=7f09891c64f0 a1=0 a2=0 a3=38 items=0 ppid=8927 pid=18105 auid=501 uid=0 gid=501 euid=0 suid=0 fsuid=0 egid=501 sgid=501 fsgid=501 tty=pts1 ses=6 comm="sudo" exe="/usr/bin/sudo" subj=staff_u:staff_r:staff_sudo_t:s0 key=(null)
type=AVC msg=audit(1319112778.915:35255): avc:  denied  { chown } for  pid=18105 comm="sudo" capability=0  scontext=staff_u:staff_r:staff_sudo_t:s0 tcontext=staff_u:staff_r:staff_sudo_t:s0 tclass=capability

Comment 21 Daniel Kopeček 2011-10-20 12:28:34 UTC
(In reply to comment #20)
> There are still some AVCs. I guess we need to allow chown for the sesh process.
> It's needed to change the owner of the temporary file before and after editing.

I meant the _sudo_ process.

Comment 22 Daniel Walsh 2011-10-20 19:50:56 UTC
Miroslav we should add this to policy.

Comment 30 Daniel Kopeček 2012-05-29 11:55:58 UTC
    Technical note added. If any revisions are required, please edit the "Technical Notes" field
    accordingly. All revisions will be proofread by the Engineering Content Services team.
    
    New Contents:
Cause:
File manipulation done by sudoedit was performed under a wrong SELinux context.

Consequence:
Editing files using sudoedit was impossible when SELinux was in enforcing mode and if a SELinux context was specified by the sudoers rule allowing the user to use sudoedit.

Fix:
The code was modified in a way that allows a transition to the correct SELinux context and perform file manipulation under the correct SELinux context. 

Result:
The user is able to edit files using sudoedit with SELinux set to enforcing mode.

Comment 31 errata-xmlrpc 2012-06-20 14:18:29 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.

http://rhn.redhat.com/errata/RHBA-2012-0905.html


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