Question

I'm trying to understand what logic determines whether a user can log in with a particular MLS sensitivity level. At first I suspected that pam_selinux.so reads the /etc/selinux/.../seusers file to understand which user is bound to which seuser and then restricts the user to sensitivities equal to or lower than the high component of the MLS range.

However, after scratching through its source code I found that, after asking the user if he would like to change their security context from the the default context, pam_selinux checks that the new MLS labels are appropriate by calling into the kernel policy.

The following code is in modules/pam_selinux/pam_selinux.c from the Ubuntu libpam-modules 1.1.1-4ubuntu2 package.

static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, security_context_t dst, int debug)
{
  struct av_decision avd;
  int retval;
  unsigned int bit = CONTEXT__CONTAINS;
  context_t src_context = context_new (src);
  context_t dst_context = context_new (dst);
  context_range_set(dst_context, context_range_get(src_context));
  if (debug)
    pam_syslog(pamh, LOG_NOTICE, "Checking if %s mls range valid for  %s", dst, context_str(dst_context));

  retval = security_compute_av(context_str(dst_context), dst, SECCLASS_CONTEXT, bit, &avd);
  context_free(src_context);
  context_free(dst_context);
  if (retval || ((bit & avd.allowed) != bit))
    return 0;

  return 1;
}

It seems to me that this check is actually checked in the kernel policy, seen in the security_compute_av() call. This turned my understanding of SELinux login on my head.

So, could someone please explain:

  • How is the validity of a user-chosen login security level determined?

  • How exactly is that logic implemented in the policy, in pam_selinux, and in the kernel?

Currently, I'm not too interested in type enforcement multi, categories security, or role based access control, so no need to explain how those components are validated if they don't affect MLS sensitivities.

Was it helpful?

Solution

Given that I also share the "SELinux folds my brain in half" problem, I think I can help. First and foremost, you need to remember the difference between discretionary access control and mandatory access control. You also need to remember that user space defines a lot of things, but the kernel gets to enforce them.

First, here is a partial list of user space versus kernel space issues:

  • User space defines a valid user ID, the kernel creates processes owned by that user ID (the number, not the name)
  • User space puts permissions and ownership on a file on an ext3/4 file system, the kernel enforces access to that file based upon the file inode and every subsequent parent directory inode
  • If two users share the same user ID in /etc/passwd, the kernel will grant them both the same privileges because enforcement is done by the numeric identifier, not the textual one
  • User space requests a network socket to another host, the kernel isolates that conversation from others on the same system
  • With SELinux, user space defines roles, logins, and users via semanage and the kernel compiles those down into a large Access Vector Cache (AVC) so that it can enforce role-based access control and mandatory access control
  • Also under SELinux, a security administrator can use semanage to define a minimum and maximum security context. If you are in a multi-level security (MLS) configuration, and during log in, the users picks some context, then the kernel measures that against the AVC to determine if it is allowed.

What would probably help this make sense is to be in a multi-level security configuration. I took the class on SELinux and we touched it for about two hours. Most people don't want to go there. Ever. I've been in an MLS configuration quite a bit, so I understand the reasoning behind the coding decision you were chasing, but I agree that tinkering with MLS is a pretty painful way to understand how and why PAM works like it does.

Discretionary Access Control (DAC) is where user space, especially non-root users, can define who can access data that they control and in what fashion. Think file permissions. Because users control it, there is a trivial amount of effort needed to allow one user to see processes and/or files owned by another user. Normally, we don't care that much because a good administrator assumes that any one user could compromise the whole box and so all users are trusted equally. This might be very little trust, but there is still some level of trust.

Mandatory Access Control (MAC) is where user space is not to be trusted. Not all users are created equal. From a non-MLS perspective, consider the case where you have a web server and a database server on the same hardware (it will never survive the Slashdot effect). The only time the two processes communicate is over a dedicated connection channel over TCP. Otherwise, they must not even know that the other exists. We would operate them under two different contexts and the kernel will enforce the separation. Even looking at the process table or wandering around the hard drive as root will not get you any closer unless you change contexts.

In an MLS configuration, I can't tell you how many times I've tried to get random combinations of sensitivity and context only to be rebuffed for picking an invalid combination. It can be very frustrating because it takes a lot of exploring of your existing policy (/etc/selinux/policy/src/policy/policy under Red Hat 5) to know what it or is not allowed.

Under a Strict configuration, I can clearly see why all of this is overkill. And that's simply because SELinux is overkill for simple situations. It has other features though that partially redeem it, but chief among them is fine grained access control that enforces administrator-set permissions. One area that this is used the most is in restricting service daemons to just their essential access needed. It is painful to set up a new daemon, but it keeps trivial exploitations like a shared library exploit from going any further because the process in question may be assigned to a role that won't let it run non-daemon commands like /bin/ls or a shell. Exploits don't do you much good in those situations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top