ia64/xen-unstable

changeset 15816:6c8c934b235c

Xen Security Modules: FLASK
Signed-off-by: George Coker <gscoker@alpha.ncsc.mil>
author kfraser@localhost.localdomain
date Fri Aug 31 11:31:18 2007 +0100 (2007-08-31)
parents 96f64f4c42f0
children 993655d24b55
files Config.mk xen/Rules.mk xen/common/vsprintf.c xen/include/public/xsm/flask_op.h xen/include/xen/lib.h xen/xsm/Makefile xen/xsm/flask/Makefile xen/xsm/flask/avc.c xen/xsm/flask/flask_op.c xen/xsm/flask/hooks.c xen/xsm/flask/include/av_inherit.h xen/xsm/flask/include/av_perm_to_string.h xen/xsm/flask/include/av_permissions.h xen/xsm/flask/include/avc.h xen/xsm/flask/include/avc_ss.h xen/xsm/flask/include/class_to_string.h xen/xsm/flask/include/common_perm_to_string.h xen/xsm/flask/include/conditional.h xen/xsm/flask/include/flask.h xen/xsm/flask/include/initial_sid_to_string.h xen/xsm/flask/include/objsec.h xen/xsm/flask/include/security.h xen/xsm/flask/ss/Makefile xen/xsm/flask/ss/avtab.c xen/xsm/flask/ss/avtab.h xen/xsm/flask/ss/conditional.c xen/xsm/flask/ss/conditional.h xen/xsm/flask/ss/constraint.h xen/xsm/flask/ss/context.h xen/xsm/flask/ss/ebitmap.c xen/xsm/flask/ss/ebitmap.h xen/xsm/flask/ss/hashtab.c xen/xsm/flask/ss/hashtab.h xen/xsm/flask/ss/mls.c xen/xsm/flask/ss/mls.h xen/xsm/flask/ss/mls_types.h xen/xsm/flask/ss/policydb.c xen/xsm/flask/ss/policydb.h xen/xsm/flask/ss/services.c xen/xsm/flask/ss/services.h xen/xsm/flask/ss/sidtab.c xen/xsm/flask/ss/sidtab.h xen/xsm/flask/ss/symtab.c xen/xsm/flask/ss/symtab.h
line diff
     1.1 --- a/Config.mk	Fri Aug 31 11:21:35 2007 +0100
     1.2 +++ b/Config.mk	Fri Aug 31 11:31:18 2007 +0100
     1.3 @@ -81,6 +81,14 @@ CFLAGS += $(foreach i, $(EXTRA_INCLUDES)
     1.4  # Enable XSM security module.  Enabling XSM requires selection of an 
     1.5  # XSM security module.
     1.6  XSM_ENABLE ?= n
     1.7 +ifeq ($(XSM_ENABLE),y)
     1.8 +FLASK_ENABLE ?= n
     1.9 +ifeq ($(FLASK_ENABLE),y)
    1.10 +FLASK_DEVELOP ?= y
    1.11 +FLASK_BOOTPARAM ?= y
    1.12 +FLASK_AVC_STATS ?= y
    1.13 +endif
    1.14 +endif
    1.15  
    1.16  # If ACM_SECURITY = y, then the access control module is compiled
    1.17  # into Xen and the policy type can be set by the boot policy file
     2.1 --- a/xen/Rules.mk	Fri Aug 31 11:21:35 2007 +0100
     2.2 +++ b/xen/Rules.mk	Fri Aug 31 11:31:18 2007 +0100
     2.3 @@ -58,6 +58,10 @@ ALL_OBJS-y               += $(BASEDIR)/a
     2.4  
     2.5  CFLAGS-y                += -g -D__XEN__
     2.6  CFLAGS-$(XSM_ENABLE)    += -DXSM_ENABLE
     2.7 +CFLAGS-$(FLASK_ENABLE)    += -DFLASK_ENABLE -DXSM_MAGIC=0xf97cff8c
     2.8 +CFLAGS-$(FLASK_DEVELOP)   += -DFLASK_DEVELOP
     2.9 +CFLAGS-$(FLASK_BOOTPARAM) += -DFLASK_BOOTPARAM
    2.10 +CFLAGS-$(FLASK_AVC_STATS) += -DFLASK_AVC_STATS
    2.11  CFLAGS-$(ACM_SECURITY)  += -DACM_SECURITY
    2.12  CFLAGS-$(verbose)       += -DVERBOSE
    2.13  CFLAGS-$(crash_debug)   += -DCRASH_DEBUG
     3.1 --- a/xen/common/vsprintf.c	Fri Aug 31 11:21:35 2007 +0100
     3.2 +++ b/xen/common/vsprintf.c	Fri Aug 31 11:31:18 2007 +0100
     3.3 @@ -513,6 +513,223 @@ int vscnprintf(char *buf, size_t size, c
     3.4  EXPORT_SYMBOL(vscnprintf);
     3.5  
     3.6  /**
     3.7 + * vsscanf - Unformat a buffer into a list of arguments
     3.8 + * @buf:    input buffer
     3.9 + * @fmt:    format of buffer
    3.10 + * @args:   arguments
    3.11 + */
    3.12 +int vsscanf(const char * buf, const char * fmt, va_list args)
    3.13 +{
    3.14 +    const char *str = buf;
    3.15 +    const char *next;
    3.16 +    char digit;
    3.17 +    int num = 0;
    3.18 +    int qualifier;
    3.19 +    int base;
    3.20 +    int field_width;
    3.21 +    int is_sign = 0;
    3.22 +
    3.23 +    while (*fmt && *str) {
    3.24 +        /* skip any white space in format */
    3.25 +        /* white space in format matchs any amount of
    3.26 +         * white space, including none, in the input.
    3.27 +         */
    3.28 +        if (isspace(*fmt)) {
    3.29 +            while (isspace(*fmt))
    3.30 +                ++fmt;
    3.31 +            while (isspace(*str))
    3.32 +                ++str;
    3.33 +        }
    3.34 +
    3.35 +        /* anything that is not a conversion must match exactly */
    3.36 +        if (*fmt != '%' && *fmt) {
    3.37 +            if (*fmt++ != *str++)
    3.38 +                break;
    3.39 +            continue;
    3.40 +        }
    3.41 +
    3.42 +        if (!*fmt)
    3.43 +            break;
    3.44 +        ++fmt;
    3.45 +
    3.46 +        /* skip this conversion.
    3.47 +         * advance both strings to next white space
    3.48 +         */
    3.49 +        if (*fmt == '*') {
    3.50 +            while (!isspace(*fmt) && *fmt)
    3.51 +                fmt++;
    3.52 +            while (!isspace(*str) && *str)
    3.53 +                str++;
    3.54 +            continue;
    3.55 +        }
    3.56 +
    3.57 +        /* get field width */
    3.58 +        field_width = -1;
    3.59 +        if (isdigit(*fmt))
    3.60 +            field_width = skip_atoi(&fmt);
    3.61 +
    3.62 +        /* get conversion qualifier */
    3.63 +        qualifier = -1;
    3.64 +        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z'
    3.65 +            || *fmt == 'z') {
    3.66 +            qualifier = *fmt++;
    3.67 +            if (unlikely(qualifier == *fmt)) {
    3.68 +                if (qualifier == 'h') {
    3.69 +                    qualifier = 'H';
    3.70 +                    fmt++;
    3.71 +                } else if (qualifier == 'l') {
    3.72 +                    qualifier = 'L';
    3.73 +                    fmt++;
    3.74 +                }
    3.75 +            }
    3.76 +        }
    3.77 +        base = 10;
    3.78 +        is_sign = 0;
    3.79 +
    3.80 +        if (!*fmt || !*str)
    3.81 +            break;
    3.82 +
    3.83 +        switch(*fmt++) {
    3.84 +            case 'c': {
    3.85 +                char *s = (char *) va_arg(args,char*);
    3.86 +                if (field_width == -1)
    3.87 +                    field_width = 1;
    3.88 +                do {
    3.89 +                    *s++ = *str++;
    3.90 +                } while (--field_width > 0 && *str);
    3.91 +                num++;
    3.92 +            }
    3.93 +            continue;
    3.94 +            case 's': {
    3.95 +                char *s = (char *) va_arg(args, char *);
    3.96 +                if(field_width == -1)
    3.97 +                    field_width = INT_MAX;
    3.98 +                /* first, skip leading white space in buffer */
    3.99 +                while (isspace(*str))
   3.100 +                    str++;
   3.101 +
   3.102 +                /* now copy until next white space */
   3.103 +                while (*str && !isspace(*str) && field_width--)
   3.104 +                    *s++ = *str++;
   3.105 +                *s = '\0';
   3.106 +                num++;
   3.107 +            }
   3.108 +            continue;
   3.109 +            case 'n': {
   3.110 +            /* return number of characters read so far */
   3.111 +                int *i = (int *)va_arg(args,int*);
   3.112 +                *i = str - buf;
   3.113 +            }
   3.114 +            continue;
   3.115 +            case 'o':
   3.116 +                base = 8;
   3.117 +            break;
   3.118 +            case 'x':
   3.119 +            case 'X':
   3.120 +                base = 16;
   3.121 +            break;
   3.122 +            case 'i':
   3.123 +                base = 0;
   3.124 +            case 'd':
   3.125 +                is_sign = 1;
   3.126 +            case 'u':
   3.127 +            break;
   3.128 +            case '%':
   3.129 +                /* looking for '%' in str */
   3.130 +                if (*str++ != '%') 
   3.131 +                    return num;
   3.132 +            continue;
   3.133 +            default:
   3.134 +                /* invalid format; stop here */
   3.135 +                return num;
   3.136 +        }
   3.137 +
   3.138 +        /* have some sort of integer conversion.
   3.139 +         * first, skip white space in buffer.
   3.140 +         */
   3.141 +        while (isspace(*str))
   3.142 +            str++;
   3.143 +
   3.144 +        digit = *str;
   3.145 +        if (is_sign && digit == '-')
   3.146 +            digit = *(str + 1);
   3.147 +
   3.148 +        if (!digit || (base == 16 && !isxdigit(digit))
   3.149 +                || (base == 10 && !isdigit(digit))
   3.150 +                || (base == 8 && (!isdigit(digit) || digit > '7'))
   3.151 +                || (base == 0 && !isdigit(digit)))
   3.152 +            break;
   3.153 +
   3.154 +        switch(qualifier) {
   3.155 +            case 'H': /* that's 'hh' in format */
   3.156 +                if (is_sign) {
   3.157 +                    signed char *s = (signed char *) va_arg(args,signed char *);
   3.158 +                    *s = (signed char) simple_strtol(str,&next,base);
   3.159 +                } else {
   3.160 +                    unsigned char *s = (unsigned char *) 
   3.161 +                                                va_arg(args, unsigned char *);
   3.162 +                    *s = (unsigned char) simple_strtoul(str, &next, base);
   3.163 +                }
   3.164 +            break;
   3.165 +            case 'h':
   3.166 +                if (is_sign) {
   3.167 +                    short *s = (short *) va_arg(args,short *);
   3.168 +                    *s = (short) simple_strtol(str,&next,base);
   3.169 +                } else {
   3.170 +                    unsigned short *s = (unsigned short *) 
   3.171 +                                                va_arg(args, unsigned short *);
   3.172 +                    *s = (unsigned short) simple_strtoul(str, &next, base);
   3.173 +                }
   3.174 +            break;
   3.175 +            case 'l':
   3.176 +                if (is_sign) {
   3.177 +                    long *l = (long *) va_arg(args,long *);
   3.178 +                    *l = simple_strtol(str,&next,base);
   3.179 +                } else {
   3.180 +                    unsigned long *l = (unsigned long*) 
   3.181 +                                                    va_arg(args,unsigned long*);
   3.182 +                    *l = simple_strtoul(str,&next,base);
   3.183 +                }
   3.184 +            break;
   3.185 +            case 'L':
   3.186 +                if (is_sign) {
   3.187 +                    long long *l = (long long*) va_arg(args,long long *);
   3.188 +                    *l = simple_strtoll(str,&next,base);
   3.189 +                } else {
   3.190 +                    unsigned long long *l = (unsigned long long*) 
   3.191 +                                            va_arg(args,unsigned long long*);
   3.192 +                    *l = simple_strtoull(str,&next,base);
   3.193 +                }
   3.194 +            break;
   3.195 +            case 'Z':
   3.196 +            case 'z': {
   3.197 +                size_t *s = (size_t*) va_arg(args,size_t*);
   3.198 +                *s = (size_t) simple_strtoul(str,&next,base);
   3.199 +            }
   3.200 +            break;
   3.201 +            default:
   3.202 +                if (is_sign) {
   3.203 +                    int *i = (int *) va_arg(args, int*);
   3.204 +                    *i = (int) simple_strtol(str,&next,base);
   3.205 +                } else {
   3.206 +                    unsigned int *i = (unsigned int*) 
   3.207 +                                                    va_arg(args, unsigned int*);
   3.208 +                    *i = (unsigned int) simple_strtoul(str,&next,base);
   3.209 +                }
   3.210 +            break;
   3.211 +        }
   3.212 +        num++;
   3.213 +
   3.214 +        if (!next)
   3.215 +            break;
   3.216 +        str = next;
   3.217 +    }
   3.218 +    return num;
   3.219 +}
   3.220 +
   3.221 +EXPORT_SYMBOL(vsscanf);
   3.222 +
   3.223 +/**
   3.224   * snprintf - Format a string and place it in a buffer
   3.225   * @buf: The buffer to place the result into
   3.226   * @size: The size of the buffer, including the trailing null space
   3.227 @@ -561,6 +778,25 @@ int scnprintf(char * buf, size_t size, c
   3.228  }
   3.229  EXPORT_SYMBOL(scnprintf);
   3.230  
   3.231 +/**
   3.232 + * sscanf - Unformat a buffer into a list of arguments
   3.233 + * @buf:    input buffer
   3.234 + * @fmt:    formatting of buffer
   3.235 + * @...:    resulting arguments
   3.236 + */
   3.237 +int sscanf(const char * buf, const char * fmt, ...)
   3.238 +{
   3.239 +    va_list args;
   3.240 +    int i;
   3.241 +
   3.242 +    va_start(args,fmt);
   3.243 +    i = vsscanf(buf,fmt,args);
   3.244 +    va_end(args);
   3.245 +    return i;
   3.246 +}
   3.247 +
   3.248 +EXPORT_SYMBOL(sscanf);
   3.249 +
   3.250  /*
   3.251   * Local variables:
   3.252   * mode: C
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/include/public/xsm/flask_op.h	Fri Aug 31 11:31:18 2007 +0100
     4.3 @@ -0,0 +1,45 @@
     4.4 +/*
     4.5 + *  This file contains the flask_op hypercall commands and definitions.
     4.6 + *
     4.7 + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
     4.8 + *
     4.9 + *  This program is free software; you can redistribute it and/or modify
    4.10 + *  it under the terms of the GNU General Public License version 2,
    4.11 + *  as published by the Free Software Foundation.
    4.12 + */
    4.13 +
    4.14 +#ifndef __FLASK_OP_H__
    4.15 +#define __FLASK_OP_H__
    4.16 +
    4.17 +#define FLASK_LOAD              1
    4.18 +#define FLASK_GETENFORCE        2
    4.19 +#define FLASK_SETENFORCE        3
    4.20 +#define FLASK_CONTEXT_TO_SID    4
    4.21 +#define FLASK_SID_TO_CONTEXT    5
    4.22 +#define FLASK_ACCESS            6
    4.23 +#define FLASK_CREATE            7
    4.24 +#define FLASK_RELABEL           8
    4.25 +#define FLASK_USER              9
    4.26 +#define FLASK_POLICYVERS        10
    4.27 +#define FLASK_GETBOOL           11
    4.28 +#define FLASK_SETBOOL           12
    4.29 +#define FLASK_COMMITBOOLS       13
    4.30 +#define FLASK_MLS               14
    4.31 +#define FLASK_DISABLE           15
    4.32 +#define FLASK_GETAVC_THRESHOLD  16
    4.33 +#define FLASK_SETAVC_THRESHOLD  17
    4.34 +#define FLASK_AVC_HASHSTATS     18
    4.35 +#define FLASK_AVC_CACHESTATS    19
    4.36 +#define FLASK_MEMBER            20
    4.37 +
    4.38 +typedef struct flask_op {
    4.39 +    int   cmd;
    4.40 +    int   size;
    4.41 +    char *buf;
    4.42 +} flask_op_t;
    4.43 +
    4.44 +DEFINE_XEN_GUEST_HANDLE(flask_op_t);
    4.45 +
    4.46 +long do_flask_op (XEN_GUEST_HANDLE(xsm_op_t) u_flask_op);
    4.47 +
    4.48 +#endif
     5.1 --- a/xen/include/xen/lib.h	Fri Aug 31 11:21:35 2007 +0100
     5.2 +++ b/xen/include/xen/lib.h	Fri Aug 31 11:31:18 2007 +0100
     5.3 @@ -75,6 +75,10 @@ extern int scnprintf(char * buf, size_t 
     5.4      __attribute__ ((format (printf, 3, 4)));
     5.5  extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
     5.6      __attribute__ ((format (printf, 3, 0)));
     5.7 +extern int sscanf(const char * buf, const char * fmt, ...)
     5.8 +    __attribute__ ((format (scanf, 2, 3)));
     5.9 +extern int vsscanf(const char * buf, const char * fmt, va_list args)
    5.10 +    __attribute__ ((format (scanf, 2, 0)));
    5.11  
    5.12  long simple_strtol(
    5.13      const char *cp,const char **endp, unsigned int base);
     6.1 --- a/xen/xsm/Makefile	Fri Aug 31 11:21:35 2007 +0100
     6.2 +++ b/xen/xsm/Makefile	Fri Aug 31 11:31:18 2007 +0100
     6.3 @@ -3,3 +3,5 @@ obj-y += xsm_policy.o
     6.4  ifeq ($(XSM_ENABLE),y)
     6.5  obj-y += dummy.o
     6.6  endif
     6.7 +
     6.8 +subdir-$(FLASK_ENABLE) += flask
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/xsm/flask/Makefile	Fri Aug 31 11:31:18 2007 +0100
     7.3 @@ -0,0 +1,7 @@
     7.4 +obj-y += avc.o
     7.5 +obj-y += hooks.o
     7.6 +obj-y += flask_op.o
     7.7 +
     7.8 +subdir-y += ss
     7.9 +
    7.10 +CFLAGS += -I./include
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/xsm/flask/avc.c	Fri Aug 31 11:31:18 2007 +0100
     8.3 @@ -0,0 +1,817 @@
     8.4 +/*
     8.5 + * Implementation of the kernel access vector cache (AVC).
     8.6 + *
     8.7 + * Authors:  Stephen Smalley, <sds@epoch.ncsc.mil>
     8.8 + *           James Morris <jmorris@redhat.com>
     8.9 + *
    8.10 + * Update:   KaiGai, Kohei <kaigai@ak.jp.nec.com>
    8.11 + *     Replaced the avc_lock spinlock by RCU.
    8.12 + *
    8.13 + * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
    8.14 + *
    8.15 + *    This program is free software; you can redistribute it and/or modify
    8.16 + *    it under the terms of the GNU General Public License version 2,
    8.17 + *      as published by the Free Software Foundation.
    8.18 + */
    8.19 + 
    8.20 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
    8.21 + 
    8.22 +#include <xen/lib.h>
    8.23 +#include <xen/xmalloc.h>
    8.24 +#include <xen/types.h>
    8.25 +#include <xen/list.h>
    8.26 +#include <xen/spinlock.h>
    8.27 +#include <xen/prefetch.h>
    8.28 +#include <xen/kernel.h>
    8.29 +#include <xen/sched.h>
    8.30 +#include <xen/init.h>
    8.31 +#include <xen/rcupdate.h>
    8.32 +#include <asm/atomic.h>
    8.33 +#include <asm/current.h>
    8.34 +
    8.35 +#include "avc.h"
    8.36 +#include "avc_ss.h"
    8.37 +
    8.38 +static const struct av_perm_to_string
    8.39 +{
    8.40 +    u16 tclass;
    8.41 +    u32 value;
    8.42 +    const char *name;
    8.43 +} av_perm_to_string[] = {
    8.44 +#define S_(c, v, s) { c, v, s },
    8.45 +#include "av_perm_to_string.h"
    8.46 +#undef S_
    8.47 +};
    8.48 +
    8.49 +static const char *class_to_string[] = {
    8.50 +#define S_(s) s,
    8.51 +#include "class_to_string.h"
    8.52 +#undef S_
    8.53 +};
    8.54 +
    8.55 +#define TB_(s) static const char * s [] = {
    8.56 +#define TE_(s) };
    8.57 +#define S_(s) s,
    8.58 +#include "common_perm_to_string.h"
    8.59 +#undef TB_
    8.60 +#undef TE_
    8.61 +#undef S_
    8.62 +
    8.63 +static const struct av_inherit
    8.64 +{
    8.65 +    u16 tclass;
    8.66 +    const char **common_pts;
    8.67 +    u32 common_base;
    8.68 +} av_inherit[] = {
    8.69 +#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
    8.70 +#include "av_inherit.h"
    8.71 +#undef S_
    8.72 +};
    8.73 +
    8.74 +#define AVC_CACHE_SLOTS            512
    8.75 +#define AVC_DEF_CACHE_THRESHOLD        512
    8.76 +#define AVC_CACHE_RECLAIM        16
    8.77 +
    8.78 +#ifdef FLASK_AVC_STATS
    8.79 +#define avc_cache_stats_incr(field)                 \
    8.80 +do {                                \
    8.81 +    __get_cpu_var(avc_cache_stats).field++;        \
    8.82 +} while (0)
    8.83 +#else
    8.84 +#define avc_cache_stats_incr(field)    do {} while (0)
    8.85 +#endif
    8.86 +
    8.87 +struct avc_entry {
    8.88 +    u32            ssid;
    8.89 +    u32            tsid;
    8.90 +    u16            tclass;
    8.91 +    struct av_decision    avd;
    8.92 +    atomic_t        used;    /* used recently */
    8.93 +};
    8.94 +
    8.95 +struct avc_node {
    8.96 +    struct avc_entry    ae;
    8.97 +    struct list_head    list;
    8.98 +    struct rcu_head     rhead;
    8.99 +};
   8.100 +
   8.101 +struct avc_cache {
   8.102 +    struct list_head    slots[AVC_CACHE_SLOTS];
   8.103 +    spinlock_t        slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
   8.104 +    atomic_t        lru_hint;    /* LRU hint for reclaim scan */
   8.105 +    atomic_t        active_nodes;
   8.106 +    u32            latest_notif;    /* latest revocation notification */
   8.107 +};
   8.108 +
   8.109 +struct avc_callback_node {
   8.110 +    int (*callback) (u32 event, u32 ssid, u32 tsid,
   8.111 +                     u16 tclass, u32 perms,
   8.112 +                     u32 *out_retained);
   8.113 +    u32 events;
   8.114 +    u32 ssid;
   8.115 +    u32 tsid;
   8.116 +    u16 tclass;
   8.117 +    u32 perms;
   8.118 +    struct avc_callback_node *next;
   8.119 +};
   8.120 +
   8.121 +/* Exported via Flask hypercall */
   8.122 +unsigned int avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD;
   8.123 +
   8.124 +#ifdef FLASK_AVC_STATS
   8.125 +DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
   8.126 +#endif
   8.127 +
   8.128 +static struct avc_cache avc_cache;
   8.129 +static struct avc_callback_node *avc_callbacks;
   8.130 +
   8.131 +static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
   8.132 +{
   8.133 +    return (ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1);
   8.134 +}
   8.135 +
   8.136 +/**
   8.137 + * avc_dump_av - Display an access vector in human-readable form.
   8.138 + * @tclass: target security class
   8.139 + * @av: access vector
   8.140 + */
   8.141 +static void avc_dump_av(u16 tclass, u32 av)
   8.142 +{
   8.143 +    const char **common_pts = NULL;
   8.144 +    u32 common_base = 0;
   8.145 +    int i, i2, perm;
   8.146 +
   8.147 +    if ( av == 0 )
   8.148 +    {
   8.149 +        printk(" null");
   8.150 +        return;
   8.151 +    }
   8.152 +
   8.153 +    for ( i = 0; i < ARRAY_SIZE(av_inherit); i++ )
   8.154 +    {
   8.155 +        if (av_inherit[i].tclass == tclass)
   8.156 +        {
   8.157 +            common_pts = av_inherit[i].common_pts;
   8.158 +            common_base = av_inherit[i].common_base;
   8.159 +            break;
   8.160 +        }
   8.161 +    }
   8.162 +
   8.163 +    printk(" {");
   8.164 +    i = 0;
   8.165 +    perm = 1;
   8.166 +    while ( perm < common_base )
   8.167 +    {
   8.168 +        if (perm & av)
   8.169 +        {
   8.170 +            printk(" %s", common_pts[i]);
   8.171 +            av &= ~perm;
   8.172 +        }
   8.173 +        i++;
   8.174 +        perm <<= 1;
   8.175 +    }
   8.176 +
   8.177 +    while ( i < sizeof(av) * 8 )
   8.178 +    {
   8.179 +        if ( perm & av )
   8.180 +        {
   8.181 +            for ( i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++ )
   8.182 +            {
   8.183 +                if ( (av_perm_to_string[i2].tclass == tclass) &&
   8.184 +                    (av_perm_to_string[i2].value == perm) )
   8.185 +                    break;
   8.186 +            }
   8.187 +            if ( i2 < ARRAY_SIZE(av_perm_to_string) )
   8.188 +            {
   8.189 +                printk(" %s", av_perm_to_string[i2].name);
   8.190 +                av &= ~perm;
   8.191 +            }
   8.192 +        }
   8.193 +        i++;
   8.194 +        perm <<= 1;
   8.195 +    }
   8.196 +
   8.197 +    if ( av )
   8.198 +        printk(" 0x%x", av);
   8.199 +
   8.200 +    printk(" }");
   8.201 +}
   8.202 +
   8.203 +/**
   8.204 + * avc_dump_query - Display a SID pair and a class in human-readable form.
   8.205 + * @ssid: source security identifier
   8.206 + * @tsid: target security identifier
   8.207 + * @tclass: target security class
   8.208 + */
   8.209 +static void avc_dump_query(u32 ssid, u32 tsid, u16 tclass)
   8.210 +{
   8.211 +    int rc;
   8.212 +    char *scontext;
   8.213 +    u32 scontext_len;
   8.214 +
   8.215 +    rc = security_sid_to_context(ssid, &scontext, &scontext_len);
   8.216 +    if ( rc )
   8.217 +        printk("ssid=%d", ssid);
   8.218 +    else
   8.219 +    {
   8.220 +        printk("scontext=%s", scontext);
   8.221 +        xfree(scontext);
   8.222 +    }
   8.223 +
   8.224 +    rc = security_sid_to_context(tsid, &scontext, &scontext_len);
   8.225 +    if ( rc )
   8.226 +        printk(" tsid=%d", tsid);
   8.227 +    else
   8.228 +    {
   8.229 +        printk(" tcontext=%s", scontext);
   8.230 +        xfree(scontext);
   8.231 +    }
   8.232 +    printk("\n");
   8.233 +    printk("tclass=%s", class_to_string[tclass]);
   8.234 +}
   8.235 +
   8.236 +/**
   8.237 + * avc_init - Initialize the AVC.
   8.238 + *
   8.239 + * Initialize the access vector cache.
   8.240 + */
   8.241 +void __init avc_init(void)
   8.242 +{
   8.243 +    int i;
   8.244 +
   8.245 +    for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
   8.246 +    {
   8.247 +        INIT_LIST_HEAD(&avc_cache.slots[i]);
   8.248 +        spin_lock_init(&avc_cache.slots_lock[i]);
   8.249 +    }
   8.250 +    atomic_set(&avc_cache.active_nodes, 0);
   8.251 +    atomic_set(&avc_cache.lru_hint, 0);
   8.252 +
   8.253 +    printk("AVC INITIALIZED\n");
   8.254 +}
   8.255 +
   8.256 +int avc_get_hash_stats(char *page)
   8.257 +{
   8.258 +    int i, chain_len, max_chain_len, slots_used;
   8.259 +    struct avc_node *node;
   8.260 +
   8.261 +    rcu_read_lock();
   8.262 +
   8.263 +    slots_used = 0;
   8.264 +    max_chain_len = 0;
   8.265 +    for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
   8.266 +    {
   8.267 +        if ( !list_empty(&avc_cache.slots[i]) )
   8.268 +        {
   8.269 +            slots_used++;
   8.270 +            chain_len = 0;
   8.271 +            list_for_each_entry_rcu(node, &avc_cache.slots[i], list)
   8.272 +                chain_len++;
   8.273 +            if ( chain_len > max_chain_len )
   8.274 +                max_chain_len = chain_len;
   8.275 +        }
   8.276 +    }
   8.277 +
   8.278 +    rcu_read_unlock();
   8.279 +    
   8.280 +    return snprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n"
   8.281 +                                "longest chain: %d\n",
   8.282 +                                atomic_read(&avc_cache.active_nodes),
   8.283 +                                slots_used, AVC_CACHE_SLOTS, max_chain_len);
   8.284 +}
   8.285 +
   8.286 +static void avc_node_free(struct rcu_head *rhead)
   8.287 +{
   8.288 +    struct avc_node *node = container_of(rhead, struct avc_node, rhead);
   8.289 +    xfree(node);
   8.290 +    avc_cache_stats_incr(frees);
   8.291 +}
   8.292 +
   8.293 +static void avc_node_delete(struct avc_node *node)
   8.294 +{
   8.295 +    list_del_rcu(&node->list);
   8.296 +    call_rcu(&node->rhead, avc_node_free);
   8.297 +    atomic_dec(&avc_cache.active_nodes);
   8.298 +}
   8.299 +
   8.300 +static void avc_node_kill(struct avc_node *node)
   8.301 +{
   8.302 +    xfree(node);
   8.303 +    avc_cache_stats_incr(frees);
   8.304 +    atomic_dec(&avc_cache.active_nodes);
   8.305 +}
   8.306 +
   8.307 +static void avc_node_replace(struct avc_node *new, struct avc_node *old)
   8.308 +{
   8.309 +    list_replace_rcu(&old->list, &new->list);
   8.310 +    call_rcu(&old->rhead, avc_node_free);
   8.311 +    atomic_dec(&avc_cache.active_nodes);
   8.312 +}
   8.313 +
   8.314 +static inline int avc_reclaim_node(void)
   8.315 +{
   8.316 +    struct avc_node *node;
   8.317 +    int hvalue, try, ecx;
   8.318 +	unsigned long flags;
   8.319 +
   8.320 +    for ( try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ )
   8.321 +    {
   8.322 +        atomic_inc(&avc_cache.lru_hint);
   8.323 +        hvalue =  atomic_read(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
   8.324 +
   8.325 +		spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flags);
   8.326 +
   8.327 +        list_for_each_entry(node, &avc_cache.slots[hvalue], list)
   8.328 +        {
   8.329 +            if ( atomic_dec_and_test(&node->ae.used) )
   8.330 +            {
   8.331 +                /* Recently Unused */
   8.332 +                avc_node_delete(node);
   8.333 +                avc_cache_stats_incr(reclaims);
   8.334 +                ecx++;
   8.335 +                if ( ecx >= AVC_CACHE_RECLAIM )
   8.336 +                {
   8.337 +					spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
   8.338 +                    goto out;
   8.339 +                }
   8.340 +            }
   8.341 +        }
   8.342 +		spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
   8.343 +    }    
   8.344 +out:
   8.345 +    return ecx;
   8.346 +}
   8.347 +
   8.348 +static struct avc_node *avc_alloc_node(void)
   8.349 +{
   8.350 +    struct avc_node *node;
   8.351 +
   8.352 +    node = xmalloc(struct avc_node);
   8.353 +    if (!node)
   8.354 +        goto out;
   8.355 +
   8.356 +    memset(node, 0, sizeof(*node));
   8.357 +    INIT_RCU_HEAD(&node->rhead);
   8.358 +    INIT_LIST_HEAD(&node->list);
   8.359 +    atomic_set(&node->ae.used, 1);
   8.360 +    avc_cache_stats_incr(allocations);
   8.361 +
   8.362 +    atomic_inc(&avc_cache.active_nodes);
   8.363 +    if ( atomic_read(&avc_cache.active_nodes) > avc_cache_threshold )
   8.364 +        avc_reclaim_node();
   8.365 +
   8.366 +out:
   8.367 +    return node;
   8.368 +}
   8.369 +
   8.370 +static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
   8.371 +{
   8.372 +    node->ae.ssid = ssid;
   8.373 +    node->ae.tsid = tsid;
   8.374 +    node->ae.tclass = tclass;
   8.375 +    memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd));
   8.376 +}
   8.377 +
   8.378 +static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
   8.379 +{
   8.380 +    struct avc_node *node, *ret = NULL;
   8.381 +    int hvalue;
   8.382 +
   8.383 +    hvalue = avc_hash(ssid, tsid, tclass);
   8.384 +    list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list)
   8.385 +    {
   8.386 +        if ( ssid == node->ae.ssid && tclass == node->ae.tclass && 
   8.387 +                                                        tsid == node->ae.tsid )
   8.388 +        {
   8.389 +            ret = node;
   8.390 +            break;
   8.391 +        }
   8.392 +    }
   8.393 +
   8.394 +    if ( ret == NULL )
   8.395 +    {
   8.396 +        /* cache miss */
   8.397 +        goto out;
   8.398 +    }
   8.399 +
   8.400 +    /* cache hit */
   8.401 +    if ( atomic_read(&ret->ae.used) != 1 )
   8.402 +        atomic_set(&ret->ae.used, 1);
   8.403 +out:
   8.404 +    return ret;
   8.405 +}
   8.406 +
   8.407 +/**
   8.408 + * avc_lookup - Look up an AVC entry.
   8.409 + * @ssid: source security identifier
   8.410 + * @tsid: target security identifier
   8.411 + * @tclass: target security class
   8.412 + * @requested: requested permissions, interpreted based on @tclass
   8.413 + *
   8.414 + * Look up an AVC entry that is valid for the
   8.415 + * @requested permissions between the SID pair
   8.416 + * (@ssid, @tsid), interpreting the permissions
   8.417 + * based on @tclass.  If a valid AVC entry exists,
   8.418 + * then this function return the avc_node.
   8.419 + * Otherwise, this function returns NULL.
   8.420 + */
   8.421 +static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested)
   8.422 +{
   8.423 +    struct avc_node *node;
   8.424 +
   8.425 +    avc_cache_stats_incr(lookups);
   8.426 +    node = avc_search_node(ssid, tsid, tclass);
   8.427 +
   8.428 +    if ( node && ((node->ae.avd.decided & requested) == requested) )
   8.429 +    {
   8.430 +        avc_cache_stats_incr(hits);
   8.431 +        goto out;
   8.432 +    }
   8.433 +
   8.434 +    node = NULL;
   8.435 +    avc_cache_stats_incr(misses);
   8.436 +out:
   8.437 +    return node;
   8.438 +}
   8.439 +
   8.440 +static int avc_latest_notif_update(int seqno, int is_insert)
   8.441 +{
   8.442 +    int ret = 0;
   8.443 +    static DEFINE_SPINLOCK(notif_lock);
   8.444 +    unsigned long flag;
   8.445 +
   8.446 +    spin_lock_irqsave(&notif_lock, flag);
   8.447 +    if ( is_insert )
   8.448 +    {
   8.449 +        if ( seqno < avc_cache.latest_notif )
   8.450 +        {
   8.451 +            printk(KERN_WARNING "avc:  seqno %d < latest_notif %d\n",
   8.452 +                   seqno, avc_cache.latest_notif);
   8.453 +            ret = -EAGAIN;
   8.454 +        }
   8.455 +    }
   8.456 +    else
   8.457 +    {
   8.458 +        if ( seqno > avc_cache.latest_notif )
   8.459 +            avc_cache.latest_notif = seqno;
   8.460 +    }
   8.461 +    spin_unlock_irqrestore(&notif_lock, flag);
   8.462 +
   8.463 +    return ret;
   8.464 +}
   8.465 +
   8.466 +/**
   8.467 + * avc_insert - Insert an AVC entry.
   8.468 + * @ssid: source security identifier
   8.469 + * @tsid: target security identifier
   8.470 + * @tclass: target security class
   8.471 + * @ae: AVC entry
   8.472 + *
   8.473 + * Insert an AVC entry for the SID pair
   8.474 + * (@ssid, @tsid) and class @tclass.
   8.475 + * The access vectors and the sequence number are
   8.476 + * normally provided by the security server in
   8.477 + * response to a security_compute_av() call.  If the
   8.478 + * sequence number @ae->avd.seqno is not less than the latest
   8.479 + * revocation notification, then the function copies
   8.480 + * the access vectors into a cache entry, returns
   8.481 + * avc_node inserted. Otherwise, this function returns NULL.
   8.482 + */
   8.483 +static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
   8.484 +{
   8.485 +    struct avc_node *pos, *node = NULL;
   8.486 +    int hvalue;
   8.487 +	unsigned long flag;
   8.488 +
   8.489 +    if ( avc_latest_notif_update(ae->avd.seqno, 1) )
   8.490 +        goto out;
   8.491 +
   8.492 +    node = avc_alloc_node();
   8.493 +    if ( node )
   8.494 +    {
   8.495 +        hvalue = avc_hash(ssid, tsid, tclass);
   8.496 +        avc_node_populate(node, ssid, tsid, tclass, ae);
   8.497 +
   8.498 +		spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
   8.499 +        list_for_each_entry(pos, &avc_cache.slots[hvalue], list)
   8.500 +        {
   8.501 +            if ( pos->ae.ssid == ssid && pos->ae.tsid == tsid &&
   8.502 +                                                    pos->ae.tclass == tclass )
   8.503 +            {
   8.504 +                avc_node_replace(node, pos);
   8.505 +                goto found;
   8.506 +            }
   8.507 +        }
   8.508 +        list_add_rcu(&node->list, &avc_cache.slots[hvalue]);
   8.509 +found:
   8.510 +		spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
   8.511 +    }
   8.512 +out:
   8.513 +    return node;
   8.514 +}
   8.515 +
   8.516 +/**
   8.517 + * avc_audit - Audit the granting or denial of permissions.
   8.518 + * @ssid: source security identifier
   8.519 + * @tsid: target security identifier
   8.520 + * @tclass: target security class
   8.521 + * @requested: requested permissions
   8.522 + * @avd: access vector decisions
   8.523 + * @result: result from avc_has_perm_noaudit
   8.524 + * @a:  auxiliary audit data
   8.525 + *
   8.526 + * Audit the granting or denial of permissions in accordance
   8.527 + * with the policy.  This function is typically called by
   8.528 + * avc_has_perm() after a permission check, but can also be
   8.529 + * called directly by callers who use avc_has_perm_noaudit()
   8.530 + * in order to separate the permission check from the auditing.
   8.531 + * For example, this separation is useful when the permission check must
   8.532 + * be performed under a lock, to allow the lock to be released
   8.533 + * before calling the auditing code.
   8.534 + */
   8.535 +void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   8.536 +               struct av_decision *avd, int result, struct avc_audit_data *a)
   8.537 +{
   8.538 +    struct domain *d = current->domain;
   8.539 +    u32 denied, audited;
   8.540 +
   8.541 +    denied = requested & ~avd->allowed;
   8.542 +    if ( denied )
   8.543 +    {
   8.544 +        audited = denied;
   8.545 +        if ( !(audited & avd->auditdeny) )
   8.546 +            return;
   8.547 +    }
   8.548 +    else if ( result )
   8.549 +    {
   8.550 +        audited = denied = requested;
   8.551 +    }
   8.552 +    else
   8.553 +    {
   8.554 +        audited = requested;
   8.555 +        if ( !(audited & avd->auditallow) )
   8.556 +            return;
   8.557 +    }
   8.558 +
   8.559 +    printk("avc:  %s ", denied ? "denied" : "granted");
   8.560 +    avc_dump_av(tclass, audited);
   8.561 +    printk(" for ");
   8.562 +
   8.563 +    if ( a && a->d )
   8.564 +        d = a->d;
   8.565 +    if ( d )
   8.566 +        printk("domid=%d", d->domain_id);
   8.567 +
   8.568 +    printk("\n");
   8.569 +    avc_dump_query(ssid, tsid, tclass);
   8.570 +    printk("\n");
   8.571 +
   8.572 +}
   8.573 +
   8.574 +/**
   8.575 + * avc_add_callback - Register a callback for security events.
   8.576 + * @callback: callback function
   8.577 + * @events: security events
   8.578 + * @ssid: source security identifier or %SECSID_WILD
   8.579 + * @tsid: target security identifier or %SECSID_WILD
   8.580 + * @tclass: target security class
   8.581 + * @perms: permissions
   8.582 + *
   8.583 + * Register a callback function for events in the set @events
   8.584 + * related to the SID pair (@ssid, @tsid) and
   8.585 + * and the permissions @perms, interpreting
   8.586 + * @perms based on @tclass.  Returns %0 on success or
   8.587 + * -%ENOMEM if insufficient memory exists to add the callback.
   8.588 + */
   8.589 +int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, u16 tclass,
   8.590 +                u32 perms, u32 *out_retained), u32 events, u32 ssid, u32 tsid,
   8.591 +                                                        u16 tclass, u32 perms)
   8.592 +{
   8.593 +    struct avc_callback_node *c;
   8.594 +    int rc = 0;
   8.595 +
   8.596 +    c = xmalloc(struct avc_callback_node);
   8.597 +    if ( !c )
   8.598 +    {
   8.599 +        rc = -ENOMEM;
   8.600 +        goto out;
   8.601 +    }
   8.602 +
   8.603 +    c->callback = callback;
   8.604 +    c->events = events;
   8.605 +    c->ssid = ssid;
   8.606 +    c->tsid = tsid;
   8.607 +    c->perms = perms;
   8.608 +    c->next = avc_callbacks;
   8.609 +    avc_callbacks = c;
   8.610 +out:
   8.611 +    return rc;
   8.612 +}
   8.613 +
   8.614 +static inline int avc_sidcmp(u32 x, u32 y)
   8.615 +{
   8.616 +    return (x == y || x == SECSID_WILD || y == SECSID_WILD);
   8.617 +}
   8.618 +
   8.619 +/**
   8.620 + * avc_update_node Update an AVC entry
   8.621 + * @event : Updating event
   8.622 + * @perms : Permission mask bits
   8.623 + * @ssid,@tsid,@tclass : identifier of an AVC entry
   8.624 + *
   8.625 + * if a valid AVC entry doesn't exist,this function returns -ENOENT.
   8.626 + * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
   8.627 + * otherwise, this function update the AVC entry. The original AVC-entry object
   8.628 + * will release later by RCU.
   8.629 + */
   8.630 +static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
   8.631 +{
   8.632 +    int hvalue, rc = 0;
   8.633 +	unsigned long flag;
   8.634 +    struct avc_node *pos, *node, *orig = NULL;
   8.635 +    
   8.636 +    node = avc_alloc_node();
   8.637 +    if ( !node )
   8.638 +    {
   8.639 +        rc = -ENOMEM;
   8.640 +        goto out;
   8.641 +    }
   8.642 +
   8.643 +    hvalue = avc_hash(ssid, tsid, tclass);    
   8.644 +	spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
   8.645 +
   8.646 +    list_for_each_entry(pos, &avc_cache.slots[hvalue], list)
   8.647 +    {
   8.648 +        if ( ssid==pos->ae.ssid && tsid==pos->ae.tsid &&
   8.649 +                                                        tclass==pos->ae.tclass )
   8.650 +        {
   8.651 +            orig = pos;
   8.652 +            break;
   8.653 +        }
   8.654 +    }
   8.655 +
   8.656 +    if ( !orig )
   8.657 +    {
   8.658 +        rc = -ENOENT;
   8.659 +        avc_node_kill(node);
   8.660 +        goto out_unlock;
   8.661 +    }
   8.662 +
   8.663 +    /*
   8.664 +     * Copy and replace original node.
   8.665 +     */
   8.666 +
   8.667 +    avc_node_populate(node, ssid, tsid, tclass, &orig->ae);
   8.668 +
   8.669 +    switch ( event )
   8.670 +    {
   8.671 +    case AVC_CALLBACK_GRANT:
   8.672 +        node->ae.avd.allowed |= perms;
   8.673 +    break;
   8.674 +    case AVC_CALLBACK_TRY_REVOKE:
   8.675 +    case AVC_CALLBACK_REVOKE:
   8.676 +        node->ae.avd.allowed &= ~perms;
   8.677 +    break;
   8.678 +    case AVC_CALLBACK_AUDITALLOW_ENABLE:
   8.679 +        node->ae.avd.auditallow |= perms;
   8.680 +    break;
   8.681 +    case AVC_CALLBACK_AUDITALLOW_DISABLE:
   8.682 +        node->ae.avd.auditallow &= ~perms;
   8.683 +    break;
   8.684 +    case AVC_CALLBACK_AUDITDENY_ENABLE:
   8.685 +        node->ae.avd.auditdeny |= perms;
   8.686 +    break;
   8.687 +    case AVC_CALLBACK_AUDITDENY_DISABLE:
   8.688 +        node->ae.avd.auditdeny &= ~perms;
   8.689 +    break;
   8.690 +    }
   8.691 +    avc_node_replace(node, orig);
   8.692 +out_unlock:
   8.693 +	spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
   8.694 +out:
   8.695 +    return rc;
   8.696 +}
   8.697 +
   8.698 +/**
   8.699 + * avc_ss_reset - Flush the cache and revalidate migrated permissions.
   8.700 + * @seqno: policy sequence number
   8.701 + */
   8.702 +int avc_ss_reset(u32 seqno)
   8.703 +{
   8.704 +    struct avc_callback_node *c;
   8.705 +    int i, rc = 0;
   8.706 +	unsigned long flag;
   8.707 +    struct avc_node *node;
   8.708 +
   8.709 +    for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
   8.710 +    {
   8.711 +		spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
   8.712 +        list_for_each_entry(node, &avc_cache.slots[i], list)
   8.713 +            avc_node_delete(node);
   8.714 +		spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
   8.715 +    }
   8.716 +    
   8.717 +    for ( c = avc_callbacks; c; c = c->next )
   8.718 +    {
   8.719 +        if ( c->events & AVC_CALLBACK_RESET )
   8.720 +        {
   8.721 +            rc = c->callback(AVC_CALLBACK_RESET,
   8.722 +                     0, 0, 0, 0, NULL);
   8.723 +            if ( rc )
   8.724 +                goto out;
   8.725 +        }
   8.726 +    }
   8.727 +
   8.728 +    avc_latest_notif_update(seqno, 0);
   8.729 +out:
   8.730 +    return rc;
   8.731 +}
   8.732 +
   8.733 +/**
   8.734 + * avc_has_perm_noaudit - Check permissions but perform no auditing.
   8.735 + * @ssid: source security identifier
   8.736 + * @tsid: target security identifier
   8.737 + * @tclass: target security class
   8.738 + * @requested: requested permissions, interpreted based on @tclass
   8.739 + * @avd: access vector decisions
   8.740 + *
   8.741 + * Check the AVC to determine whether the @requested permissions are granted
   8.742 + * for the SID pair (@ssid, @tsid), interpreting the permissions
   8.743 + * based on @tclass, and call the security server on a cache miss to obtain
   8.744 + * a new decision and add it to the cache.  Return a copy of the decisions
   8.745 + * in @avd.  Return %0 if all @requested permissions are granted,
   8.746 + * -%EACCES if any permissions are denied, or another -errno upon
   8.747 + * other errors.  This function is typically called by avc_has_perm(),
   8.748 + * but may also be called directly to separate permission checking from
   8.749 + * auditing, e.g. in cases where a lock must be held for the check but
   8.750 + * should be released for the auditing.
   8.751 + */
   8.752 +int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   8.753 +                                                     struct av_decision *avd)
   8.754 +{
   8.755 +    struct avc_node *node;
   8.756 +    struct avc_entry entry, *p_ae;
   8.757 +    int rc = 0;
   8.758 +    u32 denied;
   8.759 +
   8.760 +    rcu_read_lock();
   8.761 +
   8.762 +    node = avc_lookup(ssid, tsid, tclass, requested);
   8.763 +    if ( !node )
   8.764 +    {
   8.765 +        rcu_read_unlock();
   8.766 +        rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
   8.767 +        if ( rc )
   8.768 +            goto out;
   8.769 +        rcu_read_lock();
   8.770 +        node = avc_insert(ssid,tsid,tclass,&entry);
   8.771 +    }
   8.772 +
   8.773 +    p_ae = node ? &node->ae : &entry;
   8.774 +
   8.775 +    if ( avd )
   8.776 +        memcpy(avd, &p_ae->avd, sizeof(*avd));
   8.777 +
   8.778 +    denied = requested & ~(p_ae->avd.allowed);
   8.779 +
   8.780 +    if ( !requested || denied )
   8.781 +    {
   8.782 +        if ( flask_enforcing )
   8.783 +            rc = -EACCES;
   8.784 +        else
   8.785 +            if ( node )
   8.786 +                avc_update_node(AVC_CALLBACK_GRANT,requested,
   8.787 +                        ssid,tsid,tclass);
   8.788 +    }
   8.789 +
   8.790 +    rcu_read_unlock();
   8.791 +out:
   8.792 +    return rc;
   8.793 +}
   8.794 +
   8.795 +/**
   8.796 + * avc_has_perm - Check permissions and perform any appropriate auditing.
   8.797 + * @ssid: source security identifier
   8.798 + * @tsid: target security identifier
   8.799 + * @tclass: target security class
   8.800 + * @requested: requested permissions, interpreted based on @tclass
   8.801 + * @auditdata: auxiliary audit data
   8.802 + *
   8.803 + * Check the AVC to determine whether the @requested permissions are granted
   8.804 + * for the SID pair (@ssid, @tsid), interpreting the permissions
   8.805 + * based on @tclass, and call the security server on a cache miss to obtain
   8.806 + * a new decision and add it to the cache.  Audit the granting or denial of
   8.807 + * permissions in accordance with the policy.  Return %0 if all @requested
   8.808 + * permissions are granted, -%EACCES if any permissions are denied, or
   8.809 + * another -errno upon other errors.
   8.810 + */
   8.811 +int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
   8.812 +                 u32 requested, struct avc_audit_data *auditdata)
   8.813 +{
   8.814 +    struct av_decision avd;
   8.815 +    int rc;
   8.816 +
   8.817 +    rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
   8.818 +    avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
   8.819 +    return rc;
   8.820 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/xsm/flask/flask_op.c	Fri Aug 31 11:31:18 2007 +0100
     9.3 @@ -0,0 +1,1079 @@
     9.4 +/*
     9.5 + *  This file contains the flask_op hypercall and associated functions.
     9.6 + *
     9.7 + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
     9.8 + *
     9.9 + *  This program is free software; you can redistribute it and/or modify
    9.10 + *  it under the terms of the GNU General Public License version 2,
    9.11 + *  as published by the Free Software Foundation.
    9.12 + */
    9.13 +
    9.14 +#include <xen/errno.h>
    9.15 +#include <xsm/xsm.h>
    9.16 +#include <xen/guest_access.h>
    9.17 +
    9.18 +#include <public/xsm/flask_op.h>
    9.19 +
    9.20 +#include <avc.h>
    9.21 +#include <avc_ss.h>
    9.22 +#include <objsec.h>
    9.23 +#include <conditional.h>
    9.24 +
    9.25 +#ifdef FLASK_DEVELOP
    9.26 +int flask_enforcing = 0;
    9.27 +integer_param("flask_enforcing", flask_enforcing);
    9.28 +#endif
    9.29 +
    9.30 +#ifdef FLASK_BOOTPARAM
    9.31 +int flask_enabled = 1;
    9.32 +integer_param("flask_enabled", flask_enabled);
    9.33 +#endif
    9.34 +
    9.35 +static DEFINE_SPINLOCK(sel_sem);
    9.36 +
    9.37 +/* global data for booleans */
    9.38 +static int bool_num = 0;
    9.39 +static int *bool_pending_values = NULL;
    9.40 +
    9.41 +extern int ss_initialized;
    9.42 +
    9.43 +extern struct xsm_operations *original_ops;
    9.44 +
    9.45 +static int domain_has_security(struct domain *d, u32 perms)
    9.46 +{
    9.47 +    struct domain_security_struct *dsec;
    9.48 +    
    9.49 +    dsec = d->ssid;
    9.50 +    if ( !dsec )
    9.51 +        return -EACCES;
    9.52 +        
    9.53 +    return avc_has_perm(dsec->sid, SECINITSID_SECURITY, SECCLASS_SECURITY, 
    9.54 +                                                                perms, NULL);
    9.55 +}
    9.56 +
    9.57 +static int flask_security_user(char *buf, int size)
    9.58 +{
    9.59 +    char *page = NULL;
    9.60 +    char *con, *user, *ptr;
    9.61 +    u32 sid, *sids;
    9.62 +    int length;
    9.63 +    char *newcon;
    9.64 +    int i, rc;
    9.65 +    u32 len, nsids;
    9.66 +        
    9.67 +    length = domain_has_security(current->domain, SECURITY__COMPUTE_USER);
    9.68 +    if ( length )
    9.69 +        return length;
    9.70 +            
    9.71 +    length = -ENOMEM;
    9.72 +    con = xmalloc_array(char, size+1);
    9.73 +    if ( !con )
    9.74 +        return length;
    9.75 +    memset(con, 0, size+1);
    9.76 +    
    9.77 +    user = xmalloc_array(char, size+1);
    9.78 +    if ( !user )
    9.79 +        goto out;
    9.80 +    memset(user, 0, size+1);
    9.81 +    
    9.82 +    length = -ENOMEM;
    9.83 +    page = xmalloc_bytes(PAGE_SIZE);
    9.84 +    if ( !page )
    9.85 +        goto out2;
    9.86 +    memset(page, 0, PAGE_SIZE);
    9.87 +
    9.88 +    length = -EFAULT;
    9.89 +    if ( copy_from_user(page, buf, size) )
    9.90 +        goto out2;
    9.91 +        
    9.92 +    length = -EINVAL;
    9.93 +    if ( sscanf(page, "%s %s", con, user) != 2 )
    9.94 +        goto out2;
    9.95 +
    9.96 +    length = security_context_to_sid(con, strlen(con)+1, &sid);
    9.97 +    if ( length < 0 )
    9.98 +        goto out2;
    9.99 +            
   9.100 +    length = security_get_user_sids(sid, user, &sids, &nsids);
   9.101 +    if ( length < 0 )
   9.102 +        goto out2;
   9.103 +    
   9.104 +    memset(page, 0, PAGE_SIZE);
   9.105 +    length = snprintf(page, PAGE_SIZE, "%u", nsids) + 1;
   9.106 +    ptr = page + length;
   9.107 +    for ( i = 0; i < nsids; i++ )
   9.108 +    {
   9.109 +        rc = security_sid_to_context(sids[i], &newcon, &len);
   9.110 +        if ( rc )
   9.111 +        {
   9.112 +            length = rc;
   9.113 +            goto out3;
   9.114 +        }
   9.115 +        if ( (length + len) >= PAGE_SIZE )
   9.116 +        {
   9.117 +            xfree(newcon);
   9.118 +            length = -ERANGE;
   9.119 +            goto out3;
   9.120 +        }
   9.121 +        memcpy(ptr, newcon, len);
   9.122 +        xfree(newcon);
   9.123 +        ptr += len;
   9.124 +        length += len;
   9.125 +    }
   9.126 +    
   9.127 +    if ( copy_to_user(buf, page, length) )
   9.128 +        length = -EFAULT;
   9.129 +        
   9.130 +out3:
   9.131 +    xfree(sids);
   9.132 +out2:
   9.133 +    if ( page )
   9.134 +        xfree(page);
   9.135 +    xfree(user);
   9.136 +out:
   9.137 +    xfree(con);
   9.138 +    return length;
   9.139 +}
   9.140 +
   9.141 +static int flask_security_relabel(char *buf, int size)
   9.142 +{
   9.143 +    char *scon, *tcon;
   9.144 +    u32 ssid, tsid, newsid;
   9.145 +    u16 tclass;
   9.146 +    int length;
   9.147 +    char *newcon;
   9.148 +    u32 len;
   9.149 +
   9.150 +    length = domain_has_security(current->domain, SECURITY__COMPUTE_RELABEL);
   9.151 +    if ( length )
   9.152 +        return length;
   9.153 +            
   9.154 +    length = -ENOMEM;
   9.155 +    scon = xmalloc_array(char, size+1);
   9.156 +    if ( !scon )
   9.157 +        return length;
   9.158 +    memset(scon, 0, size+1);
   9.159 +        
   9.160 +    tcon = xmalloc_array(char, size+1);
   9.161 +    if ( !tcon )
   9.162 +        goto out;
   9.163 +    memset(tcon, 0, size+1);
   9.164 +        
   9.165 +    length = -EINVAL;
   9.166 +    if ( sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3 )
   9.167 +        goto out2;
   9.168 +            
   9.169 +    length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
   9.170 +    if ( length < 0 )
   9.171 +        goto out2;
   9.172 +    length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
   9.173 +    if ( length < 0 )
   9.174 +        goto out2;
   9.175 +            
   9.176 +    length = security_change_sid(ssid, tsid, tclass, &newsid);
   9.177 +    if ( length < 0 )
   9.178 +        goto out2;
   9.179 +            
   9.180 +    length = security_sid_to_context(newsid, &newcon, &len);
   9.181 +    if ( length < 0 )
   9.182 +        goto out2;
   9.183 +            
   9.184 +    if ( len > PAGE_SIZE )
   9.185 +    {
   9.186 +        length = -ERANGE;
   9.187 +        goto out3;
   9.188 +    }
   9.189 +        
   9.190 +    if ( copy_to_user(buf, newcon, len) )
   9.191 +        len = -EFAULT;
   9.192 +
   9.193 +    length = len;
   9.194 +        
   9.195 +out3:
   9.196 +    xfree(newcon);
   9.197 +out2:
   9.198 +    xfree(tcon);
   9.199 +out:
   9.200 +    xfree(scon);
   9.201 +    return length;
   9.202 +}
   9.203 +
   9.204 +static int flask_security_create(char *buf, int size)
   9.205 +{
   9.206 +    char *scon, *tcon;
   9.207 +    u32 ssid, tsid, newsid;
   9.208 +    u16 tclass;
   9.209 +    int length;
   9.210 +    char *newcon;
   9.211 +    u32 len;
   9.212 +
   9.213 +    length = domain_has_security(current->domain, SECURITY__COMPUTE_CREATE);
   9.214 +    if ( length )
   9.215 +        return length;
   9.216 +
   9.217 +    length = -ENOMEM;
   9.218 +    scon = xmalloc_array(char, size+1);
   9.219 +    if ( !scon )
   9.220 +        return length;
   9.221 +    memset(scon, 0, size+1);
   9.222 +
   9.223 +    tcon = xmalloc_array(char, size+1);
   9.224 +    if ( !tcon )
   9.225 +        goto out;
   9.226 +    memset(tcon, 0, size+1);
   9.227 +
   9.228 +    length = -EINVAL;
   9.229 +    if ( sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3 )
   9.230 +        goto out2;
   9.231 +
   9.232 +    length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
   9.233 +    if ( length < 0 )
   9.234 +        goto out2;
   9.235 +
   9.236 +    length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
   9.237 +    if ( length < 0 )
   9.238 +        goto out2;
   9.239 +
   9.240 +    length = security_transition_sid(ssid, tsid, tclass, &newsid);
   9.241 +    if ( length < 0 )
   9.242 +        goto out2;
   9.243 +
   9.244 +    length = security_sid_to_context(newsid, &newcon, &len);
   9.245 +    if ( length < 0 )    
   9.246 +        goto out2;
   9.247 +
   9.248 +    if ( len > PAGE_SIZE )
   9.249 +    {
   9.250 +        printk( "%s:  context size (%u) exceeds payload "
   9.251 +                "max\n", __FUNCTION__, len);
   9.252 +        length = -ERANGE;
   9.253 +        goto out3;
   9.254 +    }
   9.255 +
   9.256 +    if ( copy_to_user(buf, newcon, len) )
   9.257 +        len = -EFAULT;
   9.258 +
   9.259 +    length = len;
   9.260 +        
   9.261 +out3:
   9.262 +    xfree(newcon);
   9.263 +out2:
   9.264 +    xfree(tcon);
   9.265 +out:
   9.266 +    xfree(scon);
   9.267 +    return length;
   9.268 +}
   9.269 +
   9.270 +static int flask_security_access(char *buf, int size)
   9.271 +{
   9.272 +    char *page = NULL;
   9.273 +    char *scon, *tcon;
   9.274 +    u32 ssid, tsid;
   9.275 +    u16 tclass;
   9.276 +    u32 req;
   9.277 +    struct av_decision avd;
   9.278 +    int length;
   9.279 +
   9.280 +    length = domain_has_security(current->domain, SECURITY__COMPUTE_AV);
   9.281 +    if ( length )
   9.282 +        return length;
   9.283 +
   9.284 +    length = -ENOMEM;
   9.285 +    scon = xmalloc_array(char, size+1);
   9.286 +    if (!scon)
   9.287 +        return length;
   9.288 +    memset(scon, 0, size+1);
   9.289 +
   9.290 +    tcon = xmalloc_array(char, size+1);
   9.291 +    if ( !tcon )
   9.292 +        goto out;
   9.293 +    memset( tcon, 0, size+1 );
   9.294 +
   9.295 +    length = -EINVAL;
   9.296 +    if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
   9.297 +        goto out2;
   9.298 +
   9.299 +    length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
   9.300 +    if ( length < 0 )
   9.301 +        goto out2;
   9.302 +
   9.303 +    length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
   9.304 +    if ( length < 0 )
   9.305 +        goto out2;
   9.306 +
   9.307 +    length = security_compute_av(ssid, tsid, tclass, req, &avd);
   9.308 +    if ( length < 0 )
   9.309 +        goto out2;
   9.310 +
   9.311 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.312 +    if ( !page )
   9.313 +    {
   9.314 +        length = -ENOMEM;
   9.315 +        goto out2;
   9.316 +    }
   9.317 +
   9.318 +    memset(page, 0, PAGE_SIZE);
   9.319 +
   9.320 +    length = snprintf(page, PAGE_SIZE, "%x %x %x %x %u", 
   9.321 +                                        avd.allowed, avd.decided,
   9.322 +                                        avd.auditallow, avd.auditdeny, 
   9.323 +                                        avd.seqno);
   9.324 +                
   9.325 +    if ( copy_to_user(buf, page, length) )
   9.326 +        length = -EFAULT;
   9.327 +        
   9.328 +out2:
   9.329 +    xfree(tcon);
   9.330 +out:
   9.331 +    xfree(scon);
   9.332 +    return length;
   9.333 +}
   9.334 +
   9.335 +static int flask_security_member(char *buf, int size)
   9.336 +{
   9.337 +    char *scon, *tcon;
   9.338 +    u32 ssid, tsid, newsid;
   9.339 +    u16 tclass;
   9.340 +    int length;
   9.341 +    char *newcon;
   9.342 +    u32 len;
   9.343 +
   9.344 +    length = domain_has_security(current->domain, SECURITY__COMPUTE_MEMBER);
   9.345 +    if ( length )
   9.346 +        return length;
   9.347 +
   9.348 +    length = -ENOMEM;
   9.349 +    scon = xmalloc_array(char, size+1);
   9.350 +    if ( !scon )
   9.351 +        return length;
   9.352 +    memset(scon, 0, size+1);
   9.353 +
   9.354 +    tcon = xmalloc_array(char, size+1);
   9.355 +    if ( !tcon )
   9.356 +        goto out;
   9.357 +    memset(tcon, 0, size+1);
   9.358 +
   9.359 +    length = -EINVAL;
   9.360 +    if ( sscanf(buf, "%s, %s, %hu", scon, tcon, &tclass) != 3 )
   9.361 +        goto out2;
   9.362 +
   9.363 +    length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
   9.364 +    if ( length < 0 )
   9.365 +        goto out2;
   9.366 +
   9.367 +    length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
   9.368 +    if ( length < 0 )
   9.369 +        goto out2;
   9.370 +
   9.371 +    length = security_member_sid(ssid, tsid, tclass, &newsid);
   9.372 +    if ( length < 0 )
   9.373 +        goto out2;
   9.374 +
   9.375 +    length = security_sid_to_context(newsid, &newcon, &len);
   9.376 +    if ( length < 0 )
   9.377 +        goto out2;
   9.378 +
   9.379 +    if ( len > PAGE_SIZE )
   9.380 +    {
   9.381 +        printk("%s:  context size (%u) exceeds payload "
   9.382 +                "max\n", __FUNCTION__, len);
   9.383 +        length = -ERANGE;
   9.384 +        goto out3;
   9.385 +    }
   9.386 +
   9.387 +    if ( copy_to_user(buf, newcon, len) )
   9.388 +        len = -EFAULT;
   9.389 +
   9.390 +    length = len;
   9.391 +
   9.392 +out3:
   9.393 +    xfree(newcon);
   9.394 +out2:
   9.395 +    xfree(tcon);
   9.396 +out:
   9.397 +    xfree(scon);
   9.398 +    return length;
   9.399 +}
   9.400 +
   9.401 +static int flask_security_setenforce(char *buf, int count)
   9.402 +{
   9.403 +    char *page = NULL;
   9.404 +    int length;
   9.405 +    int new_value;
   9.406 +
   9.407 +    if ( count < 0 || count >= PAGE_SIZE )
   9.408 +        return -ENOMEM;
   9.409 +
   9.410 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.411 +    if ( !page )
   9.412 +        return -ENOMEM;
   9.413 +    memset(page, 0, PAGE_SIZE);
   9.414 +    length = -EFAULT;
   9.415 +    if ( copy_from_user(page, buf, count) )
   9.416 +        goto out;
   9.417 +
   9.418 +    length = -EINVAL;
   9.419 +    if ( sscanf(page, "%d", &new_value) != 1 )
   9.420 +        goto out;
   9.421 +
   9.422 +    if ( new_value != flask_enforcing )
   9.423 +    {
   9.424 +        length = domain_has_security(current->domain, SECURITY__SETENFORCE);
   9.425 +        if ( length )
   9.426 +            goto out;
   9.427 +        flask_enforcing = new_value;
   9.428 +        if ( flask_enforcing )
   9.429 +            avc_ss_reset(0);
   9.430 +    }
   9.431 +    length = count;
   9.432 +
   9.433 +out:
   9.434 +    xfree(page);
   9.435 +    return length;
   9.436 +}
   9.437 +
   9.438 +static int flask_security_context(char *buf, int count)
   9.439 +{
   9.440 +    char *page = NULL;
   9.441 +    u32 sid;
   9.442 +    int length;
   9.443 +
   9.444 +    length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
   9.445 +    if ( length )
   9.446 +        goto out;
   9.447 +
   9.448 +    if ( count < 0 || count >= PAGE_SIZE )
   9.449 +        return -ENOMEM;
   9.450 +
   9.451 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.452 +    if ( !page )
   9.453 +        return -ENOMEM;
   9.454 +    memset(page, 0, PAGE_SIZE);
   9.455 +    length = -EFAULT;
   9.456 +    if ( copy_from_user(page, buf, count) )
   9.457 +        goto out;
   9.458 +
   9.459 +    length = security_context_to_sid(page, count, &sid);
   9.460 +    if ( length < 0 )
   9.461 +        goto out;
   9.462 +
   9.463 +    memset(page, 0, PAGE_SIZE);
   9.464 +    length = snprintf(page, PAGE_SIZE, "%u", sid);
   9.465 +
   9.466 +    if ( copy_to_user(buf, page, count) )
   9.467 +        length = -EFAULT;
   9.468 +
   9.469 +out:
   9.470 +    xfree(page);
   9.471 +    return length;
   9.472 +}
   9.473 +
   9.474 +static int flask_security_sid(char *buf, int count)
   9.475 +{
   9.476 +    char *page = NULL;
   9.477 +    char *context;
   9.478 +    u32 sid;
   9.479 +    u32 len;
   9.480 +    int length;
   9.481 +
   9.482 +    length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
   9.483 +    if ( length )
   9.484 +        goto out;
   9.485 +
   9.486 +    if ( count < 0 || count >= PAGE_SIZE )
   9.487 +        return -ENOMEM;
   9.488 +
   9.489 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.490 +    if ( !page )
   9.491 +        return -ENOMEM;
   9.492 +    memset(page, 0, PAGE_SIZE);
   9.493 +    length = -EFAULT;
   9.494 +    if ( copy_from_user(page, buf, count) )
   9.495 +        goto out;
   9.496 +
   9.497 +    if ( sscanf(page, "%u", &sid) != 1 )
   9.498 +        goto out;
   9.499 +
   9.500 +    length = security_sid_to_context(sid, &context, &len);
   9.501 +    if ( length < 0 )
   9.502 +        goto out;
   9.503 +
   9.504 +    if ( copy_to_user(buf, context, len) )
   9.505 +        length = -EFAULT;
   9.506 +    
   9.507 +    xfree(context);
   9.508 +
   9.509 +out:
   9.510 +    xfree(page);
   9.511 +    return length;
   9.512 +}
   9.513 +
   9.514 +int flask_disable(void)
   9.515 +{
   9.516 +    static int flask_disabled = 0;
   9.517 +
   9.518 +    if ( ss_initialized )
   9.519 +    {
   9.520 +        /* Not permitted after initial policy load. */
   9.521 +        return -EINVAL;
   9.522 +    }
   9.523 +
   9.524 +    if ( flask_disabled )
   9.525 +    {
   9.526 +        /* Only do this once. */
   9.527 +        return -EINVAL;
   9.528 +    }
   9.529 +
   9.530 +    printk("Flask:  Disabled at runtime.\n");
   9.531 +
   9.532 +    flask_disabled = 1;
   9.533 +
   9.534 +    /* Reset xsm_ops to the original module. */
   9.535 +    xsm_ops = original_ops;
   9.536 +
   9.537 +    return 0;
   9.538 +}
   9.539 +
   9.540 +static int flask_security_disable(char *buf, int count)
   9.541 +{
   9.542 +    char *page = NULL;
   9.543 +    int length;
   9.544 +    int new_value;
   9.545 +
   9.546 +    if ( count < 0 || count >= PAGE_SIZE )
   9.547 +        return -ENOMEM;
   9.548 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.549 +    if ( !page )
   9.550 +        return -ENOMEM;
   9.551 +    memset(page, 0, PAGE_SIZE);
   9.552 +    length = -EFAULT;
   9.553 +    if ( copy_from_user(page, buf, count) )
   9.554 +        goto out;
   9.555 +
   9.556 +    length = -EINVAL;
   9.557 +    if ( sscanf(page, "%d", &new_value) != 1 )
   9.558 +        goto out;
   9.559 +
   9.560 +    if ( new_value )
   9.561 +    {
   9.562 +        length = flask_disable();
   9.563 +        if ( length < 0 )
   9.564 +            goto out;
   9.565 +    }
   9.566 +
   9.567 +    length = count;
   9.568 +
   9.569 +out:
   9.570 +    xfree(page);
   9.571 +    return length;
   9.572 +}
   9.573 +
   9.574 +static int flask_security_setavc_threshold(char *buf, int count)
   9.575 +{
   9.576 +    char *page = NULL;
   9.577 +    int ret;
   9.578 +    int new_value;
   9.579 +
   9.580 +    if ( count < 0 || count >= PAGE_SIZE )
   9.581 +    {
   9.582 +        ret = -ENOMEM;
   9.583 +        goto out;
   9.584 +    }
   9.585 +
   9.586 +    page = (char*)xmalloc_bytes(PAGE_SIZE);
   9.587 +    if (!page)
   9.588 +        return -ENOMEM;
   9.589 +    memset(page, 0, PAGE_SIZE);
   9.590 +
   9.591 +    if ( copy_from_user(page, buf, count) )
   9.592 +    {
   9.593 +        ret = -EFAULT;
   9.594 +        goto out_free;
   9.595 +    }
   9.596 +
   9.597 +    if ( sscanf(page, "%u", &new_value) != 1 )
   9.598 +    {
   9.599 +        ret = -EINVAL;
   9.600 +        goto out_free;
   9.601 +    }
   9.602 +
   9.603 +    if ( new_value != avc_cache_threshold )
   9.604 +    {
   9.605 +        ret = domain_has_security(current->domain, SECURITY__SETSECPARAM);
   9.606 +        if ( ret )
   9.607 +            goto out_free;
   9.608 +        avc_cache_threshold = new_value;
   9.609 +    }
   9.610 +    ret = count;
   9.611 +
   9.612 +out_free:
   9.613 +    xfree(page);
   9.614 +out:
   9.615 +    return ret;
   9.616 +}
   9.617 +
   9.618 +static int flask_security_set_bool(char *buf, int count)
   9.619 +{
   9.620 +    char *page = NULL;
   9.621 +    int length = -EFAULT;
   9.622 +    int i, new_value;
   9.623 +
   9.624 +    spin_lock(&sel_sem);
   9.625 +
   9.626 +    length = domain_has_security(current->domain, SECURITY__SETBOOL);
   9.627 +    if ( length )
   9.628 +        goto out;
   9.629 +
   9.630 +    if ( count < 0 || count >= PAGE_SIZE )
   9.631 +    {
   9.632 +        length = -ENOMEM;
   9.633 +        goto out;
   9.634 +    }
   9.635 +
   9.636 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.637 +    if ( !page )
   9.638 +    {
   9.639 +        length = -ENOMEM;
   9.640 +        goto out;
   9.641 +    }
   9.642 +    memset(page, 0, PAGE_SIZE);
   9.643 +
   9.644 +    if ( copy_from_user(page, buf, count) )
   9.645 +        goto out;
   9.646 +
   9.647 +    length = -EINVAL;
   9.648 +    if ( sscanf(page, "%d %d", &i, &new_value) != 2 )
   9.649 +        goto out;
   9.650 +
   9.651 +    if ( new_value )
   9.652 +    {
   9.653 +        new_value = 1;
   9.654 +    }
   9.655 +
   9.656 +    bool_pending_values[i] = new_value;
   9.657 +    length = count;
   9.658 +
   9.659 +out:
   9.660 +    spin_unlock(&sel_sem);
   9.661 +    if ( page )
   9.662 +        xfree(page);
   9.663 +    return length;
   9.664 +}
   9.665 +
   9.666 +static int flask_security_commit_bools(char *buf, int count)
   9.667 +{
   9.668 +    char *page = NULL;
   9.669 +    int length = -EFAULT;
   9.670 +    int new_value;
   9.671 +
   9.672 +    spin_lock(&sel_sem);
   9.673 +
   9.674 +    length = domain_has_security(current->domain, SECURITY__SETBOOL);
   9.675 +    if ( length )
   9.676 +        goto out;
   9.677 +
   9.678 +    if ( count < 0 || count >= PAGE_SIZE )
   9.679 +    {
   9.680 +        length = -ENOMEM;
   9.681 +        goto out;
   9.682 +    }
   9.683 +
   9.684 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.685 +    if ( !page )
   9.686 +    {
   9.687 +        length = -ENOMEM;
   9.688 +        goto out;
   9.689 +    }
   9.690 +    memset(page, 0, PAGE_SIZE);
   9.691 +
   9.692 +    if ( copy_from_user(page, buf, count) )
   9.693 +        goto out;
   9.694 +
   9.695 +    length = -EINVAL;
   9.696 +    if ( sscanf(page, "%d", &new_value) != 1 )
   9.697 +        goto out;
   9.698 +
   9.699 +    if ( new_value )
   9.700 +        security_set_bools(bool_num, bool_pending_values);
   9.701 +    
   9.702 +    length = count;
   9.703 +
   9.704 +out:
   9.705 +    spin_unlock(&sel_sem);
   9.706 +    if ( page )
   9.707 +        xfree(page);
   9.708 +    return length;
   9.709 +}
   9.710 +
   9.711 +static int flask_security_get_bool(char *buf, int count)
   9.712 +{
   9.713 +    char *page = NULL;
   9.714 +    int length;
   9.715 +    int i, cur_enforcing;
   9.716 +    
   9.717 +    spin_lock(&sel_sem);
   9.718 +    
   9.719 +    length = -EFAULT;
   9.720 +
   9.721 +    if ( count < 0 || count > PAGE_SIZE )
   9.722 +    {
   9.723 +        length = -EINVAL;
   9.724 +        goto out;
   9.725 +    }
   9.726 +
   9.727 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.728 +    if ( !page )
   9.729 +    {
   9.730 +        length = -ENOMEM;
   9.731 +        goto out;
   9.732 +    }
   9.733 +    memset(page, 0, PAGE_SIZE);
   9.734 +
   9.735 +    if ( copy_from_user(page, buf, count) )
   9.736 +        goto out;
   9.737 +
   9.738 +    length = -EINVAL;
   9.739 +    if ( sscanf(page, "%d", &i) != 1 )
   9.740 +        goto out;
   9.741 +
   9.742 +    cur_enforcing = security_get_bool_value(i);
   9.743 +    if ( cur_enforcing < 0 )
   9.744 +    {
   9.745 +        length = cur_enforcing;
   9.746 +        goto out;
   9.747 +    }
   9.748 +
   9.749 +    length = snprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
   9.750 +                bool_pending_values[i]);
   9.751 +    if ( length < 0 )
   9.752 +        goto out;
   9.753 +
   9.754 +    if ( copy_to_user(buf, page, length) )
   9.755 +        length = -EFAULT;
   9.756 +
   9.757 +out:
   9.758 +    spin_unlock(&sel_sem);
   9.759 +    if ( page )
   9.760 +        xfree(page);
   9.761 +    return length;
   9.762 +}
   9.763 +
   9.764 +static int flask_security_make_bools(void)
   9.765 +{
   9.766 +    int i, ret = 0;
   9.767 +    char **names = NULL;
   9.768 +    int num;
   9.769 +    int *values = NULL;
   9.770 +    
   9.771 +    xfree(bool_pending_values);
   9.772 +    
   9.773 +    ret = security_get_bools(&num, &names, &values);
   9.774 +    if ( ret != 0 )
   9.775 +        goto out;
   9.776 +
   9.777 +    bool_num = num;
   9.778 +    bool_pending_values = values;
   9.779 +
   9.780 +out:
   9.781 +    if ( names )
   9.782 +    {
   9.783 +        for ( i = 0; i < num; i++ )
   9.784 +            xfree(names[i]);
   9.785 +        xfree(names);
   9.786 +    }    
   9.787 +    return ret;
   9.788 +}
   9.789 +
   9.790 +#ifdef FLASK_AVC_STATS
   9.791 +
   9.792 +static int flask_security_avc_cachestats(char *buf, int count)
   9.793 +{
   9.794 +    char *page = NULL;
   9.795 +    int len = 0;
   9.796 +    int length = 0;
   9.797 +    long long idx = 0;
   9.798 +    int cpu;
   9.799 +    struct avc_cache_stats *st;
   9.800 +
   9.801 +    page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.802 +    if ( !page )
   9.803 +        return -ENOMEM;
   9.804 +    memset(page, 0, PAGE_SIZE);
   9.805 +
   9.806 +    len = snprintf(page, PAGE_SIZE, "lookups hits misses allocations reclaims "
   9.807 +                                                                   "frees\n");
   9.808 +    memcpy(buf, page, len);
   9.809 +    buf += len;
   9.810 +    length += len;
   9.811 +
   9.812 +    for ( cpu = idx; cpu < NR_CPUS; ++cpu )
   9.813 +    {
   9.814 +        if ( !cpu_possible(cpu) )
   9.815 +            continue;
   9.816 +        idx = cpu + 1;
   9.817 +        st = &per_cpu(avc_cache_stats, cpu);
   9.818 +
   9.819 +        len = snprintf(page, PAGE_SIZE, "%u %u %u %u %u %u\n", st->lookups,
   9.820 +                                       st->hits, st->misses, st->allocations,
   9.821 +                                                       st->reclaims, st->frees);
   9.822 +        memcpy(buf, page, len);
   9.823 +        buf += len;
   9.824 +        length += len;
   9.825 +    }
   9.826 +
   9.827 +    xfree(page);    
   9.828 +    return length;
   9.829 +}
   9.830 +
   9.831 +#endif
   9.832 +
   9.833 +static int flask_security_load(char *buf, int count)
   9.834 +{
   9.835 +    int ret;
   9.836 +    int length;
   9.837 +    void *data = NULL;
   9.838 +
   9.839 +    spin_lock(&sel_sem);
   9.840 +
   9.841 +    length = domain_has_security(current->domain, SECURITY__LOAD_POLICY);
   9.842 +    if ( length )
   9.843 +        goto out;
   9.844 +
   9.845 +    if ( (count < 0) || (count > 64 * 1024 * 1024) 
   9.846 +                               || (data = xmalloc_array(char, count)) == NULL )
   9.847 +    {
   9.848 +        length = -ENOMEM;
   9.849 +        goto out;
   9.850 +    }
   9.851 +
   9.852 +    length = -EFAULT;
   9.853 +    if ( copy_from_user(data, buf, count) != 0 )
   9.854 +        goto out;
   9.855 +
   9.856 +    length = security_load_policy(data, count);
   9.857 +    if ( length )
   9.858 +        goto out;
   9.859 +
   9.860 +    ret = flask_security_make_bools();
   9.861 +    if ( ret )
   9.862 +        length = ret;
   9.863 +    else
   9.864 +        length = count;
   9.865 +
   9.866 +out:
   9.867 +    spin_unlock(&sel_sem);
   9.868 +    xfree(data);
   9.869 +    return length;
   9.870 +}
   9.871 +
   9.872 +long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op)
   9.873 +{
   9.874 +    flask_op_t curop, *op = &curop;
   9.875 +    int rc = 0;
   9.876 +    int length = 0;
   9.877 +    char *page = NULL;
   9.878 +
   9.879 +    if ( copy_from_guest(op, u_flask_op, 1) )
   9.880 +        return -EFAULT;
   9.881 +
   9.882 +    switch ( op->cmd )
   9.883 +    {
   9.884 +
   9.885 +    case FLASK_LOAD:
   9.886 +    {
   9.887 +        length = flask_security_load(op->buf, op->size);
   9.888 +    }
   9.889 +    break;
   9.890 +    
   9.891 +    case FLASK_GETENFORCE:
   9.892 +    {
   9.893 +        page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.894 +        if ( !page )
   9.895 +            return -ENOMEM;
   9.896 +        memset(page, 0, PAGE_SIZE);
   9.897 +        
   9.898 +        length = snprintf(page, PAGE_SIZE, "%d", flask_enforcing);
   9.899 +        
   9.900 +        if ( copy_to_user(op->buf, page, length) )
   9.901 +        {
   9.902 +            rc = -EFAULT;
   9.903 +            goto out;
   9.904 +        }
   9.905 +    }
   9.906 +    break;    
   9.907 +
   9.908 +    case FLASK_SETENFORCE:
   9.909 +    {
   9.910 +        length = flask_security_setenforce(op->buf, op->size);
   9.911 +    }
   9.912 +    break;    
   9.913 +
   9.914 +    case FLASK_CONTEXT_TO_SID:
   9.915 +    {
   9.916 +        length = flask_security_context(op->buf, op->size);
   9.917 +    }
   9.918 +    break;    
   9.919 +
   9.920 +    case FLASK_SID_TO_CONTEXT:
   9.921 +    {
   9.922 +        length = flask_security_sid(op->buf, op->size);
   9.923 +    }
   9.924 +    break; 
   9.925 +
   9.926 +    case FLASK_ACCESS:
   9.927 +    {
   9.928 +        length = flask_security_access(op->buf, op->size);
   9.929 +    }
   9.930 +    break;    
   9.931 +
   9.932 +    case FLASK_CREATE:
   9.933 +    {
   9.934 +        length = flask_security_create(op->buf, op->size);
   9.935 +    }
   9.936 +    break;    
   9.937 +
   9.938 +    case FLASK_RELABEL:
   9.939 +    {
   9.940 +        length = flask_security_relabel(op->buf, op->size);
   9.941 +    }
   9.942 +    break;
   9.943 +
   9.944 +    case FLASK_USER:
   9.945 +    {
   9.946 +        length = flask_security_user(op->buf, op->size);
   9.947 +    }
   9.948 +    break;    
   9.949 +
   9.950 +    case FLASK_POLICYVERS:
   9.951 +    {
   9.952 +        page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.953 +        if ( !page )
   9.954 +            return -ENOMEM;
   9.955 +        memset(page, 0, PAGE_SIZE);
   9.956 +
   9.957 +        length = snprintf(page, PAGE_SIZE, "%d", POLICYDB_VERSION_MAX);
   9.958 +
   9.959 +        if ( copy_to_user(op->buf, page, length) )
   9.960 +        {
   9.961 +            rc = -EFAULT;
   9.962 +            goto out;
   9.963 +        }
   9.964 +    }
   9.965 +    break;    
   9.966 +
   9.967 +    case FLASK_GETBOOL:
   9.968 +    {
   9.969 +        length = flask_security_get_bool(op->buf, op->size);
   9.970 +    }
   9.971 +    break;
   9.972 +
   9.973 +    case FLASK_SETBOOL:
   9.974 +    {
   9.975 +        length = flask_security_set_bool(op->buf, op->size);
   9.976 +    }
   9.977 +    break;
   9.978 +
   9.979 +    case FLASK_COMMITBOOLS:
   9.980 +    {
   9.981 +        length = flask_security_commit_bools(op->buf, op->size);
   9.982 +    }
   9.983 +    break;
   9.984 +
   9.985 +    case FLASK_MLS:
   9.986 +    {
   9.987 +        page = (char *)xmalloc_bytes(PAGE_SIZE);
   9.988 +        if ( !page )
   9.989 +            return -ENOMEM;
   9.990 +        memset(page, 0, PAGE_SIZE);
   9.991 +
   9.992 +        length = snprintf(page, PAGE_SIZE, "%d", flask_mls_enabled);
   9.993 +
   9.994 +        if ( copy_to_user(op->buf, page, length) )
   9.995 +        {
   9.996 +            rc = -EFAULT;
   9.997 +            goto out;
   9.998 +        }
   9.999 +    }
  9.1000 +    break;    
  9.1001 +
  9.1002 +    case FLASK_DISABLE:
  9.1003 +    {
  9.1004 +        length = flask_security_disable(op->buf, op->size);
  9.1005 +    }
  9.1006 +    break;    
  9.1007 +
  9.1008 +    case FLASK_GETAVC_THRESHOLD:
  9.1009 +    {
  9.1010 +        page = (char *)xmalloc_bytes(PAGE_SIZE);
  9.1011 +        if ( !page )
  9.1012 +            return -ENOMEM;
  9.1013 +        memset(page, 0, PAGE_SIZE);
  9.1014 +
  9.1015 +        length = snprintf(page, PAGE_SIZE, "%d", avc_cache_threshold);
  9.1016 +
  9.1017 +        if ( copy_to_user(op->buf, page, length) )
  9.1018 +        {
  9.1019 +            rc = -EFAULT;
  9.1020 +            goto out;
  9.1021 +        }
  9.1022 +    }
  9.1023 +    break;
  9.1024 +
  9.1025 +    case FLASK_SETAVC_THRESHOLD:
  9.1026 +    {
  9.1027 +        length = flask_security_setavc_threshold(op->buf, op->size);
  9.1028 +    }
  9.1029 +    break;
  9.1030 +
  9.1031 +    case FLASK_AVC_HASHSTATS:
  9.1032 +    {
  9.1033 +        page = (char *)xmalloc_bytes(PAGE_SIZE);
  9.1034 +        if ( !page )
  9.1035 +            return -ENOMEM;
  9.1036 +        memset(page, 0, PAGE_SIZE);
  9.1037 +
  9.1038 +        length = avc_get_hash_stats(page);
  9.1039 +
  9.1040 +        if ( copy_to_user(op->buf, page, length) )
  9.1041 +        {
  9.1042 +            rc = -EFAULT;
  9.1043 +            goto out;
  9.1044 +        }
  9.1045 +    }
  9.1046 +    break;
  9.1047 +
  9.1048 +#ifdef FLASK_AVC_STATS    
  9.1049 +    case FLASK_AVC_CACHESTATS:
  9.1050 +    {
  9.1051 +        length = flask_security_avc_cachestats(op->buf, op->size);
  9.1052 +    }
  9.1053 +    break;
  9.1054 +#endif    
  9.1055 +
  9.1056 +    case FLASK_MEMBER:
  9.1057 +    {
  9.1058 +        length = flask_security_member(op->buf, op->size);
  9.1059 +    }
  9.1060 +    break;    
  9.1061 +
  9.1062 +    default:
  9.1063 +        length = -ENOSYS;
  9.1064 +        break;
  9.1065 +
  9.1066 +    }
  9.1067 +
  9.1068 +    if ( length < 0 )
  9.1069 +    {
  9.1070 +        rc = length;
  9.1071 +        goto out;
  9.1072 +    }
  9.1073 +    op->size = length;
  9.1074 +    if ( copy_to_guest(u_flask_op, op, 1) )
  9.1075 +        rc = -EFAULT;
  9.1076 +
  9.1077 +out:
  9.1078 +    if ( page )
  9.1079 +        xfree(page);
  9.1080 +    return rc;
  9.1081 +}
  9.1082 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/xsm/flask/hooks.c	Fri Aug 31 11:31:18 2007 +0100
    10.3 @@ -0,0 +1,1159 @@
    10.4 + /*
    10.5 + *  This file contains the Flask hook function implementations for Xen.
    10.6 + *
    10.7 + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
    10.8 + *
    10.9 + *    This program is free software; you can redistribute it and/or modify
   10.10 + *    it under the terms of the GNU General Public License version 2,
   10.11 + *      as published by the Free Software Foundation.
   10.12 + */
   10.13 +
   10.14 +#include <xen/init.h>
   10.15 +#include <xen/lib.h>
   10.16 +#include <xen/sched.h>
   10.17 +#include <xen/xmalloc.h>
   10.18 +#include <xsm/xsm.h>
   10.19 +#include <xen/spinlock.h>
   10.20 +#include <xen/cpumask.h>
   10.21 +#include <xen/errno.h>
   10.22 +#include <xen/guest_access.h>
   10.23 +#include <public/xen.h>
   10.24 +#include <public/physdev.h>
   10.25 +#include <public/platform.h>
   10.26 +
   10.27 +#include <public/xsm/flask_op.h>
   10.28 +
   10.29 +#include <avc.h>
   10.30 +#include <avc_ss.h>
   10.31 +#include <objsec.h>
   10.32 +#include <conditional.h>
   10.33 +
   10.34 +struct xsm_operations *original_ops = NULL;
   10.35 +
   10.36 +static int domain_has_perm(struct domain *dom1, struct domain *dom2, 
   10.37 +                                                        u16 class, u32 perms)
   10.38 +{
   10.39 +    struct domain_security_struct *dsec1, *dsec2;
   10.40 +
   10.41 +    dsec1 = dom1->ssid;
   10.42 +    dsec2 = dom2->ssid;
   10.43 +
   10.44 +    return avc_has_perm(dsec1->sid, dsec2->sid, class, perms, NULL);
   10.45 +}
   10.46 +
   10.47 +static int domain_has_evtchn(struct domain *d, struct evtchn *chn, u32 perms)
   10.48 +{
   10.49 +    struct domain_security_struct *dsec;
   10.50 +    struct evtchn_security_struct *esec;
   10.51 +
   10.52 +    dsec = d->ssid;
   10.53 +    esec = chn->ssid;
   10.54 +
   10.55 +    return avc_has_perm(dsec->sid, esec->sid, SECCLASS_EVENT, perms, NULL);
   10.56 +}
   10.57 +
   10.58 +static int domain_has_xen(struct domain *d, u32 perms)
   10.59 +{
   10.60 +    struct domain_security_struct *dsec;
   10.61 +    dsec = d->ssid;
   10.62 +
   10.63 +    return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, perms, NULL);
   10.64 +}
   10.65 +
   10.66 +static int flask_domain_alloc_security(struct domain *d)
   10.67 +{
   10.68 +    struct domain_security_struct *dsec;
   10.69 +
   10.70 +    dsec = xmalloc(struct domain_security_struct);
   10.71 +
   10.72 +    if ( !dsec )
   10.73 +        return -ENOMEM;
   10.74 +
   10.75 +    memset(dsec, 0, sizeof(struct domain_security_struct));
   10.76 +
   10.77 +    dsec->d = d;
   10.78 +
   10.79 +    if ( d->domain_id == IDLE_DOMAIN_ID )
   10.80 +    {
   10.81 +        dsec->sid = SECINITSID_XEN;
   10.82 +        dsec->create_sid = SECINITSID_DOM0;
   10.83 +    }
   10.84 +    else
   10.85 +    {
   10.86 +        dsec->sid = SECINITSID_UNLABELED;
   10.87 +        dsec->create_sid = SECSID_NULL;
   10.88 +    }
   10.89 +
   10.90 +    d->ssid = dsec;
   10.91 +
   10.92 +    return 0;
   10.93 +}
   10.94 +
   10.95 +static void flask_domain_free_security(struct domain *d)
   10.96 +{
   10.97 +    struct domain_security_struct *dsec = d->ssid;
   10.98 +
   10.99 +    if ( !dsec )
  10.100 +        return;
  10.101 +
  10.102 +    d->ssid = NULL;
  10.103 +    xfree(dsec);
  10.104 +}
  10.105 +
  10.106 +static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn, 
  10.107 +                                                                    domid_t id2)
  10.108 +{
  10.109 +    u32 newsid;
  10.110 +    int rc;
  10.111 +    domid_t id;
  10.112 +    struct domain *d2;
  10.113 +    struct domain_security_struct *dsec, *dsec1, *dsec2;
  10.114 +    struct evtchn_security_struct *esec;
  10.115 +
  10.116 +    dsec = current->domain->ssid;
  10.117 +    dsec1 = d1->ssid;
  10.118 +    esec = chn->ssid;
  10.119 +
  10.120 +    if ( id2 == DOMID_SELF )
  10.121 +        id = current->domain->domain_id;
  10.122 +    else
  10.123 +        id = id2;
  10.124 +
  10.125 +    d2 = get_domain_by_id(id);
  10.126 +    if ( d2 == NULL )
  10.127 +        return -EPERM;
  10.128 +
  10.129 +    dsec2 = d2->ssid;
  10.130 +    rc = security_transition_sid(dsec1->sid, dsec2->sid, SECCLASS_EVENT, 
  10.131 +                                                                    &newsid);
  10.132 +    if ( rc )
  10.133 +        goto out;
  10.134 +
  10.135 +    rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT,
  10.136 +                                            EVENT__CREATE|EVENT__ALLOC, NULL);
  10.137 +    if ( rc )
  10.138 +        goto out;
  10.139 +
  10.140 +    rc = avc_has_perm(newsid, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, NULL);
  10.141 +    if ( rc )
  10.142 +        goto out;
  10.143 +    else
  10.144 +        esec->sid = newsid;
  10.145 +
  10.146 +out:
  10.147 +    put_domain(d2);
  10.148 +    return rc;
  10.149 +}
  10.150 +
  10.151 +static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1, 
  10.152 +                                        struct domain *d2, struct evtchn *chn2)
  10.153 +{
  10.154 +    u32 newsid1;
  10.155 +    u32 newsid2;
  10.156 +    int rc;
  10.157 +    struct domain_security_struct *dsec1, *dsec2;
  10.158 +    struct evtchn_security_struct *esec1, *esec2;
  10.159 +
  10.160 +    dsec1 = d1->ssid;
  10.161 +    dsec2 = d2->ssid;
  10.162 +
  10.163 +    esec1 = chn1->ssid;
  10.164 +    esec2 = chn2->ssid;
  10.165 +
  10.166 +    rc = security_transition_sid(dsec1->sid, dsec2->sid, 
  10.167 +                                        SECCLASS_EVENT, &newsid1);
  10.168 +    if ( rc )
  10.169 +    {
  10.170 +        printk("%s: security_transition_sid failed, rc=%d (domain=%d)\n",
  10.171 +                                            __FUNCTION__, -rc, d2->domain_id);
  10.172 +        return rc;
  10.173 +    }
  10.174 +
  10.175 +    rc = avc_has_perm(dsec1->sid, newsid1, SECCLASS_EVENT, EVENT__CREATE, NULL);
  10.176 +    if ( rc )
  10.177 +        return rc;
  10.178 +
  10.179 +    rc = security_transition_sid(dsec2->sid, dsec1->sid, 
  10.180 +                                        SECCLASS_EVENT, &newsid2);
  10.181 +    if ( rc )
  10.182 +    {
  10.183 +        printk("%s: security_transition_sid failed, rc=%d (domain=%d)\n",
  10.184 +                                            __FUNCTION__, -rc, d1->domain_id);
  10.185 +        return rc;
  10.186 +    }
  10.187 +
  10.188 +    rc = avc_has_perm(dsec2->sid, newsid2, SECCLASS_EVENT, EVENT__CREATE, NULL);
  10.189 +    if ( rc )
  10.190 +        return rc;
  10.191 +
  10.192 +    rc = avc_has_perm(newsid1, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, NULL);
  10.193 +    if ( rc )
  10.194 +        return rc;
  10.195 +
  10.196 +    rc = avc_has_perm(newsid2, dsec1->sid, SECCLASS_EVENT, EVENT__BIND, NULL);
  10.197 +    if ( rc )
  10.198 +        return rc;    
  10.199 +
  10.200 +    esec1->sid = newsid1;
  10.201 +    esec2->sid = newsid2;
  10.202 +
  10.203 +    return rc;
  10.204 +}
  10.205 +
  10.206 +static void flask_evtchn_close_post(struct evtchn *chn)
  10.207 +{
  10.208 +    struct evtchn_security_struct *esec;
  10.209 +    esec = chn->ssid;
  10.210 +
  10.211 +    esec->sid = SECINITSID_UNLABELED;
  10.212 +}
  10.213 +
  10.214 +static int flask_evtchn_send(struct domain *d, struct evtchn *chn)
  10.215 +{
  10.216 +    return domain_has_evtchn(d, chn, EVENT__SEND);
  10.217 +}
  10.218 +
  10.219 +static int flask_evtchn_status(struct domain *d, struct evtchn *chn)
  10.220 +{
  10.221 +    return domain_has_evtchn(d, chn, EVENT__STATUS);
  10.222 +}
  10.223 +
  10.224 +static int flask_evtchn_reset(struct domain *d1, struct domain *d2)
  10.225 +{
  10.226 +    return domain_has_perm(d1, d2, SECCLASS_EVENT, EVENT__RESET);
  10.227 +}
  10.228 +
  10.229 +static int flask_alloc_security_evtchn(struct evtchn *chn)
  10.230 +{
  10.231 +    struct evtchn_security_struct *esec;
  10.232 +
  10.233 +    esec = xmalloc(struct evtchn_security_struct);
  10.234 +
  10.235 +    if ( !esec )
  10.236 +        return -ENOMEM;
  10.237 +
  10.238 +    memset(esec, 0, sizeof(struct evtchn_security_struct));
  10.239 +
  10.240 +    esec->chn = chn;
  10.241 +    esec->sid = SECINITSID_UNLABELED;
  10.242 +
  10.243 +    chn->ssid = esec;
  10.244 +
  10.245 +    return 0;    
  10.246 +}
  10.247 +
  10.248 +static void flask_free_security_evtchn(struct evtchn *chn)
  10.249 +{
  10.250 +    struct evtchn_security_struct *esec;
  10.251 +
  10.252 +    if ( !chn )
  10.253 +        return;
  10.254 +
  10.255 +    esec = chn->ssid;
  10.256 +
  10.257 +    if ( !esec )
  10.258 +        return;
  10.259 +
  10.260 +    chn->ssid = NULL;
  10.261 +    xfree(esec);
  10.262 +}
  10.263 +
  10.264 +static int flask_grant_mapref(struct domain *d1, struct domain *d2, 
  10.265 +                                                                uint32_t flags)
  10.266 +{
  10.267 +    u32 perms = GRANT__MAP_READ;
  10.268 +
  10.269 +    if ( flags & GTF_writing )
  10.270 +        perms |= GRANT__MAP_WRITE;
  10.271 +
  10.272 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, perms);
  10.273 +}
  10.274 +
  10.275 +static int flask_grant_unmapref(struct domain *d1, struct domain *d2)
  10.276 +{
  10.277 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__UNMAP);
  10.278 +}
  10.279 +
  10.280 +static int flask_grant_setup(struct domain *d1, struct domain *d2)
  10.281 +{
  10.282 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__SETUP);
  10.283 +}
  10.284 +
  10.285 +static int flask_grant_transfer(struct domain *d1, struct domain *d2)
  10.286 +{
  10.287 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__TRANSFER);
  10.288 +}
  10.289 +
  10.290 +static int flask_grant_copy(struct domain *d1, struct domain *d2)
  10.291 +{
  10.292 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__COPY);
  10.293 +}
  10.294 +
  10.295 +static int flask_grant_query_size(struct domain *d1, struct domain *d2)
  10.296 +{
  10.297 +    return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__QUERY);
  10.298 +}
  10.299 +
  10.300 +static int get_page_sid(struct page_info *page, u32 *sid)
  10.301 +{
  10.302 +    int rc = 0;
  10.303 +    struct domain *d;
  10.304 +    struct domain_security_struct *dsec;
  10.305 +    unsigned long mfn;
  10.306 +
  10.307 +    d = page_get_owner(page);
  10.308 +
  10.309 +    if ( d == NULL )
  10.310 +    {
  10.311 +        mfn = page_to_mfn(page);
  10.312 +        rc = security_iomem_sid(mfn, sid);
  10.313 +        return rc;
  10.314 +    }
  10.315 +
  10.316 +    switch ( d->domain_id )
  10.317 +    {
  10.318 +        case DOMID_IO:
  10.319 +            /*A tracked IO page?*/
  10.320 +            *sid = SECINITSID_DOMIO;
  10.321 +        break;
  10.322 +
  10.323 +        case DOMID_XEN:
  10.324 +            /*A page from Xen's private heap?*/
  10.325 +            *sid = SECINITSID_DOMXEN;
  10.326 +        break;
  10.327 +
  10.328 +        default:
  10.329 +            /*Pages are implicitly labeled by domain ownership!*/
  10.330 +            dsec = d->ssid;
  10.331 +            *sid = dsec->sid;
  10.332 +        break;
  10.333 +    }
  10.334 +
  10.335 +    return rc;
  10.336 +}
  10.337 +
  10.338 +static int get_mfn_sid(unsigned long mfn, u32 *sid)
  10.339 +{
  10.340 +    int rc = 0;
  10.341 +    struct page_info *page;
  10.342 +
  10.343 +    if ( mfn_valid(mfn) )
  10.344 +    {
  10.345 +        /*mfn is valid if this is a page that Xen is tracking!*/
  10.346 +        page = mfn_to_page(mfn);        
  10.347 +        rc = get_page_sid(page, sid);
  10.348 +    }
  10.349 +    else
  10.350 +    {
  10.351 +        /*Possibly an untracked IO page?*/
  10.352 +        rc = security_iomem_sid(mfn, sid);
  10.353 +    }
  10.354 +
  10.355 +    return rc;    
  10.356 +}
  10.357 +
  10.358 +static int flask_translate_gpfn_list(struct domain *d, unsigned long mfn)
  10.359 +{
  10.360 +    int rc = 0;
  10.361 +    u32 sid;
  10.362 +    struct domain_security_struct *dsec;
  10.363 +    dsec = d->ssid;
  10.364 +
  10.365 +    rc = get_mfn_sid(mfn, &sid);
  10.366 +    if ( rc )
  10.367 +        return rc;
  10.368 +
  10.369 +    return avc_has_perm(dsec->sid, sid, SECCLASS_MMU, MMU__TRANSLATEGP, NULL);
  10.370 +}
  10.371 +
  10.372 +static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2)
  10.373 +{
  10.374 +    return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__ADJUST);
  10.375 +}
  10.376 +
  10.377 +static int flask_memory_stat_reservation(struct domain *d1, struct domain *d2)
  10.378 +{
  10.379 +    return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__STAT);
  10.380 +}
  10.381 +
  10.382 +static int flask_memory_pin_page(struct domain *d, struct page_info *page)
  10.383 +{
  10.384 +    int rc = 0;
  10.385 +    u32 sid;
  10.386 +    struct domain_security_struct *dsec;
  10.387 +    dsec = d->ssid;
  10.388 +
  10.389 +    rc = get_page_sid(page, &sid);
  10.390 +    if ( rc )
  10.391 +        return rc;
  10.392 +
  10.393 +    return avc_has_perm(dsec->sid, sid, SECCLASS_MMU, MMU__PINPAGE, NULL);
  10.394 +}
  10.395 +
  10.396 +/* Used to defer flushing of memory structures. */
  10.397 +struct percpu_mm_info {
  10.398 +#define DOP_FLUSH_TLB      (1<<0) /* Flush the local TLB.                    */
  10.399 +#define DOP_FLUSH_ALL_TLBS (1<<1) /* Flush TLBs of all VCPUs of current dom. */
  10.400 +#define DOP_RELOAD_LDT     (1<<2) /* Reload the LDT shadow mapping.          */
  10.401 +    unsigned int   deferred_ops;
  10.402 +    /* If non-NULL, specifies a foreign subject domain for some operations. */
  10.403 +    struct domain *foreign;
  10.404 +};
  10.405 +static DEFINE_PER_CPU(struct percpu_mm_info, percpu_mm_info);
  10.406 +
  10.407 +/*
  10.408 + * Returns the current foreign domain; defaults to the currently-executing
  10.409 + * domain if a foreign override hasn't been specified.
  10.410 + */
  10.411 +#define FOREIGNDOM (this_cpu(percpu_mm_info).foreign ?: current->domain)
  10.412 +
  10.413 +static int flask_update_va_mapping(struct domain *d, l1_pgentry_t pte)
  10.414 +{
  10.415 +    int rc = 0;
  10.416 +    u32 psid;
  10.417 +    u32 map_perms = MMU__MAP_READ;
  10.418 +    unsigned long mfn;
  10.419 +    struct domain_security_struct *dsec;
  10.420 +
  10.421 +    dsec = d->ssid;
  10.422 +
  10.423 +    mfn = gmfn_to_mfn(FOREIGNDOM, l1e_get_pfn(pte));        
  10.424 +    rc = get_mfn_sid(mfn, &psid);
  10.425 +    if ( rc )
  10.426 +        return rc;
  10.427 +
  10.428 +    if ( l1e_get_flags(pte) & _PAGE_RW )
  10.429 +        map_perms |= MMU__MAP_WRITE;
  10.430 +
  10.431 +    return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, map_perms, NULL);
  10.432 +}
  10.433 +
  10.434 +static int flask_console_io(struct domain *d, int cmd)
  10.435 +{
  10.436 +    u32 perm;
  10.437 +
  10.438 +    switch ( cmd )
  10.439 +    {
  10.440 +        case CONSOLEIO_read:
  10.441 +            perm = XEN__READCONSOLE;
  10.442 +        break;
  10.443 +        case CONSOLEIO_write:
  10.444 +            perm = XEN__WRITECONSOLE;
  10.445 +        break;
  10.446 +        default:
  10.447 +            return -EPERM;
  10.448 +    }
  10.449 +
  10.450 +    return domain_has_xen(d, perm);
  10.451 +}
  10.452 +
  10.453 +static int flask_profile(struct domain *d, int op)
  10.454 +{
  10.455 +    u32 perm;
  10.456 +
  10.457 +    switch ( op )
  10.458 +    {
  10.459 +        case XENOPROF_init:
  10.460 +        case XENOPROF_enable_virq:
  10.461 +        case XENOPROF_disable_virq:
  10.462 +        case XENOPROF_get_buffer:
  10.463 +            perm = XEN__NONPRIVPROFILE;
  10.464 +        break;
  10.465 +        case XENOPROF_reset_active_list:
  10.466 +        case XENOPROF_reset_passive_list:
  10.467 +        case XENOPROF_set_active:
  10.468 +        case XENOPROF_set_passive:
  10.469 +        case XENOPROF_reserve_counters:
  10.470 +        case XENOPROF_counter:
  10.471 +        case XENOPROF_setup_events:
  10.472 +        case XENOPROF_start:
  10.473 +        case XENOPROF_stop:
  10.474 +        case XENOPROF_release_counters:
  10.475 +        case XENOPROF_shutdown:
  10.476 +            perm = XEN__PRIVPROFILE;
  10.477 +        break;
  10.478 +        default:
  10.479 +            return -EPERM;
  10.480 +    }
  10.481 +
  10.482 +    return domain_has_xen(d, perm);
  10.483 +}
  10.484 +
  10.485 +static int flask_kexec(void)
  10.486 +{
  10.487 +    return domain_has_xen(current->domain, XEN__KEXEC);
  10.488 +}
  10.489 +
  10.490 +static int flask_schedop_shutdown(struct domain *d1, struct domain *d2)
  10.491 +{
  10.492 +    return domain_has_perm(d1, d2, SECCLASS_DOMAIN, DOMAIN__SHUTDOWN);
  10.493 +}
  10.494 +
  10.495 +static void flask_security_domaininfo(struct domain *d, 
  10.496 +                                        struct xen_domctl_getdomaininfo *info)
  10.497 +{
  10.498 +    struct domain_security_struct *dsec;
  10.499 +
  10.500 +    dsec = d->ssid;
  10.501 +    info->ssidref = dsec->sid;
  10.502 +}
  10.503 +
  10.504 +static int flask_setvcpucontext(struct domain *d)
  10.505 +{
  10.506 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, 
  10.507 +                                                        DOMAIN__SETVCPUCONTEXT);
  10.508 +}
  10.509 +
  10.510 +static int flask_pausedomain(struct domain *d)
  10.511 +{
  10.512 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__PAUSE);
  10.513 +}
  10.514 +
  10.515 +static int flask_unpausedomain(struct domain *d)
  10.516 +{
  10.517 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__UNPAUSE);
  10.518 +}
  10.519 +
  10.520 +static int flask_resumedomain(struct domain *d)
  10.521 +{
  10.522 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__RESUME);
  10.523 +}
  10.524 +
  10.525 +static int flask_domain_create(struct domain *d, u32 ssidref)
  10.526 +{
  10.527 +    int rc;
  10.528 +    struct domain_security_struct *dsec1;
  10.529 +    struct domain_security_struct *dsec2;
  10.530 +
  10.531 +    dsec1 = current->domain->ssid;
  10.532 +
  10.533 +    if ( dsec1->create_sid == SECSID_NULL )
  10.534 +        dsec1->create_sid = ssidref;
  10.535 +
  10.536 +    rc = avc_has_perm(dsec1->sid, dsec1->create_sid, SECCLASS_DOMAIN, 
  10.537 +                                                        DOMAIN__CREATE, NULL);
  10.538 +    if ( rc )
  10.539 +    {
  10.540 +        dsec1->create_sid = SECSID_NULL;
  10.541 +        return rc;
  10.542 +    }
  10.543 +
  10.544 +    dsec2 = d->ssid;
  10.545 +    dsec2->sid = dsec1->create_sid;
  10.546 +
  10.547 +    dsec1->create_sid = SECSID_NULL;
  10.548 +    dsec2->create_sid = SECSID_NULL;
  10.549 +
  10.550 +    return rc;
  10.551 +}
  10.552 +
  10.553 +static int flask_max_vcpus(struct domain *d)
  10.554 +{
  10.555 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, 
  10.556 +                                                            DOMAIN__MAX_VCPUS);
  10.557 +}
  10.558 +
  10.559 +static int flask_destroydomain(struct domain *d)
  10.560 +{
  10.561 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, 
  10.562 +                                                            DOMAIN__DESTROY);
  10.563 +}
  10.564 +
  10.565 +static int flask_vcpuaffinity(int cmd, struct domain *d)
  10.566 +{
  10.567 +    u32 perm;
  10.568 +
  10.569 +    switch ( cmd )
  10.570 +    {
  10.571 +        case XEN_DOMCTL_setvcpuaffinity:
  10.572 +            perm = DOMAIN__SETVCPUAFFINITY;
  10.573 +        break;
  10.574 +        case XEN_DOMCTL_getvcpuaffinity:
  10.575 +            perm = DOMAIN__GETVCPUAFFINITY;
  10.576 +        break;
  10.577 +        default:
  10.578 +            return -EPERM;
  10.579 +    }
  10.580 +
  10.581 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm );
  10.582 +}
  10.583 +
  10.584 +static int flask_scheduler(struct domain *d)
  10.585 +{
  10.586 +    int rc = 0;
  10.587 +
  10.588 +    rc = domain_has_xen(current->domain, XEN__SCHEDULER);
  10.589 +    if ( rc )
  10.590 +        return rc;
  10.591 +
  10.592 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, 
  10.593 +                                                            DOMAIN__SCHEDULER);
  10.594 +}
  10.595 +
  10.596 +static int flask_getdomaininfo(struct domain *d)
  10.597 +{
  10.598 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.599 +                                                        DOMAIN__GETDOMAININFO);
  10.600 +}
  10.601 +
  10.602 +static int flask_getvcpucontext(struct domain *d)
  10.603 +{
  10.604 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, 
  10.605 +                                                        DOMAIN__GETVCPUCONTEXT);
  10.606 +}
  10.607 +
  10.608 +static int flask_getvcpuinfo(struct domain *d)
  10.609 +{
  10.610 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.611 +                                                        DOMAIN__GETVCPUINFO);
  10.612 +}
  10.613 +
  10.614 +static int flask_domain_settime(struct domain *d)
  10.615 +{
  10.616 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETTIME);
  10.617 +}
  10.618 +
  10.619 +static int flask_tbufcontrol(void)
  10.620 +{
  10.621 +    return domain_has_xen(current->domain, SECCLASS_XEN);
  10.622 +}
  10.623 +
  10.624 +static int flask_readconsole(uint32_t clear)
  10.625 +{
  10.626 +    u32 perms = XEN__READCONSOLE;
  10.627 +
  10.628 +    if ( clear )
  10.629 +        perms |= XEN__CLEARCONSOLE;
  10.630 +
  10.631 +    return domain_has_xen(current->domain, perms);
  10.632 +}
  10.633 +
  10.634 +static int flask_sched_id(void)
  10.635 +{
  10.636 +    return domain_has_xen(current->domain, XEN__SCHEDULER);
  10.637 +}
  10.638 +
  10.639 +static int flask_setdomainmaxmem(struct domain *d)
  10.640 +{
  10.641 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.642 +                                                    DOMAIN__SETDOMAINMAXMEM);
  10.643 +}
  10.644 +
  10.645 +static int flask_setdomainhandle(struct domain *d)
  10.646 +{
  10.647 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.648 +                                                    DOMAIN__SETDOMAINHANDLE);
  10.649 +}
  10.650 +
  10.651 +static int flask_setdebugging(struct domain *d)
  10.652 +{
  10.653 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.654 +                                                        DOMAIN__SETDEBUGGING);
  10.655 +}
  10.656 +
  10.657 +static inline u32 resource_to_perm(uint8_t access)
  10.658 +{
  10.659 +    if ( access )
  10.660 +        return RESOURCE__ADD;
  10.661 +    else
  10.662 +        return RESOURCE__REMOVE;
  10.663 +}
  10.664 +
  10.665 +static int flask_irq_permission(struct domain *d, uint8_t pirq, uint8_t access)
  10.666 +{
  10.667 +    u32 perm;
  10.668 +    u32 rsid;
  10.669 +    int rc = -EPERM;
  10.670 +
  10.671 +    struct domain_security_struct *ssec, *tsec;
  10.672 +
  10.673 +    rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE,
  10.674 +                                                    resource_to_perm(access));
  10.675 +
  10.676 +    if ( rc )
  10.677 +        return rc;
  10.678 +
  10.679 +    if ( access )
  10.680 +        perm = RESOURCE__ADD_IRQ;
  10.681 +    else
  10.682 +        perm = RESOURCE__REMOVE_IRQ;
  10.683 +
  10.684 +    ssec = current->domain->ssid;
  10.685 +    tsec = d->ssid;
  10.686 +
  10.687 +    rc = security_pirq_sid(pirq, &rsid);
  10.688 +    if ( rc )
  10.689 +        return rc;
  10.690 +
  10.691 +    rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL);
  10.692 +
  10.693 +    if ( rc )
  10.694 +        return rc;
  10.695 +
  10.696 +    return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, 
  10.697 +                                                        RESOURCE__USE, NULL);
  10.698 +}
  10.699 +
  10.700 +static int flask_iomem_permission(struct domain *d, unsigned long mfn, 
  10.701 +                                                                uint8_t access)
  10.702 +{
  10.703 +    u32 perm;
  10.704 +    u32 rsid;
  10.705 +    int rc = -EPERM;
  10.706 +
  10.707 +    struct domain_security_struct *ssec, *tsec;
  10.708 +
  10.709 +    rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE,
  10.710 +                                                    resource_to_perm(access));
  10.711 +
  10.712 +    if ( rc )
  10.713 +        return rc;
  10.714 +
  10.715 +    if ( access )
  10.716 +        perm = RESOURCE__ADD_IOMEM;
  10.717 +    else
  10.718 +        perm = RESOURCE__REMOVE_IOMEM;
  10.719 +
  10.720 +    ssec = current->domain->ssid;
  10.721 +    tsec = d->ssid;
  10.722 +
  10.723 +    rc = security_iomem_sid(mfn, &rsid);
  10.724 +    if ( rc )
  10.725 +        return rc;
  10.726 +
  10.727 +    rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL);
  10.728 +
  10.729 +    if ( rc )
  10.730 +        return rc;
  10.731 +
  10.732 +    return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, 
  10.733 +                                                        RESOURCE__USE, NULL);
  10.734 +}
  10.735 +
  10.736 +static int flask_perfcontrol(void)
  10.737 +{
  10.738 +    return domain_has_xen(current->domain, XEN__PERFCONTROL);
  10.739 +}
  10.740 +
  10.741 +void flask_complete_init(struct domain *d)
  10.742 +{
  10.743 +    struct domain_security_struct *dsec;
  10.744 +
  10.745 +    /* Set the security state for the Dom0 domain. */
  10.746 +    dsec = d->ssid;
  10.747 +    dsec->sid = SECINITSID_DOM0;
  10.748 +    dsec->create_sid = SECINITSID_UNLABELED;
  10.749 +
  10.750 +    printk("Flask:  Completed initialization.\n");
  10.751 +}
  10.752 +
  10.753 +#ifdef CONFIG_X86
  10.754 +static int flask_shadow_control(struct domain *d, uint32_t op)
  10.755 +{
  10.756 +    u32 perm;
  10.757 +
  10.758 +    switch ( op )
  10.759 +    {
  10.760 +        case XEN_DOMCTL_SHADOW_OP_OFF:
  10.761 +            perm = SHADOW__DISABLE;
  10.762 +        break;
  10.763 +        case XEN_DOMCTL_SHADOW_OP_ENABLE:
  10.764 +        case XEN_DOMCTL_SHADOW_OP_ENABLE_TEST:
  10.765 +        case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE:
  10.766 +        case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
  10.767 +        case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
  10.768 +            perm = SHADOW__ENABLE;
  10.769 +        break;
  10.770 +        case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
  10.771 +        case XEN_DOMCTL_SHADOW_OP_PEEK:
  10.772 +        case XEN_DOMCTL_SHADOW_OP_CLEAN:
  10.773 +            perm = SHADOW__LOGDIRTY;
  10.774 +        break;
  10.775 +        default:
  10.776 +            return -EPERM;
  10.777 +    }
  10.778 +
  10.779 +    return domain_has_perm(current->domain, d, SECCLASS_SHADOW, perm);
  10.780 +}
  10.781 +
  10.782 +static int flask_ioport_permission(struct domain *d, uint32_t ioport, 
  10.783 +                                                                uint8_t access)
  10.784 +{
  10.785 +    u32 perm;
  10.786 +    u32 rsid;
  10.787 +    int rc = -EPERM;
  10.788 +
  10.789 +    struct domain_security_struct *ssec, *tsec;
  10.790 +
  10.791 +    rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE,
  10.792 +                                                    resource_to_perm(access));
  10.793 +
  10.794 +    if ( rc )
  10.795 +        return rc;
  10.796 +
  10.797 +    if ( access )
  10.798 +        perm = RESOURCE__ADD_IOPORT;
  10.799 +    else
  10.800 +        perm = RESOURCE__REMOVE_IOPORT;
  10.801 +
  10.802 +    ssec = current->domain->ssid;
  10.803 +    tsec = d->ssid;
  10.804 +
  10.805 +    rc = security_ioport_sid(ioport, &rsid);
  10.806 +    if ( rc )
  10.807 +        return rc;
  10.808 +
  10.809 +    rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL);
  10.810 +    if ( rc )
  10.811 +        return rc;
  10.812 +
  10.813 +    return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, 
  10.814 +                                                        RESOURCE__USE, NULL);    
  10.815 +}
  10.816 +
  10.817 +static int flask_getpageframeinfo(struct page_info *page)
  10.818 +{
  10.819 +    int rc = 0;
  10.820 +    u32 tsid;
  10.821 +    struct domain_security_struct *dsec;
  10.822 +
  10.823 +    dsec = current->domain->ssid;
  10.824 +
  10.825 +    rc = get_page_sid(page, &tsid);
  10.826 +    if ( rc )
  10.827 +        return rc;
  10.828 +
  10.829 +    return avc_has_perm(dsec->sid, tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL);    
  10.830 +}
  10.831 +
  10.832 +static int flask_getmemlist(struct domain *d)
  10.833 +{
  10.834 +    return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGELIST);
  10.835 +}
  10.836 +
  10.837 +static int flask_hypercall_init(struct domain *d)
  10.838 +{
  10.839 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN,
  10.840 +                                                            DOMAIN__HYPERCALL);
  10.841 +}
  10.842 +
  10.843 +static int flask_hvmcontext(struct domain *d, uint32_t cmd)
  10.844 +{
  10.845 +    u32 perm;
  10.846 +
  10.847 +    switch ( cmd )
  10.848 +    {
  10.849 +        case XEN_DOMCTL_sethvmcontext:
  10.850 +            perm = HVM__SETHVMC;
  10.851 +        break;
  10.852 +        case XEN_DOMCTL_gethvmcontext:
  10.853 +            perm = HVM__GETHVMC;
  10.854 +        break;
  10.855 +        default:
  10.856 +            return -EPERM;
  10.857 +    }
  10.858 +
  10.859 +    return domain_has_perm(current->domain, d, SECCLASS_HVM, perm);
  10.860 +}
  10.861 +
  10.862 +static int flask_address_size(struct domain *d, uint32_t cmd)
  10.863 +{
  10.864 +    u32 perm;
  10.865 +
  10.866 +    switch ( cmd )
  10.867 +    {
  10.868 +        case XEN_DOMCTL_set_address_size:
  10.869 +            perm = DOMAIN__SETADDRSIZE;
  10.870 +        break;
  10.871 +        case XEN_DOMCTL_get_address_size:
  10.872 +            perm = DOMAIN__GETADDRSIZE;
  10.873 +        break;
  10.874 +        default:
  10.875 +            return -EPERM;
  10.876 +    }
  10.877 +
  10.878 +    return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm);
  10.879 +}
  10.880 +
  10.881 +static int flask_hvm_param(struct domain *d, unsigned long op)
  10.882 +{
  10.883 +    u32 perm;
  10.884 +
  10.885 +    switch ( op )
  10.886 +    {
  10.887 +        case HVMOP_set_param:
  10.888 +            perm = HVM__SETPARAM;
  10.889 +        break;
  10.890 +        case HVMOP_get_param:
  10.891 +            perm = HVM__GETPARAM;
  10.892 +        break;
  10.893 +        default:
  10.894 +            return -EPERM;
  10.895 +    }
  10.896 +
  10.897 +    return domain_has_perm(current->domain, d, SECCLASS_HVM, perm);
  10.898 +}
  10.899 +
  10.900 +static int flask_hvm_set_pci_intx_level(struct domain *d)
  10.901 +{
  10.902 +    return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCILEVEL);
  10.903 +}
  10.904 +
  10.905 +static int flask_hvm_set_isa_irq_level(struct domain *d)
  10.906 +{
  10.907 +    return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__IRQLEVEL);
  10.908 +}
  10.909 +
  10.910 +static int flask_hvm_set_pci_link_route(struct domain *d)
  10.911 +{
  10.912 +    return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCIROUTE);
  10.913 +}
  10.914 +
  10.915 +static int flask_apic(struct domain *d, int cmd)
  10.916 +{
  10.917 +    u32 perm;
  10.918 +
  10.919 +    switch ( cmd )
  10.920 +    {
  10.921 +        case PHYSDEVOP_APIC_READ:
  10.922 +            perm = XEN__READAPIC;
  10.923 +        break;
  10.924 +        case PHYSDEVOP_APIC_WRITE:
  10.925 +            perm = XEN__WRITEAPIC;
  10.926 +        break;
  10.927 +        default:
  10.928 +            return -EPERM;
  10.929 +    }
  10.930 +
  10.931 +    return domain_has_xen(d, perm);
  10.932 +}
  10.933 +
  10.934 +static int flask_assign_vector(struct domain *d, uint32_t pirq)
  10.935 +{
  10.936 +    u32 psid;
  10.937 +    struct domain_security_struct *dsec;
  10.938 +    dsec = d->ssid;
  10.939 +
  10.940 +    if ( security_pirq_sid(pirq, &psid) )
  10.941 +        return -EPERM;
  10.942 +
  10.943 +    return avc_has_perm(dsec->sid, psid, SECCLASS_EVENT, EVENT__VECTOR, NULL);
  10.944 +}
  10.945 +
  10.946 +static int flask_xen_settime(void)
  10.947 +{
  10.948 +    return domain_has_xen(current->domain, XEN__SETTIME);
  10.949 +}
  10.950 +
  10.951 +static int flask_memtype(uint32_t access)
  10.952 +{
  10.953 +    u32 perm;
  10.954 +
  10.955 +    switch ( access )
  10.956 +    {
  10.957 +        case XENPF_add_memtype:
  10.958 +            perm = XEN__MTRR_ADD;
  10.959 +        break;
  10.960 +        case XENPF_del_memtype:
  10.961 +            perm = XEN__MTRR_DEL;
  10.962 +        break;
  10.963 +        case XENPF_read_memtype:
  10.964 +            perm = XEN__MTRR_READ;
  10.965 +        break;
  10.966 +        default:
  10.967 +            return -EPERM;
  10.968 +    }
  10.969 +
  10.970 +    return domain_has_xen(current->domain, perm);
  10.971 +}
  10.972 +
  10.973 +static int flask_microcode(void)
  10.974 +{
  10.975 +    return domain_has_xen(current->domain, XEN__MICROCODE);
  10.976 +}
  10.977 +
  10.978 +static int flask_physinfo(void)
  10.979 +{
  10.980 +    return domain_has_xen(current->domain, XEN__PHYSINFO);
  10.981 +}
  10.982 +
  10.983 +static int flask_platform_quirk(uint32_t quirk)
  10.984 +{
  10.985 +    struct domain_security_struct *dsec;
  10.986 +    dsec = current->domain->ssid;
  10.987 +
  10.988 +    return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, 
  10.989 +                                                            XEN__QUIRK, NULL);
  10.990 +}
  10.991 +
  10.992 +static int flask_machine_memory_map(void)
  10.993 +{
  10.994 +    struct domain_security_struct *dsec;
  10.995 +    dsec = current->domain->ssid;
  10.996 +
  10.997 +    return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_MMU, 
  10.998 +                                                          MMU__MEMORYMAP, NULL);
  10.999 +}
 10.1000 +
 10.1001 +static int flask_domain_memory_map(struct domain *d)
 10.1002 +{
 10.1003 +    return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__MEMORYMAP);
 10.1004 +}
 10.1005 +
 10.1006 +static int flask_mmu_normal_update(struct domain *d, intpte_t fpte)
 10.1007 +{
 10.1008 +    int rc = 0;
 10.1009 +    u32 map_perms = MMU__MAP_READ;
 10.1010 +    unsigned long fmfn;
 10.1011 +    struct domain_security_struct *dsec;
 10.1012 +    u32 fsid;
 10.1013 +
 10.1014 +    dsec = d->ssid;
 10.1015 +
 10.1016 +    if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW )
 10.1017 +        map_perms |= MMU__MAP_WRITE;
 10.1018 +
 10.1019 +    fmfn = gmfn_to_mfn(FOREIGNDOM, l1e_get_pfn(l1e_from_intpte(fpte)));
 10.1020 +
 10.1021 +    rc = get_mfn_sid(fmfn, &fsid);
 10.1022 +    if ( rc )
 10.1023 +        return rc;
 10.1024 +
 10.1025 +    return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, NULL);
 10.1026 +}
 10.1027 +
 10.1028 +static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn)
 10.1029 +{
 10.1030 +    int rc = 0;
 10.1031 +    u32 psid;
 10.1032 +    struct domain_security_struct *dsec;
 10.1033 +    dsec = d->ssid;
 10.1034 +
 10.1035 +    rc = get_mfn_sid(mfn, &psid);
 10.1036 +    if ( rc )
 10.1037 +        return rc;
 10.1038 +
 10.1039 +    return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL);
 10.1040 +}
 10.1041 +
 10.1042 +static int flask_add_to_physmap(struct domain *d1, struct domain *d2)
 10.1043 +{
 10.1044 +    return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
 10.1045 +}
 10.1046 +#endif
 10.1047 +
 10.1048 +static struct xsm_operations flask_ops = {
 10.1049 +    .security_domaininfo = flask_security_domaininfo,
 10.1050 +    .setvcpucontext = flask_setvcpucontext,
 10.1051 +    .pausedomain = flask_pausedomain,
 10.1052 +    .unpausedomain = flask_unpausedomain,    
 10.1053 +    .resumedomain = flask_resumedomain,    
 10.1054 +    .domain_create = flask_domain_create,
 10.1055 +    .max_vcpus = flask_max_vcpus,
 10.1056 +    .destroydomain = flask_destroydomain,
 10.1057 +    .vcpuaffinity = flask_vcpuaffinity,
 10.1058 +    .scheduler = flask_scheduler,
 10.1059 +    .getdomaininfo = flask_getdomaininfo,
 10.1060 +    .getvcpucontext = flask_getvcpucontext,
 10.1061 +    .getvcpuinfo = flask_getvcpuinfo,
 10.1062 +    .domain_settime = flask_domain_settime,
 10.1063 +    .tbufcontrol = flask_tbufcontrol,
 10.1064 +    .readconsole = flask_readconsole,
 10.1065 +    .sched_id = flask_sched_id,
 10.1066 +    .setdomainmaxmem = flask_setdomainmaxmem,
 10.1067 +    .setdomainhandle = flask_setdomainhandle,
 10.1068 +    .setdebugging = flask_setdebugging,
 10.1069 +    .irq_permission = flask_irq_permission,
 10.1070 +    .iomem_permission = flask_iomem_permission,
 10.1071 +    .perfcontrol = flask_perfcontrol,
 10.1072 +
 10.1073 +    .evtchn_unbound = flask_evtchn_unbound,
 10.1074 +    .evtchn_interdomain = flask_evtchn_interdomain,
 10.1075 +    .evtchn_close_post = flask_evtchn_close_post,
 10.1076 +    .evtchn_send = flask_evtchn_send,
 10.1077 +    .evtchn_status = flask_evtchn_status,
 10.1078 +    .evtchn_reset = flask_evtchn_reset,
 10.1079 +
 10.1080 +    .grant_mapref = flask_grant_mapref,
 10.1081 +    .grant_unmapref = flask_grant_unmapref,
 10.1082 +    .grant_setup = flask_grant_setup,
 10.1083 +    .grant_transfer = flask_grant_transfer,
 10.1084 +    .grant_copy = flask_grant_copy,
 10.1085 +    .grant_query_size = flask_grant_query_size,
 10.1086 +
 10.1087 +    .alloc_security_domain = flask_domain_alloc_security,
 10.1088 +    .free_security_domain = flask_domain_free_security,
 10.1089 +    .alloc_security_evtchn = flask_alloc_security_evtchn,
 10.1090 +    .free_security_evtchn = flask_free_security_evtchn,
 10.1091 +
 10.1092 +    .translate_gpfn_list = flask_translate_gpfn_list,
 10.1093 +    .memory_adjust_reservation = flask_memory_adjust_reservation,
 10.1094 +    .memory_stat_reservation = flask_memory_stat_reservation,
 10.1095 +    .memory_pin_page = flask_memory_pin_page,
 10.1096 +    .update_va_mapping = flask_update_va_mapping,
 10.1097 +
 10.1098 +    .console_io = flask_console_io,
 10.1099 +
 10.1100 +    .profile = flask_profile,
 10.1101 +
 10.1102 +    .kexec = flask_kexec,
 10.1103 +    .schedop_shutdown = flask_schedop_shutdown,
 10.1104 +
 10.1105 +    .__do_xsm_op = do_flask_op,
 10.1106 +    .complete_init = flask_complete_init,    
 10.1107 +
 10.1108 +#ifdef CONFIG_X86
 10.1109 +    .shadow_control = flask_shadow_control,
 10.1110 +    .ioport_permission = flask_ioport_permission,
 10.1111 +    .getpageframeinfo = flask_getpageframeinfo,
 10.1112 +    .getmemlist = flask_getmemlist,
 10.1113 +    .hypercall_init = flask_hypercall_init,
 10.1114 +    .hvmcontext = flask_hvmcontext,
 10.1115 +    .address_size = flask_address_size,
 10.1116 +    .hvm_param = flask_hvm_param,
 10.1117 +    .hvm_set_pci_intx_level = flask_hvm_set_pci_intx_level,
 10.1118 +    .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level,
 10.1119 +    .hvm_set_pci_link_route = flask_hvm_set_pci_link_route,
 10.1120 +    .apic = flask_apic,
 10.1121 +    .assign_vector = flask_assign_vector,
 10.1122 +    .xen_settime = flask_xen_settime,
 10.1123 +    .memtype = flask_memtype,
 10.1124 +    .microcode = flask_microcode,
 10.1125 +    .physinfo = flask_physinfo,
 10.1126 +    .platform_quirk = flask_platform_quirk,
 10.1127 +    .machine_memory_map = flask_machine_memory_map,
 10.1128 +    .domain_memory_map = flask_domain_memory_map,
 10.1129 +    .mmu_normal_update = flask_mmu_normal_update,
 10.1130 +    .mmu_machphys_update = flask_mmu_machphys_update,
 10.1131 +    .add_to_physmap = flask_add_to_physmap,
 10.1132 +#endif
 10.1133 +};
 10.1134 +
 10.1135 +static __init int flask_init(void)
 10.1136 +{
 10.1137 +    int ret = 0;
 10.1138 +
 10.1139 +    if ( !flask_enabled ) {
 10.1140 +        printk("Flask:  Disabled at boot.\n");
 10.1141 +        return 0;
 10.1142 +    }
 10.1143 +
 10.1144 +    printk("Flask:  Initializing.\n");
 10.1145 +
 10.1146 +    avc_init();
 10.1147 +
 10.1148 +    original_ops = xsm_ops;
 10.1149 +    if ( register_xsm(&flask_ops) )
 10.1150 +        panic("Flask: Unable to register with XSM.\n");
 10.1151 +
 10.1152 +    ret = security_load_policy(policy_buffer, policy_size);
 10.1153 +
 10.1154 +    if ( flask_enforcing )
 10.1155 +        printk("Flask:  Starting in enforcing mode.\n");
 10.1156 +    else
 10.1157 +        printk("Flask:  Starting in permissive mode.\n");
 10.1158 +
 10.1159 +    return ret;
 10.1160 +}
 10.1161 +
 10.1162 +xsm_initcall(flask_init);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen/xsm/flask/include/av_inherit.h	Fri Aug 31 11:31:18 2007 +0100
    11.3 @@ -0,0 +1,1 @@
    11.4 +/* This file is automatically generated.  Do not edit. */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xen/xsm/flask/include/av_perm_to_string.h	Fri Aug 31 11:31:18 2007 +0100
    12.3 @@ -0,0 +1,99 @@
    12.4 +/* This file is automatically generated.  Do not edit. */
    12.5 +   S_(SECCLASS_XEN, XEN__SCHEDULER, "scheduler")
    12.6 +   S_(SECCLASS_XEN, XEN__SETTIME, "settime")
    12.7 +   S_(SECCLASS_XEN, XEN__TBUFCONTROL, "tbufcontrol")
    12.8 +   S_(SECCLASS_XEN, XEN__READCONSOLE, "readconsole")
    12.9 +   S_(SECCLASS_XEN, XEN__CLEARCONSOLE, "clearconsole")
   12.10 +   S_(SECCLASS_XEN, XEN__PERFCONTROL, "perfcontrol")
   12.11 +   S_(SECCLASS_XEN, XEN__MTRR_ADD, "mtrr_add")
   12.12 +   S_(SECCLASS_XEN, XEN__MTRR_DEL, "mtrr_del")
   12.13 +   S_(SECCLASS_XEN, XEN__MTRR_READ, "mtrr_read")
   12.14 +   S_(SECCLASS_XEN, XEN__MICROCODE, "microcode")
   12.15 +   S_(SECCLASS_XEN, XEN__PHYSINFO, "physinfo")
   12.16 +   S_(SECCLASS_XEN, XEN__QUIRK, "quirk")
   12.17 +   S_(SECCLASS_XEN, XEN__WRITECONSOLE, "writeconsole")
   12.18 +   S_(SECCLASS_XEN, XEN__READAPIC, "readapic")
   12.19 +   S_(SECCLASS_XEN, XEN__WRITEAPIC, "writeapic")
   12.20 +   S_(SECCLASS_XEN, XEN__PRIVPROFILE, "privprofile")
   12.21 +   S_(SECCLASS_XEN, XEN__NONPRIVPROFILE, "nonprivprofile")
   12.22 +   S_(SECCLASS_XEN, XEN__KEXEC, "kexec")
   12.23 +   S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT, "setvcpucontext")
   12.24 +   S_(SECCLASS_DOMAIN, DOMAIN__PAUSE, "pause")
   12.25 +   S_(SECCLASS_DOMAIN, DOMAIN__UNPAUSE, "unpause")
   12.26 +   S_(SECCLASS_DOMAIN, DOMAIN__RESUME, "resume")
   12.27 +   S_(SECCLASS_DOMAIN, DOMAIN__CREATE, "create")
   12.28 +   S_(SECCLASS_DOMAIN, DOMAIN__MAX_VCPUS, "max_vcpus")
   12.29 +   S_(SECCLASS_DOMAIN, DOMAIN__DESTROY, "destroy")
   12.30 +   S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUAFFINITY, "setvcpuaffinity")
   12.31 +   S_(SECCLASS_DOMAIN, DOMAIN__GETVCPUAFFINITY, "getvcpuaffinity")
   12.32 +   S_(SECCLASS_DOMAIN, DOMAIN__SCHEDULER, "scheduler")
   12.33 +   S_(SECCLASS_DOMAIN, DOMAIN__GETDOMAININFO, "getdomaininfo")
   12.34 +   S_(SECCLASS_DOMAIN, DOMAIN__GETVCPUINFO, "getvcpuinfo")
   12.35 +   S_(SECCLASS_DOMAIN, DOMAIN__GETVCPUCONTEXT, "getvcpucontext")
   12.36 +   S_(SECCLASS_DOMAIN, DOMAIN__SETDOMAINMAXMEM, "setdomainmaxmem")
   12.37 +   S_(SECCLASS_DOMAIN, DOMAIN__SETDOMAINHANDLE, "setdomainhandle")
   12.38 +   S_(SECCLASS_DOMAIN, DOMAIN__SETDEBUGGING, "setdebugging")
   12.39 +   S_(SECCLASS_DOMAIN, DOMAIN__HYPERCALL, "hypercall")
   12.40 +   S_(SECCLASS_DOMAIN, DOMAIN__TRANSITION, "transition")
   12.41 +   S_(SECCLASS_DOMAIN, DOMAIN__SETTIME, "settime")
   12.42 +   S_(SECCLASS_DOMAIN, DOMAIN__SHUTDOWN, "shutdown")
   12.43 +   S_(SECCLASS_DOMAIN, DOMAIN__SETADDRSIZE, "setaddrsize")
   12.44 +   S_(SECCLASS_DOMAIN, DOMAIN__GETADDRSIZE, "getaddrsize")
   12.45 +   S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc")
   12.46 +   S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc")
   12.47 +   S_(SECCLASS_HVM, HVM__SETPARAM, "setparam")
   12.48 +   S_(SECCLASS_HVM, HVM__GETPARAM, "getparam")
   12.49 +   S_(SECCLASS_HVM, HVM__PCILEVEL, "pcilevel")
   12.50 +   S_(SECCLASS_HVM, HVM__IRQLEVEL, "irqlevel")
   12.51 +   S_(SECCLASS_HVM, HVM__PCIROUTE, "pciroute")
   12.52 +   S_(SECCLASS_EVENT, EVENT__BIND, "bind")
   12.53 +   S_(SECCLASS_EVENT, EVENT__CLOSE, "close")
   12.54 +   S_(SECCLASS_EVENT, EVENT__SEND, "send")
   12.55 +   S_(SECCLASS_EVENT, EVENT__STATUS, "status")
   12.56 +   S_(SECCLASS_EVENT, EVENT__UNMASK, "unmask")
   12.57 +   S_(SECCLASS_EVENT, EVENT__NOTIFY, "notify")
   12.58 +   S_(SECCLASS_EVENT, EVENT__CREATE, "create")
   12.59 +   S_(SECCLASS_EVENT, EVENT__ALLOC, "alloc")
   12.60 +   S_(SECCLASS_EVENT, EVENT__VECTOR, "vector")
   12.61 +   S_(SECCLASS_EVENT, EVENT__RESET, "reset")
   12.62 +   S_(SECCLASS_GRANT, GRANT__MAP_READ, "map_read")
   12.63 +   S_(SECCLASS_GRANT, GRANT__MAP_WRITE, "map_write")
   12.64 +   S_(SECCLASS_GRANT, GRANT__UNMAP, "unmap")
   12.65 +   S_(SECCLASS_GRANT, GRANT__TRANSFER, "transfer")
   12.66 +   S_(SECCLASS_GRANT, GRANT__SETUP, "setup")
   12.67 +   S_(SECCLASS_GRANT, GRANT__COPY, "copy")
   12.68 +   S_(SECCLASS_GRANT, GRANT__QUERY, "query")
   12.69 +   S_(SECCLASS_MMU, MMU__MAP_READ, "map_read")
   12.70 +   S_(SECCLASS_MMU, MMU__MAP_WRITE, "map_write")
   12.71 +   S_(SECCLASS_MMU, MMU__PAGEINFO, "pageinfo")
   12.72 +   S_(SECCLASS_MMU, MMU__PAGELIST, "pagelist")
   12.73 +   S_(SECCLASS_MMU, MMU__ADJUST, "adjust")
   12.74 +   S_(SECCLASS_MMU, MMU__STAT, "stat")
   12.75 +   S_(SECCLASS_MMU, MMU__TRANSLATEGP, "translategp")
   12.76 +   S_(SECCLASS_MMU, MMU__UPDATEMP, "updatemp")
   12.77 +   S_(SECCLASS_MMU, MMU__PHYSMAP, "physmap")
   12.78 +   S_(SECCLASS_MMU, MMU__PINPAGE, "pinpage")
   12.79 +   S_(SECCLASS_MMU, MMU__MFNLIST, "mfnlist")
   12.80 +   S_(SECCLASS_MMU, MMU__MEMORYMAP, "memorymap")
   12.81 +   S_(SECCLASS_SHADOW, SHADOW__DISABLE, "disable")
   12.82 +   S_(SECCLASS_SHADOW, SHADOW__ENABLE, "enable")
   12.83 +   S_(SECCLASS_SHADOW, SHADOW__LOGDIRTY, "logdirty")
   12.84 +   S_(SECCLASS_RESOURCE, RESOURCE__ADD, "add")
   12.85 +   S_(SECCLASS_RESOURCE, RESOURCE__REMOVE, "remove")
   12.86 +   S_(SECCLASS_RESOURCE, RESOURCE__USE, "use")
   12.87 +   S_(SECCLASS_RESOURCE, RESOURCE__ADD_IRQ, "add_irq")
   12.88 +   S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_IRQ, "remove_irq")
   12.89 +   S_(SECCLASS_RESOURCE, RESOURCE__ADD_IOPORT, "add_ioport")
   12.90 +   S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_IOPORT, "remove_ioport")
   12.91 +   S_(SECCLASS_RESOURCE, RESOURCE__ADD_IOMEM, "add_iomem")
   12.92 +   S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_IOMEM, "remove_iomem")
   12.93 +   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av")
   12.94 +   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create")
   12.95 +   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member")
   12.96 +   S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context")
   12.97 +   S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy")
   12.98 +   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel")
   12.99 +   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user")
  12.100 +   S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce")
  12.101 +   S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
  12.102 +   S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen/xsm/flask/include/av_permissions.h	Fri Aug 31 11:31:18 2007 +0100
    13.3 @@ -0,0 +1,108 @@
    13.4 +/* This file is automatically generated.  Do not edit. */
    13.5 +#define XEN__SCHEDULER                            0x00000001UL
    13.6 +#define XEN__SETTIME                              0x00000002UL
    13.7 +#define XEN__TBUFCONTROL                          0x00000004UL
    13.8 +#define XEN__READCONSOLE                          0x00000008UL
    13.9 +#define XEN__CLEARCONSOLE                         0x00000010UL
   13.10 +#define XEN__PERFCONTROL                          0x00000020UL
   13.11 +#define XEN__MTRR_ADD                             0x00000040UL
   13.12 +#define XEN__MTRR_DEL                             0x00000080UL
   13.13 +#define XEN__MTRR_READ                            0x00000100UL
   13.14 +#define XEN__MICROCODE                            0x00000200UL
   13.15 +#define XEN__PHYSINFO                             0x00000400UL
   13.16 +#define XEN__QUIRK                                0x00000800UL
   13.17 +#define XEN__WRITECONSOLE                         0x00001000UL
   13.18 +#define XEN__READAPIC                             0x00002000UL
   13.19 +#define XEN__WRITEAPIC                            0x00004000UL
   13.20 +#define XEN__PRIVPROFILE                          0x00008000UL
   13.21 +#define XEN__NONPRIVPROFILE                       0x00010000UL
   13.22 +#define XEN__KEXEC                                0x00020000UL
   13.23 +
   13.24 +#define DOMAIN__SETVCPUCONTEXT                    0x00000001UL
   13.25 +#define DOMAIN__PAUSE                             0x00000002UL
   13.26 +#define DOMAIN__UNPAUSE                           0x00000004UL
   13.27 +#define DOMAIN__RESUME                            0x00000008UL
   13.28 +#define DOMAIN__CREATE                            0x00000010UL
   13.29 +#define DOMAIN__MAX_VCPUS                         0x00000020UL
   13.30 +#define DOMAIN__DESTROY                           0x00000040UL
   13.31 +#define DOMAIN__SETVCPUAFFINITY                   0x00000080UL
   13.32 +#define DOMAIN__GETVCPUAFFINITY                   0x00000100UL
   13.33 +#define DOMAIN__SCHEDULER                         0x00000200UL
   13.34 +#define DOMAIN__GETDOMAININFO                     0x00000400UL
   13.35 +#define DOMAIN__GETVCPUINFO                       0x00000800UL
   13.36 +#define DOMAIN__GETVCPUCONTEXT                    0x00001000UL
   13.37 +#define DOMAIN__SETDOMAINMAXMEM                   0x00002000UL
   13.38 +#define DOMAIN__SETDOMAINHANDLE                   0x00004000UL
   13.39 +#define DOMAIN__SETDEBUGGING                      0x00008000UL
   13.40 +#define DOMAIN__HYPERCALL                         0x00010000UL
   13.41 +#define DOMAIN__TRANSITION                        0x00020000UL
   13.42 +#define DOMAIN__SETTIME                           0x00040000UL
   13.43 +#define DOMAIN__SHUTDOWN                          0x00080000UL
   13.44 +#define DOMAIN__SETADDRSIZE                       0x00100000UL
   13.45 +#define DOMAIN__GETADDRSIZE                       0x00200000UL
   13.46 +
   13.47 +#define HVM__SETHVMC                              0x00000001UL
   13.48 +#define HVM__GETHVMC                              0x00000002UL
   13.49 +#define HVM__SETPARAM                             0x00000004UL
   13.50 +#define HVM__GETPARAM                             0x00000008UL
   13.51 +#define HVM__PCILEVEL                             0x00000010UL
   13.52 +#define HVM__IRQLEVEL                             0x00000020UL
   13.53 +#define HVM__PCIROUTE                             0x00000040UL
   13.54 +
   13.55 +#define EVENT__BIND                               0x00000001UL
   13.56 +#define EVENT__CLOSE                              0x00000002UL
   13.57 +#define EVENT__SEND                               0x00000004UL
   13.58 +#define EVENT__STATUS                             0x00000008UL
   13.59 +#define EVENT__UNMASK                             0x00000010UL
   13.60 +#define EVENT__NOTIFY                             0x00000020UL
   13.61 +#define EVENT__CREATE                             0x00000040UL
   13.62 +#define EVENT__ALLOC                              0x00000080UL
   13.63 +#define EVENT__VECTOR                             0x00000100UL
   13.64 +#define EVENT__RESET                              0x00000200UL
   13.65 +
   13.66 +#define GRANT__MAP_READ                           0x00000001UL
   13.67 +#define GRANT__MAP_WRITE                          0x00000002UL
   13.68 +#define GRANT__UNMAP                              0x00000004UL
   13.69 +#define GRANT__TRANSFER                           0x00000008UL
   13.70 +#define GRANT__SETUP                              0x00000010UL
   13.71 +#define GRANT__COPY                               0x00000020UL
   13.72 +#define GRANT__QUERY                              0x00000040UL
   13.73 +
   13.74 +#define MMU__MAP_READ                             0x00000001UL
   13.75 +#define MMU__MAP_WRITE                            0x00000002UL
   13.76 +#define MMU__PAGEINFO                             0x00000004UL
   13.77 +#define MMU__PAGELIST                             0x00000008UL
   13.78 +#define MMU__ADJUST                               0x00000010UL
   13.79 +#define MMU__STAT                                 0x00000020UL
   13.80 +#define MMU__TRANSLATEGP                          0x00000040UL
   13.81 +#define MMU__UPDATEMP                             0x00000080UL
   13.82 +#define MMU__PHYSMAP                              0x00000100UL
   13.83 +#define MMU__PINPAGE                              0x00000200UL
   13.84 +#define MMU__MFNLIST                              0x00000400UL
   13.85 +#define MMU__MEMORYMAP                            0x00000800UL
   13.86 +
   13.87 +#define SHADOW__DISABLE                           0x00000001UL
   13.88 +#define SHADOW__ENABLE                            0x00000002UL
   13.89 +#define SHADOW__LOGDIRTY                          0x00000004UL
   13.90 +
   13.91 +#define RESOURCE__ADD                             0x00000001UL
   13.92 +#define RESOURCE__REMOVE                          0x00000002UL
   13.93 +#define RESOURCE__USE                             0x00000004UL
   13.94 +#define RESOURCE__ADD_IRQ                         0x00000008UL
   13.95 +#define RESOURCE__REMOVE_IRQ                      0x00000010UL
   13.96 +#define RESOURCE__ADD_IOPORT                      0x00000020UL
   13.97 +#define RESOURCE__REMOVE_IOPORT                   0x00000040UL
   13.98 +#define RESOURCE__ADD_IOMEM                       0x00000080UL
   13.99 +#define RESOURCE__REMOVE_IOMEM                    0x00000100UL
  13.100 +
  13.101 +#define SECURITY__COMPUTE_AV                      0x00000001UL
  13.102 +#define SECURITY__COMPUTE_CREATE                  0x00000002UL
  13.103 +#define SECURITY__COMPUTE_MEMBER                  0x00000004UL
  13.104 +#define SECURITY__CHECK_CONTEXT                   0x00000008UL
  13.105 +#define SECURITY__LOAD_POLICY                     0x00000010UL
  13.106 +#define SECURITY__COMPUTE_RELABEL                 0x00000020UL
  13.107 +#define SECURITY__COMPUTE_USER                    0x00000040UL
  13.108 +#define SECURITY__SETENFORCE                      0x00000080UL
  13.109 +#define SECURITY__SETBOOL                         0x00000100UL
  13.110 +#define SECURITY__SETSECPARAM                     0x00000200UL
  13.111 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen/xsm/flask/include/avc.h	Fri Aug 31 11:31:18 2007 +0100
    14.3 @@ -0,0 +1,106 @@
    14.4 +/*
    14.5 + * Access vector cache interface for object managers.
    14.6 + *
    14.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    14.8 + */
    14.9 + 
   14.10 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   14.11 +
   14.12 +#ifndef _FLASK_AVC_H_
   14.13 +#define _FLASK_AVC_H_
   14.14 +
   14.15 +#include <xen/errno.h>
   14.16 +#include <xen/lib.h>
   14.17 +#include <xen/spinlock.h>
   14.18 +#include <asm/percpu.h>
   14.19 +#include "flask.h"
   14.20 +#include "av_permissions.h"
   14.21 +#include "security.h"
   14.22 +
   14.23 +#ifdef FLASK_DEVELOP
   14.24 +extern int flask_enforcing;
   14.25 +#else
   14.26 +#define flask_enforcing 1
   14.27 +#endif
   14.28 +
   14.29 +/*
   14.30 + * An entry in the AVC.
   14.31 + */
   14.32 +struct avc_entry;
   14.33 +
   14.34 +struct task_struct;
   14.35 +struct vfsmount;
   14.36 +struct dentry;
   14.37 +struct inode;
   14.38 +struct sock;
   14.39 +struct sk_buff;
   14.40 +
   14.41 +/* Auxiliary data to use in generating the audit record. */
   14.42 +struct avc_audit_data {
   14.43 +    char    type;
   14.44 +#define AVC_AUDIT_DATA_FS   1
   14.45 +#define AVC_AUDIT_DATA_NET  2
   14.46 +#define AVC_AUDIT_DATA_CAP  3
   14.47 +#define AVC_AUDIT_DATA_IPC  4
   14.48 +    struct domain *d;
   14.49 +};
   14.50 +
   14.51 +#define v4info fam.v4
   14.52 +#define v6info fam.v6
   14.53 +
   14.54 +/* Initialize an AVC audit data structure. */
   14.55 +#define AVC_AUDIT_DATA_INIT(_d,_t) \
   14.56 +        { memset((_d), 0, sizeof(struct avc_audit_data)); \
   14.57 +         (_d)->type = AVC_AUDIT_DATA_##_t; }
   14.58 +
   14.59 +/*
   14.60 + * AVC statistics
   14.61 + */
   14.62 +struct avc_cache_stats
   14.63 +{
   14.64 +    unsigned int lookups;
   14.65 +    unsigned int hits;
   14.66 +    unsigned int misses;
   14.67 +    unsigned int allocations;
   14.68 +    unsigned int reclaims;
   14.69 +    unsigned int frees;
   14.70 +};
   14.71 +
   14.72 +/*
   14.73 + * AVC operations
   14.74 + */
   14.75 +
   14.76 +void avc_init(void);
   14.77 +
   14.78 +void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   14.79 +        struct av_decision *avd, int result, struct avc_audit_data *auditdata);
   14.80 +
   14.81 +int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   14.82 +                                                     struct av_decision *avd);
   14.83 +
   14.84 +int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   14.85 +                                             struct avc_audit_data *auditdata);
   14.86 +
   14.87 +#define AVC_CALLBACK_GRANT        1
   14.88 +#define AVC_CALLBACK_TRY_REVOKE        2
   14.89 +#define AVC_CALLBACK_REVOKE        4
   14.90 +#define AVC_CALLBACK_RESET        8
   14.91 +#define AVC_CALLBACK_AUDITALLOW_ENABLE    16
   14.92 +#define AVC_CALLBACK_AUDITALLOW_DISABLE    32
   14.93 +#define AVC_CALLBACK_AUDITDENY_ENABLE    64
   14.94 +#define AVC_CALLBACK_AUDITDENY_DISABLE    128
   14.95 +
   14.96 +int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
   14.97 +                        u16 tclass, u32 perms, u32 *out_retained), u32 events, 
   14.98 +                                    u32 ssid, u32 tsid, u16 tclass, u32 perms);
   14.99 +
  14.100 +/* Exported to selinuxfs */
  14.101 +int avc_get_hash_stats(char *page);
  14.102 +extern unsigned int avc_cache_threshold;
  14.103 +
  14.104 +#ifdef FLASK_AVC_STATS
  14.105 +DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
  14.106 +#endif
  14.107 +
  14.108 +#endif /* _FLASK_AVC_H_ */
  14.109 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/xsm/flask/include/avc_ss.h	Fri Aug 31 11:31:18 2007 +0100
    15.3 @@ -0,0 +1,14 @@
    15.4 +/*
    15.5 + * Access vector cache interface for the security server.
    15.6 + *
    15.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    15.8 + */
    15.9 +#ifndef _FLASK_AVC_SS_H_
   15.10 +#define _FLASK_AVC_SS_H_
   15.11 +
   15.12 +#include "flask.h"
   15.13 +
   15.14 +int avc_ss_reset(u32 seqno);
   15.15 +
   15.16 +#endif /* _FLASK_AVC_SS_H_ */
   15.17 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xen/xsm/flask/include/class_to_string.h	Fri Aug 31 11:31:18 2007 +0100
    16.3 @@ -0,0 +1,14 @@
    16.4 +/* This file is automatically generated.  Do not edit. */
    16.5 +/*
    16.6 + * Security object class definitions
    16.7 + */
    16.8 +    S_("null")
    16.9 +    S_("xen")
   16.10 +    S_("domain")
   16.11 +    S_("hvm")
   16.12 +    S_("mmu")
   16.13 +    S_("resource")
   16.14 +    S_("shadow")
   16.15 +    S_("event")
   16.16 +    S_("grant")
   16.17 +    S_("security")
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xen/xsm/flask/include/common_perm_to_string.h	Fri Aug 31 11:31:18 2007 +0100
    17.3 @@ -0,0 +1,1 @@
    17.4 +/* This file is automatically generated.  Do not edit. */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xen/xsm/flask/include/conditional.h	Fri Aug 31 11:31:18 2007 +0100
    18.3 @@ -0,0 +1,22 @@
    18.4 +/*
    18.5 + * Interface to booleans in the security server. This is exported
    18.6 + * for the selinuxfs.
    18.7 + *
    18.8 + * Author: Karl MacMillan <kmacmillan@tresys.com>
    18.9 + *
   18.10 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
   18.11 + *    This program is free software; you can redistribute it and/or modify
   18.12 + *      it under the terms of the GNU General Public License as published by
   18.13 + *    the Free Software Foundation, version 2.
   18.14 + */
   18.15 +
   18.16 +#ifndef _FLASK_CONDITIONAL_H_
   18.17 +#define _FLASK_CONDITIONAL_H_
   18.18 +
   18.19 +int security_get_bools(int *len, char ***names, int **values);
   18.20 +
   18.21 +int security_set_bools(int len, int *values);
   18.22 +
   18.23 +int security_get_bool_value(int bool);
   18.24 +
   18.25 +#endif
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xen/xsm/flask/include/flask.h	Fri Aug 31 11:31:18 2007 +0100
    19.3 @@ -0,0 +1,36 @@
    19.4 +/* This file is automatically generated.  Do not edit. */
    19.5 +#ifndef _FLASK_FLASK_H_
    19.6 +#define _FLASK_FLASK_H_
    19.7 +
    19.8 +/*
    19.9 + * Security object class definitions
   19.10 + */
   19.11 +#define SECCLASS_XEN                                     1
   19.12 +#define SECCLASS_DOMAIN                                  2
   19.13 +#define SECCLASS_HVM                                     3
   19.14 +#define SECCLASS_MMU                                     4
   19.15 +#define SECCLASS_RESOURCE                                5
   19.16 +#define SECCLASS_SHADOW                                  6
   19.17 +#define SECCLASS_EVENT                                   7
   19.18 +#define SECCLASS_GRANT                                   8
   19.19 +#define SECCLASS_SECURITY                                9
   19.20 +
   19.21 +/*
   19.22 + * Security identifier indices for initial entities
   19.23 + */
   19.24 +#define SECINITSID_XEN                                  1
   19.25 +#define SECINITSID_DOM0                                 2
   19.26 +#define SECINITSID_DOMU                                 3
   19.27 +#define SECINITSID_DOMIO                                4
   19.28 +#define SECINITSID_DOMXEN                               5
   19.29 +#define SECINITSID_UNLABELED                            6
   19.30 +#define SECINITSID_SECURITY                             7
   19.31 +#define SECINITSID_IOPORT                               8
   19.32 +#define SECINITSID_IOMEM                                9
   19.33 +#define SECINITSID_VCPU                                 10
   19.34 +#define SECINITSID_VIRQ                                 11
   19.35 +#define SECINITSID_PIRQ                                 12
   19.36 +
   19.37 +#define SECINITSID_NUM                                  12
   19.38 +
   19.39 +#endif
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xen/xsm/flask/include/initial_sid_to_string.h	Fri Aug 31 11:31:18 2007 +0100
    20.3 @@ -0,0 +1,18 @@
    20.4 +/* This file is automatically generated.  Do not edit. */
    20.5 +static char *initial_sid_to_string[] =
    20.6 +{
    20.7 +    "null",
    20.8 +    "xen",
    20.9 +    "dom0",
   20.10 +    "domU",
   20.11 +    "domio",
   20.12 +    "domxen",
   20.13 +    "unlabeled",
   20.14 +    "security",
   20.15 +    "ioport",
   20.16 +    "iomem",
   20.17 +    "vcpu",
   20.18 +    "virq",
   20.19 +    "pirq",
   20.20 +};
   20.21 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/xen/xsm/flask/include/objsec.h	Fri Aug 31 11:31:18 2007 +0100
    21.3 @@ -0,0 +1,33 @@
    21.4 +/*
    21.5 + *  NSA Security-Enhanced Linux (SELinux) security module
    21.6 + *
    21.7 + *  This file contains the Flask security data structures for xen objects.
    21.8 + *
    21.9 + *  Author(s):  George Coker, <gscoker@alpha.ncsc.mil>
   21.10 + *
   21.11 + *    This program is free software; you can redistribute it and/or modify
   21.12 + *    it under the terms of the GNU General Public License version 2,
   21.13 + *      as published by the Free Software Foundation.
   21.14 + */
   21.15 +
   21.16 +#ifndef _FLASK_OBJSEC_H_
   21.17 +#define _FLASK_OBJSEC_H_
   21.18 +
   21.19 +#include <xen/sched.h>
   21.20 +#include "flask.h"
   21.21 +#include "avc.h"
   21.22 +
   21.23 +struct domain_security_struct {
   21.24 +    struct domain *d;      /* back pointer to domain object */
   21.25 +    u32 sid;               /* current SID */
   21.26 +    u32 create_sid;
   21.27 +};
   21.28 +
   21.29 +struct evtchn_security_struct {
   21.30 +    struct evtchn *chn;      /* back pointer to evtchn object */
   21.31 +    u32 sid;                 /* current SID */
   21.32 +};
   21.33 +
   21.34 +extern unsigned int selinux_checkreqprot;
   21.35 +
   21.36 +#endif /* _FLASK_OBJSEC_H_ */
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xen/xsm/flask/include/security.h	Fri Aug 31 11:31:18 2007 +0100
    22.3 @@ -0,0 +1,83 @@
    22.4 +/*
    22.5 + * Security server interface.
    22.6 + *
    22.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    22.8 + *
    22.9 + */
   22.10 +
   22.11 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   22.12 +
   22.13 +#ifndef _FLASK_SECURITY_H_
   22.14 +#define _FLASK_SECURITY_H_
   22.15 +
   22.16 +#include "flask.h"
   22.17 +
   22.18 +#define SECSID_NULL            0x00000000 /* unspecified SID */
   22.19 +#define SECSID_WILD            0xffffffff /* wildcard SID */
   22.20 +#define SECCLASS_NULL            0x0000 /* no class */
   22.21 +
   22.22 +#define FLASK_MAGIC 0xf97cff8c
   22.23 +
   22.24 +/* Identify specific policy version changes */
   22.25 +#define POLICYDB_VERSION_BASE        15
   22.26 +#define POLICYDB_VERSION_BOOL        16
   22.27 +#define POLICYDB_VERSION_IPV6        17
   22.28 +#define POLICYDB_VERSION_NLCLASS    18
   22.29 +#define POLICYDB_VERSION_VALIDATETRANS    19
   22.30 +#define POLICYDB_VERSION_MLS        19
   22.31 +#define POLICYDB_VERSION_AVTAB        20
   22.32 +
   22.33 +/* Range of policy versions we understand*/
   22.34 +#define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
   22.35 +#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_AVTAB
   22.36 +
   22.37 +#ifdef FLASK_BOOTPARAM
   22.38 +extern int flask_enabled;
   22.39 +#else
   22.40 +#define flask_enabled 1
   22.41 +#endif
   22.42 +
   22.43 +extern int flask_mls_enabled;
   22.44 +
   22.45 +int security_load_policy(void * data, size_t len);
   22.46 +
   22.47 +struct av_decision {
   22.48 +    u32 allowed;
   22.49 +    u32 decided;
   22.50 +    u32 auditallow;
   22.51 +    u32 auditdeny;
   22.52 +    u32 seqno;
   22.53 +};
   22.54 +
   22.55 +int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
   22.56 +                                                    struct av_decision *avd);
   22.57 +
   22.58 +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
   22.59 +
   22.60 +int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
   22.61 +
   22.62 +int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
   22.63 +
   22.64 +int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
   22.65 +
   22.66 +int security_context_to_sid(char *scontext, u32 scontext_len, u32 *out_sid);
   22.67 +
   22.68 +int security_context_to_sid_default(char *scontext, u32 scontext_len, 
   22.69 +                                                    u32 *out_sid, u32 def_sid);
   22.70 +
   22.71 +int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
   22.72 +
   22.73 +int security_pirq_sid(int pirq, u32 *out_sid);
   22.74 +
   22.75 +int security_virq_sid(int virq, u32 *out_sid);
   22.76 +
   22.77 +int security_vcpu_sid(int vcpu, u32 *out_sid);
   22.78 +
   22.79 +int security_iomem_sid(unsigned long, u32 *out_sid);
   22.80 +
   22.81 +int security_ioport_sid(u32 ioport, u32 *out_sid);
   22.82 +
   22.83 +int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
   22.84 +                                                                    u16 tclass);
   22.85 +
   22.86 +#endif /* _FLASK_SECURITY_H_ */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/xen/xsm/flask/ss/Makefile	Fri Aug 31 11:31:18 2007 +0100
    23.3 @@ -0,0 +1,11 @@
    23.4 +obj-y += ebitmap.o
    23.5 +obj-y += hashtab.o
    23.6 +obj-y += symtab.o
    23.7 +obj-y += sidtab.o
    23.8 +obj-y += avtab.o
    23.9 +obj-y += policydb.o
   23.10 +obj-y += services.o
   23.11 +obj-y += conditional.o
   23.12 +obj-y += mls.o
   23.13 +
   23.14 +CFLAGS += -I../include
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/xen/xsm/flask/ss/avtab.c	Fri Aug 31 11:31:18 2007 +0100
    24.3 @@ -0,0 +1,471 @@
    24.4 +/*
    24.5 + * Implementation of the access vector table type.
    24.6 + *
    24.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    24.8 + */
    24.9 +
   24.10 +/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
   24.11 + *
   24.12 + *     Added conditional policy language extensions
   24.13 + *
   24.14 + * Copyright (C) 2003 Tresys Technology, LLC
   24.15 + *    This program is free software; you can redistribute it and/or modify
   24.16 + *      it under the terms of the GNU General Public License as published by
   24.17 + *    the Free Software Foundation, version 2.
   24.18 + */
   24.19 +
   24.20 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   24.21 +
   24.22 +#include <xen/lib.h>
   24.23 +#include <asm/byteorder.h>
   24.24 +#include <xen/types.h>
   24.25 +#include <xen/xmalloc.h>
   24.26 +#include <xen/errno.h>
   24.27 +
   24.28 +#include "avtab.h"
   24.29 +#include "policydb.h"
   24.30 +
   24.31 +#define AVTAB_HASH(keyp) \
   24.32 +((keyp->target_class + \
   24.33 + (keyp->target_type << 2) + \
   24.34 + (keyp->source_type << 9)) & \
   24.35 + AVTAB_HASH_MASK)
   24.36 +
   24.37 +static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue,
   24.38 +    struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key, 
   24.39 +                                                    struct avtab_datum *datum)
   24.40 +{
   24.41 +    struct avtab_node * newnode;
   24.42 +    newnode = xmalloc(struct avtab_node);
   24.43 +    if ( newnode == NULL )
   24.44 +        return NULL;
   24.45 +    memset(newnode, 0, sizeof(struct avtab_node));
   24.46 +    newnode->key = *key;
   24.47 +    newnode->datum = *datum;
   24.48 +    if ( prev )
   24.49 +    {
   24.50 +        newnode->next = prev->next;
   24.51 +        prev->next = newnode;
   24.52 +    }
   24.53 +    else
   24.54 +    {
   24.55 +        newnode->next = h->htable[hvalue];
   24.56 +        h->htable[hvalue] = newnode;
   24.57 +    }
   24.58 +
   24.59 +    h->nel++;
   24.60 +    return newnode;
   24.61 +}
   24.62 +
   24.63 +static int avtab_insert(struct avtab *h, struct avtab_key *key, 
   24.64 +                                                    struct avtab_datum *datum)
   24.65 +{
   24.66 +    int hvalue;
   24.67 +    struct avtab_node *prev, *cur, *newnode;
   24.68 +    u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
   24.69 +
   24.70 +    if ( !h )
   24.71 +        return -EINVAL;
   24.72 +
   24.73 +    hvalue = AVTAB_HASH(key);
   24.74 +    for ( prev = NULL, cur = h->htable[hvalue]; cur;
   24.75 +                                                    prev = cur, cur = cur->next)
   24.76 +    {
   24.77 +        if ( key->source_type == cur->key.source_type &&
   24.78 +                                key->target_type == cur->key.target_type &&
   24.79 +                                key->target_class == cur->key.target_class &&
   24.80 +                                            (specified & cur->key.specified) )
   24.81 +            return -EEXIST;
   24.82 +        if ( key->source_type < cur->key.source_type )
   24.83 +            break;
   24.84 +        if ( key->source_type == cur->key.source_type &&
   24.85 +                                    key->target_type < cur->key.target_type )
   24.86 +            break;
   24.87 +        if ( key->source_type == cur->key.source_type &&
   24.88 +                                    key->target_type == cur->key.target_type &&
   24.89 +                                    key->target_class < cur->key.target_class )
   24.90 +            break;
   24.91 +    }
   24.92 +
   24.93 +    newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
   24.94 +    if( !newnode )
   24.95 +        return -ENOMEM;
   24.96 +
   24.97 +    return 0;
   24.98 +}
   24.99 +
  24.100 +/* Unlike avtab_insert(), this function allow multiple insertions of the same
  24.101 + * key/specified mask into the table, as needed by the conditional avtab.
  24.102 + * It also returns a pointer to the node inserted.
  24.103 + */
  24.104 +struct avtab_node * avtab_insert_nonunique(struct avtab * h, 
  24.105 +                            struct avtab_key * key, struct avtab_datum * datum)
  24.106 +{
  24.107 +    int hvalue;
  24.108 +    struct avtab_node *prev, *cur, *newnode;
  24.109 +    u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
  24.110 +
  24.111 +    if ( !h )
  24.112 +        return NULL;
  24.113 +    hvalue = AVTAB_HASH(key);
  24.114 +    for ( prev = NULL, cur = h->htable[hvalue]; cur; 
  24.115 +                                                prev = cur, cur = cur->next )
  24.116 +    {
  24.117 +        if ( key->source_type == cur->key.source_type &&
  24.118 +                                key->target_type == cur->key.target_type &&
  24.119 +                                key->target_class == cur->key.target_class &&
  24.120 +                                            (specified & cur->key.specified) )
  24.121 +            break;
  24.122 +        if ( key->source_type < cur->key.source_type )
  24.123 +            break;
  24.124 +        if ( key->source_type == cur->key.source_type &&
  24.125 +                                    key->target_type < cur->key.target_type )
  24.126 +            break;
  24.127 +        if ( key->source_type == cur->key.source_type &&
  24.128 +                                key->target_type == cur->key.target_type &&
  24.129 +                                key->target_class < cur->key.target_class )
  24.130 +            break;
  24.131 +    }
  24.132 +    newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
  24.133 +
  24.134 +    return newnode;
  24.135 +}
  24.136 +
  24.137 +struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
  24.138 +{
  24.139 +    int hvalue;
  24.140 +    struct avtab_node *cur;
  24.141 +    u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
  24.142 +
  24.143 +    if ( !h )
  24.144 +        return NULL;
  24.145 +
  24.146 +    hvalue = AVTAB_HASH(key);
  24.147 +    for ( cur = h->htable[hvalue]; cur; cur = cur->next )
  24.148 +    {
  24.149 +        if ( key->source_type == cur->key.source_type &&
  24.150 +                                key->target_type == cur->key.target_type &&
  24.151 +                                key->target_class == cur->key.target_class &&
  24.152 +                                            (specified & cur->key.specified) )
  24.153 +            return &cur->datum;
  24.154 +
  24.155 +        if ( key->source_type < cur->key.source_type )
  24.156 +            break;
  24.157 +        if ( key->source_type == cur->key.source_type &&
  24.158 +                                    key->target_type < cur->key.target_type )
  24.159 +            break;
  24.160 +        if ( key->source_type == cur->key.source_type &&
  24.161 +                                key->target_type == cur->key.target_type &&
  24.162 +                                key->target_class < cur->key.target_class )
  24.163 +            break;
  24.164 +    }
  24.165 +
  24.166 +    return NULL;
  24.167 +}
  24.168 +
  24.169 +/* This search function returns a node pointer, and can be used in
  24.170 + * conjunction with avtab_search_next_node()
  24.171 + */
  24.172 +struct avtab_node* avtab_search_node(struct avtab *h, struct avtab_key *key)
  24.173 +{
  24.174 +    int hvalue;
  24.175 +    struct avtab_node *cur;
  24.176 +    u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
  24.177 +
  24.178 +    if ( !h )
  24.179 +        return NULL;
  24.180 +
  24.181 +    hvalue = AVTAB_HASH(key);
  24.182 +    for ( cur = h->htable[hvalue]; cur; cur = cur->next )
  24.183 +    {
  24.184 +        if ( key->source_type == cur->key.source_type &&
  24.185 +                                key->target_type == cur->key.target_type &&
  24.186 +                                key->target_class == cur->key.target_class &&
  24.187 +                                            (specified & cur->key.specified) )
  24.188 +            return cur;
  24.189 +
  24.190 +        if ( key->source_type < cur->key.source_type )
  24.191 +            break;
  24.192 +        if ( key->source_type == cur->key.source_type &&
  24.193 +                                    key->target_type < cur->key.target_type )
  24.194 +            break;
  24.195 +        if ( key->source_type == cur->key.source_type &&
  24.196 +                                    key->target_type == cur->key.target_type &&
  24.197 +                                    key->target_class < cur->key.target_class )
  24.198 +            break;
  24.199 +    }
  24.200 +    return NULL;
  24.201 +}
  24.202 +
  24.203 +struct avtab_node* avtab_search_node_next(struct avtab_node *node, 
  24.204 +                                                                int specified)
  24.205 +{
  24.206 +    struct avtab_node *cur;
  24.207 +
  24.208 +    if ( !node )
  24.209 +        return NULL;
  24.210 +
  24.211 +    specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
  24.212 +    for ( cur = node->next; cur; cur = cur->next )
  24.213 +    {
  24.214 +        if ( node->key.source_type == cur->key.source_type &&
  24.215 +                            node->key.target_type == cur->key.target_type &&
  24.216 +                            node->key.target_class == cur->key.target_class &&
  24.217 +                                            (specified & cur->key.specified) )
  24.218 +            return cur;
  24.219 +
  24.220 +        if ( node->key.source_type < cur->key.source_type )
  24.221 +            break;
  24.222 +        if ( node->key.source_type == cur->key.source_type &&
  24.223 +                                node->key.target_type < cur->key.target_type )
  24.224 +            break;
  24.225 +        if ( node->key.source_type == cur->key.source_type &&
  24.226 +                            node->key.target_type == cur->key.target_type &&
  24.227 +                            node->key.target_class < cur->key.target_class )
  24.228 +            break;
  24.229 +    }
  24.230 +    return NULL;
  24.231 +}
  24.232 +
  24.233 +void avtab_destroy(struct avtab *h)
  24.234 +{
  24.235 +    int i;
  24.236 +    struct avtab_node *cur, *temp;
  24.237 +
  24.238 +    if ( !h || !h->htable )
  24.239 +        return;
  24.240 +
  24.241 +    for ( i = 0; i < AVTAB_SIZE; i++ )
  24.242 +    {
  24.243 +        cur = h->htable[i];
  24.244 +        while ( cur != NULL )
  24.245 +        {
  24.246 +            temp = cur;
  24.247 +            cur = cur->next;
  24.248 +            xfree(temp);
  24.249 +        }
  24.250 +        h->htable[i] = NULL;
  24.251 +    }
  24.252 +    xfree(h->htable);
  24.253 +    h->htable = NULL;
  24.254 +}
  24.255 +
  24.256 +
  24.257 +int avtab_init(struct avtab *h)
  24.258 +{
  24.259 +    int i;
  24.260 +
  24.261 +    h->htable = (void *)xmalloc_array(struct avtab_node, AVTAB_SIZE);
  24.262 +    if ( !h->htable )
  24.263 +        return -ENOMEM;
  24.264 +    for ( i = 0; i < AVTAB_SIZE; i++ )
  24.265 +        h->htable[i] = NULL;
  24.266 +    h->nel = 0;
  24.267 +    return 0;
  24.268 +}
  24.269 +
  24.270 +void avtab_hash_eval(struct avtab *h, char *tag)
  24.271 +{
  24.272 +    int i, chain_len, slots_used, max_chain_len;
  24.273 +    struct avtab_node *cur;
  24.274 +
  24.275 +    slots_used = 0;
  24.276 +    max_chain_len = 0;
  24.277 +    for ( i = 0; i < AVTAB_SIZE; i++ )
  24.278 +    {
  24.279 +        cur = h->htable[i];
  24.280 +        if ( cur )
  24.281 +        {
  24.282 +            slots_used++;
  24.283 +            chain_len = 0;
  24.284 +            while ( cur )
  24.285 +            {
  24.286 +                chain_len++;
  24.287 +                cur = cur->next;
  24.288 +            }
  24.289 +
  24.290 +            if ( chain_len > max_chain_len )
  24.291 +                max_chain_len = chain_len;
  24.292 +        }
  24.293 +    }
  24.294 +
  24.295 +    printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
  24.296 +           "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
  24.297 +                                                               max_chain_len);
  24.298 +}
  24.299 +
  24.300 +static uint16_t spec_order[] = {
  24.301 +    AVTAB_ALLOWED,
  24.302 +    AVTAB_AUDITDENY,
  24.303 +    AVTAB_AUDITALLOW,
  24.304 +    AVTAB_TRANSITION,
  24.305 +    AVTAB_CHANGE,
  24.306 +    AVTAB_MEMBER
  24.307 +};
  24.308 +
  24.309 +int avtab_read_item(void *fp, u32 vers, struct avtab *a,
  24.310 +                            int (*insertf)(struct avtab *a, struct avtab_key *k,
  24.311 +                                    struct avtab_datum *d, void *p), void *p)
  24.312 +{
  24.313 +    __le16 buf16[4];
  24.314 +    u16 enabled;
  24.315 +    __le32 buf32[7];
  24.316 +    u32 items, items2, val;
  24.317 +    struct avtab_key key;
  24.318 +    struct avtab_datum datum;
  24.319 +    int i, rc;
  24.320 +
  24.321 +    memset(&key, 0, sizeof(struct avtab_key));
  24.322 +    memset(&datum, 0, sizeof(struct avtab_datum));
  24.323 +
  24.324 +    if ( vers < POLICYDB_VERSION_AVTAB )
  24.325 +    {
  24.326 +        rc = next_entry(buf32, fp, sizeof(u32));
  24.327 +        if ( rc < 0 )
  24.328 +        {
  24.329 +            printk(KERN_ERR "security: avtab: truncated entry\n");
  24.330 +            return -1;
  24.331 +        }
  24.332 +        items2 = le32_to_cpu(buf32[0]);
  24.333 +        if ( items2 > ARRAY_SIZE(buf32) )
  24.334 +        {
  24.335 +            printk(KERN_ERR "security: avtab: entry overflow\n");
  24.336 +            return -1;
  24.337 +
  24.338 +        }
  24.339 +        rc = next_entry(buf32, fp, sizeof(u32)*items2);
  24.340 +        if ( rc < 0 )
  24.341 +        {
  24.342 +            printk(KERN_ERR "security: avtab: truncated entry\n");
  24.343 +            return -1;
  24.344 +        }
  24.345 +        items = 0;
  24.346 +
  24.347 +        val = le32_to_cpu(buf32[items++]);
  24.348 +        key.source_type = (u16)val;
  24.349 +        if ( key.source_type != val )
  24.350 +        {
  24.351 +            printk("security: avtab: truncated source type\n");
  24.352 +            return -1;
  24.353 +        }
  24.354 +        val = le32_to_cpu(buf32[items++]);
  24.355 +        key.target_type = (u16)val;
  24.356 +        if ( key.target_type != val )
  24.357 +        {
  24.358 +            printk("security: avtab: truncated target type\n");
  24.359 +            return -1;
  24.360 +        }
  24.361 +        val = le32_to_cpu(buf32[items++]);
  24.362 +        key.target_class = (u16)val;
  24.363 +        if ( key.target_class != val )
  24.364 +        {
  24.365 +            printk("security: avtab: truncated target class\n");
  24.366 +            return -1;
  24.367 +        }
  24.368 +
  24.369 +        val = le32_to_cpu(buf32[items++]);
  24.370 +        enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
  24.371 +
  24.372 +        if ( !(val & (AVTAB_AV | AVTAB_TYPE)) )
  24.373 +        {
  24.374 +            printk("security: avtab: null entry\n");
  24.375 +            return -1;
  24.376 +        }
  24.377 +        if ( (val & AVTAB_AV) && (val & AVTAB_TYPE) )
  24.378 +        {
  24.379 +            printk("security: avtab: entry has both access vectors and types\n");
  24.380 +            return -1;
  24.381 +        }
  24.382 +
  24.383 +        for ( i = 0; i < sizeof(spec_order)/sizeof(u16); i++ )
  24.384 +        {
  24.385 +            if ( val & spec_order[i] )
  24.386 +            {
  24.387 +                key.specified = spec_order[i] | enabled;
  24.388 +                datum.data = le32_to_cpu(buf32[items++]);
  24.389 +                rc = insertf(a, &key, &datum, p);
  24.390 +                if ( rc )
  24.391 +                    return rc;
  24.392 +            }
  24.393 +        }
  24.394 +
  24.395 +        if ( items != items2 ) {
  24.396 +            printk("security: avtab: entry only had %d items, expected %d\n", 
  24.397 +                                                                items2, items);
  24.398 +            return -1;
  24.399 +        }
  24.400 +        return 0;
  24.401 +    }
  24.402 +
  24.403 +    rc = next_entry(buf16, fp, sizeof(u16)*4);
  24.404 +    if ( rc < 0 )
  24.405 +    {
  24.406 +        printk("security: avtab: truncated entry\n");
  24.407 +        return -1;
  24.408 +    }
  24.409 +
  24.410 +    items = 0;
  24.411 +    key.source_type = le16_to_cpu(buf16[items++]);
  24.412 +    key.target_type = le16_to_cpu(buf16[items++]);
  24.413 +    key.target_class = le16_to_cpu(buf16[items++]);
  24.414 +    key.specified = le16_to_cpu(buf16[items++]);
  24.415 +
  24.416 +    rc = next_entry(buf32, fp, sizeof(u32));
  24.417 +    if ( rc < 0 )
  24.418 +    {
  24.419 +        printk("security: avtab: truncated entry\n");
  24.420 +        return -1;
  24.421 +    }
  24.422 +    datum.data = le32_to_cpu(*buf32);
  24.423 +    return insertf(a, &key, &datum, p);
  24.424 +}
  24.425 +
  24.426 +static int avtab_insertf(struct avtab *a, struct avtab_key *k,
  24.427 +                                                struct avtab_datum *d, void *p)
  24.428 +{
  24.429 +    return avtab_insert(a, k, d);
  24.430 +}
  24.431 +
  24.432 +int avtab_read(struct avtab *a, void *fp, u32 vers)
  24.433 +{
  24.434 +    int rc;
  24.435 +    __le32 buf[1];
  24.436 +    u32 nel, i;
  24.437 +
  24.438 +    rc = next_entry(buf, fp, sizeof(u32));
  24.439 +    if ( rc < 0 )
  24.440 +    {
  24.441 +        printk(KERN_ERR "security: avtab: truncated table\n");
  24.442 +        goto bad;
  24.443 +    }
  24.444 +    nel = le32_to_cpu(buf[0]);
  24.445 +    if ( !nel )
  24.446 +    {
  24.447 +        printk(KERN_ERR "security: avtab: table is empty\n");
  24.448 +        rc = -EINVAL;
  24.449 +        goto bad;
  24.450 +    }
  24.451 +    for ( i = 0; i < nel; i++ )
  24.452 +    {
  24.453 +        rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
  24.454 +        if ( rc )
  24.455 +        {
  24.456 +            if ( rc == -ENOMEM )
  24.457 +                printk(KERN_ERR "security: avtab: out of memory\n");
  24.458 +            else if ( rc == -EEXIST )
  24.459 +                printk(KERN_ERR "security: avtab: duplicate entry\n");
  24.460 +            else
  24.461 +                rc = -EINVAL;
  24.462 +            goto bad;
  24.463 +        }
  24.464 +    }
  24.465 +
  24.466 +    rc = 0;
  24.467 +out:
  24.468 +    return rc;
  24.469 +
  24.470 +bad:
  24.471 +    avtab_destroy(a);
  24.472 +    goto out;
  24.473 +}
  24.474 +
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/xen/xsm/flask/ss/avtab.h	Fri Aug 31 11:31:18 2007 +0100
    25.3 @@ -0,0 +1,85 @@
    25.4 +/*
    25.5 + * An access vector table (avtab) is a hash table
    25.6 + * of access vectors and transition types indexed
    25.7 + * by a type pair and a class.  An access vector
    25.8 + * table is used to represent the type enforcement
    25.9 + * tables.
   25.10 + *
   25.11 + *  Author : Stephen Smalley, <sds@epoch.ncsc.mil>
   25.12 + */
   25.13 +
   25.14 +/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
   25.15 + *
   25.16 + *     Added conditional policy language extensions
   25.17 + *
   25.18 + * Copyright (C) 2003 Tresys Technology, LLC
   25.19 + *    This program is free software; you can redistribute it and/or modify
   25.20 + *      it under the terms of the GNU General Public License as published by
   25.21 + *    the Free Software Foundation, version 2.
   25.22 + */
   25.23 +
   25.24 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   25.25 +
   25.26 +#ifndef _SS_AVTAB_H_
   25.27 +#define _SS_AVTAB_H_
   25.28 +
   25.29 +struct avtab_key {
   25.30 +    u16 source_type;    /* source type */
   25.31 +    u16 target_type;    /* target type */
   25.32 +    u16 target_class;    /* target object class */
   25.33 +#define AVTAB_ALLOWED     1
   25.34 +#define AVTAB_AUDITALLOW  2
   25.35 +#define AVTAB_AUDITDENY   4
   25.36 +#define AVTAB_AV         (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
   25.37 +#define AVTAB_TRANSITION 16
   25.38 +#define AVTAB_MEMBER     32
   25.39 +#define AVTAB_CHANGE     64
   25.40 +#define AVTAB_TYPE       (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
   25.41 +#define AVTAB_ENABLED_OLD    0x80000000 /* reserved for used in cond_avtab */
   25.42 +#define AVTAB_ENABLED    0x8000 /* reserved for used in cond_avtab */
   25.43 +    u16 specified;    /* what field is specified */
   25.44 +};
   25.45 +
   25.46 +struct avtab_datum {
   25.47 +    u32 data; /* access vector or type value */
   25.48 +};
   25.49 +
   25.50 +struct avtab_node {
   25.51 +    struct avtab_key key;
   25.52 +    struct avtab_datum datum;
   25.53 +    struct avtab_node *next;
   25.54 +};
   25.55 +
   25.56 +struct avtab {
   25.57 +    struct avtab_node **htable;
   25.58 +    u32 nel;    /* number of elements */
   25.59 +};
   25.60 +
   25.61 +int avtab_init(struct avtab *);
   25.62 +struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
   25.63 +void avtab_destroy(struct avtab *h);
   25.64 +void avtab_hash_eval(struct avtab *h, char *tag);
   25.65 +
   25.66 +int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
   25.67 +            int (*insert)(struct avtab *a, struct avtab_key *k,
   25.68 +                  struct avtab_datum *d, void *p),
   25.69 +            void *p);
   25.70 +
   25.71 +int avtab_read(struct avtab *a, void *fp, u32 vers);
   25.72 +
   25.73 +struct avtab_node *avtab_insert_nonunique(struct avtab *h, 
   25.74 +                            struct avtab_key *key, struct avtab_datum *datum);
   25.75 +
   25.76 +struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key);
   25.77 +
   25.78 +struct avtab_node *avtab_search_node_next(struct avtab_node *node, 
   25.79 +                                                                int specified);
   25.80 +
   25.81 +#define AVTAB_HASH_BITS 15
   25.82 +#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
   25.83 +#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
   25.84 +
   25.85 +#define AVTAB_SIZE AVTAB_HASH_BUCKETS
   25.86 +
   25.87 +#endif    /* _SS_AVTAB_H_ */
   25.88 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/xen/xsm/flask/ss/conditional.c	Fri Aug 31 11:31:18 2007 +0100
    26.3 @@ -0,0 +1,546 @@
    26.4 +/* Authors: Karl MacMillan <kmacmillan@tresys.com>
    26.5 + *          Frank Mayer <mayerf@tresys.com>
    26.6 + *
    26.7 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
    26.8 + *    This program is free software; you can redistribute it and/or modify
    26.9 + *      it under the terms of the GNU General Public License as published by
   26.10 + *    the Free Software Foundation, version 2.
   26.11 + */
   26.12 +
   26.13 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   26.14 +
   26.15 +#include <asm/byteorder.h>
   26.16 +#include <xen/lib.h>
   26.17 +#include <xen/types.h>
   26.18 +#include <xen/errno.h>
   26.19 +#include <xen/string.h>
   26.20 +#include <xen/spinlock.h>
   26.21 +#include <xen/xmalloc.h>
   26.22 +
   26.23 +#include "security.h"
   26.24 +#include "conditional.h"
   26.25 +
   26.26 +/*
   26.27 + * cond_evaluate_expr evaluates a conditional expr
   26.28 + * in reverse polish notation. It returns true (1), false (0),
   26.29 + * or undefined (-1). Undefined occurs when the expression
   26.30 + * exceeds the stack depth of COND_EXPR_MAXDEPTH.
   26.31 + */
   26.32 +static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
   26.33 +{
   26.34 +    struct cond_expr *cur;
   26.35 +    int s[COND_EXPR_MAXDEPTH];
   26.36 +    int sp = -1;
   26.37 +
   26.38 +    for ( cur = expr; cur != NULL; cur = cur->next )
   26.39 +    {
   26.40 +        switch ( cur->expr_type )
   26.41 +        {
   26.42 +            case COND_BOOL:
   26.43 +                if ( sp == (COND_EXPR_MAXDEPTH - 1) )
   26.44 +                    return -1;
   26.45 +                sp++;
   26.46 +                s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
   26.47 +            break;
   26.48 +            case COND_NOT:
   26.49 +                if ( sp < 0 )
   26.50 +                    return -1;
   26.51 +                s[sp] = !s[sp];
   26.52 +            break;
   26.53 +            case COND_OR:
   26.54 +                if ( sp < 1 )
   26.55 +                    return -1;
   26.56 +                sp--;
   26.57 +                s[sp] |= s[sp + 1];
   26.58 +            break;
   26.59 +            case COND_AND:
   26.60 +                if ( sp < 1 )
   26.61 +                    return -1;
   26.62 +                sp--;
   26.63 +                s[sp] &= s[sp + 1];
   26.64 +            break;
   26.65 +          case COND_XOR:
   26.66 +                if ( sp < 1 )
   26.67 +                    return -1;
   26.68 +               sp--;
   26.69 +                s[sp] ^= s[sp + 1];
   26.70 +               break;
   26.71 +            case COND_EQ:
   26.72 +                if ( sp < 1 )
   26.73 +                    return -1;
   26.74 +                sp--;
   26.75 +                s[sp] = (s[sp] == s[sp + 1]);
   26.76 +            break;
   26.77 +            case COND_NEQ:
   26.78 +                if ( sp < 1 )
   26.79 +                    return -1;
   26.80 +                sp--;
   26.81 +                s[sp] = (s[sp] != s[sp + 1]);
   26.82 +            break;
   26.83 +            default:
   26.84 +                return -1;
   26.85 +        }
   26.86 +    }
   26.87 +    return s[0];
   26.88 +}
   26.89 +
   26.90 +/*
   26.91 + * evaluate_cond_node evaluates the conditional stored in
   26.92 + * a struct cond_node and if the result is different than the
   26.93 + * current state of the node it sets the rules in the true/false
   26.94 + * list appropriately. If the result of the expression is undefined
   26.95 + * all of the rules are disabled for safety.
   26.96 + */
   26.97 +int evaluate_cond_node(struct policydb *p, struct cond_node *node)
   26.98 +{
   26.99 +    int new_state;
  26.100 +    struct cond_av_list* cur;
  26.101 +
  26.102 +    new_state = cond_evaluate_expr(p, node->expr);
  26.103 +    if ( new_state != node->cur_state )
  26.104 +    {
  26.105 +        node->cur_state = new_state;
  26.106 +        if ( new_state == -1 )
  26.107 +            printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
  26.108 +        /* turn the rules on or off */
  26.109 +        for ( cur = node->true_list; cur != NULL; cur = cur->next )
  26.110 +        {
  26.111 +            if ( new_state <= 0 )
  26.112 +                cur->node->key.specified &= ~AVTAB_ENABLED;
  26.113 +            else
  26.114 +                cur->node->key.specified |= AVTAB_ENABLED;
  26.115 +        }
  26.116 +
  26.117 +        for ( cur = node->false_list; cur != NULL; cur = cur->next )
  26.118 +        {
  26.119 +            /* -1 or 1 */
  26.120 +            if ( new_state )
  26.121 +                cur->node->key.specified &= ~AVTAB_ENABLED;
  26.122 +            else
  26.123 +                cur->node->key.specified |= AVTAB_ENABLED;
  26.124 +        }
  26.125 +    }
  26.126 +    return 0;
  26.127 +}
  26.128 +
  26.129 +int cond_policydb_init(struct policydb *p)
  26.130 +{
  26.131 +    p->bool_val_to_struct = NULL;
  26.132 +    p->cond_list = NULL;
  26.133 +    if ( avtab_init(&p->te_cond_avtab) )
  26.134 +        return -1;
  26.135 +
  26.136 +    return 0;
  26.137 +}
  26.138 +
  26.139 +static void cond_av_list_destroy(struct cond_av_list *list)
  26.140 +{
  26.141 +    struct cond_av_list *cur, *next;
  26.142 +    for ( cur = list; cur != NULL; cur = next )
  26.143 +    {
  26.144 +        next = cur->next;
  26.145 +        /* the avtab_ptr_t node is destroy by the avtab */
  26.146 +        xfree(cur);
  26.147 +    }
  26.148 +}
  26.149 +
  26.150 +static void cond_node_destroy(struct cond_node *node)
  26.151 +{
  26.152 +    struct cond_expr *cur_expr, *next_expr;
  26.153 +
  26.154 +    for ( cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr )
  26.155 +    {
  26.156 +        next_expr = cur_expr->next;
  26.157 +        xfree(cur_expr);
  26.158 +    }
  26.159 +    cond_av_list_destroy(node->true_list);
  26.160 +    cond_av_list_destroy(node->false_list);
  26.161 +    xfree(node);
  26.162 +}
  26.163 +
  26.164 +static void cond_list_destroy(struct cond_node *list)
  26.165 +{
  26.166 +    struct cond_node *next, *cur;
  26.167 +
  26.168 +    if ( list == NULL )
  26.169 +        return;
  26.170 +
  26.171 +    for ( cur = list; cur != NULL; cur = next )
  26.172 +    {
  26.173 +        next = cur->next;
  26.174 +        cond_node_destroy(cur);
  26.175 +    }
  26.176 +}
  26.177 +
  26.178 +void cond_policydb_destroy(struct policydb *p)
  26.179 +{
  26.180 +    xfree(p->bool_val_to_struct);
  26.181 +    avtab_destroy(&p->te_cond_avtab);
  26.182 +    cond_list_destroy(p->cond_list);
  26.183 +}
  26.184 +
  26.185 +int cond_init_bool_indexes(struct policydb *p)
  26.186 +{
  26.187 +    xfree(p->bool_val_to_struct);
  26.188 +    p->bool_val_to_struct = (struct cond_bool_datum**)
  26.189 +        xmalloc_array(struct cond_bool_datum*, p->p_bools.nprim);
  26.190 +    if ( !p->bool_val_to_struct )
  26.191 +        return -1;
  26.192 +    return 0;
  26.193 +}
  26.194 +
  26.195 +int cond_destroy_bool(void *key, void *datum, void *p)
  26.196 +{
  26.197 +    xfree(key);
  26.198 +    xfree(datum);
  26.199 +    return 0;
  26.200 +}
  26.201 +
  26.202 +int cond_index_bool(void *key, void *datum, void *datap)
  26.203 +{
  26.204 +    struct policydb *p;
  26.205 +    struct cond_bool_datum *booldatum;
  26.206 +
  26.207 +    booldatum = datum;
  26.208 +    p = datap;
  26.209 +
  26.210 +    if ( !booldatum->value || booldatum->value > p->p_bools.nprim )
  26.211 +        return -EINVAL;
  26.212 +
  26.213 +    p->p_bool_val_to_name[booldatum->value - 1] = key;
  26.214 +    p->bool_val_to_struct[booldatum->value -1] = booldatum;
  26.215 +
  26.216 +    return 0;
  26.217 +}
  26.218 +
  26.219 +static int bool_isvalid(struct cond_bool_datum *b)
  26.220 +{
  26.221 +    if ( !(b->state == 0 || b->state == 1) )
  26.222 +        return 0;
  26.223 +    return 1;
  26.224 +}
  26.225 +
  26.226 +int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
  26.227 +{
  26.228 +    char *key = NULL;
  26.229 +    struct cond_bool_datum *booldatum;
  26.230 +    __le32 buf[3];
  26.231 +    u32 len;
  26.232 +    int rc;
  26.233 +
  26.234 +    booldatum = xmalloc(struct cond_bool_datum);
  26.235 +    if ( !booldatum )
  26.236 +        return -1;
  26.237 +    memset(booldatum, 0, sizeof(struct cond_bool_datum));
  26.238 +
  26.239 +    rc = next_entry(buf, fp, sizeof buf);
  26.240 +    if ( rc < 0 )
  26.241 +        goto err;
  26.242 +
  26.243 +    booldatum->value = le32_to_cpu(buf[0]);
  26.244 +    booldatum->state = le32_to_cpu(buf[1]);
  26.245 +
  26.246 +    if ( !bool_isvalid(booldatum) )
  26.247 +        goto err;
  26.248 +
  26.249 +    len = le32_to_cpu(buf[2]);
  26.250 +
  26.251 +    key = xmalloc_array(char, len + 1);
  26.252 +    if ( !key )
  26.253 +        goto err;
  26.254 +    rc = next_entry(key, fp, len);
  26.255 +    if ( rc < 0 )
  26.256 +        goto err;
  26.257 +    key[len] = 0;
  26.258 +    if ( hashtab_insert(h, key, booldatum) )
  26.259 +        goto err;
  26.260 +
  26.261 +    return 0;
  26.262 +err:
  26.263 +    cond_destroy_bool(key, booldatum, NULL);
  26.264 +    return -1;
  26.265 +}
  26.266 +
  26.267 +struct cond_insertf_data
  26.268 +{
  26.269 +    struct policydb *p;
  26.270 +    struct cond_av_list *other;
  26.271 +    struct cond_av_list *head;
  26.272 +    struct cond_av_list *tail;
  26.273 +};
  26.274 +
  26.275 +static int cond_insertf(struct avtab *a, struct avtab_key *k, 
  26.276 +                                            struct avtab_datum *d, void *ptr)
  26.277 +{
  26.278 +    struct cond_insertf_data *data = ptr;
  26.279 +    struct policydb *p = data->p;
  26.280 +    struct cond_av_list *other = data->other, *list, *cur;
  26.281 +    struct avtab_node *node_ptr;
  26.282 +    u8 found;
  26.283 +
  26.284 +    /*
  26.285 +     * For type rules we have to make certain there aren't any
  26.286 +     * conflicting rules by searching the te_avtab and the
  26.287 +     * cond_te_avtab.
  26.288 +     */
  26.289 +    if ( k->specified & AVTAB_TYPE )
  26.290 +    {
  26.291 +        if ( avtab_search(&p->te_avtab, k) )
  26.292 +        {
  26.293 +            printk("security: type rule already exists outside of a "
  26.294 +                                                                "conditional.");
  26.295 +            goto err;
  26.296 +        }
  26.297 +        /*
  26.298 +         * If we are reading the false list other will be a pointer to
  26.299 +         * the true list. We can have duplicate entries if there is only
  26.300 +         * 1 other entry and it is in our true list.
  26.301 +         *
  26.302 +         * If we are reading the true list (other == NULL) there shouldn't
  26.303 +         * be any other entries.
  26.304 +         */
  26.305 +        if ( other )
  26.306 +        {
  26.307 +            node_ptr = avtab_search_node(&p->te_cond_avtab, k);
  26.308 +            if ( node_ptr )
  26.309 +            {
  26.310 +                if ( avtab_search_node_next(node_ptr, k->specified) )
  26.311 +                {
  26.312 +                    printk("security: too many conflicting type rules.");
  26.313 +                    goto err;
  26.314 +                }
  26.315 +                found = 0;
  26.316 +                for ( cur = other; cur != NULL; cur = cur->next )
  26.317 +                {
  26.318 +                    if ( cur->node == node_ptr )
  26.319 +                    {
  26.320 +                        found = 1;
  26.321 +                        break;
  26.322 +                    }
  26.323 +                }
  26.324 +                if ( !found )
  26.325 +                {
  26.326 +                    printk("security: conflicting type rules.\n");
  26.327 +                    goto err;
  26.328 +                }
  26.329 +            }
  26.330 +        }
  26.331 +        else
  26.332 +        {
  26.333 +            if ( avtab_search(&p->te_cond_avtab, k) )
  26.334 +            {
  26.335 +                printk("security: conflicting type rules when adding type rule "
  26.336 +                                                                "for true.\n");
  26.337 +                goto err;
  26.338 +            }
  26.339 +        }
  26.340 +    }
  26.341 +
  26.342 +    node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
  26.343 +    if ( !node_ptr )
  26.344 +    {
  26.345 +        printk("security: could not insert rule.");
  26.346 +        goto err;
  26.347 +    }
  26.348 +
  26.349 +    list = xmalloc(struct cond_av_list);
  26.350 +    if ( !list )
  26.351 +        goto err;
  26.352 +    memset(list, 0, sizeof(*list));
  26.353 +
  26.354 +    list->node = node_ptr;
  26.355 +    if ( !data->head )
  26.356 +        data->head = list;
  26.357 +    else
  26.358 +        data->tail->next = list;
  26.359 +    data->tail = list;
  26.360 +    return 0;
  26.361 +
  26.362 +err:
  26.363 +    cond_av_list_destroy(data->head);
  26.364 +    data->head = NULL;
  26.365 +    return -1;
  26.366 +}
  26.367 +
  26.368 +static int cond_read_av_list(struct policydb *p, void *fp, 
  26.369 +                    struct cond_av_list **ret_list, struct cond_av_list *other)
  26.370 +{
  26.371 +    int i, rc;
  26.372 +    __le32 buf[1];
  26.373 +    u32 len;
  26.374 +    struct cond_insertf_data data;
  26.375 +
  26.376 +    *ret_list = NULL;
  26.377 +
  26.378 +    len = 0;
  26.379 +    rc = next_entry(buf, fp, sizeof(u32));
  26.380 +    if ( rc < 0 )
  26.381 +        return -1;
  26.382 +
  26.383 +    len = le32_to_cpu(buf[0]);
  26.384 +    if ( len == 0 )
  26.385 +    {
  26.386 +        return 0;
  26.387 +    }
  26.388 +
  26.389 +    data.p = p;
  26.390 +    data.other = other;
  26.391 +    data.head = NULL;
  26.392 +    data.tail = NULL;
  26.393 +    for ( i = 0; i < len; i++ )
  26.394 +    {
  26.395 +        rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf,
  26.396 +                                                                        &data);
  26.397 +        if ( rc )
  26.398 +            return rc;
  26.399 +    }
  26.400 +
  26.401 +    *ret_list = data.head;
  26.402 +    return 0;
  26.403 +}
  26.404 +
  26.405 +static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
  26.406 +{
  26.407 +    if ( expr->expr_type <= 0 || expr->expr_type > COND_LAST )
  26.408 +    {
  26.409 +        printk("security: conditional expressions uses unknown operator.\n");
  26.410 +        return 0;
  26.411 +    }
  26.412 +
  26.413 +    if ( expr->bool > p->p_bools.nprim )
  26.414 +    {
  26.415 +        printk("security: conditional expressions uses unknown bool.\n");
  26.416 +        return 0;
  26.417 +    }
  26.418 +    return 1;
  26.419 +}
  26.420 +
  26.421 +static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
  26.422 +{
  26.423 +    __le32 buf[2];
  26.424 +    u32 len, i;
  26.425 +    int rc;
  26.426 +    struct cond_expr *expr = NULL, *last = NULL;
  26.427 +
  26.428 +    rc = next_entry(buf, fp, sizeof(u32));
  26.429 +    if ( rc < 0 )
  26.430 +        return -1;
  26.431 +
  26.432 +    node->cur_state = le32_to_cpu(buf[0]);
  26.433 +
  26.434 +    len = 0;
  26.435 +    rc = next_entry(buf, fp, sizeof(u32));
  26.436 +    if ( rc < 0 )
  26.437 +        return -1;
  26.438 +
  26.439 +    /* expr */
  26.440 +    len = le32_to_cpu(buf[0]);
  26.441 +
  26.442 +    for ( i = 0; i < len; i++ )
  26.443 +    {
  26.444 +        rc = next_entry(buf, fp, sizeof(u32) * 2);
  26.445 +        if ( rc < 0 )
  26.446 +            goto err;
  26.447 +
  26.448 +        expr = xmalloc(struct cond_expr);
  26.449 +        if ( !expr )
  26.450 +        {
  26.451 +            goto err;
  26.452 +        }
  26.453 +        memset(expr, 0, sizeof(struct cond_expr));
  26.454 +
  26.455 +        expr->expr_type = le32_to_cpu(buf[0]);
  26.456 +        expr->bool = le32_to_cpu(buf[1]);
  26.457 +
  26.458 +        if ( !expr_isvalid(p, expr) )
  26.459 +        {
  26.460 +            xfree(expr);
  26.461 +            goto err;
  26.462 +        }
  26.463 +
  26.464 +        if ( i == 0 ) 
  26.465 +            node->expr = expr;
  26.466 +        else
  26.467 +            last->next = expr;
  26.468 +
  26.469 +        last = expr;
  26.470 +    }
  26.471 +
  26.472 +    if ( cond_read_av_list(p, fp, &node->true_list, NULL) != 0 )
  26.473 +        goto err;
  26.474 +    if ( cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0 )
  26.475 +        goto err;
  26.476 +    return 0;
  26.477 +err:
  26.478 +    cond_node_destroy(node);
  26.479 +    return -1;
  26.480 +}
  26.481 +
  26.482 +int cond_read_list(struct policydb *p, void *fp)
  26.483 +{
  26.484 +    struct cond_node *node, *last = NULL;
  26.485 +    __le32 buf[1];
  26.486 +    u32 i, len;
  26.487 +    int rc;
  26.488 +
  26.489 +    rc = next_entry(buf, fp, sizeof buf);
  26.490 +    if ( rc < 0 )
  26.491 +        return -1;
  26.492 +
  26.493 +    len = le32_to_cpu(buf[0]);
  26.494 +
  26.495 +    for ( i = 0; i < len; i++ )
  26.496 +    {
  26.497 +        node = xmalloc(struct cond_node);
  26.498 +        if ( !node )
  26.499 +            goto err;
  26.500 +        memset(node, 0, sizeof(struct cond_node));
  26.501 +
  26.502 +        if ( cond_read_node(p, node, fp) != 0 )
  26.503 +            goto err;
  26.504 +
  26.505 +        if ( i == 0 )
  26.506 +            p->cond_list = node;
  26.507 +        else
  26.508 +            last->next = node;
  26.509 +
  26.510 +        last = node;
  26.511 +    }
  26.512 +    return 0;
  26.513 +err:
  26.514 +    cond_list_destroy(p->cond_list);
  26.515 +    p->cond_list = NULL;
  26.516 +    return -1;
  26.517 +}
  26.518 +
  26.519 +/* Determine whether additional permissions are granted by the conditional
  26.520 + * av table, and if so, add them to the result
  26.521 + */
  26.522 +void cond_compute_av(struct avtab *ctab, struct avtab_key *key, 
  26.523 +                                                        struct av_decision *avd)
  26.524 +{
  26.525 +    struct avtab_node *node;
  26.526 +
  26.527 +    if( !ctab || !key || !avd )
  26.528 +        return;
  26.529 +
  26.530 +    for( node = avtab_search_node(ctab, key); node != NULL;
  26.531 +                node = avtab_search_node_next(node, key->specified) )
  26.532 +    {
  26.533 +        if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
  26.534 +             (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)) )
  26.535 +            avd->allowed |= node->datum.data;
  26.536 +        if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
  26.537 +             (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)) )
  26.538 +            /* Since a '0' in an auditdeny mask represents a
  26.539 +             * permission we do NOT want to audit (dontaudit), we use
  26.540 +             * the '&' operand to ensure that all '0's in the mask
  26.541 +             * are retained (much unlike the allow and auditallow cases).
  26.542 +             */
  26.543 +            avd->auditdeny &= node->datum.data;
  26.544 +        if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
  26.545 +             (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)) )
  26.546 +            avd->auditallow |= node->datum.data;
  26.547 +    }
  26.548 +    return;
  26.549 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/xen/xsm/flask/ss/conditional.h	Fri Aug 31 11:31:18 2007 +0100
    27.3 @@ -0,0 +1,77 @@
    27.4 +/* Authors: Karl MacMillan <kmacmillan@tresys.com>
    27.5 + *          Frank Mayer <mayerf@tresys.com>
    27.6 + *
    27.7 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
    27.8 + *    This program is free software; you can redistribute it and/or modify
    27.9 + *      it under the terms of the GNU General Public License as published by
   27.10 + *    the Free Software Foundation, version 2.
   27.11 + */
   27.12 +
   27.13 +#ifndef _CONDITIONAL_H_
   27.14 +#define _CONDITIONAL_H_
   27.15 +
   27.16 +#include "avtab.h"
   27.17 +#include "symtab.h"
   27.18 +#include "policydb.h"
   27.19 +
   27.20 +#define COND_EXPR_MAXDEPTH 10
   27.21 +
   27.22 +/*
   27.23 + * A conditional expression is a list of operators and operands
   27.24 + * in reverse polish notation.
   27.25 + */
   27.26 +struct cond_expr {
   27.27 +#define COND_BOOL    1 /* plain bool */
   27.28 +#define COND_NOT    2 /* !bool */
   27.29 +#define COND_OR        3 /* bool || bool */
   27.30 +#define COND_AND    4 /* bool && bool */
   27.31 +#define COND_XOR    5 /* bool ^ bool */
   27.32 +#define COND_EQ        6 /* bool == bool */
   27.33 +#define COND_NEQ    7 /* bool != bool */
   27.34 +#define COND_LAST    8
   27.35 +    __u32 expr_type;
   27.36 +    __u32 bool;
   27.37 +    struct cond_expr *next;
   27.38 +};
   27.39 +
   27.40 +/*
   27.41 + * Each cond_node contains a list of rules to be enabled/disabled
   27.42 + * depending on the current value of the conditional expression. This
   27.43 + * struct is for that list.
   27.44 + */
   27.45 +struct cond_av_list {
   27.46 +    struct avtab_node *node;
   27.47 +    struct cond_av_list *next;
   27.48 +};
   27.49 +
   27.50 +/*
   27.51 + * A cond node represents a conditional block in a policy. It
   27.52 + * contains a conditional expression, the current state of the expression,
   27.53 + * two lists of rules to enable/disable depending on the value of the
   27.54 + * expression (the true list corresponds to if and the false list corresponds
   27.55 + * to else)..
   27.56 + */
   27.57 +struct cond_node {
   27.58 +    int cur_state;
   27.59 +    struct cond_expr *expr;
   27.60 +    struct cond_av_list *true_list;
   27.61 +    struct cond_av_list *false_list;
   27.62 +    struct cond_node *next;
   27.63 +};
   27.64 +
   27.65 +int cond_policydb_init(struct policydb* p);
   27.66 +void cond_policydb_destroy(struct policydb* p);
   27.67 +
   27.68 +int cond_init_bool_indexes(struct policydb* p);
   27.69 +int cond_destroy_bool(void *key, void *datum, void *p);
   27.70 +
   27.71 +int cond_index_bool(void *key, void *datum, void *datap);
   27.72 +
   27.73 +int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
   27.74 +int cond_read_list(struct policydb *p, void *fp);
   27.75 +
   27.76 +void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
   27.77 +
   27.78 +int evaluate_cond_node(struct policydb *p, struct cond_node *node);
   27.79 +
   27.80 +#endif /* _CONDITIONAL_H_ */
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/xen/xsm/flask/ss/constraint.h	Fri Aug 31 11:31:18 2007 +0100
    28.3 @@ -0,0 +1,61 @@
    28.4 +/*
    28.5 + * A constraint is a condition that must be satisfied in
    28.6 + * order for one or more permissions to be granted.
    28.7 + * Constraints are used to impose additional restrictions
    28.8 + * beyond the type-based rules in `te' or the role-based
    28.9 + * transition rules in `rbac'.  Constraints are typically
   28.10 + * used to prevent a process from transitioning to a new user
   28.11 + * identity or role unless it is in a privileged type.
   28.12 + * Constraints are likewise typically used to prevent a
   28.13 + * process from labeling an object with a different user
   28.14 + * identity.
   28.15 + *
   28.16 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
   28.17 + */
   28.18 +#ifndef _SS_CONSTRAINT_H_
   28.19 +#define _SS_CONSTRAINT_H_
   28.20 +
   28.21 +#include "ebitmap.h"
   28.22 +
   28.23 +#define CEXPR_MAXDEPTH 5
   28.24 +
   28.25 +struct constraint_expr {
   28.26 +#define CEXPR_NOT        1 /* not expr */
   28.27 +#define CEXPR_AND        2 /* expr and expr */
   28.28 +#define CEXPR_OR        3 /* expr or expr */
   28.29 +#define CEXPR_ATTR        4 /* attr op attr */
   28.30 +#define CEXPR_NAMES        5 /* attr op names */
   28.31 +    u32 expr_type;        /* expression type */
   28.32 +
   28.33 +#define CEXPR_USER 1        /* user */
   28.34 +#define CEXPR_ROLE 2        /* role */
   28.35 +#define CEXPR_TYPE 4        /* type */
   28.36 +#define CEXPR_TARGET 8        /* target if set, source otherwise */
   28.37 +#define CEXPR_XTARGET 16    /* special 3rd target for validatetrans rule */
   28.38 +#define CEXPR_L1L2 32        /* low level 1 vs. low level 2 */
   28.39 +#define CEXPR_L1H2 64        /* low level 1 vs. high level 2 */
   28.40 +#define CEXPR_H1L2 128        /* high level 1 vs. low level 2 */
   28.41 +#define CEXPR_H1H2 256        /* high level 1 vs. high level 2 */
   28.42 +#define CEXPR_L1H1 512        /* low level 1 vs. high level 1 */
   28.43 +#define CEXPR_L2H2 1024        /* low level 2 vs. high level 2 */
   28.44 +    u32 attr;        /* attribute */
   28.45 +
   28.46 +#define CEXPR_EQ     1        /* == or eq */
   28.47 +#define CEXPR_NEQ    2        /* != */
   28.48 +#define CEXPR_DOM    3        /* dom */
   28.49 +#define CEXPR_DOMBY  4        /* domby  */
   28.50 +#define CEXPR_INCOMP 5        /* incomp */
   28.51 +    u32 op;            /* operator */
   28.52 +
   28.53 +    struct ebitmap names;    /* names */
   28.54 +
   28.55 +    struct constraint_expr *next;   /* next expression */
   28.56 +};
   28.57 +
   28.58 +struct constraint_node {
   28.59 +    u32 permissions;    /* constrained permissions */
   28.60 +    struct constraint_expr *expr;    /* constraint on permissions */
   28.61 +    struct constraint_node *next;    /* next constraint */
   28.62 +};
   28.63 +
   28.64 +#endif    /* _SS_CONSTRAINT_H_ */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/xen/xsm/flask/ss/context.h	Fri Aug 31 11:31:18 2007 +0100
    29.3 @@ -0,0 +1,110 @@
    29.4 +/*
    29.5 + * A security context is a set of security attributes
    29.6 + * associated with each subject and object controlled
    29.7 + * by the security policy.  Security contexts are
    29.8 + * externally represented as variable-length strings
    29.9 + * that can be interpreted by a user or application
   29.10 + * with an understanding of the security policy.
   29.11 + * Internally, the security server uses a simple
   29.12 + * structure.  This structure is private to the
   29.13 + * security server and can be changed without affecting
   29.14 + * clients of the security server.
   29.15 + *
   29.16 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
   29.17 + */
   29.18 + 
   29.19 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   29.20 + 
   29.21 +#ifndef _SS_CONTEXT_H_
   29.22 +#define _SS_CONTEXT_H_
   29.23 +
   29.24 +#include "ebitmap.h"
   29.25 +#include "mls_types.h"
   29.26 +#include "security.h"
   29.27 +
   29.28 +/*
   29.29 + * A security context consists of an authenticated user
   29.30 + * identity, a role, a type and a MLS range.
   29.31 + */
   29.32 +struct context {
   29.33 +    u32 user;
   29.34 +    u32 role;
   29.35 +    u32 type;
   29.36 +    struct mls_range range;
   29.37 +};
   29.38 +
   29.39 +static inline void mls_context_init(struct context *c)
   29.40 +{
   29.41 +    memset(&c->range, 0, sizeof(c->range));
   29.42 +}
   29.43 +
   29.44 +static inline int mls_context_cpy(struct context *dst, struct context *src)
   29.45 +{
   29.46 +    int rc;
   29.47 +
   29.48 +    if (!flask_mls_enabled)
   29.49 +        return 0;
   29.50 +
   29.51 +    dst->range.level[0].sens = src->range.level[0].sens;
   29.52 +    rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
   29.53 +    if (rc)
   29.54 +        goto out;
   29.55 +
   29.56 +    dst->range.level[1].sens = src->range.level[1].sens;
   29.57 +    rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
   29.58 +    if (rc)
   29.59 +        ebitmap_destroy(&dst->range.level[0].cat);
   29.60 +out:
   29.61 +    return rc;
   29.62 +}
   29.63 +
   29.64 +static inline int mls_context_cmp(struct context *c1, struct context *c2)
   29.65 +{
   29.66 +    if (!flask_mls_enabled)
   29.67 +        return 1;
   29.68 +
   29.69 +    return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
   29.70 +        ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
   29.71 +        (c1->range.level[1].sens == c2->range.level[1].sens) &&
   29.72 +        ebitmap_cmp(&c1->range.level[1].cat,&c2->range.level[1].cat));
   29.73 +}
   29.74 +
   29.75 +static inline void mls_context_destroy(struct context *c)
   29.76 +{
   29.77 +    if (!flask_mls_enabled)
   29.78 +        return;
   29.79 +
   29.80 +    ebitmap_destroy(&c->range.level[0].cat);
   29.81 +    ebitmap_destroy(&c->range.level[1].cat);
   29.82 +    mls_context_init(c);
   29.83 +}
   29.84 +
   29.85 +static inline void context_init(struct context *c)
   29.86 +{
   29.87 +    memset(c, 0, sizeof(*c));
   29.88 +}
   29.89 +
   29.90 +static inline int context_cpy(struct context *dst, struct context *src)
   29.91 +{
   29.92 +    dst->user = src->user;
   29.93 +    dst->role = src->role;
   29.94 +    dst->type = src->type;
   29.95 +    return mls_context_cpy(dst, src);
   29.96 +}
   29.97 +
   29.98 +static inline void context_destroy(struct context *c)
   29.99 +{
  29.100 +    c->user = c->role = c->type = 0;
  29.101 +    mls_context_destroy(c);
  29.102 +}
  29.103 +
  29.104 +static inline int context_cmp(struct context *c1, struct context *c2)
  29.105 +{
  29.106 +    return ((c1->user == c2->user) &&
  29.107 +        (c1->role == c2->role) &&
  29.108 +        (c1->type == c2->type) &&
  29.109 +        mls_context_cmp(c1, c2));
  29.110 +}
  29.111 +
  29.112 +#endif    /* _SS_CONTEXT_H_ */
  29.113 +
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/xen/xsm/flask/ss/ebitmap.c	Fri Aug 31 11:31:18 2007 +0100
    30.3 @@ -0,0 +1,328 @@
    30.4 +/*
    30.5 + * Implementation of the extensible bitmap type.
    30.6 + *
    30.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    30.8 + */
    30.9 +
   30.10 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   30.11 +
   30.12 +#include <asm/byteorder.h>
   30.13 +#include <xen/lib.h>
   30.14 +#include <xen/xmalloc.h>
   30.15 +#include <xen/errno.h>
   30.16 +#include <xen/spinlock.h>
   30.17 +#include "ebitmap.h"
   30.18 +#include "policydb.h"
   30.19 +
   30.20 +int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
   30.21 +{
   30.22 +    struct ebitmap_node *n1, *n2;
   30.23 +
   30.24 +    if ( e1->highbit != e2->highbit )
   30.25 +        return 0;
   30.26 +
   30.27 +    n1 = e1->node;
   30.28 +    n2 = e2->node;
   30.29 +    while ( n1 && n2 && (n1->startbit == n2->startbit) && (n1->map == n2->map) )
   30.30 +    {
   30.31 +        n1 = n1->next;
   30.32 +        n2 = n2->next;
   30.33 +    }
   30.34 +
   30.35 +    if ( n1 || n2 )
   30.36 +        return 0;
   30.37 +
   30.38 +    return 1;
   30.39 +}
   30.40 +
   30.41 +int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
   30.42 +{
   30.43 +    struct ebitmap_node *n, *new, *prev;
   30.44 +
   30.45 +    ebitmap_init(dst);
   30.46 +    n = src->node;
   30.47 +    prev = NULL;
   30.48 +    while ( n )
   30.49 +    {
   30.50 +        new = xmalloc(struct ebitmap_node);
   30.51 +        if ( !new )
   30.52 +        {
   30.53 +            ebitmap_destroy(dst);
   30.54 +            return -ENOMEM;
   30.55 +        }
   30.56 +        memset(new, 0, sizeof(*new));
   30.57 +        new->startbit = n->startbit;
   30.58 +        new->map = n->map;
   30.59 +        new->next = NULL;
   30.60 +        if ( prev )
   30.61 +            prev->next = new;
   30.62 +        else
   30.63 +            dst->node = new;
   30.64 +        prev = new;
   30.65 +        n = n->next;
   30.66 +    }
   30.67 +
   30.68 +    dst->highbit = src->highbit;
   30.69 +    return 0;
   30.70 +}
   30.71 +
   30.72 +int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
   30.73 +{
   30.74 +    struct ebitmap_node *n1, *n2;
   30.75 +
   30.76 +    if ( e1->highbit < e2->highbit )
   30.77 +        return 0;
   30.78 +
   30.79 +    n1 = e1->node;
   30.80 +    n2 = e2->node;
   30.81 +    while ( n1 && n2 && (n1->startbit <= n2->startbit) )
   30.82 +    {
   30.83 +        if ( n1->startbit < n2->startbit )
   30.84 +        {
   30.85 +            n1 = n1->next;
   30.86 +            continue;
   30.87 +        }
   30.88 +        if ( (n1->map & n2->map) != n2->map )
   30.89 +            return 0;
   30.90 +
   30.91 +        n1 = n1->next;
   30.92 +        n2 = n2->next;
   30.93 +    }
   30.94 +
   30.95 +    if ( n2 )
   30.96 +        return 0;
   30.97 +
   30.98 +    return 1;
   30.99 +}
  30.100 +
  30.101 +int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
  30.102 +{
  30.103 +    struct ebitmap_node *n;
  30.104 +
  30.105 +    if ( e->highbit < bit )
  30.106 +        return 0;
  30.107 +
  30.108 +    n = e->node;
  30.109 +    while ( n && (n->startbit <= bit) )
  30.110 +    {
  30.111 +        if ( (n->startbit + MAPSIZE) > bit )
  30.112 +        {
  30.113 +            if ( n->map & (MAPBIT << (bit - n->startbit)) )
  30.114 +                return 1;
  30.115 +            else
  30.116 +                return 0;
  30.117 +        }
  30.118 +        n = n->next;
  30.119 +    }
  30.120 +
  30.121 +    return 0;
  30.122 +}
  30.123 +
  30.124 +int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
  30.125 +{
  30.126 +    struct ebitmap_node *n, *prev, *new;
  30.127 +
  30.128 +    prev = NULL;
  30.129 +    n = e->node;
  30.130 +    while ( n && n->startbit <= bit )
  30.131 +    {
  30.132 +        if ( (n->startbit + MAPSIZE) > bit )
  30.133 +        {
  30.134 +            if ( value )
  30.135 +            {
  30.136 +                n->map |= (MAPBIT << (bit - n->startbit));
  30.137 +            }
  30.138 +            else
  30.139 +            {
  30.140 +                n->map &= ~(MAPBIT << (bit - n->startbit));
  30.141 +                if ( !n->map )
  30.142 +                {
  30.143 +                    /* drop this node from the bitmap */
  30.144 +
  30.145 +                    if ( !n->next )
  30.146 +                    {
  30.147 +                        /*
  30.148 +                         * this was the highest map
  30.149 +                         * within the bitmap
  30.150 +                         */
  30.151 +                        if ( prev )
  30.152 +                            e->highbit = prev->startbit + MAPSIZE;
  30.153 +                        else
  30.154 +                            e->highbit = 0;
  30.155 +                    }
  30.156 +                    if ( prev )
  30.157 +                        prev->next = n->next;
  30.158 +                    else
  30.159 +                        e->node = n->next;
  30.160 +
  30.161 +                    xfree(n);
  30.162 +                }
  30.163 +            }
  30.164 +            return 0;
  30.165 +        }
  30.166 +        prev = n;
  30.167 +        n = n->next;
  30.168 +    }
  30.169 +
  30.170 +    if ( !value )
  30.171 +        return 0;
  30.172 +
  30.173 +    new = xmalloc(struct ebitmap_node);
  30.174 +    if ( !new )
  30.175 +        return -ENOMEM;
  30.176 +    memset(new, 0, sizeof(*new));
  30.177 +
  30.178 +    new->startbit = bit & ~(MAPSIZE - 1);
  30.179 +    new->map = (MAPBIT << (bit - new->startbit));
  30.180 +
  30.181 +    if ( !n )
  30.182 +        /* this node will be the highest map within the bitmap */
  30.183 +        e->highbit = new->startbit + MAPSIZE;
  30.184 +
  30.185 +    if ( prev )
  30.186 +    {
  30.187 +        new->next = prev->next;
  30.188 +        prev->next = new;
  30.189 +    }
  30.190 +    else
  30.191 +    {
  30.192 +        new->next = e->node;
  30.193 +        e->node = new;
  30.194 +    }
  30.195 +
  30.196 +    return 0;
  30.197 +}
  30.198 +
  30.199 +void ebitmap_destroy(struct ebitmap *e)
  30.200 +{
  30.201 +    struct ebitmap_node *n, *temp;
  30.202 +
  30.203 +    if ( !e )
  30.204 +        return;
  30.205 +
  30.206 +    n = e->node;
  30.207 +    while ( n )
  30.208 +    {
  30.209 +        temp = n;
  30.210 +        n = n->next;
  30.211 +        xfree(temp);
  30.212 +    }
  30.213 +
  30.214 +    e->highbit = 0;
  30.215 +    e->node = NULL;
  30.216 +    return;
  30.217 +}
  30.218 +
  30.219 +int ebitmap_read(struct ebitmap *e, void *fp)
  30.220 +{
  30.221 +    int rc;
  30.222 +    struct ebitmap_node *n, *l;
  30.223 +    __le32 buf[3];
  30.224 +    u32 mapsize, count, i;
  30.225 +    __le64 map;
  30.226 +
  30.227 +    ebitmap_init(e);
  30.228 +
  30.229 +    rc = next_entry(buf, fp, sizeof buf);
  30.230 +    if ( rc < 0 )
  30.231 +        goto out;
  30.232 +
  30.233 +    mapsize = le32_to_cpu(buf[0]);
  30.234 +    e->highbit = le32_to_cpu(buf[1]);
  30.235 +    count = le32_to_cpu(buf[2]);
  30.236 +
  30.237 +    if ( mapsize != MAPSIZE )
  30.238 +    {
  30.239 +        printk(KERN_ERR "security: ebitmap: map size %u does not "
  30.240 +               "match my size %Zd (high bit was %d)\n", mapsize,
  30.241 +               MAPSIZE, e->highbit);
  30.242 +        goto bad;
  30.243 +    }
  30.244 +    if ( !e->highbit )
  30.245 +    {
  30.246 +        e->node = NULL;
  30.247 +        goto ok;
  30.248 +    }
  30.249 +    if ( e->highbit & (MAPSIZE - 1) )
  30.250 +    {
  30.251 +        printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
  30.252 +               "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
  30.253 +        goto bad;
  30.254 +    }
  30.255 +    l = NULL;
  30.256 +    for ( i = 0; i < count; i++ )
  30.257 +    {
  30.258 +        rc = next_entry(buf, fp, sizeof(u32));
  30.259 +        if ( rc < 0 )
  30.260 +        {
  30.261 +            printk(KERN_ERR "security: ebitmap: truncated map\n");
  30.262 +            goto bad;
  30.263 +        }
  30.264 +        n = xmalloc(struct ebitmap_node);
  30.265 +        if ( !n )
  30.266 +        {
  30.267 +            printk(KERN_ERR "security: ebitmap: out of memory\n");
  30.268 +            rc = -ENOMEM;
  30.269 +            goto bad;
  30.270 +        }
  30.271 +        memset(n, 0, sizeof(*n));
  30.272 +
  30.273 +        n->startbit = le32_to_cpu(buf[0]);
  30.274 +
  30.275 +        if ( n->startbit & (MAPSIZE - 1) )
  30.276 +        {
  30.277 +            printk(KERN_ERR "security: ebitmap start bit (%d) is "
  30.278 +                   "not a multiple of the map size (%Zd)\n",
  30.279 +                   n->startbit, MAPSIZE);
  30.280 +            goto bad_free;
  30.281 +        }
  30.282 +        if ( n->startbit > (e->highbit - MAPSIZE) )
  30.283 +        {
  30.284 +            printk(KERN_ERR "security: ebitmap start bit (%d) is "
  30.285 +                   "beyond the end of the bitmap (%Zd)\n",
  30.286 +                   n->startbit, (e->highbit - MAPSIZE));
  30.287 +            goto bad_free;
  30.288 +        }
  30.289 +        rc = next_entry(&map, fp, sizeof(u64));
  30.290 +        if ( rc < 0 )
  30.291 +        {
  30.292 +            printk(KERN_ERR "security: ebitmap: truncated map\n");
  30.293 +            goto bad_free;
  30.294 +        }
  30.295 +        n->map = le64_to_cpu(map);
  30.296 +
  30.297 +        if ( !n->map )
  30.298 +        {
  30.299 +            printk(KERN_ERR "security: ebitmap: null map in "
  30.300 +                   "ebitmap (startbit %d)\n", n->startbit);
  30.301 +            goto bad_free;
  30.302 +        }
  30.303 +        if ( l )
  30.304 +        {
  30.305 +            if ( n->startbit <= l->startbit )
  30.306 +            {
  30.307 +                printk(KERN_ERR "security: ebitmap: start "
  30.308 +                       "bit %d comes after start bit %d\n",
  30.309 +                       n->startbit, l->startbit);
  30.310 +                goto bad_free;
  30.311 +            }
  30.312 +            l->next = n;
  30.313 +        }
  30.314 +        else
  30.315 +            e->node = n;
  30.316 +
  30.317 +        l = n;
  30.318 +    }
  30.319 +
  30.320 +ok:
  30.321 +    rc = 0;
  30.322 +out:
  30.323 +    return rc;
  30.324 +bad_free:
  30.325 +    xfree(n);
  30.326 +bad:
  30.327 +    if ( !rc )
  30.328 +        rc = -EINVAL;
  30.329 +    ebitmap_destroy(e);
  30.330 +    goto out;
  30.331 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/xen/xsm/flask/ss/ebitmap.h	Fri Aug 31 11:31:18 2007 +0100
    31.3 @@ -0,0 +1,79 @@
    31.4 +/*
    31.5 + * An extensible bitmap is a bitmap that supports an
    31.6 + * arbitrary number of bits.  Extensible bitmaps are
    31.7 + * used to represent sets of values, such as types,
    31.8 + * roles, categories, and classes.
    31.9 + *
   31.10 + * Each extensible bitmap is implemented as a linked
   31.11 + * list of bitmap nodes, where each bitmap node has
   31.12 + * an explicitly specified starting bit position within
   31.13 + * the total bitmap.
   31.14 + *
   31.15 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
   31.16 + */
   31.17 +#ifndef _SS_EBITMAP_H_
   31.18 +#define _SS_EBITMAP_H_
   31.19 +
   31.20 +#define MAPTYPE u64            /* portion of bitmap in each node */
   31.21 +#define MAPSIZE (sizeof(MAPTYPE) * 8)    /* number of bits in node bitmap */
   31.22 +#define MAPBIT  1ULL            /* a bit in the node bitmap */
   31.23 +
   31.24 +struct ebitmap_node {
   31.25 +    u32 startbit;        /* starting position in the total bitmap */
   31.26 +    MAPTYPE map;        /* this node's portion of the bitmap */
   31.27 +    struct ebitmap_node *next;
   31.28 +};
   31.29 +
   31.30 +struct ebitmap {
   31.31 +    struct ebitmap_node *node;    /* first node in the bitmap */
   31.32 +    u32 highbit;    /* highest position in the total bitmap */
   31.33 +};
   31.34 +
   31.35 +#define ebitmap_length(e) ((e)->highbit)
   31.36 +#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
   31.37 +
   31.38 +static inline unsigned int ebitmap_start(struct ebitmap *e,
   31.39 +                                                 struct ebitmap_node **n)
   31.40 +{
   31.41 +    *n = e->node;
   31.42 +    return ebitmap_startbit(e);
   31.43 +}
   31.44 +
   31.45 +static inline void ebitmap_init(struct ebitmap *e)
   31.46 +{
   31.47 +    memset(e, 0, sizeof(*e));
   31.48 +}
   31.49 +
   31.50 +static inline unsigned int ebitmap_next(struct ebitmap_node **n,
   31.51 +                                                        unsigned int bit)
   31.52 +{
   31.53 +    if ( (bit == ((*n)->startbit + MAPSIZE - 1)) && (*n)->next )
   31.54 +    {
   31.55 +        *n = (*n)->next;
   31.56 +        return (*n)->startbit;
   31.57 +    }
   31.58 +
   31.59 +    return (bit+1);
   31.60 +}
   31.61 +
   31.62 +static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
   31.63 +                                                        unsigned int bit)
   31.64 +{
   31.65 +    if ( n->map & (MAPBIT << (bit - n->startbit)) )
   31.66 +        return 1;
   31.67 +    return 0;
   31.68 +}
   31.69 +
   31.70 +#define ebitmap_for_each_bit(e, n, bit) \
   31.71 +    for ( bit = ebitmap_start(e, &n); bit < ebitmap_length(e); \
   31.72 +                                    bit = ebitmap_next(&n, bit) ) \
   31.73 +
   31.74 +int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
   31.75 +int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
   31.76 +int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
   31.77 +int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
   31.78 +int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
   31.79 +void ebitmap_destroy(struct ebitmap *e);
   31.80 +int ebitmap_read(struct ebitmap *e, void *fp);
   31.81 +
   31.82 +#endif    /* _SS_EBITMAP_H_ */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/xen/xsm/flask/ss/hashtab.c	Fri Aug 31 11:31:18 2007 +0100
    32.3 @@ -0,0 +1,181 @@
    32.4 +/*
    32.5 + * Implementation of the hash table type.
    32.6 + *
    32.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    32.8 + */
    32.9 +
   32.10 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   32.11 +
   32.12 +#include <xen/lib.h>
   32.13 +#include <xen/xmalloc.h>
   32.14 +#include <xen/errno.h>
   32.15 +#include "hashtab.h"
   32.16 +
   32.17 +struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
   32.18 +            int (*keycmp)(struct hashtab *h, void *key1, void *key2), u32 size)
   32.19 +{
   32.20 +    struct hashtab *p;
   32.21 +    u32 i;
   32.22 +
   32.23 +    p = xmalloc(struct hashtab);
   32.24 +    if ( p == NULL )
   32.25 +        return p;
   32.26 +
   32.27 +    memset(p, 0, sizeof(*p));
   32.28 +    p->size = size;
   32.29 +    p->nel = 0;
   32.30 +    p->hash_value = hash_value;
   32.31 +    p->keycmp = keycmp;
   32.32 +    p->htable = (void *)xmalloc_array(struct hashtab_node, size);
   32.33 +    if ( p->htable == NULL )
   32.34 +    {
   32.35 +        xfree(p);
   32.36 +        return NULL;
   32.37 +    }
   32.38 +
   32.39 +    for ( i = 0; i < size; i++ )
   32.40 +        p->htable[i] = NULL;
   32.41 +
   32.42 +    return p;
   32.43 +}
   32.44 +
   32.45 +int hashtab_insert(struct hashtab *h, void *key, void *datum)
   32.46 +{
   32.47 +    u32 hvalue;
   32.48 +    struct hashtab_node *prev, *cur, *newnode;
   32.49 +
   32.50 +    if ( !h || h->nel == HASHTAB_MAX_NODES )
   32.51 +        return -EINVAL;
   32.52 +
   32.53 +    hvalue = h->hash_value(h, key);
   32.54 +    prev = NULL;
   32.55 +    cur = h->htable[hvalue];
   32.56 +    while ( cur && h->keycmp(h, key, cur->key) > 0 )
   32.57 +    {
   32.58 +        prev = cur;
   32.59 +        cur = cur->next;
   32.60 +    }
   32.61 +
   32.62 +    if ( cur && (h->keycmp(h, key, cur->key) == 0) )
   32.63 +        return -EEXIST;
   32.64 +
   32.65 +    newnode = xmalloc(struct hashtab_node);
   32.66 +    if ( newnode == NULL )
   32.67 +        return -ENOMEM;
   32.68 +    memset(newnode, 0, sizeof(*newnode));
   32.69 +    newnode->key = key;
   32.70 +    newnode->datum = datum;
   32.71 +    if ( prev )
   32.72 +    {
   32.73 +        newnode->next = prev->next;
   32.74 +        prev->next = newnode;
   32.75 +    }
   32.76 +    else
   32.77 +    {
   32.78 +        newnode->next = h->htable[hvalue];
   32.79 +        h->htable[hvalue] = newnode;
   32.80 +    }
   32.81 +
   32.82 +    h->nel++;
   32.83 +    return 0;
   32.84 +}
   32.85 +
   32.86 +void *hashtab_search(struct hashtab *h, void *key)
   32.87 +{
   32.88 +    u32 hvalue;
   32.89 +    struct hashtab_node *cur;
   32.90 +
   32.91 +    if ( !h )
   32.92 +        return NULL;
   32.93 +
   32.94 +    hvalue = h->hash_value(h, key);
   32.95 +    cur = h->htable[hvalue];
   32.96 +    while ( cur != NULL && h->keycmp(h, key, cur->key) > 0 )
   32.97 +        cur = cur->next;
   32.98 +
   32.99 +    if ( cur == NULL || (h->keycmp(h, key, cur->key) != 0) )
  32.100 +        return NULL;
  32.101 +
  32.102 +    return cur->datum;
  32.103 +}
  32.104 +
  32.105 +void hashtab_destroy(struct hashtab *h)
  32.106 +{
  32.107 +    u32 i;
  32.108 +    struct hashtab_node *cur, *temp;
  32.109 +
  32.110 +    if ( !h )
  32.111 +        return;
  32.112 +
  32.113 +    for ( i = 0; i < h->size; i++ )
  32.114 +    {
  32.115 +        cur = h->htable[i];
  32.116 +        while ( cur != NULL )
  32.117 +        {
  32.118 +            temp = cur;
  32.119 +            cur = cur->next;
  32.120 +            xfree(temp);
  32.121 +        }
  32.122 +        h->htable[i] = NULL;
  32.123 +    }
  32.124 +
  32.125 +    xfree(h->htable);
  32.126 +    h->htable = NULL;
  32.127 +
  32.128 +    xfree(h);
  32.129 +}
  32.130 +
  32.131 +int hashtab_map(struct hashtab *h,
  32.132 +        int (*apply)(void *k, void *d, void *args),
  32.133 +        void *args)
  32.134 +{
  32.135 +    u32 i;
  32.136 +    int ret;
  32.137 +    struct hashtab_node *cur;
  32.138 +
  32.139 +    if ( !h )
  32.140 +        return 0;
  32.141 +
  32.142 +    for ( i = 0; i < h->size; i++ )
  32.143 +    {
  32.144 +        cur = h->htable[i];
  32.145 +        while ( cur != NULL )
  32.146 +        {
  32.147 +            ret = apply(cur->key, cur->datum, args);
  32.148 +            if ( ret )
  32.149 +                return ret;
  32.150 +            cur = cur->next;
  32.151 +        }
  32.152 +    }
  32.153 +    return 0;
  32.154 +}
  32.155 +
  32.156 +
  32.157 +void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
  32.158 +{
  32.159 +    u32 i, chain_len, slots_used, max_chain_len;
  32.160 +    struct hashtab_node *cur;
  32.161 +
  32.162 +    slots_used = 0;
  32.163 +    max_chain_len = 0;
  32.164 +    for ( slots_used = max_chain_len = i = 0; i < h->size; i++ )
  32.165 +    {
  32.166 +        cur = h->htable[i];
  32.167 +        if ( cur )
  32.168 +        {
  32.169 +            slots_used++;
  32.170 +            chain_len = 0;
  32.171 +            while ( cur )
  32.172 +            {
  32.173 +                chain_len++;
  32.174 +                cur = cur->next;
  32.175 +            }
  32.176 +
  32.177 +            if ( chain_len > max_chain_len )
  32.178 +                max_chain_len = chain_len;
  32.179 +        }
  32.180 +    }
  32.181 +
  32.182 +    info->slots_used = slots_used;
  32.183 +    info->max_chain_len = max_chain_len;
  32.184 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/xen/xsm/flask/ss/hashtab.h	Fri Aug 31 11:31:18 2007 +0100
    33.3 @@ -0,0 +1,85 @@
    33.4 +/*
    33.5 + * A hash table (hashtab) maintains associations between
    33.6 + * key values and datum values.  The type of the key values
    33.7 + * and the type of the datum values is arbitrary.  The
    33.8 + * functions for hash computation and key comparison are
    33.9 + * provided by the creator of the table.
   33.10 + *
   33.11 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
   33.12 + */
   33.13 +#ifndef _SS_HASHTAB_H_
   33.14 +#define _SS_HASHTAB_H_
   33.15 +
   33.16 +#define HASHTAB_MAX_NODES    0xffffffff
   33.17 +
   33.18 +struct hashtab_node {
   33.19 +    void *key;
   33.20 +    void *datum;
   33.21 +    struct hashtab_node *next;
   33.22 +};
   33.23 +
   33.24 +struct hashtab {
   33.25 +    struct hashtab_node **htable;    /* hash table */
   33.26 +    u32 size;            /* number of slots in hash table */
   33.27 +    u32 nel;            /* number of elements in hash table */
   33.28 +    u32 (*hash_value)(struct hashtab *h, void *key);
   33.29 +                    /* hash function */
   33.30 +    int (*keycmp)(struct hashtab *h, void *key1, void *key2);
   33.31 +                    /* key comparison function */
   33.32 +};
   33.33 +
   33.34 +struct hashtab_info {
   33.35 +    u32 slots_used;
   33.36 +    u32 max_chain_len;
   33.37 +};
   33.38 +
   33.39 +/*
   33.40 + * Creates a new hash table with the specified characteristics.
   33.41 + *
   33.42 + * Returns NULL if insufficent space is available or
   33.43 + * the new hash table otherwise.
   33.44 + */
   33.45 +struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
   33.46 +            int (*keycmp)(struct hashtab *h, void *key1, void *key2), u32 size);
   33.47 +
   33.48 +/*
   33.49 + * Inserts the specified (key, datum) pair into the specified hash table.
   33.50 + *
   33.51 + * Returns -ENOMEM on memory allocation error,
   33.52 + * -EEXIST if there is already an entry with the same key,
   33.53 + * -EINVAL for general errors or
   33.54 + * 0 otherwise.
   33.55 + */
   33.56 +int hashtab_insert(struct hashtab *h, void *k, void *d);
   33.57 +
   33.58 +/*
   33.59 + * Searches for the entry with the specified key in the hash table.
   33.60 + *
   33.61 + * Returns NULL if no entry has the specified key or
   33.62 + * the datum of the entry otherwise.
   33.63 + */
   33.64 +void *hashtab_search(struct hashtab *h, void *k);
   33.65 +
   33.66 +/*
   33.67 + * Destroys the specified hash table.
   33.68 + */
   33.69 +void hashtab_destroy(struct hashtab *h);
   33.70 +
   33.71 +/*
   33.72 + * Applies the specified apply function to (key,datum,args)
   33.73 + * for each entry in the specified hash table.
   33.74 + *
   33.75 + * The order in which the function is applied to the entries
   33.76 + * is dependent upon the internal structure of the hash table.
   33.77 + *
   33.78 + * If apply returns a non-zero status, then hashtab_map will cease
   33.79 + * iterating through the hash table and will propagate the error
   33.80 + * return to its caller.
   33.81 + */
   33.82 +int hashtab_map(struct hashtab *h,
   33.83 +                        int (*apply)(void *k, void *d, void *args), void *args);
   33.84 +
   33.85 +/* Fill info with some hash table statistics */
   33.86 +void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
   33.87 +
   33.88 +#endif    /* _SS_HASHTAB_H */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/xen/xsm/flask/ss/mls.c	Fri Aug 31 11:31:18 2007 +0100
    34.3 @@ -0,0 +1,612 @@
    34.4 +/*
    34.5 + * Implementation of the multi-level security (MLS) policy.
    34.6 + *
    34.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    34.8 + */
    34.9 +
   34.10 +/*
   34.11 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   34.12 + *
   34.13 + *    Support for enhanced MLS infrastructure.
   34.14 + *
   34.15 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   34.16 + */
   34.17 +
   34.18 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   34.19 +
   34.20 +#include <xen/lib.h>
   34.21 +#include <xen/xmalloc.h>
   34.22 +#include <xen/string.h>
   34.23 +#include <xen/errno.h>
   34.24 +#include "sidtab.h"
   34.25 +#include "mls.h"
   34.26 +#include "policydb.h"
   34.27 +#include "services.h"
   34.28 +
   34.29 +/*
   34.30 + * Return the length in bytes for the MLS fields of the
   34.31 + * security context string representation of `context'.
   34.32 + */
   34.33 +int mls_compute_context_len(struct context * context)
   34.34 +{
   34.35 +    int i, l, len, range;
   34.36 +    struct ebitmap_node *node;
   34.37 +
   34.38 +    if (!flask_mls_enabled)
   34.39 +        return 0;
   34.40 +
   34.41 +    len = 1; /* for the beginning ":" */
   34.42 +    for ( l = 0; l < 2; l++ )
   34.43 +    {
   34.44 +        range = 0;
   34.45 +        len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
   34.46 +
   34.47 +        ebitmap_for_each_bit(&context->range.level[l].cat, node, i)
   34.48 +        {
   34.49 +            if ( ebitmap_node_get_bit(node, i) )
   34.50 +            {
   34.51 +                if ( range )
   34.52 +                {
   34.53 +                    range++;
   34.54 +                    continue;
   34.55 +                }
   34.56 +
   34.57 +                len += strlen(policydb.p_cat_val_to_name[i]) + 1;
   34.58 +                range++;
   34.59 +            }
   34.60 +            else
   34.61 +            {
   34.62 +                if ( range > 1 )
   34.63 +                    len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
   34.64 +                range = 0;
   34.65 +            }
   34.66 +        }
   34.67 +        /* Handle case where last category is the end of range */
   34.68 +        if ( range > 1 )
   34.69 +            len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
   34.70 +
   34.71 +        if ( l == 0 )
   34.72 +        {
   34.73 +            if ( mls_level_eq(&context->range.level[0], 
   34.74 +                                                &context->range.level[1]) )
   34.75 +                break;
   34.76 +            else
   34.77 +                len++;
   34.78 +        }
   34.79 +    }
   34.80 +
   34.81 +    return len;
   34.82 +}
   34.83 +
   34.84 +/*
   34.85 + * Write the security context string representation of
   34.86 + * the MLS fields of `context' into the string `*scontext'.
   34.87 + * Update `*scontext' to point to the end of the MLS fields.
   34.88 + */
   34.89 +void mls_sid_to_context(struct context *context, char **scontext)
   34.90 +{
   34.91 +    char *scontextp;
   34.92 +    int i, l, range, wrote_sep;
   34.93 +    struct ebitmap_node *node;
   34.94 +
   34.95 +    if ( !flask_mls_enabled )
   34.96 +        return;
   34.97 +
   34.98 +    scontextp = *scontext;
   34.99 +
  34.100 +    *scontextp = ':';
  34.101 +    scontextp++;
  34.102 +
  34.103 +    for ( l = 0; l < 2; l++ )
  34.104 +    {
  34.105 +        range = 0;
  34.106 +        wrote_sep = 0;
  34.107 +        strlcpy(scontextp,
  34.108 +                policydb.p_sens_val_to_name[context->range.level[l].sens - 1],
  34.109 +                strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]));
  34.110 +        scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
  34.111 +
  34.112 +        /* categories */
  34.113 +        ebitmap_for_each_bit(&context->range.level[l].cat, node, i)
  34.114 +        {
  34.115 +            if ( ebitmap_node_get_bit(node, i) )
  34.116 +            {
  34.117 +                if ( range )
  34.118 +                {
  34.119 +                    range++;
  34.120 +                    continue;
  34.121 +                }
  34.122 +
  34.123 +                if ( !wrote_sep )
  34.124 +                {
  34.125 +                    *scontextp++ = ':';
  34.126 +                    wrote_sep = 1;
  34.127 +                }
  34.128 +                else
  34.129 +                    *scontextp++ = ',';
  34.130 +                strlcpy(scontextp, policydb.p_cat_val_to_name[i], 
  34.131 +                    strlen(policydb.p_cat_val_to_name[i]));
  34.132 +                scontextp += strlen(policydb.p_cat_val_to_name[i]);
  34.133 +                range++;
  34.134 +            }
  34.135 +            else
  34.136 +            {
  34.137 +                if ( range > 1 )
  34.138 +                {
  34.139 +                    if ( range > 2 )
  34.140 +                        *scontextp++ = '.';
  34.141 +                    else
  34.142 +                        *scontextp++ = ',';
  34.143 +
  34.144 +                    strlcpy(scontextp, policydb.p_cat_val_to_name[i - 1],
  34.145 +                        strlen(policydb.p_cat_val_to_name[i - 1]));
  34.146 +                    scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
  34.147 +                }
  34.148 +                range = 0;
  34.149 +            }
  34.150 +        }
  34.151 +
  34.152 +        /* Handle case where last category is the end of range */
  34.153 +        if ( range > 1 )
  34.154 +        {
  34.155 +            if ( range > 2 )
  34.156 +                *scontextp++ = '.';
  34.157 +            else
  34.158 +                *scontextp++ = ',';
  34.159 +
  34.160 +            strlcpy(scontextp, policydb.p_cat_val_to_name[i - 1],
  34.161 +                strlen(policydb.p_cat_val_to_name[i - 1]));
  34.162 +            scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
  34.163 +        }
  34.164 +
  34.165 +        if ( l == 0 )
  34.166 +        {
  34.167 +            if ( mls_level_eq(&context->range.level[0],
  34.168 +                                                 &context->range.level[1]) )
  34.169 +                break;
  34.170 +            else
  34.171 +            {
  34.172 +                *scontextp = '-';
  34.173 +                scontextp++;
  34.174 +            }
  34.175 +        }
  34.176 +    }
  34.177 +
  34.178 +    *scontext = scontextp;
  34.179 +    return;
  34.180 +}
  34.181 +
  34.182 +/*
  34.183 + * Return 1 if the MLS fields in the security context
  34.184 + * structure `c' are valid.  Return 0 otherwise.
  34.185 + */
  34.186 +int mls_context_isvalid(struct policydb *p, struct context *c)
  34.187 +{
  34.188 +    struct level_datum *levdatum;
  34.189 +    struct user_datum *usrdatum;
  34.190 +    struct ebitmap_node *node;
  34.191 +    int i, l;
  34.192 +
  34.193 +    if ( !flask_mls_enabled )
  34.194 +        return 1;
  34.195 +
  34.196 +    /*
  34.197 +     * MLS range validity checks: high must dominate low, low level must
  34.198 +     * be valid (category set <-> sensitivity check), and high level must
  34.199 +     * be valid (category set <-> sensitivity check)
  34.200 +     */
  34.201 +    if ( !mls_level_dom(&c->range.level[1], &c->range.level[0]) )
  34.202 +        /* High does not dominate low. */
  34.203 +        return 0;
  34.204 +
  34.205 +    for ( l = 0; l < 2; l++ )
  34.206 +    {
  34.207 +        if ( !c->range.level[l].sens || c->range.level[l].sens > 
  34.208 +                                                            p->p_levels.nprim )
  34.209 +            return 0;
  34.210 +        levdatum = hashtab_search(p->p_levels.table,
  34.211 +            p->p_sens_val_to_name[c->range.level[l].sens - 1]);
  34.212 +        if ( !levdatum )
  34.213 +            return 0;
  34.214 +
  34.215 +        ebitmap_for_each_bit(&c->range.level[l].cat, node, i)
  34.216 +        {
  34.217 +            if ( ebitmap_node_get_bit(node, i) )
  34.218 +            {
  34.219 +                if ( i > p->p_cats.nprim )
  34.220 +                    return 0;
  34.221 +                if ( !ebitmap_get_bit(&levdatum->level->cat, i) )
  34.222 +                    /*
  34.223 +                     * Category may not be associated with
  34.224 +                     * sensitivity in low level.
  34.225 +                     */
  34.226 +                    return 0;
  34.227 +            }
  34.228 +        }
  34.229 +    }
  34.230 +
  34.231 +    if ( c->role == OBJECT_R_VAL )
  34.232 +        return 1;
  34.233 +
  34.234 +    /*
  34.235 +     * User must be authorized for the MLS range.
  34.236 +     */
  34.237 +    if ( !c->user || c->user > p->p_users.nprim )
  34.238 +        return 0;
  34.239 +    usrdatum = p->user_val_to_struct[c->user - 1];
  34.240 +    if ( !mls_range_contains(usrdatum->range, c->range) )
  34.241 +        return 0; /* user may not be associated with range */
  34.242 +
  34.243 +    return 1;
  34.244 +}
  34.245 +
  34.246 +/*
  34.247 + * Copies the MLS range from `src' into `dst'.
  34.248 + */
  34.249 +static inline int mls_copy_context(struct context *dst, struct context *src)
  34.250 +{
  34.251 +    int l, rc = 0;
  34.252 +
  34.253 +    /* Copy the MLS range from the source context */
  34.254 +    for ( l = 0; l < 2; l++ )
  34.255 +    {
  34.256 +        dst->range.level[l].sens = src->range.level[l].sens;
  34.257 +        rc = ebitmap_cpy(&dst->range.level[l].cat,
  34.258 +                 &src->range.level[l].cat);
  34.259 +        if ( rc )
  34.260 +            break;
  34.261 +    }
  34.262 +
  34.263 +    return rc;
  34.264 +}
  34.265 +
  34.266 +/*
  34.267 + * Set the MLS fields in the security context structure
  34.268 + * `context' based on the string representation in
  34.269 + * the string `*scontext'.  Update `*scontext' to
  34.270 + * point to the end of the string representation of
  34.271 + * the MLS fields.
  34.272 + *
  34.273 + * This function modifies the string in place, inserting
  34.274 + * NULL characters to terminate the MLS fields.
  34.275 + *
  34.276 + * If a def_sid is provided and no MLS field is present,
  34.277 + * copy the MLS field of the associated default context.
  34.278 + * Used for upgraded to MLS systems where objects may lack
  34.279 + * MLS fields.
  34.280 + *
  34.281 + * Policy read-lock must be held for sidtab lookup.
  34.282 + *
  34.283 + */
  34.284 +int mls_context_to_sid(char oldc, char **scontext, struct context *context,
  34.285 +                                                struct sidtab *s, u32 def_sid)
  34.286 +{
  34.287 +
  34.288 +    char delim;
  34.289 +    char *scontextp, *p, *rngptr;
  34.290 +    struct level_datum *levdatum;
  34.291 +    struct cat_datum *catdatum, *rngdatum;
  34.292 +    int l, rc = -EINVAL;
  34.293 +
  34.294 +    if ( !flask_mls_enabled )
  34.295 +        return 0;
  34.296 +
  34.297 +    /*
  34.298 +     * No MLS component to the security context, try and map to
  34.299 +     * default if provided.
  34.300 +     */
  34.301 +    if ( !oldc )
  34.302 +    {
  34.303 +        struct context *defcon;
  34.304 +
  34.305 +        if ( def_sid == SECSID_NULL )
  34.306 +            goto out;
  34.307 +
  34.308 +        defcon = sidtab_search(s, def_sid);
  34.309 +        if ( !defcon )
  34.310 +            goto out;
  34.311 +
  34.312 +        rc = mls_copy_context(context, defcon);
  34.313 +        goto out;
  34.314 +    }
  34.315 +
  34.316 +    /* Extract low sensitivity. */
  34.317 +    scontextp = p = *scontext;
  34.318 +    while ( *p && *p != ':' && *p != '-' )
  34.319 +        p++;
  34.320 +
  34.321 +    delim = *p;
  34.322 +    if ( delim != 0 )
  34.323 +        *p++ = 0;
  34.324 +
  34.325 +    for ( l = 0; l < 2; l++ )
  34.326 +    {
  34.327 +        levdatum = hashtab_search(policydb.p_levels.table, scontextp);
  34.328 +        if ( !levdatum )
  34.329 +        {
  34.330 +            rc = -EINVAL;
  34.331 +            goto out;
  34.332 +        }
  34.333 +
  34.334 +        context->range.level[l].sens = levdatum->level->sens;
  34.335 +
  34.336 +        if ( delim == ':' )
  34.337 +        {
  34.338 +            /* Extract category set. */
  34.339 +            while ( 1 )
  34.340 +            {
  34.341 +                scontextp = p;
  34.342 +                while ( *p && *p != ',' && *p != '-' )
  34.343 +                    p++;
  34.344 +                delim = *p;
  34.345 +                if ( delim != 0 )
  34.346 +                    *p++ = 0;
  34.347 +
  34.348 +                /* Separate into range if exists */
  34.349 +                if ( (rngptr = strchr(scontextp, '.')) != NULL )
  34.350 +                {
  34.351 +                    /* Remove '.' */
  34.352 +                    *rngptr++ = 0;
  34.353 +                }
  34.354 +
  34.355 +                catdatum = hashtab_search(policydb.p_cats.table, scontextp);
  34.356 +                if ( !catdatum )
  34.357 +                {
  34.358 +                    rc = -EINVAL;
  34.359 +                    goto out;
  34.360 +                }
  34.361 +
  34.362 +                rc = ebitmap_set_bit(&context->range.level[l].cat,
  34.363 +                                                    catdatum->value - 1, 1);
  34.364 +                if ( rc )
  34.365 +                    goto out;
  34.366 +
  34.367 +                /* If range, set all categories in range */
  34.368 +                if ( rngptr )
  34.369 +                {
  34.370 +                    int i;
  34.371 +
  34.372 +                    rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
  34.373 +                    if ( !rngdatum )
  34.374 +                    {
  34.375 +                        rc = -EINVAL;
  34.376 +                        goto out;
  34.377 +                    }
  34.378 +
  34.379 +                    if ( catdatum->value >= rngdatum->value )
  34.380 +                    {
  34.381 +                        rc = -EINVAL;
  34.382 +                        goto out;
  34.383 +                    }
  34.384 +
  34.385 +                    for ( i = catdatum->value; i < rngdatum->value; i++ )
  34.386 +                    {
  34.387 +                        rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
  34.388 +                        if ( rc )
  34.389 +                            goto out;
  34.390 +                    }
  34.391 +                }
  34.392 +
  34.393 +                if ( delim != ',' )
  34.394 +                    break;
  34.395 +            }
  34.396 +        }
  34.397 +        if ( delim == '-' )
  34.398 +        {
  34.399 +            /* Extract high sensitivity. */
  34.400 +            scontextp = p;
  34.401 +            while ( *p && *p != ':' )
  34.402 +                p++;
  34.403 +
  34.404 +            delim = *p;
  34.405 +            if ( delim != 0 )
  34.406 +                *p++ = 0;
  34.407 +        }
  34.408 +        else
  34.409 +            break;
  34.410 +    }
  34.411 +
  34.412 +    if ( l == 0 )
  34.413 +    {
  34.414 +        context->range.level[1].sens = context->range.level[0].sens;
  34.415 +        rc = ebitmap_cpy(&context->range.level[1].cat,
  34.416 +                 &context->range.level[0].cat);
  34.417 +        if ( rc )
  34.418 +            goto out;
  34.419 +    }
  34.420 +    *scontext = ++p;
  34.421 +    rc = 0;
  34.422 +out:
  34.423 +    return rc;
  34.424 +}
  34.425 +
  34.426 +/*
  34.427 + * Copies the effective MLS range from `src' into `dst'.
  34.428 + */
  34.429 +static inline int mls_scopy_context(struct context *dst, struct context *src)
  34.430 +{
  34.431 +    int l, rc = 0;
  34.432 +
  34.433 +    /* Copy the MLS range from the source context */
  34.434 +    for ( l = 0; l < 2; l++ )
  34.435 +    {
  34.436 +        dst->range.level[l].sens = src->range.level[0].sens;
  34.437 +        rc = ebitmap_cpy(&dst->range.level[l].cat,
  34.438 +                 &src->range.level[0].cat);
  34.439 +        if ( rc )
  34.440 +            break;
  34.441 +    }
  34.442 +
  34.443 +    return rc;
  34.444 +}
  34.445 +
  34.446 +/*
  34.447 + * Copies the MLS range `range' into `context'.
  34.448 + */
  34.449 +static inline int mls_range_set(struct context *context,
  34.450 +                                                    struct mls_range *range)
  34.451 +{
  34.452 +    int l, rc = 0;
  34.453 +
  34.454 +    /* Copy the MLS range into the  context */
  34.455 +    for ( l = 0; l < 2; l++ )
  34.456 +    {
  34.457 +        context->range.level[l].sens = range->level[l].sens;
  34.458 +        rc = ebitmap_cpy(&context->range.level[l].cat,
  34.459 +                 &range->level[l].cat);
  34.460 +        if ( rc )
  34.461 +            break;
  34.462 +    }
  34.463 +
  34.464 +    return rc;
  34.465 +}
  34.466 +
  34.467 +int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
  34.468 +                                                        struct context *usercon)
  34.469 +{
  34.470 +    if ( flask_mls_enabled )
  34.471 +    {
  34.472 +        struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
  34.473 +        struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
  34.474 +        struct mls_level *user_low = &(user->range.level[0]);
  34.475 +        struct mls_level *user_clr = &(user->range.level[1]);
  34.476 +        struct mls_level *user_def = &(user->dfltlevel);
  34.477 +        struct mls_level *usercon_sen = &(usercon->range.level[0]);
  34.478 +        struct mls_level *usercon_clr = &(usercon->range.level[1]);
  34.479 +
  34.480 +        /* Honor the user's default level if we can */
  34.481 +        if ( mls_level_between(user_def, fromcon_sen, fromcon_clr) )
  34.482 +        {
  34.483 +            *usercon_sen = *user_def;
  34.484 +        }
  34.485 +        else if ( mls_level_between(fromcon_sen, user_def, user_clr) )
  34.486 +        {
  34.487 +            *usercon_sen = *fromcon_sen;
  34.488 +        }
  34.489 +        else if ( mls_level_between(fromcon_clr, user_low, user_def) )
  34.490 +        {
  34.491 +            *usercon_sen = *user_low;
  34.492 +        }
  34.493 +        else
  34.494 +            return -EINVAL;
  34.495 +
  34.496 +        /* Lower the clearance of available contexts
  34.497 +           if the clearance of "fromcon" is lower than
  34.498 +           that of the user's default clearance (but
  34.499 +           only if the "fromcon" clearance dominates
  34.500 +           the user's computed sensitivity level) */
  34.501 +        if ( mls_level_dom(user_clr, fromcon_clr) )
  34.502 +        {
  34.503 +            *usercon_clr = *fromcon_clr;
  34.504 +        }
  34.505 +        else if ( mls_level_dom(fromcon_clr, user_clr) )
  34.506 +        {
  34.507 +            *usercon_clr = *user_clr;
  34.508 +        }
  34.509 +        else
  34.510 +            return -EINVAL;
  34.511 +    }
  34.512 +
  34.513 +    return 0;
  34.514 +}
  34.515 +
  34.516 +/*
  34.517 + * Convert the MLS fields in the security context
  34.518 + * structure `c' from the values specified in the
  34.519 + * policy `oldp' to the values specified in the policy `newp'.
  34.520 + */
  34.521 +int mls_convert_context(struct policydb *oldp, struct policydb *newp,
  34.522 +                                                            struct context *c)
  34.523 +{
  34.524 +    struct level_datum *levdatum;
  34.525 +    struct cat_datum *catdatum;
  34.526 +    struct ebitmap bitmap;
  34.527 +    struct ebitmap_node *node;
  34.528 +    int l, i;
  34.529 +
  34.530 +    if ( !flask_mls_enabled )
  34.531 +        return 0;
  34.532 +
  34.533 +    for ( l = 0; l < 2; l++ )
  34.534 +    {
  34.535 +        levdatum = hashtab_search(newp->p_levels.table,
  34.536 +                        oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
  34.537 +
  34.538 +        if ( !levdatum )
  34.539 +            return -EINVAL;
  34.540 +        c->range.level[l].sens = levdatum->level->sens;
  34.541 +
  34.542 +        ebitmap_init(&bitmap);
  34.543 +        ebitmap_for_each_bit(&c->range.level[l].cat, node, i)
  34.544 +        {
  34.545 +            if ( ebitmap_node_get_bit(node, i) )
  34.546 +            {
  34.547 +                int rc;
  34.548 +
  34.549 +                catdatum = hashtab_search(newp->p_cats.table,
  34.550 +                             oldp->p_cat_val_to_name[i]);
  34.551 +                if ( !catdatum )
  34.552 +                    return -EINVAL;
  34.553 +                rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
  34.554 +                if ( rc )
  34.555 +                    return rc;
  34.556 +            }
  34.557 +        }
  34.558 +        ebitmap_destroy(&c->range.level[l].cat);
  34.559 +        c->range.level[l].cat = bitmap;
  34.560 +    }
  34.561 +
  34.562 +    return 0;
  34.563 +}
  34.564 +
  34.565 +int mls_compute_sid(struct context *scontext, struct context *tcontext,
  34.566 +                        u16 tclass, u32 specified, struct context *newcontext)
  34.567 +{
  34.568 +    if ( !flask_mls_enabled )
  34.569 +        return 0;
  34.570 +
  34.571 +    switch ( specified )
  34.572 +    {
  34.573 +        case AVTAB_TRANSITION:
  34.574 +            if ( tclass == SECCLASS_DOMAIN )
  34.575 +            {
  34.576 +                struct range_trans *rangetr;
  34.577 +                /* Look for a range transition rule. */
  34.578 +                for ( rangetr = policydb.range_tr; rangetr;
  34.579 +                                                    rangetr = rangetr->next)
  34.580 +                {
  34.581 +                    if ( rangetr->dom == scontext->type &&
  34.582 +                                        rangetr->type == tcontext->type)
  34.583 +                    {
  34.584 +                        /* Set the range from the rule */
  34.585 +                        return mls_range_set(newcontext, &rangetr->range);
  34.586 +                    }
  34.587 +                }
  34.588 +            }
  34.589 +            /* Fallthrough */
  34.590 +        case AVTAB_CHANGE:
  34.591 +            if ( tclass == SECCLASS_DOMAIN )
  34.592 +                /* Use the process MLS attributes. */
  34.593 +                return mls_copy_context(newcontext, scontext);
  34.594 +            else
  34.595 +            /* Use the process effective MLS attributes. */
  34.596 +            return mls_scopy_context(newcontext, scontext);
  34.597 +        case AVTAB_MEMBER:
  34.598 +            /* Only polyinstantiate the MLS attributes if
  34.599 +               the type is being polyinstantiated */
  34.600 +            if ( newcontext->type != tcontext->type )
  34.601 +            {
  34.602 +                /* Use the process effective MLS attributes. */
  34.603 +                return mls_scopy_context(newcontext, scontext);
  34.604 +            }
  34.605 +            else
  34.606 +            {
  34.607 +                /* Use the related object MLS attributes. */
  34.608 +                return mls_copy_context(newcontext, tcontext);
  34.609 +            }
  34.610 +        default:
  34.611 +            return -EINVAL;
  34.612 +    }
  34.613 +    return -EINVAL;
  34.614 +}
  34.615 +
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/xen/xsm/flask/ss/mls.h	Fri Aug 31 11:31:18 2007 +0100
    35.3 @@ -0,0 +1,37 @@
    35.4 +/*
    35.5 + * Multi-level security (MLS) policy operations.
    35.6 + *
    35.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    35.8 + */
    35.9 +/*
   35.10 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   35.11 + *
   35.12 + *    Support for enhanced MLS infrastructure.
   35.13 + *
   35.14 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   35.15 + */
   35.16 +
   35.17 +#ifndef _SS_MLS_H_
   35.18 +#define _SS_MLS_H_
   35.19 +
   35.20 +#include "context.h"
   35.21 +#include "policydb.h"
   35.22 +
   35.23 +int mls_compute_context_len(struct context *context);
   35.24 +void mls_sid_to_context(struct context *context, char **scontext);
   35.25 +int mls_context_isvalid(struct policydb *p, struct context *c);
   35.26 +
   35.27 +int mls_context_to_sid(char oldc, char **scontext, struct context *context,
   35.28 +                                               struct sidtab *s, u32 def_sid);
   35.29 +
   35.30 +int mls_convert_context(struct policydb *oldp, struct policydb *newp,
   35.31 +                                                    struct context *context);
   35.32 +
   35.33 +int mls_compute_sid(struct context *scontext, struct context *tcontext,
   35.34 +                        u16 tclass, u32 specified, struct context *newcontext);
   35.35 +
   35.36 +int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
   35.37 +                                                     struct context *usercon);
   35.38 +
   35.39 +#endif    /* _SS_MLS_H */
   35.40 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/xen/xsm/flask/ss/mls_types.h	Fri Aug 31 11:31:18 2007 +0100
    36.3 @@ -0,0 +1,58 @@
    36.4 +/*
    36.5 + * Type definitions for the multi-level security (MLS) policy.
    36.6 + *
    36.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    36.8 + */
    36.9 +/*
   36.10 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   36.11 + *
   36.12 + *    Support for enhanced MLS infrastructure.
   36.13 + *
   36.14 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   36.15 + */
   36.16 +
   36.17 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   36.18 +
   36.19 +#ifndef _SS_MLS_TYPES_H_
   36.20 +#define _SS_MLS_TYPES_H_
   36.21 +
   36.22 +#include "security.h"
   36.23 +
   36.24 +struct mls_level {
   36.25 +    u32 sens;        /* sensitivity */
   36.26 +    struct ebitmap cat;    /* category set */
   36.27 +};
   36.28 +
   36.29 +struct mls_range {
   36.30 +    struct mls_level level[2]; /* low == level[0], high == level[1] */
   36.31 +};
   36.32 +
   36.33 +static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
   36.34 +{
   36.35 +    if ( !flask_mls_enabled )
   36.36 +        return 1;
   36.37 +
   36.38 +    return ((l1->sens == l2->sens) &&
   36.39 +            ebitmap_cmp(&l1->cat, &l2->cat));
   36.40 +}
   36.41 +
   36.42 +static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
   36.43 +{
   36.44 +    if ( !flask_mls_enabled )
   36.45 +        return 1;
   36.46 +
   36.47 +    return ((l1->sens >= l2->sens) &&
   36.48 +            ebitmap_contains(&l1->cat, &l2->cat));
   36.49 +}
   36.50 +
   36.51 +#define mls_level_incomp(l1, l2) \
   36.52 +(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
   36.53 +
   36.54 +#define mls_level_between(l1, l2, l3) \
   36.55 +(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
   36.56 +
   36.57 +#define mls_range_contains(r1, r2) \
   36.58 +(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
   36.59 + mls_level_dom(&(r1).level[1], &(r2).level[1]))
   36.60 +
   36.61 +#endif    /* _SS_MLS_TYPES_H_ */
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/xen/xsm/flask/ss/policydb.c	Fri Aug 31 11:31:18 2007 +0100
    37.3 @@ -0,0 +1,1798 @@
    37.4 +/*
    37.5 + * Implementation of the policy database.
    37.6 + *
    37.7 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    37.8 + */
    37.9 +
   37.10 +/*
   37.11 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   37.12 + *
   37.13 + *    Support for enhanced MLS infrastructure.
   37.14 + *
   37.15 + * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
   37.16 + *
   37.17 + *     Added conditional policy language extensions
   37.18 + *
   37.19 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   37.20 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
   37.21 + *    This program is free software; you can redistribute it and/or modify
   37.22 + *      it under the terms of the GNU General Public License as published by
   37.23 + *    the Free Software Foundation, version 2.
   37.24 + */
   37.25 +
   37.26 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   37.27 +
   37.28 +#include <asm/byteorder.h>
   37.29 +#include <xen/lib.h>
   37.30 +#include <xen/types.h>
   37.31 +#include <xen/xmalloc.h>
   37.32 +#include <xen/string.h>
   37.33 +#include <xen/errno.h>
   37.34 +#include "security.h"
   37.35 +
   37.36 +#include "policydb.h"
   37.37 +#include "conditional.h"
   37.38 +#include "mls.h"
   37.39 +
   37.40 +#define _DEBUG_HASHES
   37.41 +
   37.42 +#ifdef DEBUG_HASHES
   37.43 +static char *symtab_name[SYM_NUM] = {
   37.44 +    "common prefixes",
   37.45 +    "classes",
   37.46 +    "roles",
   37.47 +    "types",
   37.48 +    "users",
   37.49 +    "bools",
   37.50 +    "levels",
   37.51 +    "categories",
   37.52 +};
   37.53 +#endif
   37.54 +
   37.55 +int flask_mls_enabled = 0;
   37.56 +
   37.57 +static unsigned int symtab_sizes[SYM_NUM] = {
   37.58 +    2,
   37.59 +    32,
   37.60 +    16,
   37.61 +    512,
   37.62 +    128,
   37.63 +    16,
   37.64 +    16,
   37.65 +    16,
   37.66 +};
   37.67 +
   37.68 +struct policydb_compat_info {
   37.69 +    int version;
   37.70 +    int sym_num;
   37.71 +    int ocon_num;
   37.72 +};
   37.73 +
   37.74 +/* These need to be updated if SYM_NUM or OCON_NUM changes */
   37.75 +static struct policydb_compat_info policydb_compat[] = {
   37.76 +    {
   37.77 +        .version        = POLICYDB_VERSION_BASE,
   37.78 +        .sym_num        = SYM_NUM - 3,
   37.79 +        .ocon_num       = OCON_NUM - 1,
   37.80 +    },
   37.81 +    {
   37.82 +        .version        = POLICYDB_VERSION_BOOL,
   37.83 +        .sym_num        = SYM_NUM - 2,
   37.84 +        .ocon_num       = OCON_NUM - 1,
   37.85 +    },
   37.86 +    {
   37.87 +        .version        = POLICYDB_VERSION_IPV6,
   37.88 +        .sym_num        = SYM_NUM - 2,
   37.89 +        .ocon_num       = OCON_NUM,
   37.90 +    },
   37.91 +    {
   37.92 +        .version        = POLICYDB_VERSION_NLCLASS,
   37.93 +        .sym_num        = SYM_NUM - 2,
   37.94 +        .ocon_num       = OCON_NUM,
   37.95 +    },
   37.96 +    {
   37.97 +        .version        = POLICYDB_VERSION_MLS,
   37.98 +        .sym_num        = SYM_NUM,
   37.99 +        .ocon_num       = OCON_NUM,
  37.100 +    },
  37.101 +    {
  37.102 +        .version        = POLICYDB_VERSION_AVTAB,
  37.103 +        .sym_num        = SYM_NUM,
  37.104 +        .ocon_num       = OCON_NUM,
  37.105 +    },
  37.106 +};
  37.107 +
  37.108 +static struct policydb_compat_info *policydb_lookup_compat(int version)
  37.109 +{
  37.110 +    int i;
  37.111 +    struct policydb_compat_info *info = NULL;
  37.112 +
  37.113 +    for ( i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++ )
  37.114 +    {
  37.115 +        if ( policydb_compat[i].version == version )
  37.116 +        {
  37.117 +            info = &policydb_compat[i];
  37.118 +            break;
  37.119 +        }
  37.120 +    }
  37.121 +    return info;
  37.122 +}
  37.123 +
  37.124 +/*
  37.125 + * Initialize the role table.
  37.126 + */
  37.127 +static int roles_init(struct policydb *p)
  37.128 +{
  37.129 +    char *key = NULL;
  37.130 +    int rc;
  37.131 +    struct role_datum *role;
  37.132 +
  37.133 +    role = xmalloc(struct role_datum);
  37.134 +    if ( !role )
  37.135 +    {
  37.136 +        rc = -ENOMEM;
  37.137 +        goto out;
  37.138 +    }
  37.139 +    memset(role, 0, sizeof(*role));
  37.140 +    role->value = ++p->p_roles.nprim;
  37.141 +    if ( role->value != OBJECT_R_VAL )
  37.142 +    {
  37.143 +        rc = -EINVAL;
  37.144 +        goto out_free_role;
  37.145 +    }
  37.146 +    key = xmalloc_array(char, strlen(OBJECT_R)+1);
  37.147 +    if ( !key )
  37.148 +    {
  37.149 +        rc = -ENOMEM;
  37.150 +        goto out_free_role;
  37.151 +    }
  37.152 +    strlcpy(key, OBJECT_R, strlen(OBJECT_R)+1);
  37.153 +    rc = hashtab_insert(p->p_roles.table, key, role);
  37.154 +    if ( rc )
  37.155 +        goto out_free_key;
  37.156 +out:
  37.157 +    return rc;
  37.158 +
  37.159 +out_free_key:
  37.160 +    xfree(key);
  37.161 +out_free_role:
  37.162 +    xfree(role);
  37.163 +    goto out;
  37.164 +}
  37.165 +
  37.166 +/*
  37.167 + * Initialize a policy database structure.
  37.168 + */
  37.169 +static int policydb_init(struct policydb *p)
  37.170 +{
  37.171 +    int i, rc;
  37.172 +
  37.173 +    memset(p, 0, sizeof(*p));
  37.174 +
  37.175 +    for ( i = 0; i < SYM_NUM; i++ )
  37.176 +    {
  37.177 +        rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
  37.178 +        if ( rc )
  37.179 +            goto out_free_symtab;
  37.180 +    }
  37.181 +
  37.182 +    rc = avtab_init(&p->te_avtab);
  37.183 +    if ( rc )
  37.184 +        goto out_free_symtab;
  37.185 +
  37.186 +    rc = roles_init(p);
  37.187 +    if ( rc )
  37.188 +        goto out_free_avtab;
  37.189 +
  37.190 +    rc = cond_policydb_init(p);
  37.191 +    if ( rc )
  37.192 +        goto out_free_avtab;
  37.193 +
  37.194 +out:
  37.195 +    return rc;
  37.196 +
  37.197 +out_free_avtab:
  37.198 +    avtab_destroy(&p->te_avtab);
  37.199 +
  37.200 +out_free_symtab:
  37.201 +    for ( i = 0; i < SYM_NUM; i++ )
  37.202 +        hashtab_destroy(p->symtab[i].table);
  37.203 +    goto out;
  37.204 +}
  37.205 +
  37.206 +/*
  37.207 + * The following *_index functions are used to
  37.208 + * define the val_to_name and val_to_struct arrays
  37.209 + * in a policy database structure.  The val_to_name
  37.210 + * arrays are used when converting security context
  37.211 + * structures into string representations.  The
  37.212 + * val_to_struct arrays are used when the attributes
  37.213 + * of a class, role, or user are needed.
  37.214 + */
  37.215 +
  37.216 +static int common_index(void *key, void *datum, void *datap)
  37.217 +{
  37.218 +    struct policydb *p;
  37.219 +    struct common_datum *comdatum;
  37.220 +
  37.221 +    comdatum = datum;
  37.222 +    p = datap;
  37.223 +    if ( !comdatum->value || comdatum->value > p->p_commons.nprim )
  37.224 +        return -EINVAL;
  37.225 +    p->p_common_val_to_name[comdatum->value - 1] = key;
  37.226 +    return 0;
  37.227 +}
  37.228 +
  37.229 +static int class_index(void *key, void *datum, void *datap)
  37.230 +{
  37.231 +    struct policydb *p;
  37.232 +    struct class_datum *cladatum;
  37.233 +
  37.234 +    cladatum = datum;
  37.235 +    p = datap;
  37.236 +    if ( !cladatum->value || cladatum->value > p->p_classes.nprim )
  37.237 +        return -EINVAL;
  37.238 +    p->p_class_val_to_name[cladatum->value - 1] = key;
  37.239 +    p->class_val_to_struct[cladatum->value - 1] = cladatum;
  37.240 +    return 0;
  37.241 +}
  37.242 +
  37.243 +static int role_index(void *key, void *datum, void *datap)
  37.244 +{
  37.245 +    struct policydb *p;
  37.246 +    struct role_datum *role;
  37.247 +
  37.248 +    role = datum;
  37.249 +    p = datap;
  37.250 +    if ( !role->value || role->value > p->p_roles.nprim )
  37.251 +        return -EINVAL;
  37.252 +    p->p_role_val_to_name[role->value - 1] = key;
  37.253 +    p->role_val_to_struct[role->value - 1] = role;
  37.254 +    return 0;
  37.255 +}
  37.256 +
  37.257 +static int type_index(void *key, void *datum, void *datap)
  37.258 +{
  37.259 +    struct policydb *p;
  37.260 +    struct type_datum *typdatum;
  37.261 +
  37.262 +    typdatum = datum;
  37.263 +    p = datap;
  37.264 +
  37.265 +    if ( typdatum->primary )
  37.266 +    {
  37.267 +        if ( !typdatum->value || typdatum->value > p->p_types.nprim )
  37.268 +            return -EINVAL;
  37.269 +        p->p_type_val_to_name[typdatum->value - 1] = key;
  37.270 +    }
  37.271 +
  37.272 +    return 0;
  37.273 +}
  37.274 +
  37.275 +static int user_index(void *key, void *datum, void *datap)
  37.276 +{
  37.277 +    struct policydb *p;
  37.278 +    struct user_datum *usrdatum;
  37.279 +
  37.280 +    usrdatum = datum;
  37.281 +    p = datap;
  37.282 +    if ( !usrdatum->value || usrdatum->value > p->p_users.nprim )
  37.283 +        return -EINVAL;
  37.284 +    p->p_user_val_to_name[usrdatum->value - 1] = key;
  37.285 +    p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
  37.286 +    return 0;
  37.287 +}
  37.288 +
  37.289 +static int sens_index(void *key, void *datum, void *datap)
  37.290 +{
  37.291 +    struct policydb *p;
  37.292 +    struct level_datum *levdatum;
  37.293 +
  37.294 +    levdatum = datum;
  37.295 +    p = datap;
  37.296 +
  37.297 +    if ( !levdatum->isalias )
  37.298 +    {
  37.299 +        if ( !levdatum->level->sens || levdatum->level->sens > 
  37.300 +                                                        p->p_levels.nprim )
  37.301 +            return -EINVAL;
  37.302 +        p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
  37.303 +    }
  37.304 +
  37.305 +    return 0;
  37.306 +}
  37.307 +
  37.308 +static int cat_index(void *key, void *datum, void *datap)
  37.309 +{
  37.310 +    struct policydb *p;
  37.311 +    struct cat_datum *catdatum;
  37.312 +
  37.313 +    catdatum = datum;
  37.314 +    p = datap;
  37.315 +
  37.316 +    if ( !catdatum->isalias )
  37.317 +    {
  37.318 +        if ( !catdatum->value || catdatum->value > p->p_cats.nprim )
  37.319 +            return -EINVAL;
  37.320 +        p->p_cat_val_to_name[catdatum->value - 1] = key;
  37.321 +    }
  37.322 +
  37.323 +    return 0;
  37.324 +}
  37.325 +
  37.326 +static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
  37.327 +{
  37.328 +    common_index,
  37.329 +    class_index,
  37.330 +    role_index,
  37.331 +    type_index,
  37.332 +    user_index,
  37.333 +    cond_index_bool,
  37.334 +    sens_index,
  37.335 +    cat_index,
  37.336 +};
  37.337 +
  37.338 +/*
  37.339 + * Define the common val_to_name array and the class
  37.340 + * val_to_name and val_to_struct arrays in a policy
  37.341 + * database structure.
  37.342 + *
  37.343 + * Caller must clean up upon failure.
  37.344 + */
  37.345 +static int policydb_index_classes(struct policydb *p)
  37.346 +{
  37.347 +    int rc;
  37.348 +
  37.349 +    p->p_common_val_to_name =
  37.350 +        xmalloc_array(char *, p->p_commons.nprim);
  37.351 +    if ( !p->p_common_val_to_name )
  37.352 +    {
  37.353 +        rc = -ENOMEM;
  37.354 +        goto out;
  37.355 +    }
  37.356 +
  37.357 +    rc = hashtab_map(p->p_commons.table, common_index, p);
  37.358 +    if ( rc )
  37.359 +        goto out;
  37.360 +
  37.361 +    p->class_val_to_struct =
  37.362 +        (void *)xmalloc_array(struct class_datum, p->p_classes.nprim);
  37.363 +    if ( !p->class_val_to_struct )
  37.364 +    {
  37.365 +        rc = -ENOMEM;
  37.366 +        goto out;
  37.367 +    }
  37.368 +
  37.369 +    p->p_class_val_to_name =
  37.370 +        xmalloc_array(char *, p->p_classes.nprim);
  37.371 +    if ( !p->p_class_val_to_name )
  37.372 +    {
  37.373 +        rc = -ENOMEM;
  37.374 +        goto out;
  37.375 +    }
  37.376 +
  37.377 +    rc = hashtab_map(p->p_classes.table, class_index, p);
  37.378 +out:
  37.379 +    return rc;
  37.380 +}
  37.381 +
  37.382 +#ifdef DEBUG_HASHES
  37.383 +static void symtab_hash_eval(struct symtab *s)
  37.384 +{
  37.385 +    int i;
  37.386 +
  37.387 +    for ( i = 0; i < SYM_NUM; i++ )
  37.388 +    {
  37.389 +        struct hashtab *h = s[i].table;
  37.390 +        struct hashtab_info info;
  37.391 +
  37.392 +        hashtab_stat(h, &info);
  37.393 +        printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, "
  37.394 +               "longest chain length %d\n", symtab_name[i], h->nel,
  37.395 +               info.slots_used, h->size, info.max_chain_len);
  37.396 +    }
  37.397 +}
  37.398 +#endif
  37.399 +
  37.400 +/*
  37.401 + * Define the other val_to_name and val_to_struct arrays
  37.402 + * in a policy database structure.
  37.403 + *
  37.404 + * Caller must clean up on failure.
  37.405 + */
  37.406 +static int policydb_index_others(struct policydb *p)
  37.407 +{
  37.408 +    int i, rc = 0;
  37.409 +
  37.410 +    printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
  37.411 +           p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
  37.412 +    if ( flask_mls_enabled )
  37.413 +        printk(", %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim);
  37.414 +
  37.415 +    printk("\n");
  37.416 +
  37.417 +    printk(KERN_INFO "security:  %d classes, %d rules\n",
  37.418 +           p->p_classes.nprim, p->te_avtab.nel);
  37.419 +
  37.420 +#ifdef DEBUG_HASHES
  37.421 +    avtab_hash_eval(&p->te_avtab, "rules");
  37.422 +    symtab_hash_eval(p->symtab);
  37.423 +#endif
  37.424 +
  37.425 +    p->role_val_to_struct =
  37.426 +        (void *)xmalloc_array(struct role_datum, p->p_roles.nprim);
  37.427 +    if ( !p->role_val_to_struct )
  37.428 +    {
  37.429 +        rc = -ENOMEM;
  37.430 +        goto out;
  37.431 +    }
  37.432 +
  37.433 +    p->user_val_to_struct =
  37.434 +        (void *)xmalloc_array(struct user_datum, p->p_users.nprim);
  37.435 +    if ( !p->user_val_to_struct )
  37.436 +    {
  37.437 +        rc = -ENOMEM;
  37.438 +        goto out;
  37.439 +    }
  37.440 +
  37.441 +    if ( cond_init_bool_indexes(p) )
  37.442 +    {
  37.443 +        rc = -ENOMEM;
  37.444 +        goto out;
  37.445 +    }
  37.446 +
  37.447 +    for ( i = SYM_ROLES; i < SYM_NUM; i++ )
  37.448 +    {
  37.449 +        p->sym_val_to_name[i] =
  37.450 +            xmalloc_array(char *, p->symtab[i].nprim);
  37.451 +        if ( !p->sym_val_to_name[i] )
  37.452 +        {
  37.453 +            rc = -ENOMEM;
  37.454 +            goto out;
  37.455 +        }
  37.456 +        rc = hashtab_map(p->symtab[i].table, index_f[i], p);
  37.457 +        if ( rc )
  37.458 +            goto out;
  37.459 +    }
  37.460 +
  37.461 +out:
  37.462 +    return rc;
  37.463 +}
  37.464 +
  37.465 +/*
  37.466 + * The following *_destroy functions are used to
  37.467 + * free any memory allocated for each kind of
  37.468 + * symbol data in the policy database.
  37.469 + */
  37.470 +
  37.471 +static int perm_destroy(void *key, void *datum, void *p)
  37.472 +{
  37.473 +    xfree(key);
  37.474 +    xfree(datum);
  37.475 +    return 0;
  37.476 +}
  37.477 +
  37.478 +static int common_destroy(void *key, void *datum, void *p)
  37.479 +{
  37.480 +    struct common_datum *comdatum;
  37.481 +
  37.482 +    xfree(key);
  37.483 +    comdatum = datum;
  37.484 +    hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
  37.485 +    hashtab_destroy(comdatum->permissions.table);
  37.486 +    xfree(datum);
  37.487 +    return 0;
  37.488 +}
  37.489 +
  37.490 +static int class_destroy(void *key, void *datum, void *p)
  37.491 +{
  37.492 +    struct class_datum *cladatum;
  37.493 +    struct constraint_node *constraint, *ctemp;
  37.494 +    struct constraint_expr *e, *etmp;
  37.495 +
  37.496 +    xfree(key);
  37.497 +    cladatum = datum;
  37.498 +    hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
  37.499 +    hashtab_destroy(cladatum->permissions.table);
  37.500 +    constraint = cladatum->constraints;
  37.501 +    while ( constraint )
  37.502 +    {
  37.503 +        e = constraint->expr;
  37.504 +        while ( e )
  37.505 +        {
  37.506 +            ebitmap_destroy(&e->names);
  37.507 +            etmp = e;
  37.508 +            e = e->next;
  37.509 +            xfree(etmp);
  37.510 +        }
  37.511 +        ctemp = constraint;
  37.512 +        constraint = constraint->next;
  37.513 +        xfree(ctemp);
  37.514 +    }
  37.515 +
  37.516 +    constraint = cladatum->validatetrans;
  37.517 +    while ( constraint )
  37.518 +    {
  37.519 +        e = constraint->expr;
  37.520 +        while ( e )
  37.521 +        {
  37.522 +            ebitmap_destroy(&e->names);
  37.523 +            etmp = e;
  37.524 +            e = e->next;
  37.525 +            xfree(etmp);
  37.526 +        }
  37.527 +        ctemp = constraint;
  37.528 +        constraint = constraint->next;
  37.529 +        xfree(ctemp);
  37.530 +    }
  37.531 +
  37.532 +    xfree(cladatum->comkey);
  37.533 +    xfree(datum);
  37.534 +    return 0;
  37.535 +}
  37.536 +
  37.537 +static int role_destroy(void *key, void *datum, void *p)
  37.538 +{
  37.539 +    struct role_datum *role;
  37.540 +
  37.541 +    xfree(key);
  37.542 +    role = datum;
  37.543 +    ebitmap_destroy(&role->dominates);
  37.544 +    ebitmap_destroy(&role->types);
  37.545 +    xfree(datum);
  37.546 +    return 0;
  37.547 +}
  37.548 +
  37.549 +static int type_destroy(void *key, void *datum, void *p)
  37.550 +{
  37.551 +    xfree(key);
  37.552 +    xfree(datum);
  37.553 +    return 0;
  37.554 +}
  37.555 +
  37.556 +static int user_destroy(void *key, void *datum, void *p)
  37.557 +{
  37.558 +    struct user_datum *usrdatum;
  37.559 +
  37.560 +    xfree(key);
  37.561 +    usrdatum = datum;
  37.562 +    ebitmap_destroy(&usrdatum->roles);
  37.563 +    ebitmap_destroy(&usrdatum->range.level[0].cat);
  37.564 +    ebitmap_destroy(&usrdatum->range.level[1].cat);
  37.565 +    ebitmap_destroy(&usrdatum->dfltlevel.cat);
  37.566 +    xfree(datum);
  37.567 +    return 0;
  37.568 +}
  37.569 +
  37.570 +static int sens_destroy(void *key, void *datum, void *p)
  37.571 +{
  37.572 +    struct level_datum *levdatum;
  37.573 +
  37.574 +    xfree(key);
  37.575 +    levdatum = datum;
  37.576 +    ebitmap_destroy(&levdatum->level->cat);
  37.577 +    xfree(levdatum->level);
  37.578 +    xfree(datum);
  37.579 +    return 0;
  37.580 +}
  37.581 +
  37.582 +static int cat_destroy(void *key, void *datum, void *p)
  37.583 +{
  37.584 +    xfree(key);
  37.585 +    xfree(datum);
  37.586 +    return 0;
  37.587 +}
  37.588 +
  37.589 +static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
  37.590 +{
  37.591 +    common_destroy,
  37.592 +    class_destroy,
  37.593 +    role_destroy,
  37.594 +    type_destroy,
  37.595 +    user_destroy,
  37.596 +    cond_destroy_bool,
  37.597 +    sens_destroy,
  37.598 +    cat_destroy,
  37.599 +};
  37.600 +
  37.601 +static void ocontext_destroy(struct ocontext *c, int i)
  37.602 +{
  37.603 +    context_destroy(&c->context[0]);
  37.604 +    context_destroy(&c->context[1]);
  37.605 +    if ( i == OCON_ISID )
  37.606 +        xfree(c->u.name);
  37.607 +    xfree(c);
  37.608 +}
  37.609 +
  37.610 +/*
  37.611 + * Free any memory allocated by a policy database structure.
  37.612 + */
  37.613 +void policydb_destroy(struct policydb *p)
  37.614 +{
  37.615 +    struct ocontext *c, *ctmp;
  37.616 +    int i;
  37.617 +    struct role_allow *ra, *lra = NULL;
  37.618 +    struct role_trans *tr, *ltr = NULL;
  37.619 +    struct range_trans *rt, *lrt = NULL;
  37.620 +
  37.621 +    for ( i = 0; i < SYM_NUM; i++ )
  37.622 +    {
  37.623 +        hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
  37.624 +        hashtab_destroy(p->symtab[i].table);
  37.625 +    }
  37.626 +
  37.627 +    for ( i = 0; i < SYM_NUM; i++ )
  37.628 +        xfree(p->sym_val_to_name[i]);
  37.629 +
  37.630 +    xfree(p->class_val_to_struct);
  37.631 +    xfree(p->role_val_to_struct);
  37.632 +    xfree(p->user_val_to_struct);
  37.633 +
  37.634 +    avtab_destroy(&p->te_avtab);
  37.635 +
  37.636 +    for ( i = 0; i < OCON_NUM; i++ )
  37.637 +    {
  37.638 +        c = p->ocontexts[i];
  37.639 +        while ( c )
  37.640 +        {
  37.641 +            ctmp = c;
  37.642 +            c = c->next;
  37.643 +            ocontext_destroy(ctmp,i);
  37.644 +        }
  37.645 +    }
  37.646 +
  37.647 +    cond_policydb_destroy(p);
  37.648 +
  37.649 +    for ( tr = p->role_tr; tr; tr = tr->next )
  37.650 +    {
  37.651 +        if ( ltr ) xfree(ltr);
  37.652 +        ltr = tr;
  37.653 +    }
  37.654 +    if ( ltr ) xfree(ltr);
  37.655 +
  37.656 +    for ( ra = p->role_allow; ra; ra = ra -> next )
  37.657 +    {
  37.658 +        if ( lra ) xfree(lra);
  37.659 +        lra = ra;
  37.660 +    }
  37.661 +    if ( lra ) xfree(lra);
  37.662 +
  37.663 +    for ( rt = p->range_tr; rt; rt = rt -> next )
  37.664 +    {
  37.665 +        if ( lrt ) xfree(lrt);
  37.666 +        lrt = rt;
  37.667 +    }
  37.668 +    if ( lrt ) xfree(lrt);
  37.669 +
  37.670 +    for ( i = 0; i < p->p_types.nprim; i++ )
  37.671 +        ebitmap_destroy(&p->type_attr_map[i]);
  37.672 +    xfree(p->type_attr_map);
  37.673 +
  37.674 +    return;
  37.675 +}
  37.676 +
  37.677 +/*
  37.678 + * Load the initial SIDs specified in a policy database
  37.679 + * structure into a SID table.
  37.680 + */
  37.681 +int policydb_load_isids(struct policydb *p, struct sidtab *s)
  37.682 +{
  37.683 +    struct ocontext *head, *c;
  37.684 +    int rc;
  37.685 +
  37.686 +    rc = sidtab_init(s);
  37.687 +    if ( rc )
  37.688 +    {
  37.689 +        printk(KERN_ERR "security:  out of memory on SID table init\n");
  37.690 +        goto out;
  37.691 +    }
  37.692 +
  37.693 +    head = p->ocontexts[OCON_ISID];
  37.694 +    for ( c = head; c; c = c->next )
  37.695 +    {
  37.696 +        if ( !c->context[0].user )
  37.697 +        {
  37.698 +            printk(KERN_ERR "security:  SID %s was never "
  37.699 +                   "defined.\n", c->u.name);
  37.700 +            rc = -EINVAL;
  37.701 +            goto out;
  37.702 +        }
  37.703 +        if ( sidtab_insert(s, c->sid[0], &c->context[0]) )
  37.704 +        {
  37.705 +            printk(KERN_ERR "security:  unable to load initial "
  37.706 +                   "SID %s.\n", c->u.name);
  37.707 +            rc = -EINVAL;
  37.708 +            goto out;
  37.709 +        }
  37.710 +    }
  37.711 +out:
  37.712 +    return rc;
  37.713 +}
  37.714 +
  37.715 +/*
  37.716 + * Return 1 if the fields in the security context
  37.717 + * structure `c' are valid.  Return 0 otherwise.
  37.718 + */
  37.719 +int policydb_context_isvalid(struct policydb *p, struct context *c)
  37.720 +{
  37.721 +    struct role_datum *role;
  37.722 +    struct user_datum *usrdatum;
  37.723 +
  37.724 +    if ( !c->role || c->role > p->p_roles.nprim )
  37.725 +        return 0;
  37.726 +
  37.727 +    if ( !c->user || c->user > p->p_users.nprim )
  37.728 +        return 0;
  37.729 +
  37.730 +    if ( !c->type || c->type > p->p_types.nprim )
  37.731 +        return 0;
  37.732 +
  37.733 +    if ( c->role != OBJECT_R_VAL )
  37.734 +    {
  37.735 +        /*
  37.736 +         * Role must be authorized for the type.
  37.737 +         */
  37.738 +        role = p->role_val_to_struct[c->role - 1];
  37.739 +        if ( !ebitmap_get_bit(&role->types, c->type - 1) )
  37.740 +            /* role may not be associated with type */
  37.741 +            return 0;
  37.742 +
  37.743 +        /*
  37.744 +         * User must be authorized for the role.
  37.745 +         */
  37.746 +        usrdatum = p->user_val_to_struct[c->user - 1];
  37.747 +        if ( !usrdatum )
  37.748 +            return 0;
  37.749 +
  37.750 +        if ( !ebitmap_get_bit(&usrdatum->roles, c->role - 1) )
  37.751 +            /* user may not be associated with role */
  37.752 +            return 0;
  37.753 +    }
  37.754 +
  37.755 +    if ( !mls_context_isvalid(p, c) )
  37.756 +        return 0;
  37.757 +
  37.758 +    return 1;
  37.759 +}
  37.760 +
  37.761 +/*
  37.762 + * Read a MLS range structure from a policydb binary
  37.763 + * representation file.
  37.764 + */
  37.765 +static int mls_read_range_helper(struct mls_range *r, void *fp)
  37.766 +{
  37.767 +    __le32 buf[2];
  37.768 +    u32 items;
  37.769 +    int rc;
  37.770 +
  37.771 +    rc = next_entry(buf, fp, sizeof(u32));
  37.772 +    if ( rc < 0 )
  37.773 +        goto out;
  37.774 +
  37.775 +    items = le32_to_cpu(buf[0]);
  37.776 +    if ( items > ARRAY_SIZE(buf) )
  37.777 +    {
  37.778 +        printk(KERN_ERR "security: mls:  range overflow\n");
  37.779 +        rc = -EINVAL;
  37.780 +        goto out;
  37.781 +    }
  37.782 +    rc = next_entry(buf, fp, sizeof(u32) * items);
  37.783 +    if ( rc < 0 )
  37.784 +    {
  37.785 +        printk(KERN_ERR "security: mls:  truncated range\n");
  37.786 +        goto out;
  37.787 +    }
  37.788 +    r->level[0].sens = le32_to_cpu(buf[0]);
  37.789 +    if ( items > 1 )
  37.790 +        r->level[1].sens = le32_to_cpu(buf[1]);
  37.791 +    else
  37.792 +        r->level[1].sens = r->level[0].sens;
  37.793 +
  37.794 +    rc = ebitmap_read(&r->level[0].cat, fp);
  37.795 +    if ( rc )
  37.796 +    {
  37.797 +        printk(KERN_ERR "security: mls:  error reading low "
  37.798 +               "categories\n");
  37.799 +        goto out;
  37.800 +    }
  37.801 +    if ( items > 1 )
  37.802 +    {
  37.803 +        rc = ebitmap_read(&r->level[1].cat, fp);
  37.804 +        if ( rc )
  37.805 +        {
  37.806 +            printk(KERN_ERR "security: mls:  error reading high "
  37.807 +                   "categories\n");
  37.808 +            goto bad_high;
  37.809 +        }
  37.810 +    }
  37.811 +    else
  37.812 +    {
  37.813 +        rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
  37.814 +        if ( rc )
  37.815 +        {
  37.816 +            printk(KERN_ERR "security: mls:  out of memory\n");
  37.817 +            goto bad_high;
  37.818 +        }
  37.819 +    }
  37.820 +
  37.821 +    rc = 0;
  37.822 +out:
  37.823 +    return rc;
  37.824 +bad_high:
  37.825 +    ebitmap_destroy(&r->level[0].cat);
  37.826 +    goto out;
  37.827 +}
  37.828 +
  37.829 +/*
  37.830 + * Read and validate a security context structure
  37.831 + * from a policydb binary representation file.
  37.832 + */
  37.833 +static int context_read_and_validate(struct context *c, struct policydb *p,
  37.834 +                                                                    void *fp)
  37.835 +{
  37.836 +    __le32 buf[3];
  37.837 +    int rc;
  37.838 +
  37.839 +    rc = next_entry(buf, fp, sizeof buf);
  37.840 +    if ( rc < 0 )
  37.841 +    {
  37.842 +        printk(KERN_ERR "security: context truncated\n");
  37.843 +        goto out;
  37.844 +    }
  37.845 +    c->user = le32_to_cpu(buf[0]);
  37.846 +    c->role = le32_to_cpu(buf[1]);
  37.847 +    c->type = le32_to_cpu(buf[2]);
  37.848 +    if ( p->policyvers >= POLICYDB_VERSION_MLS )
  37.849 +    {
  37.850 +        if ( mls_read_range_helper(&c->range, fp) )
  37.851 +        {
  37.852 +            printk(KERN_ERR "security: error reading MLS range of "
  37.853 +                   "context\n");
  37.854 +            rc = -EINVAL;
  37.855 +            goto out;
  37.856 +        }
  37.857 +    }
  37.858 +
  37.859 +    if ( !policydb_context_isvalid(p, c) )
  37.860 +    {
  37.861 +        printk(KERN_ERR "security:  invalid security context\n");
  37.862 +        context_destroy(c);
  37.863 +        rc = -EINVAL;
  37.864 +    }
  37.865 +out:
  37.866 +    return rc;
  37.867 +}
  37.868 +
  37.869 +/*
  37.870 + * The following *_read functions are used to
  37.871 + * read the symbol data from a policy database
  37.872 + * binary representation file.
  37.873 + */
  37.874 +
  37.875 +static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
  37.876 +{
  37.877 +    char *key = NULL;
  37.878 +    struct perm_datum *perdatum;
  37.879 +    int rc;
  37.880 +    __le32 buf[2];
  37.881 +    u32 len;
  37.882 +
  37.883 +    perdatum = xmalloc(struct perm_datum);
  37.884 +    if ( !perdatum )
  37.885 +    {
  37.886 +        rc = -ENOMEM;
  37.887 +        goto out;
  37.888 +    }
  37.889 +    memset(perdatum, 0, sizeof(*perdatum));
  37.890 +
  37.891 +    rc = next_entry(buf, fp, sizeof buf);
  37.892 +    if ( rc < 0 )
  37.893 +        goto bad;
  37.894 +
  37.895 +    len = le32_to_cpu(buf[0]);
  37.896 +    perdatum->value = le32_to_cpu(buf[1]);
  37.897 +
  37.898 +    key = xmalloc_array(char, len + 1);
  37.899 +    if ( !key )
  37.900 +    {
  37.901 +        rc = -ENOMEM;
  37.902 +        goto bad;
  37.903 +    }
  37.904 +    rc = next_entry(key, fp, len);
  37.905 +    if ( rc < 0 )
  37.906 +        goto bad;
  37.907 +    key[len] = 0;
  37.908 +
  37.909 +    rc = hashtab_insert(h, key, perdatum);
  37.910 +    if ( rc )
  37.911 +        goto bad;
  37.912 +out:
  37.913 +    return rc;
  37.914 +bad:
  37.915 +    perm_destroy(key, perdatum, NULL);
  37.916 +    goto out;
  37.917 +}
  37.918 +
  37.919 +static int common_read(struct policydb *p, struct hashtab *h, void *fp)
  37.920 +{
  37.921 +    char *key = NULL;
  37.922 +    struct common_datum *comdatum;
  37.923 +    __le32 buf[4];
  37.924 +    u32 len, nel;
  37.925 +    int i, rc;
  37.926 +
  37.927 +    comdatum = xmalloc(struct common_datum);
  37.928 +    if ( !comdatum )
  37.929 +    {
  37.930 +        rc = -ENOMEM;
  37.931 +        goto out;
  37.932 +    }
  37.933 +    memset(comdatum, 0, sizeof(*comdatum));
  37.934 +
  37.935 +    rc = next_entry(buf, fp, sizeof buf);
  37.936 +    if ( rc < 0 )
  37.937 +        goto bad;
  37.938 +
  37.939 +    len = le32_to_cpu(buf[0]);
  37.940 +    comdatum->value = le32_to_cpu(buf[1]);
  37.941 +
  37.942 +    rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
  37.943 +    if ( rc )
  37.944 +        goto bad;
  37.945 +    comdatum->permissions.nprim = le32_to_cpu(buf[2]);
  37.946 +    nel = le32_to_cpu(buf[3]);
  37.947 +
  37.948 +    key = xmalloc_array(char, len + 1);
  37.949 +    if ( !key )
  37.950 +    {
  37.951 +        rc = -ENOMEM;
  37.952 +        goto bad;
  37.953 +    }
  37.954 +    rc = next_entry(key, fp, len);
  37.955 +    if ( rc < 0 )
  37.956 +        goto bad;
  37.957 +    key[len] = 0;
  37.958 +
  37.959 +    for ( i = 0; i < nel; i++ )
  37.960 +    {
  37.961 +        rc = perm_read(p, comdatum->permissions.table, fp);
  37.962 +        if ( rc )
  37.963 +            goto bad;
  37.964 +    }
  37.965 +
  37.966 +    rc = hashtab_insert(h, key, comdatum);
  37.967 +    if ( rc )
  37.968 +        goto bad;
  37.969 +out:
  37.970 +    return rc;
  37.971 +bad:
  37.972 +    common_destroy(key, comdatum, NULL);
  37.973 +    goto out;
  37.974 +}
  37.975 +
  37.976 +static int read_cons_helper(struct constraint_node **nodep, int ncons,
  37.977 +                                                    int allowxtarget, void *fp)
  37.978 +{
  37.979 +    struct constraint_node *c, *lc;
  37.980 +    struct constraint_expr *e, *le;
  37.981 +    __le32 buf[3];
  37.982 +    u32 nexpr;
  37.983 +    int rc, i, j, depth;
  37.984 +
  37.985 +    lc = NULL;
  37.986 +    for ( i = 0; i < ncons; i++ )
  37.987 +    {
  37.988 +        c = xmalloc(struct constraint_node);
  37.989 +        if ( !c )
  37.990 +            return -ENOMEM;
  37.991 +        memset(c, 0, sizeof(*c));
  37.992 +
  37.993 +        if ( lc )
  37.994 +        {
  37.995 +            lc->next = c;
  37.996 +        }
  37.997 +        else
  37.998 +        {
  37.999 +            *nodep = c;
 37.1000 +        }
 37.1001 +
 37.1002 +        rc = next_entry(buf, fp, (sizeof(u32) * 2));
 37.1003 +        if ( rc < 0 )
 37.1004 +            return rc;
 37.1005 +        c->permissions = le32_to_cpu(buf[0]);
 37.1006 +        nexpr = le32_to_cpu(buf[1]);
 37.1007 +        le = NULL;
 37.1008 +        depth = -1;
 37.1009 +        for ( j = 0; j < nexpr; j++ )
 37.1010 +        {
 37.1011 +            e = xmalloc(struct constraint_expr);
 37.1012 +            if ( !e )
 37.1013 +                return -ENOMEM;
 37.1014 +            memset(e, 0, sizeof(*e));
 37.1015 +
 37.1016 +            if ( le )
 37.1017 +                le->next = e;
 37.1018 +            else
 37.1019 +                c->expr = e;
 37.1020 +
 37.1021 +            rc = next_entry(buf, fp, (sizeof(u32) * 3));
 37.1022 +            if ( rc < 0 )
 37.1023 +                return rc;
 37.1024 +            e->expr_type = le32_to_cpu(buf[0]);
 37.1025 +            e->attr = le32_to_cpu(buf[1]);
 37.1026 +            e->op = le32_to_cpu(buf[2]);
 37.1027 +
 37.1028 +            switch ( e->expr_type )
 37.1029 +            {
 37.1030 +                case CEXPR_NOT:
 37.1031 +                    if ( depth < 0 )
 37.1032 +                        return -EINVAL;
 37.1033 +                break;
 37.1034 +                case CEXPR_AND:
 37.1035 +                case CEXPR_OR:
 37.1036 +                    if ( depth < 1 )
 37.1037 +                        return -EINVAL;
 37.1038 +                    depth--;
 37.1039 +                break;
 37.1040 +                case CEXPR_ATTR:
 37.1041 +                    if ( depth == (CEXPR_MAXDEPTH - 1) )
 37.1042 +                        return -EINVAL;
 37.1043 +                    depth++;
 37.1044 +                break;
 37.1045 +                case CEXPR_NAMES:
 37.1046 +                    if ( !allowxtarget && (e->attr & CEXPR_XTARGET) )
 37.1047 +                        return -EINVAL;
 37.1048 +                    if ( depth == (CEXPR_MAXDEPTH - 1) )
 37.1049 +                        return -EINVAL;
 37.1050 +                    depth++;
 37.1051 +                    if ( ebitmap_read(&e->names, fp) )
 37.1052 +                        return -EINVAL;
 37.1053 +                break;
 37.1054 +                default:
 37.1055 +                    return -EINVAL;
 37.1056 +            }
 37.1057 +            le = e;
 37.1058 +        }
 37.1059 +        if ( depth != 0 )
 37.1060 +            return -EINVAL;
 37.1061 +        lc = c;
 37.1062 +    }
 37.1063 +
 37.1064 +    return 0;
 37.1065 +}
 37.1066 +
 37.1067 +static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1068 +{
 37.1069 +    char *key = NULL;
 37.1070 +    struct class_datum *cladatum;
 37.1071 +    __le32 buf[6];
 37.1072 +    u32 len, len2, ncons, nel;
 37.1073 +    int i, rc;
 37.1074 +
 37.1075 +    cladatum = xmalloc(struct class_datum);
 37.1076 +    if ( !cladatum )
 37.1077 +    {
 37.1078 +        rc = -ENOMEM;
 37.1079 +        goto out;
 37.1080 +    }
 37.1081 +    memset(cladatum, 0, sizeof(*cladatum));
 37.1082 +
 37.1083 +    rc = next_entry(buf, fp, sizeof(u32)*6);
 37.1084 +    if ( rc < 0 )
 37.1085 +        goto bad;
 37.1086 +
 37.1087 +    len = le32_to_cpu(buf[0]);
 37.1088 +    len2 = le32_to_cpu(buf[1]);
 37.1089 +    cladatum->value = le32_to_cpu(buf[2]);
 37.1090 +
 37.1091 +    rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
 37.1092 +    if ( rc )
 37.1093 +        goto bad;
 37.1094 +    cladatum->permissions.nprim = le32_to_cpu(buf[3]);
 37.1095 +    nel = le32_to_cpu(buf[4]);
 37.1096 +
 37.1097 +    ncons = le32_to_cpu(buf[5]);
 37.1098 +
 37.1099 +    key = xmalloc_array(char, len + 1);
 37.1100 +    if ( !key )
 37.1101 +    {
 37.1102 +        rc = -ENOMEM;
 37.1103 +        goto bad;
 37.1104 +    }
 37.1105 +    rc = next_entry(key, fp, len);
 37.1106 +    if ( rc < 0 )
 37.1107 +        goto bad;
 37.1108 +    key[len] = 0;
 37.1109 +
 37.1110 +    if ( len2 )
 37.1111 +    {
 37.1112 +        cladatum->comkey = xmalloc_array(char, len2 + 1);
 37.1113 +        if ( !cladatum->comkey )
 37.1114 +        {
 37.1115 +            rc = -ENOMEM;
 37.1116 +            goto bad;
 37.1117 +        }
 37.1118 +        rc = next_entry(cladatum->comkey, fp, len2);
 37.1119 +        if ( rc < 0 )
 37.1120 +            goto bad;
 37.1121 +        cladatum->comkey[len2] = 0;
 37.1122 +
 37.1123 +        cladatum->comdatum = hashtab_search(p->p_commons.table,
 37.1124 +                            cladatum->comkey);
 37.1125 +        if ( !cladatum->comdatum )
 37.1126 +        {
 37.1127 +            printk(KERN_ERR "security:  unknown common %s\n",
 37.1128 +                   cladatum->comkey);
 37.1129 +            rc = -EINVAL;
 37.1130 +            goto bad;
 37.1131 +        }
 37.1132 +    }
 37.1133 +    for ( i = 0; i < nel; i++ )
 37.1134 +    {
 37.1135 +        rc = perm_read(p, cladatum->permissions.table, fp);
 37.1136 +        if ( rc )
 37.1137 +            goto bad;
 37.1138 +    }
 37.1139 +
 37.1140 +    rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
 37.1141 +    if ( rc )
 37.1142 +        goto bad;
 37.1143 +
 37.1144 +    if ( p->policyvers >= POLICYDB_VERSION_VALIDATETRANS )
 37.1145 +    {
 37.1146 +        /* grab the validatetrans rules */
 37.1147 +        rc = next_entry(buf, fp, sizeof(u32));
 37.1148 +        if ( rc < 0 )
 37.1149 +            goto bad;
 37.1150 +        ncons = le32_to_cpu(buf[0]);
 37.1151 +        rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
 37.1152 +        if ( rc )
 37.1153 +            goto bad;
 37.1154 +    }
 37.1155 +
 37.1156 +    rc = hashtab_insert(h, key, cladatum);
 37.1157 +    if ( rc )
 37.1158 +        goto bad;
 37.1159 +
 37.1160 +    rc = 0;
 37.1161 +out:
 37.1162 +    return rc;
 37.1163 +bad:
 37.1164 +    class_destroy(key, cladatum, NULL);
 37.1165 +    goto out;
 37.1166 +}
 37.1167 +
 37.1168 +static int role_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1169 +{
 37.1170 +    char *key = NULL;
 37.1171 +    struct role_datum *role;
 37.1172 +    int rc;
 37.1173 +    __le32 buf[2];
 37.1174 +    u32 len;
 37.1175 +
 37.1176 +    role = xmalloc(struct role_datum);
 37.1177 +    if ( !role )
 37.1178 +    {
 37.1179 +        rc = -ENOMEM;
 37.1180 +        goto out;
 37.1181 +    }
 37.1182 +    memset(role, 0, sizeof(*role));
 37.1183 +
 37.1184 +    rc = next_entry(buf, fp, sizeof buf);
 37.1185 +    if ( rc < 0 )
 37.1186 +        goto bad;
 37.1187 +
 37.1188 +    len = le32_to_cpu(buf[0]);
 37.1189 +    role->value = le32_to_cpu(buf[1]);
 37.1190 +
 37.1191 +    key = xmalloc_array(char, len + 1);
 37.1192 +    if ( !key )
 37.1193 +    {
 37.1194 +        rc = -ENOMEM;
 37.1195 +        goto bad;
 37.1196 +    }
 37.1197 +    rc = next_entry(key, fp, len);
 37.1198 +    if ( rc < 0 )
 37.1199 +        goto bad;
 37.1200 +    key[len] = 0;
 37.1201 +
 37.1202 +    rc = ebitmap_read(&role->dominates, fp);
 37.1203 +    if ( rc )
 37.1204 +        goto bad;
 37.1205 +
 37.1206 +    rc = ebitmap_read(&role->types, fp);
 37.1207 +    if ( rc )
 37.1208 +        goto bad;
 37.1209 +
 37.1210 +    if ( strcmp(key, OBJECT_R) == 0 )
 37.1211 +    {
 37.1212 +        if ( role->value != OBJECT_R_VAL )
 37.1213 +        {
 37.1214 +            printk(KERN_ERR "Role %s has wrong value %d\n", OBJECT_R,
 37.1215 +                                                                role->value);
 37.1216 +            rc = -EINVAL;
 37.1217 +            goto bad;
 37.1218 +        }
 37.1219 +        rc = 0;
 37.1220 +        goto bad;
 37.1221 +    }
 37.1222 +
 37.1223 +    rc = hashtab_insert(h, key, role);
 37.1224 +    if ( rc )
 37.1225 +        goto bad;
 37.1226 +out:
 37.1227 +    return rc;
 37.1228 +bad:
 37.1229 +    role_destroy(key, role, NULL);
 37.1230 +    goto out;
 37.1231 +}
 37.1232 +
 37.1233 +static int type_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1234 +{
 37.1235 +    char *key = NULL;
 37.1236 +    struct type_datum *typdatum;
 37.1237 +    int rc;
 37.1238 +    __le32 buf[3];
 37.1239 +    u32 len;
 37.1240 +
 37.1241 +    typdatum = xmalloc(struct type_datum);
 37.1242 +    if ( !typdatum )
 37.1243 +    {
 37.1244 +        rc = -ENOMEM;
 37.1245 +        return rc;
 37.1246 +    }
 37.1247 +    memset(typdatum, 0, sizeof(*typdatum));
 37.1248 +
 37.1249 +    rc = next_entry(buf, fp, sizeof buf);
 37.1250 +    if ( rc < 0 )
 37.1251 +        goto bad;
 37.1252 +
 37.1253 +    len = le32_to_cpu(buf[0]);
 37.1254 +    typdatum->value = le32_to_cpu(buf[1]);
 37.1255 +    typdatum->primary = le32_to_cpu(buf[2]);
 37.1256 +
 37.1257 +    key = xmalloc_array(char, len + 1);
 37.1258 +    if ( !key )
 37.1259 +    {
 37.1260 +        rc = -ENOMEM;
 37.1261 +        goto bad;
 37.1262 +    }
 37.1263 +    rc = next_entry(key, fp, len);
 37.1264 +    if ( rc < 0 )
 37.1265 +        goto bad;
 37.1266 +    key[len] = 0;
 37.1267 +
 37.1268 +    rc = hashtab_insert(h, key, typdatum);
 37.1269 +    if ( rc )
 37.1270 +        goto bad;
 37.1271 +out:
 37.1272 +    return rc;
 37.1273 +bad:
 37.1274 +    type_destroy(key, typdatum, NULL);
 37.1275 +    goto out;
 37.1276 +}
 37.1277 +
 37.1278 +
 37.1279 +/*
 37.1280 + * Read a MLS level structure from a policydb binary
 37.1281 + * representation file.
 37.1282 + */
 37.1283 +static int mls_read_level(struct mls_level *lp, void *fp)
 37.1284 +{
 37.1285 +    __le32 buf[1];
 37.1286 +    int rc;
 37.1287 +
 37.1288 +    memset(lp, 0, sizeof(*lp));
 37.1289 +
 37.1290 +    rc = next_entry(buf, fp, sizeof buf);
 37.1291 +    if ( rc < 0 )
 37.1292 +    {
 37.1293 +        printk(KERN_ERR "security: mls: truncated level\n");
 37.1294 +        goto bad;
 37.1295 +    }
 37.1296 +    lp->sens = le32_to_cpu(buf[0]);
 37.1297 +
 37.1298 +    if ( ebitmap_read(&lp->cat, fp) )
 37.1299 +    {
 37.1300 +        printk(KERN_ERR "security: mls:  error reading level categories\n");
 37.1301 +        goto bad;
 37.1302 +    }
 37.1303 +    return 0;
 37.1304 +
 37.1305 +bad:
 37.1306 +    return -EINVAL;
 37.1307 +}
 37.1308 +
 37.1309 +static int user_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1310 +{
 37.1311 +    char *key = NULL;
 37.1312 +    struct user_datum *usrdatum;
 37.1313 +    int rc;
 37.1314 +    __le32 buf[2];
 37.1315 +    u32 len;
 37.1316 +
 37.1317 +    usrdatum = xmalloc(struct user_datum);
 37.1318 +    if ( !usrdatum )
 37.1319 +    {
 37.1320 +        rc = -ENOMEM;
 37.1321 +        goto out;
 37.1322 +    }
 37.1323 +    memset(usrdatum, 0, sizeof(*usrdatum));
 37.1324 +
 37.1325 +    rc = next_entry(buf, fp, sizeof buf);
 37.1326 +    if ( rc < 0 )
 37.1327 +        goto bad;
 37.1328 +
 37.1329 +    len = le32_to_cpu(buf[0]);
 37.1330 +    usrdatum->value = le32_to_cpu(buf[1]);
 37.1331 +
 37.1332 +    key = xmalloc_array(char, len + 1);
 37.1333 +    if ( !key )
 37.1334 +    {
 37.1335 +        rc = -ENOMEM;
 37.1336 +        goto bad;
 37.1337 +    }
 37.1338 +    rc = next_entry(key, fp, len);
 37.1339 +    if ( rc < 0 )
 37.1340 +        goto bad;
 37.1341 +    key[len] = 0;
 37.1342 +
 37.1343 +    rc = ebitmap_read(&usrdatum->roles, fp);
 37.1344 +    if ( rc )
 37.1345 +        goto bad;
 37.1346 +
 37.1347 +    if ( p->policyvers >= POLICYDB_VERSION_MLS )
 37.1348 +    {
 37.1349 +        rc = mls_read_range_helper(&usrdatum->range, fp);
 37.1350 +        if ( rc )
 37.1351 +            goto bad;
 37.1352 +        rc = mls_read_level(&usrdatum->dfltlevel, fp);
 37.1353 +        if ( rc )
 37.1354 +            goto bad;
 37.1355 +    }
 37.1356 +
 37.1357 +    rc = hashtab_insert(h, key, usrdatum);
 37.1358 +    if ( rc )
 37.1359 +        goto bad;
 37.1360 +out:
 37.1361 +    return rc;
 37.1362 +bad:
 37.1363 +    user_destroy(key, usrdatum, NULL);
 37.1364 +    goto out;
 37.1365 +}
 37.1366 +
 37.1367 +static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1368 +{
 37.1369 +    char *key = NULL;
 37.1370 +    struct level_datum *levdatum;
 37.1371 +    int rc;
 37.1372 +    __le32 buf[2];
 37.1373 +    u32 len;
 37.1374 +
 37.1375 +    levdatum = xmalloc(struct level_datum);
 37.1376 +    if ( !levdatum )
 37.1377 +    {
 37.1378 +        rc = -ENOMEM;
 37.1379 +        goto out;
 37.1380 +    }
 37.1381 +    memset(levdatum, 0, sizeof(*levdatum));
 37.1382 +
 37.1383 +    rc = next_entry(buf, fp, sizeof buf);
 37.1384 +    if ( rc < 0 )
 37.1385 +        goto bad;
 37.1386 +
 37.1387 +    len = le32_to_cpu(buf[0]);
 37.1388 +    levdatum->isalias = le32_to_cpu(buf[1]);
 37.1389 +
 37.1390 +    key = xmalloc_array(char, len + 1);
 37.1391 +    if ( !key )
 37.1392 +    {
 37.1393 +        rc = -ENOMEM;
 37.1394 +        goto bad;
 37.1395 +    }
 37.1396 +    rc = next_entry(key, fp, len);
 37.1397 +    if ( rc < 0 )
 37.1398 +        goto bad;
 37.1399 +    key[len] = 0;
 37.1400 +
 37.1401 +    levdatum->level = xmalloc(struct mls_level);
 37.1402 +    if ( !levdatum->level )
 37.1403 +    {
 37.1404 +        rc = -ENOMEM;
 37.1405 +        goto bad;
 37.1406 +    }
 37.1407 +    if ( mls_read_level(levdatum->level, fp) )
 37.1408 +    {
 37.1409 +        rc = -EINVAL;
 37.1410 +        goto bad;
 37.1411 +    }
 37.1412 +
 37.1413 +    rc = hashtab_insert(h, key, levdatum);
 37.1414 +    if ( rc )
 37.1415 +        goto bad;
 37.1416 +out:
 37.1417 +    return rc;
 37.1418 +bad:
 37.1419 +    sens_destroy(key, levdatum, NULL);
 37.1420 +    goto out;
 37.1421 +}
 37.1422 +
 37.1423 +static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
 37.1424 +{
 37.1425 +    char *key = NULL;
 37.1426 +    struct cat_datum *catdatum;
 37.1427 +    int rc;
 37.1428 +    __le32 buf[3];
 37.1429 +    u32 len;
 37.1430 +
 37.1431 +    catdatum = xmalloc(struct cat_datum);
 37.1432 +    if ( !catdatum )
 37.1433 +    {
 37.1434 +        rc = -ENOMEM;
 37.1435 +        goto out;
 37.1436 +    }
 37.1437 +    memset(catdatum, 0, sizeof(*catdatum));
 37.1438 +
 37.1439 +    rc = next_entry(buf, fp, sizeof buf);
 37.1440 +    if ( rc < 0 )
 37.1441 +        goto bad;
 37.1442 +
 37.1443 +    len = le32_to_cpu(buf[0]);
 37.1444 +    catdatum->value = le32_to_cpu(buf[1]);
 37.1445 +    catdatum->isalias = le32_to_cpu(buf[2]);
 37.1446 +
 37.1447 +    key = xmalloc_array(char, len + 1);
 37.1448 +    if ( !key )
 37.1449 +    {
 37.1450 +        rc = -ENOMEM;
 37.1451 +        goto bad;
 37.1452 +    }
 37.1453 +    rc = next_entry(key, fp, len);
 37.1454 +    if ( rc < 0 )
 37.1455 +        goto bad;
 37.1456 +    key[len] = 0;
 37.1457 +
 37.1458 +    rc = hashtab_insert(h, key, catdatum);
 37.1459 +    if ( rc )
 37.1460 +        goto bad;
 37.1461 +out:
 37.1462 +    return rc;
 37.1463 +
 37.1464 +bad:
 37.1465 +    cat_destroy(key, catdatum, NULL);
 37.1466 +    goto out;
 37.1467 +}
 37.1468 +
 37.1469 +static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
 37.1470 +{
 37.1471 +    common_read,
 37.1472 +    class_read,
 37.1473 +    role_read,
 37.1474 +    type_read,
 37.1475 +    user_read,
 37.1476 +    cond_read_bool,
 37.1477 +    sens_read,
 37.1478 +    cat_read,
 37.1479 +};
 37.1480 +
 37.1481 +extern int ss_initialized;
 37.1482 +
 37.1483 +/*
 37.1484 + * Read the configuration data from a policy database binary
 37.1485 + * representation file into a policy database structure.
 37.1486 + */
 37.1487 +int policydb_read(struct policydb *p, void *fp)
 37.1488 +{
 37.1489 +    struct role_allow *ra, *lra;
 37.1490 +    struct role_trans *tr, *ltr;
 37.1491 +    struct ocontext *l, *c /*, *newc*/;
 37.1492 +    int i, j, rc;
 37.1493 +    __le32 buf[8];
 37.1494 +    u32 len, /*len2,*/ config, nprim, nel /*, nel2*/;
 37.1495 +    char *policydb_str;
 37.1496 +    struct policydb_compat_info *info;
 37.1497 +    struct range_trans *rt, *lrt;
 37.1498 +
 37.1499 +    config = 0;
 37.1500 +    rc = policydb_init(p);
 37.1501 +    if ( rc )
 37.1502 +        goto out;
 37.1503 +
 37.1504 +    /* Read the magic number and string length. */
 37.1505 +    rc = next_entry(buf, fp, sizeof(u32)* 2);
 37.1506 +    if ( rc < 0 )
 37.1507 +        goto bad;
 37.1508 +
 37.1509 +    if ( le32_to_cpu(buf[0]) != POLICYDB_MAGIC )
 37.1510 +    {
 37.1511 +        printk(KERN_ERR "security:  policydb magic number 0x%x does "
 37.1512 +               "not match expected magic number 0x%x\n",
 37.1513 +               le32_to_cpu(buf[0]), POLICYDB_MAGIC);
 37.1514 +        goto bad;
 37.1515 +    }
 37.1516 +
 37.1517 +    len = le32_to_cpu(buf[1]);
 37.1518 +    if ( len != strlen(POLICYDB_STRING) )
 37.1519 +    {
 37.1520 +        printk(KERN_ERR "security:  policydb string length %d does not "
 37.1521 +               "match expected length %Zu\n",
 37.1522 +               len, (u32) strlen(POLICYDB_STRING));
 37.1523 +        goto bad;
 37.1524 +    }
 37.1525 +    policydb_str = xmalloc_array(char, len + 1);
 37.1526 +    if ( !policydb_str )
 37.1527 +    {
 37.1528 +        printk(KERN_ERR "security:  unable to allocate memory for policydb "
 37.1529 +               "string of length %d\n", len);
 37.1530 +        rc = -ENOMEM;
 37.1531 +        goto bad;
 37.1532 +    }
 37.1533 +    rc = next_entry(policydb_str, fp, len);
 37.1534 +    if ( rc < 0 )
 37.1535 +    {
 37.1536 +        printk(KERN_ERR "security:  truncated policydb string identifier\n");
 37.1537 +        xfree(policydb_str);
 37.1538 +        goto bad;
 37.1539 +    }
 37.1540 +    policydb_str[len] = 0;
 37.1541 +    if ( strcmp(policydb_str, POLICYDB_STRING) )
 37.1542 +    {
 37.1543 +        printk(KERN_ERR "security:  policydb string %s does not match "
 37.1544 +               "my string %s\n", policydb_str, POLICYDB_STRING);
 37.1545 +        xfree(policydb_str);
 37.1546 +        goto bad;
 37.1547 +    }
 37.1548 +    /* Done with policydb_str. */
 37.1549 +    xfree(policydb_str);
 37.1550 +    policydb_str = NULL;
 37.1551 +
 37.1552 +    /* Read the version, config, and table sizes. */
 37.1553 +    rc = next_entry(buf, fp, sizeof(u32)*4);
 37.1554 +    if ( rc < 0 )
 37.1555 +        goto bad;
 37.1556 +
 37.1557 +    p->policyvers = le32_to_cpu(buf[0]);
 37.1558 +    if ( p->policyvers < POLICYDB_VERSION_MIN ||
 37.1559 +                                        p->policyvers > POLICYDB_VERSION_MAX )
 37.1560 +    {
 37.1561 +            printk(KERN_ERR "security:  policydb version %d does not match "
 37.1562 +                   "my version range %d-%d\n",
 37.1563 +                   le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
 37.1564 +            goto bad;
 37.1565 +    }
 37.1566 +
 37.1567 +    if ( (le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS) )
 37.1568 +    {
 37.1569 +        if ( ss_initialized && !flask_mls_enabled )
 37.1570 +        {
 37.1571 +            printk(KERN_ERR "Cannot switch between non-MLS and MLS "
 37.1572 +                   "policies\n");
 37.1573 +            goto bad;
 37.1574 +        }
 37.1575 +        flask_mls_enabled = 1;
 37.1576 +        config |= POLICYDB_CONFIG_MLS;
 37.1577 +
 37.1578 +        if ( p->policyvers < POLICYDB_VERSION_MLS )
 37.1579 +        {
 37.1580 +            printk(KERN_ERR "security policydb version %d (MLS) "
 37.1581 +                   "not backwards compatible\n", p->policyvers);
 37.1582 +            goto bad;
 37.1583 +        }
 37.1584 +    }
 37.1585 +    else
 37.1586 +    {
 37.1587 +        if ( ss_initialized && flask_mls_enabled )
 37.1588 +        {
 37.1589 +            printk(KERN_ERR "Cannot switch between MLS and non-MLS "
 37.1590 +                   "policies\n");
 37.1591 +            goto bad;
 37.1592 +        }
 37.1593 +    }
 37.1594 +
 37.1595 +    info = policydb_lookup_compat(p->policyvers);
 37.1596 +    if ( !info )
 37.1597 +    {
 37.1598 +        printk(KERN_ERR "security:  unable to find policy compat info "
 37.1599 +               "for version %d\n", p->policyvers);
 37.1600 +        goto bad;
 37.1601 +    }
 37.1602 +
 37.1603 +    if ( le32_to_cpu(buf[2]) != info->sym_num ||
 37.1604 +                                        le32_to_cpu(buf[3]) != info->ocon_num )
 37.1605 +    {
 37.1606 +        printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
 37.1607 +               "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
 37.1608 +            le32_to_cpu(buf[3]),
 37.1609 +               info->sym_num, info->ocon_num);
 37.1610 +        goto bad;
 37.1611 +    }
 37.1612 +
 37.1613 +    for ( i = 0; i < info->sym_num; i++ )
 37.1614 +    {
 37.1615 +        rc = next_entry(buf, fp, sizeof(u32)*2);
 37.1616 +        if ( rc < 0 )
 37.1617 +            goto bad;
 37.1618 +        nprim = le32_to_cpu(buf[0]);
 37.1619 +        nel = le32_to_cpu(buf[1]);
 37.1620 +        for ( j = 0; j < nel; j++ )
 37.1621 +        {
 37.1622 +            rc = read_f[i](p, p->symtab[i].table, fp);
 37.1623 +            if ( rc )
 37.1624 +                goto bad;
 37.1625 +        }
 37.1626 +
 37.1627 +        p->symtab[i].nprim = nprim;
 37.1628 +    }
 37.1629 +
 37.1630 +    rc = avtab_read(&p->te_avtab, fp, p->policyvers);
 37.1631 +    if ( rc )
 37.1632 +        goto bad;
 37.1633 +
 37.1634 +    if ( p->policyvers >= POLICYDB_VERSION_BOOL )
 37.1635 +    {
 37.1636 +        rc = cond_read_list(p, fp);
 37.1637 +        if ( rc )
 37.1638 +            goto bad;
 37.1639 +    }
 37.1640 +
 37.1641 +    rc = next_entry(buf, fp, sizeof(u32));
 37.1642 +    if ( rc < 0 )
 37.1643 +        goto bad;
 37.1644 +    nel = le32_to_cpu(buf[0]);
 37.1645 +    ltr = NULL;
 37.1646 +    for ( i = 0; i < nel; i++ )
 37.1647 +    {
 37.1648 +        tr = xmalloc(struct role_trans);
 37.1649 +        if ( !tr )
 37.1650 +        {
 37.1651 +            rc = -ENOMEM;
 37.1652 +            goto bad;
 37.1653 +        }
 37.1654 +        memset(tr, 0, sizeof(*tr));
 37.1655 +        if ( ltr )
 37.1656 +            ltr->next = tr;
 37.1657 +        else
 37.1658 +            p->role_tr = tr;
 37.1659 +        rc = next_entry(buf, fp, sizeof(u32)*3);
 37.1660 +        if ( rc < 0 )
 37.1661 +            goto bad;
 37.1662 +        tr->role = le32_to_cpu(buf[0]);
 37.1663 +        tr->type = le32_to_cpu(buf[1]);
 37.1664 +        tr->new_role = le32_to_cpu(buf[2]);
 37.1665 +        ltr = tr;
 37.1666 +    }
 37.1667 +
 37.1668 +    rc = next_entry(buf, fp, sizeof(u32));
 37.1669 +    if ( rc < 0 )
 37.1670 +        goto bad;
 37.1671 +    nel = le32_to_cpu(buf[0]);
 37.1672 +    lra = NULL;
 37.1673 +    for ( i = 0; i < nel; i++ )
 37.1674 +    {
 37.1675 +        ra = xmalloc(struct role_allow);
 37.1676 +        if ( !ra )
 37.1677 +        {
 37.1678 +            rc = -ENOMEM;
 37.1679 +            goto bad;
 37.1680 +        }
 37.1681 +        memset(ra, 0, sizeof(*ra));
 37.1682 +        if ( lra )
 37.1683 +            lra->next = ra;
 37.1684 +        else
 37.1685 +            p->role_allow = ra;
 37.1686 +        rc = next_entry(buf, fp, sizeof(u32)*2);
 37.1687 +        if ( rc < 0 )
 37.1688 +            goto bad;
 37.1689 +        ra->role = le32_to_cpu(buf[0]);
 37.1690 +        ra->new_role = le32_to_cpu(buf[1]);
 37.1691 +        lra = ra;
 37.1692 +    }
 37.1693 +
 37.1694 +    rc = policydb_index_classes(p);
 37.1695 +    if ( rc )
 37.1696 +        goto bad;
 37.1697 +
 37.1698 +    rc = policydb_index_others(p);
 37.1699 +    if ( rc )
 37.1700 +        goto bad;
 37.1701 +
 37.1702 +    for ( i = 0; i < info->ocon_num; i++ )
 37.1703 +    {
 37.1704 +        rc = next_entry(buf, fp, sizeof(u32));
 37.1705 +        if ( rc < 0 )
 37.1706 +            goto bad;
 37.1707 +        nel = le32_to_cpu(buf[0]);
 37.1708 +        l = NULL;
 37.1709 +        for ( j = 0; j < nel; j++ )
 37.1710 +        {
 37.1711 +            c = xmalloc(struct ocontext);
 37.1712 +            if ( !c )
 37.1713 +            {
 37.1714 +                rc = -ENOMEM;
 37.1715 +                goto bad;
 37.1716 +            }
 37.1717 +            memset(c, 0, sizeof(*c));
 37.1718 +            if ( l )
 37.1719 +                l->next = c;
 37.1720 +            else
 37.1721 +                p->ocontexts[i] = c;
 37.1722 +            l = c;
 37.1723 +            rc = -EINVAL;
 37.1724 +            switch ( i )
 37.1725 +            {
 37.1726 +                case OCON_ISID:
 37.1727 +                    rc = next_entry(buf, fp, sizeof(u32));
 37.1728 +                    if ( rc < 0 )
 37.1729 +                        goto bad;
 37.1730 +                    c->sid[0] = le32_to_cpu(buf[0]);
 37.1731 +                    rc = context_read_and_validate(&c->context[0], p, fp);
 37.1732 +                    if ( rc )
 37.1733 +                        goto bad;
 37.1734 +                break;
 37.1735 +            }
 37.1736 +        }
 37.1737 +    }
 37.1738 +
 37.1739 +    rc = next_entry(buf, fp, sizeof(u32));
 37.1740 +    if ( rc < 0 )
 37.1741 +        goto bad;
 37.1742 +    nel = le32_to_cpu(buf[0]);
 37.1743 +
 37.1744 +    if ( p->policyvers >= POLICYDB_VERSION_MLS )
 37.1745 +    {
 37.1746 +        rc = next_entry(buf, fp, sizeof(u32));
 37.1747 +        if ( rc < 0 )
 37.1748 +            goto bad;
 37.1749 +        nel = le32_to_cpu(buf[0]);
 37.1750 +        lrt = NULL;
 37.1751 +        for ( i = 0; i < nel; i++ )
 37.1752 +        {
 37.1753 +            rt = xmalloc(struct range_trans);
 37.1754 +            if ( !rt )
 37.1755 +            {
 37.1756 +                rc = -ENOMEM;
 37.1757 +                goto bad;
 37.1758 +            }
 37.1759 +            memset(rt, 0, sizeof(*rt));
 37.1760 +            if ( lrt )
 37.1761 +                lrt->next = rt;
 37.1762 +            else
 37.1763 +                p->range_tr = rt;
 37.1764 +            rc = next_entry(buf, fp, (sizeof(u32) * 2));
 37.1765 +            if ( rc < 0 )
 37.1766 +                goto bad;
 37.1767 +            rt->dom = le32_to_cpu(buf[0]);
 37.1768 +            rt->type = le32_to_cpu(buf[1]);
 37.1769 +            rc = mls_read_range_helper(&rt->range, fp);
 37.1770 +            if ( rc )
 37.1771 +                goto bad;
 37.1772 +            lrt = rt;
 37.1773 +        }
 37.1774 +    }
 37.1775 +
 37.1776 +    p->type_attr_map = xmalloc_array(struct ebitmap, p->p_types.nprim);
 37.1777 +    if ( !p->type_attr_map )
 37.1778 +        goto bad;
 37.1779 +
 37.1780 +    for ( i = 0; i < p->p_types.nprim; i++ )
 37.1781 +    {
 37.1782 +        ebitmap_init(&p->type_attr_map[i]);
 37.1783 +        if ( p->policyvers >= POLICYDB_VERSION_AVTAB )
 37.1784 +        {
 37.1785 +            if ( ebitmap_read(&p->type_attr_map[i], fp) )
 37.1786 +                goto bad;
 37.1787 +        }
 37.1788 +        /* add the type itself as the degenerate case */
 37.1789 +        if ( ebitmap_set_bit(&p->type_attr_map[i], i, 1) )
 37.1790 +                goto bad;
 37.1791 +    }
 37.1792 +
 37.1793 +    rc = 0;
 37.1794 +out:
 37.1795 +    return rc;
 37.1796 +bad:
 37.1797 +    if ( !rc )
 37.1798 +        rc = -EINVAL;
 37.1799 +    policydb_destroy(p);
 37.1800 +    goto out;
 37.1801 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/xen/xsm/flask/ss/policydb.h	Fri Aug 31 11:31:18 2007 +0100
    38.3 @@ -0,0 +1,257 @@
    38.4 +/*
    38.5 + * A policy database (policydb) specifies the
    38.6 + * configuration data for the security policy.
    38.7 + *
    38.8 + * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
    38.9 + */
   38.10 +
   38.11 +/*
   38.12 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   38.13 + *
   38.14 + *    Support for enhanced MLS infrastructure.
   38.15 + *
   38.16 + * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
   38.17 + *
   38.18 + *     Added conditional policy language extensions
   38.19 + *
   38.20 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   38.21 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
   38.22 + *    This program is free software; you can redistribute it and/or modify
   38.23 + *      it under the terms of the GNU General Public License as published by
   38.24 + *    the Free Software Foundation, version 2.
   38.25 + */
   38.26 +
   38.27 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   38.28 +
   38.29 +#ifndef _SS_POLICYDB_H_
   38.30 +#define _SS_POLICYDB_H_
   38.31 +
   38.32 +#include "symtab.h"
   38.33 +#include "avtab.h"
   38.34 +#include "sidtab.h"
   38.35 +#include "context.h"
   38.36 +#include "constraint.h"
   38.37 +
   38.38 +/*
   38.39 + * A datum type is defined for each kind of symbol
   38.40 + * in the configuration data:  individual permissions,
   38.41 + * common prefixes for access vectors, classes,
   38.42 + * users, roles, types, sensitivities, categories, etc.
   38.43 + */
   38.44 +
   38.45 +/* Permission attributes */
   38.46 +struct perm_datum {
   38.47 +    u32 value;        /* permission bit + 1 */
   38.48 +};
   38.49 +
   38.50 +/* Attributes of a common prefix for access vectors */
   38.51 +struct common_datum {
   38.52 +    u32 value;            /* internal common value */
   38.53 +    struct symtab permissions;    /* common permissions */
   38.54 +};
   38.55 +
   38.56 +/* Class attributes */
   38.57 +struct class_datum {
   38.58 +    u32 value;            /* class value */
   38.59 +    char *comkey;            /* common name */
   38.60 +    struct common_datum *comdatum;    /* common datum */
   38.61 +    struct symtab permissions;    /* class-specific permission symbol table */
   38.62 +    struct constraint_node *constraints;    /* constraints on class permissions */
   38.63 +    struct constraint_node *validatetrans;    /* special transition rules */
   38.64 +};
   38.65 +
   38.66 +/* Role attributes */
   38.67 +struct role_datum {
   38.68 +    u32 value;            /* internal role value */
   38.69 +    struct ebitmap dominates;    /* set of roles dominated by this role */
   38.70 +    struct ebitmap types;        /* set of authorized types for role */
   38.71 +};
   38.72 +
   38.73 +struct role_trans {
   38.74 +    u32 role;        /* current role */
   38.75 +    u32 type;        /* program executable type */
   38.76 +    u32 new_role;        /* new role */
   38.77 +    struct role_trans *next;
   38.78 +};
   38.79 +
   38.80 +struct role_allow {
   38.81 +    u32 role;        /* current role */
   38.82 +    u32 new_role;        /* new role */
   38.83 +    struct role_allow *next;
   38.84 +};
   38.85 +
   38.86 +/* Type attributes */
   38.87 +struct type_datum {
   38.88 +    u32 value;        /* internal type value */
   38.89 +    unsigned char primary;    /* primary name? */
   38.90 +};
   38.91 +
   38.92 +/* User attributes */
   38.93 +struct user_datum {
   38.94 +    u32 value;            /* internal user value */
   38.95 +    struct ebitmap roles;        /* set of authorized roles for user */
   38.96 +    struct mls_range range;        /* MLS range (min - max) for user */
   38.97 +    struct mls_level dfltlevel;    /* default login MLS level for user */
   38.98 +};
   38.99 +
  38.100 +
  38.101 +/* Sensitivity attributes */
  38.102 +struct level_datum {
  38.103 +    struct mls_level *level;    /* sensitivity and associated categories */
  38.104 +    unsigned char isalias;    /* is this sensitivity an alias for another? */
  38.105 +};
  38.106 +
  38.107 +/* Category attributes */
  38.108 +struct cat_datum {
  38.109 +    u32 value;        /* internal category bit + 1 */
  38.110 +    unsigned char isalias;  /* is this category an alias for another? */
  38.111 +};
  38.112 +
  38.113 +struct range_trans {
  38.114 +    u32 dom;            /* current process domain */
  38.115 +    u32 type;            /* program executable type */
  38.116 +    struct mls_range range;        /* new range */
  38.117 +    struct range_trans *next;
  38.118 +};
  38.119 +
  38.120 +/* Boolean data type */
  38.121 +struct cond_bool_datum {
  38.122 +    __u32 value;        /* internal type value */
  38.123 +    int state;
  38.124 +};
  38.125 +
  38.126 +struct cond_node;
  38.127 +
  38.128 +/*
  38.129 + * The configuration data includes security contexts for
  38.130 + * initial SIDs, unlabeled file systems, TCP and UDP port numbers,
  38.131 + * network interfaces, and nodes.  This structure stores the
  38.132 + * relevant data for one such entry.  Entries of the same kind
  38.133 + * (e.g. all initial SIDs) are linked together into a list.
  38.134 + */
  38.135 +struct ocontext {
  38.136 +    union {
  38.137 +        char *name;    /* name of initial SID, fs, netif, fstype, path */
  38.138 +        int pirq;
  38.139 +        int virq;
  38.140 +        int vcpu;
  38.141 +        u32 ioport;
  38.142 +        unsigned long iomem;
  38.143 +    } u;
  38.144 +    struct context context[2];    /* security context(s) */
  38.145 +    u32 sid[2];    /* SID(s) */
  38.146 +    struct ocontext *next;
  38.147 +};
  38.148 +
  38.149 +/* symbol table array indices */
  38.150 +#define SYM_COMMONS 0
  38.151 +#define SYM_CLASSES 1
  38.152 +#define SYM_ROLES   2
  38.153 +#define SYM_TYPES   3
  38.154 +#define SYM_USERS   4
  38.155 +#define SYM_BOOLS   5
  38.156 +#define SYM_LEVELS  6
  38.157 +#define SYM_CATS    7
  38.158 +#define SYM_NUM     8
  38.159 +
  38.160 +/* object context array indices */
  38.161 +#define OCON_ISID    0    /* initial SIDs */
  38.162 +#define OCON_PIRQ    1    /* physical irqs */
  38.163 +#define OCON_VIRQ    2    /* virtual irqs */
  38.164 +#define OCON_VCPU    3    /* virtual cpus */
  38.165 +#define OCON_IOPORT  4    /* io ports */
  38.166 +#define OCON_IOMEM   5    /* io memory */
  38.167 +#define OCON_DUMMY   6
  38.168 +#define OCON_NUM     7
  38.169 +
  38.170 +/* The policy database */
  38.171 +struct policydb {
  38.172 +    /* symbol tables */
  38.173 +    struct symtab symtab[SYM_NUM];
  38.174 +#define p_commons symtab[SYM_COMMONS]
  38.175 +#define p_classes symtab[SYM_CLASSES]
  38.176 +#define p_roles symtab[SYM_ROLES]
  38.177 +#define p_types symtab[SYM_TYPES]
  38.178 +#define p_users symtab[SYM_USERS]
  38.179 +#define p_bools symtab[SYM_BOOLS]
  38.180 +#define p_levels symtab[SYM_LEVELS]
  38.181 +#define p_cats symtab[SYM_CATS]
  38.182 +
  38.183 +    /* symbol names indexed by (value - 1) */
  38.184 +    char **sym_val_to_name[SYM_NUM];
  38.185 +#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
  38.186 +#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
  38.187 +#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
  38.188 +#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
  38.189 +#define p_user_val_to_name sym_val_to_name[SYM_USERS]
  38.190 +#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
  38.191 +#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
  38.192 +#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
  38.193 +
  38.194 +    /* class, role, and user attributes indexed by (value - 1) */
  38.195 +    struct class_datum **class_val_to_struct;
  38.196 +    struct role_datum **role_val_to_struct;
  38.197 +    struct user_datum **user_val_to_struct;
  38.198 +
  38.199 +    /* type enforcement access vectors and transitions */
  38.200 +    struct avtab te_avtab;
  38.201 +
  38.202 +    /* role transitions */
  38.203 +    struct role_trans *role_tr;
  38.204 +
  38.205 +    /* bools indexed by (value - 1) */
  38.206 +    struct cond_bool_datum **bool_val_to_struct;
  38.207 +    /* type enforcement conditional access vectors and transitions */
  38.208 +    struct avtab te_cond_avtab;
  38.209 +    /* linked list indexing te_cond_avtab by conditional */
  38.210 +    struct cond_node* cond_list;
  38.211 +
  38.212 +    /* role allows */
  38.213 +    struct role_allow *role_allow;
  38.214 +
  38.215 +    /* security contexts of initial SIDs, unlabeled file systems,
  38.216 +       TCP or UDP port numbers, network interfaces and nodes */
  38.217 +    struct ocontext *ocontexts[OCON_NUM];
  38.218 +
  38.219 +    /* range transitions */
  38.220 +    struct range_trans *range_tr;
  38.221 +
  38.222 +    /* type -> attribute reverse mapping */
  38.223 +    struct ebitmap *type_attr_map;
  38.224 +
  38.225 +    unsigned int policyvers;
  38.226 +};
  38.227 +
  38.228 +extern void policydb_destroy(struct policydb *p);
  38.229 +extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
  38.230 +extern int policydb_context_isvalid(struct policydb *p, struct context *c);
  38.231 +extern int policydb_read(struct policydb *p, void *fp);
  38.232 +
  38.233 +#define PERM_SYMTAB_SIZE 32
  38.234 +
  38.235 +#define POLICYDB_CONFIG_MLS    1
  38.236 +
  38.237 +#define OBJECT_R "object_r"
  38.238 +#define OBJECT_R_VAL 1
  38.239 +
  38.240 +#define POLICYDB_MAGIC FLASK_MAGIC
  38.241 +#define POLICYDB_STRING "SE Linux"
  38.242 +
  38.243 +struct policy_file {
  38.244 +    char *data;
  38.245 +    size_t len;
  38.246 +};
  38.247 +
  38.248 +static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
  38.249 +{
  38.250 +    if ( bytes > fp->len )
  38.251 +        return -EINVAL;
  38.252 +
  38.253 +    memcpy(buf, fp->data, bytes);
  38.254 +    fp->data += bytes;
  38.255 +    fp->len -= bytes;
  38.256 +    return 0;
  38.257 +}
  38.258 +
  38.259 +#endif    /* _SS_POLICYDB_H_ */
  38.260 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/xen/xsm/flask/ss/services.c	Fri Aug 31 11:31:18 2007 +0100
    39.3 @@ -0,0 +1,1657 @@
    39.4 +/*
    39.5 + * Implementation of the security services.
    39.6 + *
    39.7 + * Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
    39.8 + *           James Morris <jmorris@redhat.com>
    39.9 + *
   39.10 + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
   39.11 + *
   39.12 + *    Support for enhanced MLS infrastructure.
   39.13 + *
   39.14 + * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
   39.15 + *
   39.16 + *     Added conditional policy language extensions
   39.17 + *
   39.18 + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
   39.19 + * Copyright (C) 2003 - 2004 Tresys Technology, LLC
   39.20 + * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
   39.21 + *    This program is free software; you can redistribute it and/or modify
   39.22 + *      it under the terms of the GNU General Public License as published by
   39.23 + *    the Free Software Foundation, version 2.
   39.24 + */
   39.25 +
   39.26 +/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
   39.27 +
   39.28 +#include <xen/lib.h>
   39.29 +#include <xen/xmalloc.h>
   39.30 +#include <xen/string.h>
   39.31 +#include <xen/spinlock.h>
   39.32 +#include <xen/errno.h>
   39.33 +#include "flask.h"
   39.34 +#include "avc.h"
   39.35 +#include "avc_ss.h"
   39.36 +#include "security.h"
   39.37 +#include "context.h"
   39.38 +#include "policydb.h"
   39.39 +#include "sidtab.h"
   39.40 +#include "services.h"
   39.41 +#include "conditional.h"
   39.42 +#include "mls.h"
   39.43 +
   39.44 +unsigned int policydb_loaded_version;
   39.45 +
   39.46 +static DEFINE_RWLOCK(policy_rwlock);
   39.47 +#define POLICY_RDLOCK read_lock(&policy_rwlock)
   39.48 +#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
   39.49 +#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
   39.50 +#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
   39.51 +
   39.52 +static DEFINE_SPINLOCK(load_sem);
   39.53 +#define LOAD_LOCK spin_lock(&load_sem)
   39.54 +#define LOAD_UNLOCK spin_unlock(&load_sem)
   39.55 +
   39.56 +static struct sidtab sidtab;
   39.57 +struct policydb policydb;
   39.58 +int ss_initialized = 0;
   39.59 +
   39.60 +/*
   39.61 + * The largest sequence number that has been used when
   39.62 + * providing an access decision to the access vector cache.
   39.63 + * The sequence number only changes when a policy change
   39.64 + * occurs.
   39.65 + */
   39.66 +static u32 latest_granting = 0;
   39.67 +
   39.68 +/* Forward declaration. */
   39.69 +static int context_struct_to_string(struct context *context, char **scontext,
   39.70 +                                                            u32 *scontext_len);
   39.71 +
   39.72 +/*
   39.73 + * Return the boolean value of a constraint expression
   39.74 + * when it is applied to the specified source and target
   39.75 + * security contexts.
   39.76 + *
   39.77 + * xcontext is a special beast...  It is used by the validatetrans rules
   39.78 + * only.  For these rules, scontext is the context before the transition,
   39.79 + * tcontext is the context after the transition, and xcontext is the context
   39.80 + * of the process performing the transition.  All other callers of
   39.81 + * constraint_expr_eval should pass in NULL for xcontext.
   39.82 + */
   39.83 +static int constraint_expr_eval(struct context *scontext,
   39.84 +                            struct context *tcontext, struct context *xcontext, 
   39.85 +                                                struct constraint_expr *cexpr)
   39.86 +{
   39.87 +    u32 val1, val2;
   39.88 +    struct context *c;
   39.89 +    struct role_datum *r1, *r2;
   39.90 +    struct mls_level *l1, *l2;
   39.91 +    struct constraint_expr *e;
   39.92 +    int s[CEXPR_MAXDEPTH];
   39.93 +    int sp = -1;
   39.94 +
   39.95 +    for ( e = cexpr; e; e = e->next )
   39.96 +    {
   39.97 +        switch ( e->expr_type )
   39.98 +        {
   39.99 +            case CEXPR_NOT:
  39.100 +                BUG_ON(sp < 0);
  39.101 +                s[sp] = !s[sp];
  39.102 +            break;
  39.103 +            case CEXPR_AND:
  39.104 +                BUG_ON(sp < 1);
  39.105 +                sp--;
  39.106 +                s[sp] &= s[sp+1];
  39.107 +            break;
  39.108 +            case CEXPR_OR:
  39.109 +                BUG_ON(sp < 1);
  39.110 +                sp--;
  39.111 +                s[sp] |= s[sp+1];
  39.112 +            break;
  39.113 +            case CEXPR_ATTR:
  39.114 +                if ( sp == (CEXPR_MAXDEPTH-1) )
  39.115 +                    return 0;
  39.116 +            switch ( e->attr )
  39.117 +            {
  39.118 +                case CEXPR_USER:
  39.119 +                    val1 = scontext->user;
  39.120 +                    val2 = tcontext->user;
  39.121 +                    break;
  39.122 +                case CEXPR_TYPE:
  39.123 +                    val1 = scontext->type;
  39.124 +                    val2 = tcontext->type;
  39.125 +                    break;
  39.126 +                case CEXPR_ROLE:
  39.127 +                    val1 = scontext->role;
  39.128 +                    val2 = tcontext->role;
  39.129 +                    r1 = policydb.role_val_to_struct[val1 - 1];
  39.130 +                    r2 = policydb.role_val_to_struct[val2 - 1];
  39.131 +                switch ( e->op )
  39.132 +                {
  39.133 +                    case CEXPR_DOM:
  39.134 +                        s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
  39.135 +                    continue;
  39.136 +                    case CEXPR_DOMBY:
  39.137 +                        s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
  39.138 +                    continue;
  39.139 +                    case CEXPR_INCOMP:
  39.140 +                        s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
  39.141 +                                         val2 - 1) &&
  39.142 +                                !ebitmap_get_bit(&r2->dominates,
  39.143 +                                         val1 - 1) );
  39.144 +                    continue;
  39.145 +                    default:
  39.146 +                    break;
  39.147 +                }
  39.148 +                break;
  39.149 +                case CEXPR_L1L2:
  39.150 +                    l1 = &(scontext->range.level[0]);
  39.151 +                    l2 = &(tcontext->range.level[0]);
  39.152 +                    goto mls_ops;
  39.153 +                case CEXPR_L1H2:
  39.154 +                    l1 = &(scontext->range.level[0]);
  39.155 +                    l2 = &(tcontext->range.level[1]);
  39.156 +                    goto mls_ops;
  39.157 +                case CEXPR_H1L2:
  39.158 +                    l1 = &(scontext->range.level[1]);
  39.159 +                    l2 = &(tcontext->range.level[0]);
  39.160 +                    goto mls_ops;
  39.161 +                case CEXPR_H1H2:
  39.162 +                    l1 = &(scontext->range.level[1]);
  39.163 +                    l2 = &(tcontext->range.level[1]);
  39.164 +                    goto mls_ops;
  39.165 +                case CEXPR_L1H1:
  39.166 +                    l1 = &(scontext->range.level[0]);
  39.167 +                    l2 = &(scontext->range.level[1]);
  39.168 +                    goto mls_ops;
  39.169 +                case CEXPR_L2H2:
  39.170 +                    l1 = &(tcontext->range.level[0]);
  39.171 +                    l2 = &(tcontext->range.level[1]);
  39.172 +                    goto mls_ops;
  39.173 +mls_ops:
  39.174 +            switch ( e->op )
  39.175 +            {
  39.176 +                case CEXPR_EQ:
  39.177 +                    s[++sp] = mls_level_eq(l1, l2);
  39.178 +                continue;
  39.179 +                case CEXPR_NEQ:
  39.180 +                    s[++sp] = !mls_level_eq(l1, l2);
  39.181 +                continue;
  39.182 +                case CEXPR_DOM:
  39.183 +                    s[++sp] = mls_level_dom(l1, l2);
  39.184 +                continue;
  39.185 +                case CEXPR_DOMBY:
  39.186 +                    s[++sp] = mls_level_dom(l2, l1);
  39.187 +                continue;
  39.188 +                case CEXPR_INCOMP:
  39.189 +                    s[++sp] = mls_level_incomp(l2, l1);
  39.190 +                continue;
  39.191 +                default:
  39.192 +                    BUG();
  39.193 +                    return 0;
  39.194 +            }
  39.195 +            break;
  39.196 +            default:
  39.197 +                BUG();
  39.198 +                return 0;
  39.199 +            }
  39.200 +
  39.201 +            switch ( e->op )
  39.202 +            {
  39.203 +                case CEXPR_EQ:
  39.204 +                    s[++sp] = (val1 == val2);
  39.205 +                break;
  39.206 +                case CEXPR_NEQ:
  39.207 +                    s[++sp] = (val1 != val2);
  39.208 +                break;
  39.209 +                default:
  39.210 +                    BUG();
  39.211 +                    return 0;
  39.212 +            }
  39.213 +            break;
  39.214 +            case CEXPR_NAMES:
  39.215 +                if ( sp == (CEXPR_MAXDEPTH-1) )
  39.216 +                    return 0;
  39.217 +                c = scontext;
  39.218 +                if ( e->attr & CEXPR_TARGET )
  39.219 +                    c = tcontext;
  39.220 +                else if ( e->attr & CEXPR_XTARGET )
  39.221 +                {
  39.222 +                    c = xcontext;
  39.223 +                    if ( !c )
  39.224 +                    {
  39.225 +                        BUG();
  39.226 +                        return 0;
  39.227 +                    }
  39.228 +                }
  39.229 +                if ( e->attr & CEXPR_USER )
  39.230 +                    val1 = c->user;
  39.231 +                else if ( e->attr & CEXPR_ROLE )
  39.232 +                    val1 = c->role;
  39.233 +                else if ( e->attr & CEXPR_TYPE )
  39.234 +                    val1 = c->type;
  39.235 +                else
  39.236 +                {
  39.237 +                    BUG();
  39.238 +                    return 0;
  39.239 +                }
  39.240 +
  39.241 +            switch ( e->op )
  39.242 +            {
  39.243 +                case CEXPR_EQ:
  39.244 +                    s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
  39.245 +                break;
  39.246 +                case CEXPR_NEQ:
  39.247 +                    s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
  39.248 +                break;
  39.249 +                default:
  39.250 +                    BUG();
  39.251 +                    return 0;
  39.252 +            }
  39.253 +            break;
  39.254 +            default:
  39.255 +                BUG();
  39.256 +                return 0;
  39.257 +        }
  39.258 +    }
  39.259 +
  39.260 +    BUG_ON(sp != 0);
  39.261 +    return s[0];
  39.262 +}
  39.263 +
  39.264 +/*
  39.265 + * Compute access vectors based on a context structure pair for
  39.266 + * the permissions in a particular class.
  39.267 + */
  39.268 +static int context_struct_compute_av(struct context *scontext,
  39.269 +                            struct context *tcontext, u16 tclass, u32 requested, 
  39.270 +                                                        struct av_decision *avd)
  39.271 +{
  39.272 +    struct constraint_node *constraint;
  39.273 +    struct role_allow *ra;
  39.274 +    struct avtab_key avkey;
  39.275 +    struct avtab_node *node;
  39.276 +    struct class_datum *tclass_datum;
  39.277 +    struct ebitmap *sattr, *tattr;
  39.278 +    struct ebitmap_node *snode, *tnode;
  39.279 +    unsigned int i, j;
  39.280 +
  39.281 +    if ( !tclass || tclass > policydb.p_classes.nprim )
  39.282 +    {
  39.283 +        printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
  39.284 +               tclass);
  39.285 +        return -EINVAL;
  39.286 +    }
  39.287 +    tclass_datum = policydb.class_val_to_struct[tclass - 1];
  39.288 +
  39.289 +    /*
  39.290 +     * Initialize the access vectors to the default values.
  39.291 +     */
  39.292 +    avd->allowed = 0;
  39.293 +    avd->decided = 0xffffffff;
  39.294 +    avd->auditallow = 0;
  39.295 +    avd->auditdeny = 0xffffffff;
  39.296 +    avd->seqno = latest_granting;
  39.297 +
  39.298 +    /*
  39.299 +     * If a specific type enforcement rule was defined for
  39.300 +     * this permission check, then use it.
  39.301 +     */
  39.302 +    avkey.target_class = tclass;
  39.303 +    avkey.specified = AVTAB_AV;
  39.304 +    sattr = &policydb.type_attr_map[scontext->type - 1];
  39.305 +    tattr = &policydb.type_attr_map[tcontext->type - 1];
  39.306 +    ebitmap_for_each_bit(sattr, snode, i)
  39.307 +    {
  39.308 +        if ( !ebitmap_node_get_bit(snode, i) )
  39.309 +            continue;
  39.310 +        ebitmap_for_each_bit(tattr, tnode, j)
  39.311 +        {
  39.312 +            if ( !ebitmap_node_get_bit(tnode, j) )
  39.313 +                continue;
  39.314 +            avkey.source_type = i + 1;
  39.315 +            avkey.target_type = j + 1;
  39.316 +            for ( node = avtab_search_node(&policydb.te_avtab, &avkey);
  39.317 +                 node != NULL;
  39.318 +                 node = avtab_search_node_next(node, avkey.specified) )
  39.319 +            {
  39.320 +                if ( node->key.specified == AVTAB_ALLOWED )
  39.321 +                    avd->allowed |= node->datum.data;
  39.322 +                else if ( node->key.specified == AVTAB_AUDITALLOW )
  39.323 +                    avd->auditallow |= node->datum.data;
  39.324 +                else if ( node->key.specified == AVTAB_AUDITDENY )
  39.325 +                    avd->auditdeny &= node->datum.data;
  39.326 +            }
  39.327 +
  39.328 +            /* Check conditional av table for additional permissions */
  39.329 +            cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
  39.330 +
  39.331 +        }
  39.332 +    }
  39.333 +
  39.334 +    /*
  39.335 +     * Remove any permissions prohibited by a constraint (this includes
  39.336 +     * the MLS policy).
  39.337 +     */
  39.338 +    constraint = tclass_datum->constraints;
  39.339 +    while ( constraint )
  39.340 +    {
  39.341 +        if ( (constraint->permissions & (avd->allowed) ) &&
  39.342 +            !constraint_expr_eval(scontext, tcontext, NULL, constraint->expr))
  39.343 +        {
  39.344 +            avd->allowed = (avd->allowed) & ~(constraint->permissions);
  39.345 +        }
  39.346 +        constraint = constraint->next;
  39.347 +    }
  39.348 +
  39.349 +    /*
  39.350 +     * If checking process transition permission and the
  39.351 +     * role is changing, then check the (current_role, new_role)
  39.352 +     * pair.
  39.353 +     */
  39.354 +    if ( tclass == SECCLASS_DOMAIN &&
  39.355 +/* removed until future dynamic domain capability
  39.356 +        (avd->allowed & (DOMAIN__TRANSITION | DOMAIN__DYNTRANSITION)) &&
  39.357 +*/
  39.358 +                                            scontext->role != tcontext->role )
  39.359 +        {
  39.360 +        for ( ra = policydb.role_allow; ra; ra = ra->next )
  39.361 +        {
  39.362 +            if ( scontext->role == ra->role && tcontext->role == ra->new_role )
  39.363 +                break;
  39.364 +        }
  39.365 +/* removed until future dynamic domain capability    
  39.366 +        if (!ra)
  39.367 +            avd->allowed = (avd->allowed) & ~(DOMAIN__TRANSITION |
  39.368 +                                            DOMAIN__DYNTRANSITION);
  39.369 +*/
  39.370 +    }
  39.371 +
  39.372 +    return 0;
  39.373 +}
  39.374 +
  39.375 +static int security_validtrans_handle_fail(struct context *ocontext,
  39.376 +                struct context *ncontext, struct context *tcontext, u16 tclass)
  39.377 +{
  39.378 +    char *o = NULL, *n = NULL, *t = NULL;
  39.379 +    u32 olen, nlen, tlen;
  39.380 +
  39.381 +    if ( context_struct_to_string(ocontext, &o, &olen) < 0 )
  39.382 +        goto out;
  39.383 +    if ( context_struct_to_string(ncontext, &n, &nlen) < 0 )
  39.384 +        goto out;
  39.385 +    if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
  39.386 +        goto out;
  39.387 +    printk("security_validate_transition:  denied for"
  39.388 +              " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
  39.389 +              o, n, t, policydb.p_class_val_to_name[tclass-1]);
  39.390 +out:
  39.391 +    xfree(o);
  39.392 +    xfree(n);
  39.393 +    xfree(t);
  39.394 +
  39.395 +    if ( !flask_enforcing )
  39.396 +        return 0;
  39.397 +    return -EPERM;
  39.398 +}
  39.399 +
  39.400 +int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
  39.401 +                                 u16 tclass)
  39.402 +{
  39.403 +    struct context *ocontext;
  39.404 +    struct context *ncontext;
  39.405 +    struct context *tcontext;
  39.406 +    struct class_datum *tclass_datum;
  39.407 +    struct constraint_node *constraint;
  39.408 +    int rc = 0;
  39.409 +
  39.410 +    if ( !ss_initialized )
  39.411 +        return 0;
  39.412 +
  39.413 +    POLICY_RDLOCK;
  39.414 +
  39.415 +    if ( !tclass || tclass > policydb.p_classes.nprim )
  39.416 +    {
  39.417 +        printk(KERN_ERR "security_validate_transition: "
  39.418 +                                            "unrecognized class %d\n", tclass);
  39.419 +        rc = -EINVAL;
  39.420 +        goto out;
  39.421 +    }
  39.422 +    tclass_datum = policydb.class_val_to_struct[tclass - 1];
  39.423 +
  39.424 +    ocontext = sidtab_search(&sidtab, oldsid);
  39.425 +    if ( !ocontext )
  39.426 +    {
  39.427 +        printk(KERN_ERR "security_validate_transition: "
  39.428 +               " unrecognized SID %d\n", oldsid);
  39.429 +        rc = -EINVAL;
  39.430 +        goto out;
  39.431 +    }
  39.432 +
  39.433 +    ncontext = sidtab_search(&sidtab, newsid);
  39.434 +    if ( !ncontext )
  39.435 +    {
  39.436 +        printk(KERN_ERR "security_validate_transition: "
  39.437 +               " unrecognized SID %d\n", newsid);
  39.438 +        rc = -EINVAL;
  39.439 +        goto out;
  39.440 +    }
  39.441 +
  39.442 +    tcontext = sidtab_search(&sidtab, tasksid);
  39.443 +    if ( !tcontext )
  39.444 +    {
  39.445 +        printk(KERN_ERR "security_validate_transition: "
  39.446 +               " unrecognized SID %d\n", tasksid);
  39.447 +        rc = -EINVAL;
  39.448 +        goto out;
  39.449 +    }
  39.450 +
  39.451 +    constraint = tclass_datum->validatetrans;
  39.452 +    while ( constraint )
  39.453 +    {
  39.454 +        if ( !constraint_expr_eval(ocontext, ncontext, tcontext,
  39.455 +                                                            constraint->expr) )
  39.456 +        {
  39.457 +            rc = security_validtrans_handle_fail(ocontext, ncontext,
  39.458 +                                                 tcontext, tclass);
  39.459 +            goto out;
  39.460 +        }
  39.461 +        constraint = constraint->next;
  39.462 +    }
  39.463 +
  39.464 +out:
  39.465 +    POLICY_RDUNLOCK;
  39.466 +    return rc;
  39.467 +}
  39.468 +
  39.469 +/**
  39.470 + * security_compute_av - Compute access vector decisions.
  39.471 + * @ssid: source security identifier
  39.472 + * @tsid: target security identifier
  39.473 + * @tclass: target security class
  39.474 + * @requested: requested permissions
  39.475 + * @avd: access vector decisions
  39.476 + *
  39.477 + * Compute a set of access vector decisions based on the
  39.478 + * SID pair (@ssid, @tsid) for the permissions in @tclass.
  39.479 + * Return -%EINVAL if any of the parameters are invalid or %0
  39.480 + * if the access vector decisions were computed successfully.
  39.481 + */
  39.482 +int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
  39.483 +                                                    struct av_decision *avd)
  39.484 +{
  39.485 +    struct context *scontext = NULL, *tcontext = NULL;
  39.486 +    int rc = 0;
  39.487 +
  39.488 +    if ( !ss_initialized )
  39.489 +    {
  39.490 +        avd->allowed = 0xffffffff;
  39.491 +        avd->decided = 0xffffffff;
  39.492 +        avd->auditallow = 0;
  39.493 +        avd->auditdeny = 0xffffffff;
  39.494 +        avd->seqno = latest_granting;
  39.495 +        return 0;
  39.496 +    }
  39.497 +
  39.498 +    POLICY_RDLOCK;
  39.499 +
  39.500 +    scontext = sidtab_search(&sidtab, ssid);
  39.501 +    if ( !scontext )
  39.502 +    {
  39.503 +        printk("security_compute_av:  unrecognized SID %d\n", ssid);
  39.504 +        rc = -EINVAL;
  39.505 +        goto out;
  39.506 +    }
  39.507 +    tcontext = sidtab_search(&sidtab, tsid);
  39.508 +    if ( !tcontext )
  39.509 +    {
  39.510 +        printk("security_compute_av:  unrecognized SID %d\n", tsid);
  39.511 +        rc = -EINVAL;
  39.512 +        goto out;
  39.513 +    }
  39.514 +
  39.515 +    rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd);
  39.516 +out:
  39.517 +    POLICY_RDUNLOCK;
  39.518 +    return rc;
  39.519 +}
  39.520 +
  39.521 +/*
  39.522 + * Write the security context string representation of
  39.523 + * the context structure `context' into a dynamically
  39.524 + * allocated string of the correct size.  Set `*scontext'
  39.525 + * to point to this string and set `*scontext_len' to
  39.526 + * the length of the string.
  39.527 + */
  39.528 +static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
  39.529 +{
  39.530 +    char *scontextp;
  39.531 +
  39.532 +    *scontext = NULL;
  39.533 +    *scontext_len = 0;
  39.534 +
  39.535 +    /* Compute the size of the context. */
  39.536 +    *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
  39.537 +    *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
  39.538 +    *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
  39.539 +    *scontext_len += mls_compute_context_len(context);
  39.540 +
  39.541 +    /* Allocate space for the context; caller must free this space. */
  39.542 +    scontextp = xmalloc_array(char, *scontext_len);
  39.543 +    if ( !scontextp )
  39.544 +        return -ENOMEM;
  39.545 +
  39.546 +    *scontext = scontextp;
  39.547 +
  39.548 +    /*
  39.549 +     * Copy the user name, role name and type name into the context.
  39.550 +     */
  39.551 +    snprintf(scontextp, *scontext_len, "%s:%s:%s",
  39.552 +        policydb.p_user_val_to_name[context->user - 1],
  39.553 +        policydb.p_role_val_to_name[context->role - 1],
  39.554 +        policydb.p_type_val_to_name[context->type - 1]);
  39.555 +    scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
  39.556 +                 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
  39.557 +                 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
  39.558 +
  39.559 +    mls_sid_to_context(context, &scontextp);
  39.560 +
  39.561 +    *scontextp = 0;
  39.562 +
  39.563 +    return 0;
  39.564 +}
  39.565 +
  39.566 +#include "initial_sid_to_string.h"
  39.567 +
  39.568 +/**
  39.569 + * security_sid_to_context - Obtain a context for a given SID.
  39.570 + * @sid: security identifier, SID
  39.571 + * @scontext: security context
  39.572 + * @scontext_len: length in bytes
  39.573 + *
  39.574 + * Write the string representation of the context associated with @sid
  39.575 + * into a dynamically allocated string of the correct size.  Set @scontext
  39.576 + * to point to this string and set @scontext_len to the length of the string.
  39.577 + */
  39.578 +int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
  39.579 +{
  39.580 +    struct context *context;
  39.581 +    int rc = 0;
  39.582 +
  39.583 +    if ( !ss_initialized )
  39.584 +    {
  39.585 +        if ( sid <= SECINITSID_NUM )
  39.586 +        {
  39.587 +            char *scontextp;
  39.588 +
  39.589 +            *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
  39.590 +            scontextp = xmalloc_array(char, *scontext_len);
  39.591 +            strlcpy(scontextp, initial_sid_to_string[sid], *scontext_len);
  39.592 +            *scontext = scontextp;
  39.593 +            goto out;
  39.594 +        }
  39.595 +        printk(KERN_ERR "security_sid_to_context:  called before initial "
  39.596 +               "load_policy on unknown SID %d\n", sid);
  39.597 +        rc = -EINVAL;
  39.598 +        goto out;
  39.599 +    }
  39.600 +    POLICY_RDLOCK;
  39.601 +    context = sidtab_search(&sidtab, sid);
  39.602 +    if ( !context )
  39.603 +    {
  39.604 +        printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
  39.605 +               "%d\n", sid);
  39.606 +        rc = -EINVAL;
  39.607 +        goto out_unlock;
  39.608 +    }
  39.609 +    rc = context_struct_to_string(context, scontext, scontext_len);
  39.610 +out_unlock:
  39.611 +    POLICY_RDUNLOCK;
  39.612 +out:
  39.613 +    return rc;
  39.614 +
  39.615 +}
  39.616 +
  39.617 +static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
  39.618 +{
  39.619 +    char *scontext2;
  39.620 +    struct context context;
  39.621 +    struct role_datum *role;
  39.622 +    struct type_datum *typdatum;
  39.623 +    struct user_datum *usrdatum;
  39.624 +    char *scontextp, *p, oldc;
  39.625 +    int rc = 0;
  39.626 +
  39.627 +    if ( !ss_initialized )
  39.628 +    {
  39.629 +        int i;
  39.630 +
  39.631 +        for ( i = 1; i < SECINITSID_NUM; i++ )
  39.632 +        {
  39.633 +            if ( !strcmp(initial_sid_to_string[i], scontext) )
  39.634 +            {
  39.635 +                *sid = i;
  39.636 +                goto out;
  39.637 +            }
  39.638 +        }
  39.639 +        *sid = SECINITSID_XEN;
  39.640 +        goto out;
  39.641 +    }
  39.642 +    *sid = SECSID_NULL;
  39.643 +
  39.644 +    /* Copy the string so that we can modify the copy as we parse it.
  39.645 +       The string should already by null terminated, but we append a
  39.646 +       null suffix to the copy to avoid problems with the existing
  39.647 +       attr package, which doesn't view the null terminator as part
  39.648 +       of the attribute value. */
  39.649 +    scontext2 = xmalloc_array(char, scontext_len+1);
  39.650 +    if ( !scontext2 )
  39.651 +    {
  39.652 +        rc = -ENOMEM;
  39.653 +        goto out;
  39.654 +    }
  39.655 +    memcpy(scontext2, scontext, scontext_len);
  39.656 +    scontext2[scontext_len] = 0;
  39.657 +
  39.658 +    context_init(&context);
  39.659 +    *sid = SECSID_NULL;
  39.660 +
  39.661 +    POLICY_RDLOCK;
  39.662 +
  39.663 +    /* Parse the security context. */
  39.664 +
  39.665 +    rc = -EINVAL;
  39.666 +    scontextp = (char *) scontext2;
  39.667 +
  39.668 +    /* Extract the user. */
  39.669 +    p = scontextp;
  39.670 +    while ( *p && *p != ':' )
  39.671 +        p++;
  39.672 +
  39.673 +    if (*p == 0)
  39.674 +        goto out_unlock;
  39.675 +
  39.676 +    *p++ = 0;
  39.677 +
  39.678 +    usrdatum = hashtab_search(policydb.p_users.table, scontextp);
  39.679 +    if ( !usrdatum )
  39.680 +        goto out_unlock;
  39.681 +
  39.682 +    context.user = usrdatum->value;
  39.683 +
  39.684 +    /* Extract role. */
  39.685 +    scontextp = p;
  39.686 +    while ( *p && *p != ':' )
  39.687 +        p++;
  39.688 +
  39.689 +    if ( *p == 0 )
  39.690 +        goto out_unlock;
  39.691 +
  39.692 +    *p++ = 0;
  39.693 +
  39.694 +    role = hashtab_search(policydb.p_roles.table, scontextp);
  39.695 +    if ( !role )
  39.696 +        goto out_unlock;
  39.697 +    context.role = role->value;
  39.698 +
  39.699 +    /* Extract type. */
  39.700 +    scontextp = p;
  39.701 +    while ( *p && *p != ':' )
  39.702 +        p++;
  39.703 +    oldc = *p;
  39.704 +    *p++ = 0;
  39.705 +
  39.706 +    typdatum = hashtab_search(policydb.p_types.table, scontextp);
  39.707 +    if ( !typdatum )
  39.708 +        goto out_unlock;
  39.709 +
  39.710 +    context.type = typdatum->value;
  39.711 +
  39.712 +    rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
  39.713 +    if ( rc )
  39.714 +        goto out_unlock;
  39.715 +
  39.716 +    if ( (p - scontext2) < scontext_len )
  39.717 +    {
  39.718 +        rc = -EINVAL;
  39.719 +        goto out_unlock;
  39.720 +    }
  39.721 +
  39.722 +    /* Check the validity of the new context. */
  39.723 +    if ( !policydb_context_isvalid(&policydb, &context) )
  39.724 +    {
  39.725 +        rc = -EINVAL;
  39.726 +        goto out_unlock;
  39.727 +    }
  39.728 +    /* Obtain the new sid. */
  39.729 +    rc = sidtab_context_to_sid(&sidtab, &context, sid);
  39.730 +out_unlock:
  39.731 +    POLICY_RDUNLOCK;
  39.732 +    context_destroy(&context);
  39.733 +    xfree(scontext2);
  39.734 +out:
  39.735 +    return rc;
  39.736 +}
  39.737 +
  39.738 +/**
  39.739 + * security_context_to_sid - Obtain a SID for a given security context.
  39.740 + * @scontext: security context
  39.741 + * @scontext_len: length in bytes
  39.742 + * @sid: security identifier, SID
  39.743 + *
  39.744 + * Obtains a SID associated with the security context that
  39.745 + * has the string representation specified by @scontext.
  39.746 + * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  39.747 + * memory is available, or 0 on success.
  39.748 + */
  39.749 +int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
  39.750 +{
  39.751 +    return security_context_to_sid_core(scontext, scontext_len,
  39.752 +                                                            sid, SECSID_NULL);
  39.753 +}
  39.754 +
  39.755 +/**
  39.756 + * security_context_to_sid_default - Obtain a SID for a given security context,
  39.757 + * falling back to specified default if needed.
  39.758 + *
  39.759 + * @scontext: security context
  39.760 + * @scontext_len: length in bytes
  39.761 + * @sid: security identifier, SID
  39.762 + * @def_sid: default SID to assign on errror
  39.763 + *
  39.764 + * Obtains a SID associated with the security context that
  39.765 + * has the string representation specified by @scontext.
  39.766 + * The default SID is passed to the MLS layer to be used to allow
  39.767 + * kernel labeling of the MLS field if the MLS field is not present
  39.768 + * (for upgrading to MLS without full relabel).
  39.769 + * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  39.770 + * memory is available, or 0 on success.
  39.771 + */
  39.772 +int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
  39.773 +{
  39.774 +    return security_context_to_sid_core(scontext, scontext_len, sid, def_sid);
  39.775 +}
  39.776 +
  39.777 +static int compute_sid_handle_invalid_context(
  39.778 +                struct context *scontext, struct context *tcontext, u16 tclass,
  39.779 +                                                    struct context *newcontext)
  39.780 +{
  39.781 +    char *s = NULL, *t = NULL, *n = NULL;
  39.782 +    u32 slen, tlen, nlen;
  39.783 +
  39.784 +    if ( context_struct_to_string(scontext, &s, &slen) < 0 )
  39.785 +        goto out;
  39.786 +    if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
  39.787 +        goto out;
  39.788 +    if ( context_struct_to_string(newcontext, &n, &nlen) < 0 )
  39.789 +        goto out;
  39.790 +    printk("security_compute_sid:  invalid context %s"
  39.791 +          " for scontext=%s"
  39.792 +          " tcontext=%s"
  39.793 +          " tclass=%s",
  39.794 +          n, s, t, policydb.p_class_val_to_name[tclass-1]);
  39.795 +out:
  39.796 +    xfree(s);
  39.797 +    xfree(t);
  39.798 +    xfree(n);
  39.799 +    if ( !flask_enforcing )
  39.800 +        return 0;
  39.801 +    return -EACCES;
  39.802 +}
  39.803 +
  39.804 +static int security_compute_sid(u32 ssid,
  39.805 +                u32 tsid,
  39.806 +                u16 tclass,
  39.807 +                u32 specified,
  39.808 +                u32 *out_sid)
  39.809 +{
  39.810 +    struct context *scontext = NULL, *tcontext = NULL, newcontext;
  39.811 +    struct role_trans *roletr = NULL;
  39.812 +    struct avtab_key avkey;
  39.813 +    struct avtab_datum *avdatum;
  39.814 +    struct avtab_node *node;
  39.815 +    int rc = 0;
  39.816 +
  39.817 +    if ( !ss_initialized )
  39.818 +    {
  39.819 +        switch ( tclass )
  39.820 +        {
  39.821 +            case SECCLASS_DOMAIN:
  39.822 +                *out_sid = ssid;
  39.823 +            break;
  39.824 +            default:
  39.825 +                *out_sid = tsid;
  39.826 +            break;
  39.827 +        }
  39.828 +        goto out;
  39.829 +    }
  39.830 +
  39.831 +    POLICY_RDLOCK;
  39.832 +
  39.833 +    scontext = sidtab_search(&sidtab, ssid);
  39.834 +    if ( !scontext )
  39.835 +    {
  39.836 +        printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", ssid);
  39.837 +        rc = -EINVAL;
  39.838 +        goto out_unlock;
  39.839 +    }
  39.840 +    tcontext = sidtab_search(&sidtab, tsid);
  39.841 +    if ( !tcontext )
  39.842 +    {
  39.843 +        printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", tsid);
  39.844 +        rc = -EINVAL;
  39.845 +        goto out_unlock;
  39.846 +    }
  39.847 +
  39.848 +    context_init(&newcontext);
  39.849 +
  39.850 +    /* Set the user identity. */
  39.851 +    switch ( specified )
  39.852 +    {
  39.853 +        case AVTAB_TRANSITION:
  39.854 +        case AVTAB_CHANGE:
  39.855 +            /* Use the process user identity. */
  39.856 +            newcontext.user = scontext->user;
  39.857 +        break;
  39.858 +        case AVTAB_MEMBER:
  39.859 +            /* Use the related object owner. */
  39.860 +            newcontext.user = tcontext->user;
  39.861 +        break;
  39.862 +    }
  39.863 +
  39.864 +    /* Set the role and type to default values. */
  39.865 +    switch ( tclass )
  39.866 +    {
  39.867 +        case SECCLASS_DOMAIN:
  39.868 +            /* Use the current role and type of process. */
  39.869 +            newcontext.role = scontext->role;
  39.870 +            newcontext.type = scontext->type;
  39.871 +        break;
  39.872 +        default:
  39.873 +            /* Use the well-defined object role. */
  39.874 +            newcontext.role = OBJECT_R_VAL;
  39.875 +            /* Use the type of the related object. */
  39.876 +            newcontext.type = tcontext->type;
  39.877 +    }
  39.878 +
  39.879 +    /* Look for a type transition/member/change rule. */
  39.880 +    avkey.source_type = scontext->type;
  39.881 +    avkey.target_type = tcontext->type;
  39.882 +    avkey.target_class = tclass;
  39.883 +    avkey.specified = specified;
  39.884 +    avdatum = avtab_search(&policydb.te_avtab, &avkey);
  39.885 +
  39.886 +    /* If no permanent rule, also check for enabled conditional rules */
  39.887 +    if ( !avdatum )
  39.888 +    {
  39.889 +        node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
  39.890 +        for ( ; node != NULL; node = avtab_search_node_next(node, specified) )
  39.891 +        {
  39.892 +            if ( node->key.specified & AVTAB_ENABLED )
  39.893 +            {
  39.894 +                avdatum = &node->datum;
  39.895 +                break;
  39.896 +            }
  39.897 +        }
  39.898 +    }
  39.899 +
  39.900 +    if ( avdatum )
  39.901 +    {
  39.902 +        /* Use the type from the type transition/member/change rule. */
  39.903 +        newcontext.type = avdatum->data;
  39.904 +    }
  39.905 +
  39.906 +    /* Check for class-specific changes. */
  39.907 +    switch ( tclass )
  39.908 +    {
  39.909 +        case SECCLASS_DOMAIN:
  39.910 +            if ( specified & AVTAB_TRANSITION )
  39.911 +            {
  39.912 +                /* Look for a role transition rule. */
  39.913 +                for ( roletr = policydb.role_tr; roletr; roletr = roletr->next )
  39.914 +                {
  39.915 +                    if ( roletr->role == scontext->role && 
  39.916 +                                            roletr->type == tcontext->type )
  39.917 +                    {
  39.918 +                        /* Use the role transition rule. */
  39.919 +                        newcontext.role = roletr->new_role;
  39.920 +                        break;
  39.921 +                    }
  39.922 +                }
  39.923 +            }
  39.924 +        break;
  39.925 +        default:
  39.926 +        break;
  39.927 +    }
  39.928 +
  39.929 +    /* Set the MLS attributes.
  39.930 +       This is done last because it may allocate memory. */
  39.931 +    rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
  39.932 +    if ( rc )
  39.933 +        goto out_unlock;
  39.934 +
  39.935 +    /* Check the validity of the context. */
  39.936 +    if ( !policydb_context_isvalid(&policydb, &newcontext) )
  39.937 +    {
  39.938 +        rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass,
  39.939 +                                                                &newcontext);
  39.940 +        if ( rc )
  39.941 +            goto out_unlock;
  39.942 +    }
  39.943 +    /* Obtain the sid for the context. */
  39.944 +    rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
  39.945 +out_unlock:
  39.946 +    POLICY_RDUNLOCK;
  39.947 +    context_destroy(&newcontext);
  39.948 +out:
  39.949 +    return rc;
  39.950 +}
  39.951 +
  39.952 +/**
  39.953 + * security_transition_sid - Compute the SID for a new subject/object.
  39.954 + * @ssid: source security identifier
  39.955 + * @tsid: target security identifier
  39.956 + * @tclass: target security class
  39.957 + * @out_sid: security identifier for new subject/object
  39.958 + *
  39.959 + * Compute a SID to use for labeling a new subject or object in the
  39.960 + * class @tclass based on a SID pair (@ssid, @tsid).
  39.961 + * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
  39.962 + * if insufficient memory is available, or %0 if the new SID was
  39.963 + * computed successfully.
  39.964 + */
  39.965 +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
  39.966 +{
  39.967 +    return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
  39.968 +}
  39.969 +
  39.970 +/**
  39.971 + * security_member_sid - Compute the SID for member selection.
  39.972 + * @ssid: source security identifier
  39.973 + * @tsid: target security identifier
  39.974 + * @tclass: target security class
  39.975 + * @out_sid: security identifier for selected member
  39.976 + *
  39.977 + * Compute a SID to use when selecting a member of a polyinstantiated
  39.978 + * object of class @tclass based on a SID pair (@ssid, @tsid).
  39.979 + * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
  39.980 + * if insufficient memory is available, or %0 if the SID was
  39.981 + * computed successfully.
  39.982 + */
  39.983 +int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
  39.984 +{
  39.985 +    return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
  39.986 +}
  39.987 +
  39.988 +/**
  39.989 + * security_change_sid - Compute the SID for object relabeling.
  39.990 + * @ssid: source security identifier
  39.991 + * @tsid: target security identifier
  39.992 + * @tclass: target security class
  39.993 + * @out_sid: security identifier for selected member
  39.994 + *
  39.995 + * Compute a SID to use for relabeling an object of class @tclass
  39.996 + * based on a SID pair (@ssid, @tsid).
  39.997 + * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
  39.998 + * if insufficient memory is available, or %0 if the SID was
  39.999 + * computed successfully.
 39.1000 + */
 39.1001 +int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
 39.1002 +{
 39.1003 +    return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
 39.1004 +}
 39.1005 +
 39.1006 +/*
 39.1007 + * Verify that each permission that is defined under the
 39.1008 + * existing policy is still defined with the same value
 39.1009 + * in the new policy.
 39.1010 + */
 39.1011 +static int validate_perm(void *key, void *datum, void *p)
 39.1012 +{
 39.1013 +    struct hashtab *h;
 39.1014 +    struct perm_datum *perdatum, *perdatum2;
 39.1015 +    int rc = 0;
 39.1016 +
 39.1017 +    h = p;
 39.1018 +    perdatum = datum;
 39.1019 +
 39.1020 +    perdatum2 = hashtab_search(h, key);
 39.1021 +    if ( !perdatum2 )
 39.1022 +    {
 39.1023 +        printk(KERN_ERR "security:  permission %s disappeared", (char *)key);
 39.1024 +        rc = -ENOENT;
 39.1025 +        goto out;
 39.1026 +    }
 39.1027 +    if ( perdatum->value != perdatum2->value )
 39.1028 +    {
 39.1029 +        printk(KERN_ERR "security:  the value of permission %s changed",
 39.1030 +                                                                (char *)key);
 39.1031 +        rc = -EINVAL;
 39.1032 +    }
 39.1033 +out:
 39.1034 +    return rc;
 39.1035 +}
 39.1036 +
 39.1037 +/*
 39.1038 + * Verify that each class that is defined under the
 39.1039 + * existing policy is still defined with the same
 39.1040 + * attributes in the new policy.
 39.1041 + */
 39.1042 +static int validate_class(void *key, void *datum, void *p)
 39.1043 +{
 39.1044 +    struct policydb *newp;
 39.1045 +    struct class_datum *cladatum, *cladatum2;
 39.1046 +    int rc;
 39.1047 +
 39.1048 +    newp = p;
 39.1049 +    cladatum = datum;
 39.1050 +
 39.1051 +    cladatum2 = hashtab_search(newp->p_classes.table, key);
 39.1052 +    if ( !cladatum2 )
 39.1053 +    {
 39.1054 +        printk(KERN_ERR "security:  class %s disappeared\n", (char *)key);
 39.1055 +        rc = -ENOENT;
 39.1056 +        goto out;
 39.1057 +    }
 39.1058 +    if (cladatum->value != cladatum2->value) {
 39.1059 +        printk(KERN_ERR "security:  the value of class %s changed\n",
 39.1060 +                                                                (char *)key);
 39.1061 +        rc = -EINVAL;
 39.1062 +        goto out;
 39.1063 +    }
 39.1064 +    if ( (cladatum->comdatum && !cladatum2->comdatum) ||
 39.1065 +                                (!cladatum->comdatum && cladatum2->comdatum) )
 39.1066 +    {
 39.1067 +        printk(KERN_ERR "security:  the inherits clause for the access "
 39.1068 +               "vector definition for class %s changed\n", (char *)key);
 39.1069 +        rc = -EINVAL;
 39.1070 +        goto out;
 39.1071 +    }
 39.1072 +    if ( cladatum->comdatum )
 39.1073 +    {
 39.1074 +        rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm,
 39.1075 +                                     cladatum2->comdatum->permissions.table);
 39.1076 +        if ( rc )
 39.1077 +        {
 39.1078 +            printk(" in the access vector definition for class %s\n", 
 39.1079 +                                                                (char *)key);
 39.1080 +            goto out;
 39.1081 +        }
 39.1082 +    }
 39.1083 +    rc = hashtab_map(cladatum->permissions.table, validate_perm,
 39.1084 +                                                cladatum2->permissions.table);
 39.1085 +    if ( rc )
 39.1086 +        printk(" in access vector definition for class %s\n", (char *)key);
 39.1087 +out:
 39.1088 +    return rc;
 39.1089 +}
 39.1090 +
 39.1091 +/* Clone the SID into the new SID table. */
 39.1092 +static int clone_sid(u32 sid, struct context *context, void *arg)
 39.1093 +{
 39.1094 +    struct sidtab *s = arg;
 39.1095 +
 39.1096 +    return sidtab_insert(s, sid, context);
 39.1097 +}
 39.1098 +
 39.1099 +static inline int convert_context_handle_invalid_context(struct context *context)
 39.1100 +{
 39.1101 +    int rc = 0;
 39.1102 +
 39.1103 +    if ( flask_enforcing )
 39.1104 +        rc = -EINVAL;
 39.1105 +    else
 39.1106 +    {
 39.1107 +        char *s;
 39.1108 +        u32 len;
 39.1109 +
 39.1110 +        context_struct_to_string(context, &s, &len);
 39.1111 +        printk(KERN_ERR "security:  context %s is invalid\n", s);
 39.1112 +        xfree(s);
 39.1113 +    }
 39.1114 +    return rc;
 39.1115 +}
 39.1116 +
 39.1117 +struct convert_context_args {
 39.1118 +    struct policydb *oldp;
 39.1119 +    struct policydb *newp;
 39.1120 +};
 39.1121 +
 39.1122 +/*
 39.1123 + * Convert the values in the security context
 39.1124 + * structure `c' from the values specified
 39.1125 + * in the policy `p->oldp' to the values specified
 39.1126 + * in the policy `p->newp'.  Verify that the
 39.1127 + * context is valid under the new policy.
 39.1128 + */
 39.1129 +static int convert_context(u32 key, struct context *c, void *p)
 39.1130 +{
 39.1131 +    struct convert_context_args *args;
 39.1132 +    struct context oldc;
 39.1133 +    struct role_datum *role;
 39.1134 +    struct type_datum *typdatum;
 39.1135 +    struct user_datum *usrdatum;
 39.1136 +    char *s;
 39.1137 +    u32 len;
 39.1138 +    int rc;
 39.1139 +
 39.1140 +    args = p;
 39.1141 +
 39.1142 +    rc = context_cpy(&oldc, c);
 39.1143 +    if ( rc )
 39.1144 +        goto out;
 39.1145 +
 39.1146 +    rc = -EINVAL;
 39.1147 +
 39.1148 +    /* Convert the user. */
 39.1149 +    usrdatum = hashtab_search(args->newp->p_users.table,
 39.1150 +                              args->oldp->p_user_val_to_name[c->user - 1]);
 39.1151 +    if ( !usrdatum )
 39.1152 +        goto bad;
 39.1153 +
 39.1154 +    c->user = usrdatum->value;
 39.1155 +
 39.1156 +    /* Convert the role. */
 39.1157 +    role = hashtab_search(args->newp->p_roles.table,
 39.1158 +                          args->oldp->p_role_val_to_name[c->role - 1]);
 39.1159 +    if ( !role )
 39.1160 +        goto bad;
 39.1161 +
 39.1162 +    c->role = role->value;
 39.1163 +
 39.1164 +    /* Convert the type. */
 39.1165 +    typdatum = hashtab_search(args->newp->p_types.table,
 39.1166 +                              args->oldp->p_type_val_to_name[c->type - 1]);
 39.1167 +    if ( !typdatum )
 39.1168 +        goto bad;
 39.1169 +
 39.1170 +    c->type = typdatum->value;
 39.1171 +
 39.1172 +    rc = mls_convert_context(args->oldp, args->newp, c);
 39.1173 +    if ( rc )
 39.1174 +        goto bad;
 39.1175 +
 39.1176 +    /* Check the validity of the new context. */
 39.1177 +    if ( !policydb_context_isvalid(args->newp, c) )
 39.1178 +    {
 39.1179 +        rc = convert_context_handle_invalid_context(&oldc);
 39.1180 +        if ( rc )
 39.1181 +            goto bad;
 39.1182 +    }
 39.1183 +
 39.1184 +    context_destroy(&oldc);
 39.1185 +out:
 39.1186 +    return rc;
 39.1187 +bad:
 39.1188 +    context_struct_to_string(&oldc, &s, &len);
 39.1189 +    context_destroy(&oldc);
 39.1190 +    printk(KERN_ERR "security:  invalidating context %s\n", s);
 39.1191 +    xfree(s);
 39.1192 +    goto out;
 39.1193 +}
 39.1194 +
 39.1195 +extern void flask_complete_init(void);
 39.1196 +
 39.1197 +/**
 39.1198 + * security_load_policy - Load a security policy configuration.
 39.1199 + * @data: binary policy data
 39.1200 + * @len: length of data in bytes
 39.1201 + *
 39.1202 + * Load a new set of security policy configuration data,
 39.1203 + * validate it and convert the SID table as necessary.
 39.1204 + * This function will flush the access vector cache after
 39.1205 + * loading the new policy.
 39.1206 + */
 39.1207 +int security_load_policy(void *data, size_t len)
 39.1208 +{
 39.1209 +    struct policydb oldpolicydb, newpolicydb;
 39.1210 +    struct sidtab oldsidtab, newsidtab;
 39.1211 +    struct convert_context_args args;
 39.1212 +    u32 seqno;
 39.1213 +    int rc = 0;
 39.1214 +    struct policy_file file = { data, len }, *fp = &file;
 39.1215 +
 39.1216 +    LOAD_LOCK;
 39.1217 +
 39.1218 +    if ( !ss_initialized )
 39.1219 +    {
 39.1220 +        if ( policydb_read(&policydb, fp) )
 39.1221 +        {
 39.1222 +            LOAD_UNLOCK;
 39.1223 +            return -EINVAL;
 39.1224 +        }
 39.1225 +        if ( policydb_load_isids(&policydb, &sidtab) )
 39.1226 +        {
 39.1227 +            LOAD_UNLOCK;
 39.1228 +            policydb_destroy(&policydb);
 39.1229 +            return -EINVAL;
 39.1230 +        }
 39.1231 +        policydb_loaded_version = policydb.policyvers;
 39.1232 +        ss_initialized = 1;
 39.1233 +        seqno = ++latest_granting;
 39.1234 +        LOAD_UNLOCK;
 39.1235 +        avc_ss_reset(seqno);
 39.1236 +        return 0;
 39.1237 +    }
 39.1238 +
 39.1239 +#if 0
 39.1240 +    sidtab_hash_eval(&sidtab, "sids");
 39.1241 +#endif
 39.1242 +