Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
SELinux Cookbook

You're reading from  SELinux Cookbook

Product type Book
Published in Sep 2014
Publisher
ISBN-13 9781783989669
Pages 240 pages
Edition 1st Edition
Languages
Author (1):
Sven Vermeulen Sven Vermeulen
Profile icon Sven Vermeulen

Table of Contents (17) Chapters

SELinux Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
1. The SELinux Development Environment 2. Dealing with File Labels 3. Confining Web Applications 4. Creating a Desktop Application Policy 5. Creating a Server Policy 6. Setting Up Separate Roles 7. Choosing the Confinement Level 8. Debugging SELinux 9. Aligning SELinux with DAC 10. Handling SELinux-aware Applications Index

Chapter 10. Handling SELinux-aware Applications

In this chapter, we will cover handling of SELinux-aware applications through the following recipes:

  • Controlling D-Bus message flows

  • Restricting service ownership

  • Understanding udev's SELinux integration

  • Using cron with SELinux

  • Checking the SELinux state programmatically

  • Querying SELinux userland configuration in C

  • Interrogating the SELinux subsystem code-wise

  • Running new processes in a new context

  • Reading the context of a resource

Introduction


For most applications, the SELinux subsystem in the Linux kernel is capable of enforcing security controls without further interaction with other applications and components. However, there are actions that cannot be handled by the SELinux subsystem autonomously. Some applications execute commands for specific users, but the target domain cannot be deduced from the path of the application that is itself being executed, making type transitions based on the label impossible.

One solution for this problem is to make the application SELinux-aware, having the application interrogate the SELinux subsystem as to what should be the context of the newly executed application. Once the context is obtained, the application can then instruct the SELinux subsystem that this context can be assigned to the process that will be launched next.

Of course, it isn't only about deciding what context a process should be in. Applications can also check the SELinux policy and act on the policy themselves...

Controlling D-Bus message flows


D-Bus implementation on Linux is an example of an SELinux-aware application, acting as a user space object manager. Applications can register themselves on a bus and can send messages between applications through D-Bus. These messages can be controlled through the SELinux policy as well.

Getting ready

Before looking at the SELinux access controls related to message flows, it is important to focus on a D-Bus service and see how its authentication is done (and how messages are relayed in D-Bus) as this is reflected in the SELinux integration.

Go to /etc/dbus-1/system.d/ (which hosts the configuration files for D-Bus services) and take a look at a configuration file. For instance, the service configuration file for dnsmasq looks like the following:

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy user="root">
    <allow own="uk...

Restricting service ownership


Applications that register themselves on the bus own a service name. The uk.org.thekelleys.dnsmasq service name is an example of this. The D-Bus policy, declared in the busconfig XML file at /etc/dbus-1/system.d/ (or session.d/ if the service is for the session bus instead of system bus) provides information for D-Bus to decide when taking ownership of a particular service is allowed.

Thanks to D-Bus' SELinux integration, additional constraints can be added to ensure that only authorized applications can take ownership of a particular service.

How to do it…

To restrict service ownership through the SELinux policy, follow the ensuing set of steps:

  1. Inside the D-Bus configuration file of the service, make sure that the own permission is properly protected. For instance, make sure only the root Linux user can own the service:

    <policy user="root">
      <allow own="uk.org.thekelleys.dnsmasq" />
    </policy>
  2. If the runtime service account can differ, it is possible...

Understanding udev's SELinux integration


The udev device manager is responsible for handling device files inside the /dev/ structure whenever changes occur. As many device files have different contexts, without any SELinux awareness, the udev policy would need to be enhanced with many, many named file transitions. Such a named file transition, for a device /dev/mydevice towards the mydevice_t type, would look like the following code:

dev_filetrans(udev_t, mydevice_t, chr_file, "mydevice")

However, when /dev/mydevice1, /dev/mydevice2, and so on need to be labeled as well, then each possible name would need to be iterated in the policy (named file transitions do not support regular expressions). Luckily, udev is SELinux-aware, making it unnecessary to create policy enhancements for every device file.

This recipe shows us when additional policy enhancements are needed and when not.

How to do it…

To understand how udev's SELinux integration works, the following decision criteria can be followed:

  1. Whenever...

Using cron with SELinux


Another example of an SELinux-aware application is cron. Well, actually a set of cron implementations, as there is not a single cron application. Examples of cron implementations are vixie-cron, cronie, and fcron.

The cron implementations invoke commands for (and as) a particular Linux user. As these commands are not set in stone (the main purpose of cron is to allow any command to be run for a particular user or even for the system itself), it is not possible to easily create a policy that is sufficiently fine-grained to accommodate all features provided by cron. After all, for SELinux itself, there is no difference between cron calling a command for one user or another: all that is involved is the cron domain (crond_t) and the target type of the command (such as bin_t).

