By spencer, Friday, May 5, 2006 · 8:49 am

I realized after posting the first article in this series that I gave very little indication on where I plan to head with this subject. So perhaps a game plan is an order.

Errata: At the beginning I planned to focus on the environment and SELinux. I hoped to explain how certain types of applications still remain vulnerable to environmental contamination even in the face of MAC like SELinux. This would simply involve a discussion of the environment, the noatsecure permission (or lack thereof), and those environmental factors which are handled by this permission and those that are still capable of influencing execution. However, after starting the article I realized that such an explanation would stop short, probably being of little value to readers in the end and leaving me feeling slightly unsatisfied.

We started in the first article by exploring the environment, the linker, and the names of the environment variables that can influence the execution. In this article we will be discussing the kernel code that facilitates enforcement of some level of environmental protection in userland. After discussing the kernel the next article will jump back into the userland and glibc and delve into the similarities between suid/sgid protection and the SELinux noatsecure permission. Finally I would like to wrap up with what started all of this, a discussion about environment vulnerabilities that still exist even in the presence of strong MAC like SELinux; this will focus on scripting and interperted languages. I apologize for the administrative errata but I wanted to layout a road map. Now, onto the kernel discussion…

Why are we talking about the kernel here?
Well I could just come out and tell you why things are the way they are, and this is what the 3rd or 4th part in this series will do. But this is not the point of my articles in general. I like exploring the whys behind things and I take my articles down that path with me. If you don’t like knowing the why you could probably just skip this article and perhaps the next one… the end result won’t be discussed until the last article in this series.

Last time I alluded to the role glibc plays in securing the environment. I said that the secret to securing the environment lay in the appropriately named __libc_enable_secure within glibc. But before we explore glibc any further we should briefly visit the kernel.

Well that took awhile but I think we’re ready to get back on track. So we have this security_ops structure with a bunch of function pointers within. For this series all we’re really worried about is a single function pointer, bprm_secureexec. From include/security.h[1]:

* @bprm_secureexec:
* Return a boolean value (0 or 1) indicating whether a "secure exec"
* is required. The flag is passed in the auxiliary table
* on the initial stack to the ELF interpreter to indicate whether libc
* should enable secure mode.
* @bprm contains the linux_binprm structure.

If traditional capabilities are used or if CONFIG_SECURITY is enabled but no specific module is loaded (eg the “dummy” module is in use) than the traditional capability hooks perform two checks:

  1. user identifier (uid) is not equal to effective user identifier(euid)
  2. group identifier (gid) is not equal to effective group identifier (egid)

If either of these cases is true than the bprm_secureexec will return true.

So this is fine and dandy for the capabilities and the dummy module, but what happens with security modules? Well security models that need to protect their definition of a target process from their definition of a source also render a decision in a similar fashion. SELinux renders a decision based on the domains involved. If a process execv()s the SELinux security hook comparies the two SIDs, the original SID of the parent process and the SID of the new child process (the in-core integer representation of the home readable security context). If the two SIDS are different it means a domain transition occured. It is under these circumstances that SELinux must protect the child process from environmental influence from the parent process. The selinux_bprm_secureexec function found in security/selinux/hooks.c on line 1575 is responsible for rendering that decision from SELinux.

Capabilities, LSM/SELinux, etc, all render a decision but what happens with the result of this decision? We only need to look in two files to have a basic understanding of what happens here: include/linux/auxvec.h and fs/binfmt_elf.c. Lets start with auxvec.h first. We really only need it for a single piece of information but the usage of that information may lead to confusion. If you open that file and read the first comment you will see that the file contains “Symbolic values for the entries in the auxiliary table put on the initial stack”. Huh? Basically it defines a set of names and their associated values. The names/values are used in when constructing an executable in memory. These values are really just indices into a table put on the stack of an executable program by the ELF loader in the kernel. If you’re still feeling a little woozy these numbers are basically used as an index to store a value. That single piece of information I mentioned above can be found on line 27, the definition of AT_SECURE. The value assigned to AT_SECURE is 23… remember that… twenty-three.

So now we can move into fs/binfmt_elf.c. We’re looking for the AT_SECURE again, it’s only in one place, on line 207:
NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));

Huh? Well there is a macro defined a few lines up that might help. If we use the expand that NEW_AUX_ENT macro we get this:
do { elf_info[ei_index++] = AT_SECURE; elf_info[ei_index++] = security_bprm_secureexec(bprm); } while (0)

Beginning to make more sense? Good. In case it doesn’t just know that elf_info stores what are basically name-value pairs in alternating locations in the array. The name, which was #defined to a value above, comes first followed by a value. So we’re storing the decision made by the security server regarding secure execution (aka cleaning the environment) at a location immediately following the location that contains AT_SECURE (the number 23).

That’s it for now… if you forget everything else by the time the next article is posted please remember one thing: the decision made in the bprm_secureexec function, regardless of the security model (basic capabilities or SELinux or another LSM), is stored in the ELF table contain interpretor information at the index indentified by AT_SECURE…. ah forget it. I can’t even remember all of that, just remember 23.

[0] AT_SECURE kernel patch post

[1] All research was based on kernel 2.6.15 w/ Gentoo patchset r7.

Add your own comment or set a trackback

Currently 1 comment

  1. Pingback by The Environment, Environmental Contamination, and SELinux (part 3) · Beyond Abstraction

    [...] OK I’m going to go ahead and post this in the hopes it forces me to finish the series (1 year later). Check back for updates. Not going to be this weekend, but by next weekend I promise I’ve had the below comments around since I start part 1, but things kinda went awry (marriage, and then things just went downhill from there ). Regardless here is a teaser of the final segment of the series. BTW, if you guys actually cared you woulda hounded me to finish :-/ Still, I promise I’ll finish up this segment this week. [...]

Add your own comment

Powered by WP Hashcash



Follow comments according to this article through a RSS 2.0 feed


Jump to start of page | Jump to posts