SELinux with omarine policy: An in-depth look at the security policy – secure program with its own domain: Part 10


This article is the last in 10 articles about security policy with detailed example programs. After reading these 10 articles, you have a basic knowledge to master your SELinux system. SELinux is still a tough topic in the open source community but now you find it not too complicated, right?

This article complements the previous article about the audit2allow utility, applying audit2allow to practice adding rules to the policy for a required operation.

When you create a virtual environment for Python, you can add and remove modules (Python) at your discretion without having to be root. Currently we need to add a rule to uninstall the modules. The uninstall script will create a temporary file, which by default has the type user_tmp_t and it needs to be changed to user_home_t for processing (similar to the myapp program to be transitioned its temporary file to type myapp_tmp_t).

For example, when we uninstall the dnspython module, the operation is denied with the following Python message:

PermissionError: [Errno 13] Permission denied: '/tmp/pip-uninstall-7ehq5lz7/home/tuyen/python-env/mysite/lib/python3.7/site-packages/dns/'

Assume the current user is staff_u with domain staff_t. audit2allow will detect rule:

allow staff_t user_tmp_t:file relabelfrom;

This rule means that allowing domain staff_t to change the label (or context) of the file object with the type user_tmp_t to another type, in this case user_home_t.

We can use audit2allow to create a policy module named local that contains the above rule, as the root user:

audit2allow -l -a -M local

The policy package local.pp will be created and you can insert it into the policy as usual

Now staff_t has permission to replace the user_tmp_t label, for example, to user_home_t. Note that alone relabelfrom permission is not enough to replace the file label, it needs to add relabelto permission to the new type. But because staff_t already has relabelto permission in the policy for user_home_t, relabeling is possible.

How does Python change file types?

We create a temporary file /tmp/myfile. It will be of type user_tmp_t

We now discover some ways to change the file type to user_home_t in several different environments.
We already know the type_transition policy statement is used in the myapp and myapp_se policy modules to transition the file types. With Python, to relabel files, Python use the setxattr() function internally to set the file's extended attributes, namely the file security context. Outside, Python provides the os module with the same name function setxattr() to set the file's extended attributes. The Python code below changes the type of the file /tmp/myfile from user_tmp_t to user_home_t:

import os

    os.setxattr(b"/tmp/myfile", b"security.selinux",
except OSError as e:
    print (e.strerror)

chcon command

On the command line interface you can use the chcon command to change the file type. It is a SELinux-aware utility of the coreutils package. chcon changes the file type using the userspace library libselinux

chcon -t user_home_t /tmp/myfile

setfattr command
The setfattr command is used to set the file's extended attributes. setfattr is a program of the attr package. You can use setfattr to set the file security context with the extended attribute name security.selinux:

setfattr -n security.selinux -v staff_u:object_r:user_home_t:s0 /tmp/myfile

chtype program

We write a program called chtype that has the function of setting the file type by setting its extended attribute. Source code is as follows:

  chtype - Set type of file for which the security policy allowed
  Usage: ./chtype type path

  File: chtype.c


#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/xattr.h>

const char *XATTR_NAME = "security.selinux";
int get_new_context(const char *, const char *, char **);

int main(int argc, char *argv[])
    if (argc != 3) {
        fprintf(stderr, "Usage: %s type path\n", argv[0]);

    const char *path = argv[2];
    const char *type = argv[1];
    char *context;
    int conlen;
    if (! (conlen =  get_new_context(path, type, &context)))
    int ret = setxattr(path, XATTR_NAME, context, conlen, 0);
    if (ret == -1) {

int get_new_context(const char *path, const char *type, char **pcontext_new) {
    char *context;
    char *p, *level;
    int vallen;
    vallen = getxattr(path, XATTR_NAME, NULL, 0);
    switch (vallen) {
    case -1:
    case 0:
        printf("no value\n");
        return 0;
    context = malloc(vallen + 1);
    if (context == NULL) {

    vallen = getxattr(path, XATTR_NAME, context, vallen);
    if (vallen == -1) {
    else {
        context[vallen] = '\0';
    p = rindex(context, ':');
    int conlen = strlen(p);
    level = malloc(conlen + 1);
    if (level == NULL) {
    strcpy(level, p);
    *p = '\0';
    p = rindex(context, ':');
    *(p + 1) = '\0';
    conlen += strlen(context) + strlen(type);
    *pcontext_new = malloc(conlen + 1);
    if (*pcontext_new == NULL) {
    strcpy(*pcontext_new, context);
    strcat(*pcontext_new, type);
    strcat(*pcontext_new, level);
    return conlen + 1;


gcc -o chtype chtype.c


./chtype user_home_t /tmp/myfile

You have completed 10 lessons on SELinux security policy. Wish you have a solid knowledge to study, research, work, do business, be assured of opening the door to share information with friends while being able to protect yourself against attacks of malicious guys on the Internet - an insecure network. If you have any questions, don't hesitate to email Feel free to comment under the posts to discuss.

Currently unrated


There are currently no comments

New Comment


required (not published)



What is 5 + 8?