For this reason, many cron implementations are made SELinux-aware, allowing the cron implementation to select the proper target context.

How to do it…

To properly interact with an SELinux-aware cron...

Checking the SELinux state programmatically


If the need arises to make an SELinux-aware application, then several languages can be used. The libselinux package usually provides bindings for multiple programming and scripting languages. In the next set of recipes, the C programming language will be used as an example implementation.

The first step to support SELinux in an application is to check the SELinux state. In this recipe, we will show how to create an application that links with the libselinux library and checks the state of SELinux.

Getting ready

As we are going to update a C application, this set of recipes will assume basic knowledge of C programming. An example C application that uses all the input from this (and other) recipes can be found in the download pack of this book.

How to do it…

In order to link with libselinux and to check the current SELinux state, the following set of steps can be used:

  1. Create a C application code file and refer to the SELinux header files through a compiler...

Querying SELinux userland configuration in C


In this recipe, we will be querying the SELinux userland to obtain the default context for a given user based on the context of the current process. The process is responsible for gathering the Linux username of the user upfront.

How to do it…

Query the SELinux configuration as follows:

  1. Get the current context of the process:

    char * curcon = 0;
    rc = getcon(&curcon);
    if (rc) {
      … // Getting context failed
      if (permissive) {
        … // Continue with the application logic, ignoring SELinux stuff
      } else {
        … // Log failure and stop application logic
      };
    };
  2. Take the Linux username (assumed to be in the name variable) and get the SELinux user:

    char * sename = 0;
    char * selevel = 0;
    rc = getseuserbyname(name, &sename, &selevel);
    if (rc) {
      … // Call failed. Again check permissive state
      … // and take appropriate action.
      freecon(curcon);
    };
  3. Now, get the default context based on the obtained SELinux user (sename) and current context (which...

Interrogating the SELinux subsystem code-wise


In order to query the SELinux policy, we have seen the use of the sesearch command and other SELinux utilities. Code-wise, SELinux policies can be queried using the security_compute_av_flags method.

Getting ready

The curcon and newcon variables can be filled in through methods such as getcon() (for the current context) or get_default_context() as we have seen in the previous recipe.

How to do it…

As an example, we want to query the transition permission between two process domains. To accomplish this, the following method is used:

  1. First of all, call the security_compute_av_flags() method:

    struct av_decision avd;
    rc = security_compute_av_flags(curcon, newcon, SECCLASS_PROCESS, PROCESS__TRANSITION, &avd);
    if (rc) {
      … // Method failed.
      freecon(curcon);
      freecon(newcon);
    };
  2. Now read the response:

    if (!(avd.allowed & PROCESS__TRANSITION)) {
      … // Transition is denied
    };
  3. Check whether the current context is a permissive domain or not:

    if (avd.flags...

Running new processes in a new context


Sometimes, it isn't possible to force a particular domain upon invocation of a new task or process. The default transition rules that can be enabled through the SELinux policy are only applicable if the source domain and file context (of the application or task to execute) are unambiguously decisive for the target context.

In applications that can run the same command (or execute commands with the same context) for different target domains, SELinux-awareness is a must.

This recipe will show how to force a particular domain for a new process.

Getting ready

The newcon variable that is used in this recipe can be filled in through methods such as get_default_context() as we have seen in a previous recipe.

How to do it…

To launch a process in a specific context, go through the following steps:

  1. Tell SELinux what the new context should be:

    int rc = setexeccon(newcon);
    if (rc) {
      … // Call failed
      freecon(newcon);
    };
  2. Fork and execute the command. For instance, to...

Reading the context of a resource


It is, of course, also important to obtain the context of a resource if the application is SELinux-aware. This could be for logging purposes or to decide which domain to transition to (based on the resource context, current context, username, and so on).

How to do it…

To read the context of a resource, the following methods are available:

  1. Given a file path, the following call to getfilecon() will provide the context of the file:

    security_context_t filecon = 0;
    char * path = "/etc/passwd";
    rc = getfilecon(path, &filecon);
    if (rc < 0) {
      … // Call failed
    };
    … // Do stuff with the context
    freecon(filecon);
  2. To get the context of a process, assuming the pid variable (of the pid_t type) has the proper process ID in it, the following code is used:

    security_context_t pidcon = 0;
    rc = getpidcon(pid, &pidcon);
    if (rc < 0) {
      … // Call failed
    };
    … // Do stuff with the context
    freecon(pidcon);

How it works…

The SELinux library has various methods for obtaining...

lock icon The rest of the chapter is locked
You have been reading a chapter from
SELinux Cookbook
Published in: Sep 2014 Publisher: ISBN-13: 9781783989669
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}