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


(0 comments)

Transitioning domain directly by designing SELinux-aware program

In the myapp module we have applied automatic domain transition for a normal program that is myapp. That is done by the type_transition statement inside the domtrans_pattern macro of the interface myapp_domtrans. Detail:

type_transition staff_t myapp_exec_t: process myapp_t;

To look deeper we perform manual domain transition in a SELinux-aware program, myapp_se program.
Policy modules myapp_se and myapp_se_perm are very similar to myapp and myapp_perm modules where myapp prefixes are replaced with myapp_se. Only two interfaces actually change:
1) Interface myapp_se_domtrans

interface(`myapp_se_domtrans',`
	gen_require(`
		type myapp_se_t, myapp_se_exec_t;
	')
    
	spec_domtrans_pattern($1,myapp_se_exec_t,myapp_se_t)
')

The macro domtrans_pattern is replaced with the spec_domtrans_pattern macro which removes the type_transition statement and adds the setexec permission to the source domain. This is to let myapp_se program call the libselinux API setexeccon() before transitioning domain.
2) Interface myapp_se_run

interface(`myapp_se_run',`
        gen_require(`
            attribute_role myapp_se_roles;
type myapp_se_exec_t; ') myapp_se_domtrans($1) roleattribute $2 myapp_se_roles;
can_exec($1, myapp_se_exec_t) ')

This interface adds the can_exec macro. It is necessary to allow the source domain to execute the /usr/bin/myapp_se binary. In this domain the program proceeds to transition to the domain myapp_se_t.

Program myapp_se

myapp_se program is more complicated than myapp program a bit. Its content is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <selinux/selinux.h>
#include <unistd.h>

void get_new_context(const char *, char **);

int main(int argc, char *argv[]) {
    char *name;
    FILE *fp;
    int n;
    errno = 0;
    char *context;
    
    getcon(&context);
    char *p = strstr(context, ":myapp_se_t:");
    
    // Check the current security context of the process
    if(!p) {
        freecon(context);
        get_new_context("myapp_se_t", &context);
        
        // Set context to prepare the domain transition
        setexeccon(context);
        free(context);
        
        // Execute the program with the new security context
        execvp(argv[0], argv);
        
        perror("execvp");
        return 0;
    }
    freecon(context);
    
    if ( argc > 1 && strcmp(argv[1],"-r") == 0 ) {
    
        fp = fopen ("/tmp/myapp_se.123456", "r");
        if (!fp) {
            perror ("fopen");
            return errno;
        }
        
        n = fscanf (fp, "%m[ a-zA-Z]", &name);
        if (n == 1) {
            printf ("Your name is %s\n", name);
            free(name);
        }
        else if (errno != 0) {
            perror("fscanf");
        } 
        else {
            fprintf(stderr, "Invalid name\n");
            fclose (fp);
            return -1;
        }
        fclose (fp);
        return errno;
    }
    
    printf ("%s", "Name: ");
    n = scanf ("%m[ a-zA-Z]", &name);
    if (n == 1) {
        printf ("Your name is %s\n", name);
    }
    else if (errno != 0) {
        perror("scanf");
        return errno;
    } 
    else {
        fprintf(stderr, "Invalid name\n");
        return -1;
    }
    
    fp = fopen ("/tmp/myapp_se.123456", "w");
    fprintf (fp, "%s", name);
    fclose (fp);
    free(name);
    
    return 0;
}

void get_new_context(const char *domain, char **pcontext_new) {
    
    char *context;
    char *p, *level;
    
    getcon(&context);
    p = rindex(context, ':');
    int len = strlen(p);
    level = malloc(len + 1);
    strcpy(level, p);
    *p = '\0';
    p = rindex(context, ':');
    *(p + 1) = '\0';
    len += strlen(context) + strlen(domain);
    *pcontext_new = malloc(len + 1);
    strcpy(*pcontext_new, context);
    strcat(*pcontext_new, domain);
    strcat(*pcontext_new, level);
    
    freecon(context);
    free(level);
}

The function get_new_context() is used to get a new context string. The program performs current context check at the beginning of the program. Initially when the staff_u user runs the program, the process is still in the staff_t domain, so the program proceeds with the domain transition. It takes the new context and sets that context for domain transition. Finally the execvp() function executes the /usr/bin/myapp_se binary again and the process transitions to the domain myapp_se_t. Now the new domain is already achieved so the program does not transition the domain and then carries out the rest of the program in the new security context

Compiling the program
To compile the program, you need to use the -l option to link to libselinux.so library


Currently unrated

Comments

There are currently no comments

New Comment

required

required (not published)

optional

required


What is 5 + 6?

required