danwalsh (danwalsh) wrote,
danwalsh
danwalsh

SELinux Reveals Bugs in other code.

One of the interesting things about SELinux is its use to discover bugs in other code. When I first started working with SELinux a few years ago, we started discovering a whole bunch of domains wanting to read and write system_u:object_r:initctl_t file. This is the context of the /dev/initctl device. After investigating for a while we found out something in the boot process was leaking an open file descriptor to /dev/initctl. This open file descriptor would allow a compromised application to change the run level of the system. Of course all of these AVC messages were being reported as bugs in SELinux, but really they were a serious bug in the boot process. Investigating this problem further I found that the default behavior of all file descriptors is to have them inherited over the fork/exec. You have to execute fcntl(fd, F_SETFD, FD_CLOEXEC); on all file descriptors that you do not want to be leaked. Needless to say, lots of programmers forget this and leaked file descriptors are quite common.

When writing policy, they are sometimes hard to detect especially if you do not know what to look for. This is one reason the review process of policy writing is good. Problems like leaked file descriptors show the weakness in tools that automatically generate policy, since the default would be allow access to the leaked descriptors.

One of the new features in Fedora Core 5 was the inclusion of the executable memory checking for unconfined applications. These checks are looking for places in code where memory could be written to and executed. Buffer overflows take advantage of programs that allow this to happen. The goal of almost every exploit is to execute the crackers own code. This is one of the main ways crackers have been able to break into systems. In the FC4 time frame we added checks for execmem, execmod, execheap, and execstack. We also added a boolean for each one of these memory checks: allow_execmem, allow_execmod, allow_execheap, allow_execstack. All of these booleans were turned on by default. This allowed all unconfined domains to run even if the kernel discovered an application of library that was coded incorrectly. Confined domains for the most part did not allow these accesses.

Ulrich Drepper has writing extensively on how to improve programming practices and the overall quality of the code, pushed hard to change these rules to be denied by default. This would allow us to improve the overall security of the system and allow us to find and clean up badly written programs. So in FC5, we turned off the boolean allow_execheap and allow_execmod. In Rawhide, we currently have allow_execstack and allow_execmem turned off also.

You as a user could turn these booleans on or off by executing.

setsebool -P allow_execmod=1 or setsebool -P allow_execmod=0

For each boolean.

Now lets delve further into these checks. Ulrich wrote up a technical explanation of these checks in http://people.redhat.com/~drepper/selinux-mem.html, which I will borrow from for this blog.

execmod

This access is seen on files, usually DSOs (shared libraries). Basically a DSO is loaded, at some point the application determines the code needs text relocation and uses the mprotect call to set the memory region read/write. After the text relocation, the code is marked back to read/exec which triggers the access check. Usually the DSO does not need to be text relocatable, but a programming mistake has happened. For further and probably a much more correct explanation of text relocation, look in section 2 of http://people.redhat.com/~drepper/dsohowto.pdf
Since this mistake is so prevalent we have added a file context textrel_shlib_t which marks DSOs as allowing this privilege. So if you get an execmod on a library, you should report this as a bug to the package maintainer or upstream. And if you really want the application to run, mark the DSO as textrel_shlib_t.

chcon -t textrel_shlib_t PATHTOSHAREDLIBRARY

If you want to survive a relabel you can modify the local file context to label this file

semanage fcontext -a -t textrel_shlib_t PATHTOSHAREDLIBRARY

If you feel this should be in the default policy should also submit a bug on the selinux-policy package.

You can also find libraries that require execmod priv by executing

readelf -d PROGRAMS | fgrep TEXTREL

execstack

We have found a few programs that had the execstack flag turned on, but have been able to fix everyone of these fairly easily.

Ulrich says it all:

"As the name suggests, this error is raised if a program tries to make its stack (or parts thereof) executable with an mprotect call. This should never, ever be necessary. Stack memory is not executable on most OSes these days and this won't change. Executable stack memory is one of the biggest security problems. An execstack error might in fact be most likely raised by malicious code."

Some libraries/applications are accidentally marked as requiring execstack. These usually happen because of a mistake in the build procedure. You can check if a library/application requires execstack by using the execstack utility.

execstack -q PATHTOPROGRAM

You can try to clean the flag and see if the application still runs.

execstack -c PATHTOPROGRAM

You should immediately report this as a bugzilla to the packager and/or the upstream maintainer to fix the code.

For a further discussion of execstack, you can look at section 4 of this security document, written by Ulrich.

http://people.redhat.com/drepper/nonselsec.pdf

execheap

Ulrich says it all:

"The POSIX specification does not permit it, but the Linux implementation of mprotect allows changing the access protection of memory on the heap (e.g., allocated using malloc). This error indicates that heap memory was supposed to be made executable. Doing this is really a bad idea. If anonymous, executable memory is needed it should be allocated using mmap which is the only portable mechanism."

I have not seen a single bugzilla on execheap, so I would guess that most of Fedora code is clean.

execmem

There might be some reasonable uses for execmem, but Ulrich describes how programs could program in a safer manner to not require this access. Again if you find an application requiring this priv you should report it immediately to the upstream maintainers and to the selinux-policy. Since there is no way to get around this one other than setting allow_execstack to on.

Conclusion

Most of the problems that arose in FC5 being released were caused by the allow_execmod check being turned off. Turns out hundreds of libraries on the system are built incorrectly. Of course when the application does not run correctly because a library like libflashplayer is denied execmod, the user sees it as SELinux broke his application. We have tried to mark all of the libraries that require this priv as we find them, and hopefully the upstream maintainers are taking action to cleanup there libraries. Hopefully the pain all of us have felt by turning up the protection on user space will allow us to have safer more secure systems.

Subscribe

  • Container Domains (Types)

    One of the things people have always had a hard time understanding about SELinux is around different types. In this blog, I am going to discuss…

  • Musings on Hybrid Cloud

    I work on the lowest levels of container runtimes and usually around process security. My team and I work on basically everything needed run…

  • Container Labeling

    An issue was recently raised on libpod, the github repo for Podman. "container_t isn't allowed to access container_var_lib_t" Container policy…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 19 comments

  • Container Domains (Types)

    One of the things people have always had a hard time understanding about SELinux is around different types. In this blog, I am going to discuss…

  • Musings on Hybrid Cloud

    I work on the lowest levels of container runtimes and usually around process security. My team and I work on basically everything needed run…

  • Container Labeling

    An issue was recently raised on libpod, the github repo for Podman. "container_t isn't allowed to access container_var_lib_t" Container policy…