2005-04-17 02:20:36 +04:00
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2008-04-19 01:38:29 +04:00
* Frank Mayer < mayerf @ tresys . com >
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 2003 - 2004 Tresys Technology , LLC
* This program is free software ; you can redistribute it and / or modify
2008-04-19 01:38:29 +04:00
* it under the terms of the GNU General Public License as published by
2005-04-17 02:20:36 +04:00
* the Free Software Foundation , version 2.
*/
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/string.h>
# include <linux/spinlock.h>
# include <linux/slab.h>
# include "security.h"
# include "conditional.h"
/*
* cond_evaluate_expr evaluates a conditional expr
* in reverse polish notation . It returns true ( 1 ) , false ( 0 ) ,
* or undefined ( - 1 ) . Undefined occurs when the expression
* exceeds the stack depth of COND_EXPR_MAXDEPTH .
*/
static int cond_evaluate_expr ( struct policydb * p , struct cond_expr * expr )
{
struct cond_expr * cur ;
int s [ COND_EXPR_MAXDEPTH ] ;
int sp = - 1 ;
2008-08-07 04:18:20 +04:00
for ( cur = expr ; cur ; cur = cur - > next ) {
2005-04-17 02:20:36 +04:00
switch ( cur - > expr_type ) {
case COND_BOOL :
if ( sp = = ( COND_EXPR_MAXDEPTH - 1 ) )
return - 1 ;
sp + + ;
s [ sp ] = p - > bool_val_to_struct [ cur - > bool - 1 ] - > state ;
break ;
case COND_NOT :
if ( sp < 0 )
return - 1 ;
s [ sp ] = ! s [ sp ] ;
break ;
case COND_OR :
if ( sp < 1 )
return - 1 ;
sp - - ;
s [ sp ] | = s [ sp + 1 ] ;
break ;
case COND_AND :
if ( sp < 1 )
return - 1 ;
sp - - ;
s [ sp ] & = s [ sp + 1 ] ;
break ;
case COND_XOR :
if ( sp < 1 )
return - 1 ;
sp - - ;
s [ sp ] ^ = s [ sp + 1 ] ;
break ;
case COND_EQ :
if ( sp < 1 )
return - 1 ;
sp - - ;
s [ sp ] = ( s [ sp ] = = s [ sp + 1 ] ) ;
break ;
case COND_NEQ :
if ( sp < 1 )
return - 1 ;
sp - - ;
s [ sp ] = ( s [ sp ] ! = s [ sp + 1 ] ) ;
break ;
default :
return - 1 ;
}
}
return s [ 0 ] ;
}
/*
* evaluate_cond_node evaluates the conditional stored in
* a struct cond_node and if the result is different than the
* current state of the node it sets the rules in the true / false
* list appropriately . If the result of the expression is undefined
* all of the rules are disabled for safety .
*/
int evaluate_cond_node ( struct policydb * p , struct cond_node * node )
{
int new_state ;
2008-04-19 01:38:29 +04:00
struct cond_av_list * cur ;
2005-04-17 02:20:36 +04:00
new_state = cond_evaluate_expr ( p , node - > expr ) ;
if ( new_state ! = node - > cur_state ) {
node - > cur_state = new_state ;
if ( new_state = = - 1 )
2008-02-26 12:42:02 +03:00
printk ( KERN_ERR " SELinux: expression result was undefined - disabling all rules. \n " ) ;
2005-04-17 02:20:36 +04:00
/* turn the rules on or off */
2008-08-07 04:18:20 +04:00
for ( cur = node - > true_list ; cur ; cur = cur - > next ) {
2008-04-19 01:38:29 +04:00
if ( new_state < = 0 )
2005-09-04 02:55:16 +04:00
cur - > node - > key . specified & = ~ AVTAB_ENABLED ;
2008-04-19 01:38:29 +04:00
else
2005-09-04 02:55:16 +04:00
cur - > node - > key . specified | = AVTAB_ENABLED ;
2005-04-17 02:20:36 +04:00
}
2008-08-07 04:18:20 +04:00
for ( cur = node - > false_list ; cur ; cur = cur - > next ) {
2005-04-17 02:20:36 +04:00
/* -1 or 1 */
2008-04-19 01:38:29 +04:00
if ( new_state )
2005-09-04 02:55:16 +04:00
cur - > node - > key . specified & = ~ AVTAB_ENABLED ;
2008-04-19 01:38:29 +04:00
else
2005-09-04 02:55:16 +04:00
cur - > node - > key . specified | = AVTAB_ENABLED ;
2005-04-17 02:20:36 +04:00
}
}
return 0 ;
}
int cond_policydb_init ( struct policydb * p )
{
2010-06-12 22:55:01 +04:00
int rc ;
2005-04-17 02:20:36 +04:00
p - > bool_val_to_struct = NULL ;
p - > cond_list = NULL ;
2010-06-12 22:55:01 +04:00
rc = avtab_init ( & p - > te_cond_avtab ) ;
if ( rc )
return rc ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static void cond_av_list_destroy ( struct cond_av_list * list )
{
struct cond_av_list * cur , * next ;
2008-08-07 04:18:20 +04:00
for ( cur = list ; cur ; cur = next ) {
2005-04-17 02:20:36 +04:00
next = cur - > next ;
/* the avtab_ptr_t node is destroy by the avtab */
kfree ( cur ) ;
}
}
static void cond_node_destroy ( struct cond_node * node )
{
struct cond_expr * cur_expr , * next_expr ;
2008-08-07 04:18:20 +04:00
for ( cur_expr = node - > expr ; cur_expr ; cur_expr = next_expr ) {
2005-04-17 02:20:36 +04:00
next_expr = cur_expr - > next ;
kfree ( cur_expr ) ;
}
cond_av_list_destroy ( node - > true_list ) ;
cond_av_list_destroy ( node - > false_list ) ;
kfree ( node ) ;
}
static void cond_list_destroy ( struct cond_node * list )
{
struct cond_node * next , * cur ;
if ( list = = NULL )
return ;
2008-08-07 04:18:20 +04:00
for ( cur = list ; cur ; cur = next ) {
2005-04-17 02:20:36 +04:00
next = cur - > next ;
cond_node_destroy ( cur ) ;
}
}
void cond_policydb_destroy ( struct policydb * p )
{
2005-06-26 01:58:51 +04:00
kfree ( p - > bool_val_to_struct ) ;
2005-04-17 02:20:36 +04:00
avtab_destroy ( & p - > te_cond_avtab ) ;
cond_list_destroy ( p - > cond_list ) ;
}
int cond_init_bool_indexes ( struct policydb * p )
{
2005-06-26 01:58:51 +04:00
kfree ( p - > bool_val_to_struct ) ;
2011-11-18 02:43:40 +04:00
p - > bool_val_to_struct =
2008-04-19 01:38:29 +04:00
kmalloc ( p - > p_bools . nprim * sizeof ( struct cond_bool_datum * ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! p - > bool_val_to_struct )
2011-01-21 18:28:04 +03:00
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
int cond_destroy_bool ( void * key , void * datum , void * p )
{
2005-06-26 01:58:51 +04:00
kfree ( key ) ;
2005-04-17 02:20:36 +04:00
kfree ( datum ) ;
return 0 ;
}
int cond_index_bool ( void * key , void * datum , void * datap )
{
struct policydb * p ;
struct cond_bool_datum * booldatum ;
2010-11-29 23:47:09 +03:00
struct flex_array * fa ;
2005-04-17 02:20:36 +04:00
booldatum = datum ;
p = datap ;
if ( ! booldatum - > value | | booldatum - > value > p - > p_bools . nprim )
return - EINVAL ;
2010-11-29 23:47:09 +03:00
fa = p - > sym_val_to_name [ SYM_BOOLS ] ;
if ( flex_array_put_ptr ( fa , booldatum - > value - 1 , key ,
GFP_KERNEL | __GFP_ZERO ) )
BUG ( ) ;
2008-04-19 01:38:29 +04:00
p - > bool_val_to_struct [ booldatum - > value - 1 ] = booldatum ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int bool_isvalid ( struct cond_bool_datum * b )
{
if ( ! ( b - > state = = 0 | | b - > state = = 1 ) )
return 0 ;
return 1 ;
}
int cond_read_bool ( struct policydb * p , struct hashtab * h , void * fp )
{
char * key = NULL ;
struct cond_bool_datum * booldatum ;
2005-09-04 02:55:17 +04:00
__le32 buf [ 3 ] ;
u32 len ;
2005-04-17 02:20:36 +04:00
int rc ;
2005-10-31 01:59:21 +03:00
booldatum = kzalloc ( sizeof ( struct cond_bool_datum ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! booldatum )
2010-06-12 22:56:01 +04:00
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
rc = next_entry ( buf , fp , sizeof buf ) ;
2010-06-12 22:56:01 +04:00
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
booldatum - > value = le32_to_cpu ( buf [ 0 ] ) ;
booldatum - > state = le32_to_cpu ( buf [ 1 ] ) ;
2010-06-12 22:56:01 +04:00
rc = - EINVAL ;
2005-04-17 02:20:36 +04:00
if ( ! bool_isvalid ( booldatum ) )
goto err ;
len = le32_to_cpu ( buf [ 2 ] ) ;
2010-06-12 22:56:01 +04:00
rc = - ENOMEM ;
2005-04-17 02:20:36 +04:00
key = kmalloc ( len + 1 , GFP_KERNEL ) ;
if ( ! key )
goto err ;
rc = next_entry ( key , fp , len ) ;
2010-06-12 22:56:01 +04:00
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
2008-07-21 00:57:01 +04:00
key [ len ] = ' \0 ' ;
2010-06-12 22:56:01 +04:00
rc = hashtab_insert ( h , key , booldatum ) ;
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
return 0 ;
err :
cond_destroy_bool ( key , booldatum , NULL ) ;
2010-06-12 22:56:01 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
2008-04-19 01:38:29 +04:00
struct cond_insertf_data {
2005-09-04 02:55:16 +04:00
struct policydb * p ;
struct cond_av_list * other ;
struct cond_av_list * head ;
struct cond_av_list * tail ;
} ;
static int cond_insertf ( struct avtab * a , struct avtab_key * k , struct avtab_datum * d , void * ptr )
{
struct cond_insertf_data * data = ptr ;
struct policydb * p = data - > p ;
struct cond_av_list * other = data - > other , * list , * cur ;
2005-04-17 02:20:36 +04:00
struct avtab_node * node_ptr ;
u8 found ;
2010-06-12 22:52:19 +04:00
int rc = - EINVAL ;
2005-04-17 02:20:36 +04:00
2005-09-04 02:55:16 +04:00
/*
* For type rules we have to make certain there aren ' t any
* conflicting rules by searching the te_avtab and the
* cond_te_avtab .
*/
if ( k - > specified & AVTAB_TYPE ) {
if ( avtab_search ( & p - > te_avtab , k ) ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: type rule already exists outside of a conditional. \n " ) ;
2005-04-17 02:20:36 +04:00
goto err ;
2005-09-04 02:55:16 +04:00
}
2005-04-17 02:20:36 +04:00
/*
2005-09-04 02:55:16 +04:00
* If we are reading the false list other will be a pointer to
* the true list . We can have duplicate entries if there is only
* 1 other entry and it is in our true list .
*
* If we are reading the true list ( other = = NULL ) there shouldn ' t
* be any other entries .
2005-04-17 02:20:36 +04:00
*/
2005-09-04 02:55:16 +04:00
if ( other ) {
node_ptr = avtab_search_node ( & p - > te_cond_avtab , k ) ;
if ( node_ptr ) {
if ( avtab_search_node_next ( node_ptr , k - > specified ) ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: too many conflicting type rules. \n " ) ;
2005-09-04 02:55:16 +04:00
goto err ;
}
found = 0 ;
2008-08-07 04:18:20 +04:00
for ( cur = other ; cur ; cur = cur - > next ) {
2005-09-04 02:55:16 +04:00
if ( cur - > node = = node_ptr ) {
found = 1 ;
break ;
2005-04-17 02:20:36 +04:00
}
}
2005-09-04 02:55:16 +04:00
if ( ! found ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: conflicting type rules. \n " ) ;
2005-04-17 02:20:36 +04:00
goto err ;
}
}
2005-09-04 02:55:16 +04:00
} else {
if ( avtab_search ( & p - > te_cond_avtab , k ) ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: conflicting type rules when adding type rule for true. \n " ) ;
2005-09-04 02:55:16 +04:00
goto err ;
}
2005-04-17 02:20:36 +04:00
}
2005-09-04 02:55:16 +04:00
}
2005-04-17 02:20:36 +04:00
2005-09-04 02:55:16 +04:00
node_ptr = avtab_insert_nonunique ( & p - > te_cond_avtab , k , d ) ;
if ( ! node_ptr ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: could not insert rule. \n " ) ;
2010-06-12 22:52:19 +04:00
rc = - ENOMEM ;
2005-09-04 02:55:16 +04:00
goto err ;
2005-04-17 02:20:36 +04:00
}
2005-10-31 01:59:21 +03:00
list = kzalloc ( sizeof ( struct cond_av_list ) , GFP_KERNEL ) ;
2010-06-12 22:52:19 +04:00
if ( ! list ) {
rc = - ENOMEM ;
2005-09-04 02:55:16 +04:00
goto err ;
2010-06-12 22:52:19 +04:00
}
2005-09-04 02:55:16 +04:00
list - > node = node_ptr ;
if ( ! data - > head )
data - > head = list ;
else
data - > tail - > next = list ;
data - > tail = list ;
2005-04-17 02:20:36 +04:00
return 0 ;
2005-09-04 02:55:16 +04:00
2005-04-17 02:20:36 +04:00
err :
2005-09-04 02:55:16 +04:00
cond_av_list_destroy ( data - > head ) ;
data - > head = NULL ;
2010-06-12 22:52:19 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
2005-09-04 02:55:16 +04:00
static int cond_read_av_list ( struct policydb * p , void * fp , struct cond_av_list * * ret_list , struct cond_av_list * other )
{
int i , rc ;
2005-09-04 02:55:17 +04:00
__le32 buf [ 1 ] ;
u32 len ;
2005-09-04 02:55:16 +04:00
struct cond_insertf_data data ;
* ret_list = NULL ;
len = 0 ;
rc = next_entry ( buf , fp , sizeof ( u32 ) ) ;
2010-06-12 22:52:19 +04:00
if ( rc )
return rc ;
2005-09-04 02:55:16 +04:00
len = le32_to_cpu ( buf [ 0 ] ) ;
2008-04-19 01:38:29 +04:00
if ( len = = 0 )
2005-09-04 02:55:16 +04:00
return 0 ;
data . p = p ;
data . other = other ;
data . head = NULL ;
data . tail = NULL ;
for ( i = 0 ; i < len ; i + + ) {
2007-11-07 18:08:00 +03:00
rc = avtab_read_item ( & p - > te_cond_avtab , fp , p , cond_insertf ,
& data ) ;
2005-09-04 02:55:16 +04:00
if ( rc )
return rc ;
}
* ret_list = data . head ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
static int expr_isvalid ( struct policydb * p , struct cond_expr * expr )
{
if ( expr - > expr_type < = 0 | | expr - > expr_type > COND_LAST ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: conditional expressions uses unknown operator. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
if ( expr - > bool > p - > p_bools . nprim ) {
2008-04-17 19:52:44 +04:00
printk ( KERN_ERR " SELinux: conditional expressions uses unknown bool. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
return 1 ;
}
static int cond_read_node ( struct policydb * p , struct cond_node * node , void * fp )
{
2005-09-04 02:55:17 +04:00
__le32 buf [ 2 ] ;
u32 len , i ;
2005-04-17 02:20:36 +04:00
int rc ;
struct cond_expr * expr = NULL , * last = NULL ;
2014-06-14 20:19:01 +04:00
rc = next_entry ( buf , fp , sizeof ( u32 ) * 2 ) ;
2010-06-12 22:53:46 +04:00
if ( rc )
2014-06-14 20:19:02 +04:00
goto err ;
2005-04-17 02:20:36 +04:00
node - > cur_state = le32_to_cpu ( buf [ 0 ] ) ;
/* expr */
2014-06-14 20:19:01 +04:00
len = le32_to_cpu ( buf [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
2008-04-19 01:38:29 +04:00
for ( i = 0 ; i < len ; i + + ) {
2005-04-17 02:20:36 +04:00
rc = next_entry ( buf , fp , sizeof ( u32 ) * 2 ) ;
2010-06-12 22:53:46 +04:00
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
2010-06-12 22:53:46 +04:00
rc = - ENOMEM ;
2005-10-31 01:59:21 +03:00
expr = kzalloc ( sizeof ( struct cond_expr ) , GFP_KERNEL ) ;
2008-04-19 01:38:29 +04:00
if ( ! expr )
2005-04-17 02:20:36 +04:00
goto err ;
expr - > expr_type = le32_to_cpu ( buf [ 0 ] ) ;
expr - > bool = le32_to_cpu ( buf [ 1 ] ) ;
if ( ! expr_isvalid ( p , expr ) ) {
2010-06-12 22:53:46 +04:00
rc = - EINVAL ;
2005-04-17 02:20:36 +04:00
kfree ( expr ) ;
goto err ;
}
2008-04-19 01:38:29 +04:00
if ( i = = 0 )
2005-04-17 02:20:36 +04:00
node - > expr = expr ;
2008-04-19 01:38:29 +04:00
else
2005-04-17 02:20:36 +04:00
last - > next = expr ;
last = expr ;
}
2010-06-12 22:53:46 +04:00
rc = cond_read_av_list ( p , fp , & node - > true_list , NULL ) ;
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
2010-06-12 22:53:46 +04:00
rc = cond_read_av_list ( p , fp , & node - > false_list , node - > true_list ) ;
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
return 0 ;
err :
cond_node_destroy ( node ) ;
2010-06-12 22:53:46 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
int cond_read_list ( struct policydb * p , void * fp )
{
struct cond_node * node , * last = NULL ;
2005-09-04 02:55:17 +04:00
__le32 buf [ 1 ] ;
u32 i , len ;
2005-04-17 02:20:36 +04:00
int rc ;
rc = next_entry ( buf , fp , sizeof buf ) ;
2010-06-12 22:51:40 +04:00
if ( rc )
return rc ;
2005-04-17 02:20:36 +04:00
len = le32_to_cpu ( buf [ 0 ] ) ;
2007-08-24 06:55:11 +04:00
rc = avtab_alloc ( & ( p - > te_cond_avtab ) , p - > te_avtab . nel ) ;
if ( rc )
goto err ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < len ; i + + ) {
2010-06-12 22:51:40 +04:00
rc = - ENOMEM ;
2005-10-31 01:59:21 +03:00
node = kzalloc ( sizeof ( struct cond_node ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! node )
goto err ;
2010-06-12 22:51:40 +04:00
rc = cond_read_node ( p , node , fp ) ;
if ( rc )
2005-04-17 02:20:36 +04:00
goto err ;
2008-04-19 01:38:29 +04:00
if ( i = = 0 )
2005-04-17 02:20:36 +04:00
p - > cond_list = node ;
2008-04-19 01:38:29 +04:00
else
2005-04-17 02:20:36 +04:00
last - > next = node ;
last = node ;
}
return 0 ;
err :
cond_list_destroy ( p - > cond_list ) ;
2005-09-04 02:55:16 +04:00
p - > cond_list = NULL ;
2010-06-12 22:51:40 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
2010-10-14 01:50:25 +04:00
int cond_write_bool ( void * vkey , void * datum , void * ptr )
{
char * key = vkey ;
struct cond_bool_datum * booldatum = datum ;
struct policy_data * pd = ptr ;
void * fp = pd - > fp ;
__le32 buf [ 3 ] ;
u32 len ;
int rc ;
len = strlen ( key ) ;
buf [ 0 ] = cpu_to_le32 ( booldatum - > value ) ;
buf [ 1 ] = cpu_to_le32 ( booldatum - > state ) ;
buf [ 2 ] = cpu_to_le32 ( len ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 3 , fp ) ;
if ( rc )
return rc ;
rc = put_entry ( key , 1 , len , fp ) ;
if ( rc )
return rc ;
return 0 ;
}
/*
* cond_write_cond_av_list doesn ' t write out the av_list nodes .
* Instead it writes out the key / value pairs from the avtab . This
* is necessary because there is no way to uniquely identifying rules
* in the avtab so it is not possible to associate individual rules
* in the avtab with a conditional without saving them as part of
* the conditional . This means that the avtab with the conditional
* rules will not be saved but will be rebuilt on policy load .
*/
static int cond_write_av_list ( struct policydb * p ,
struct cond_av_list * list , struct policy_file * fp )
{
__le32 buf [ 1 ] ;
struct cond_av_list * cur_list ;
u32 len ;
int rc ;
len = 0 ;
for ( cur_list = list ; cur_list ! = NULL ; cur_list = cur_list - > next )
len + + ;
buf [ 0 ] = cpu_to_le32 ( len ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 1 , fp ) ;
if ( rc )
return rc ;
if ( len = = 0 )
return 0 ;
for ( cur_list = list ; cur_list ! = NULL ; cur_list = cur_list - > next ) {
rc = avtab_write_item ( p , cur_list - > node , fp ) ;
if ( rc )
return rc ;
}
return 0 ;
}
2011-08-30 06:52:32 +04:00
static int cond_write_node ( struct policydb * p , struct cond_node * node ,
2010-10-14 01:50:25 +04:00
struct policy_file * fp )
{
struct cond_expr * cur_expr ;
__le32 buf [ 2 ] ;
int rc ;
u32 len = 0 ;
buf [ 0 ] = cpu_to_le32 ( node - > cur_state ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 1 , fp ) ;
if ( rc )
return rc ;
for ( cur_expr = node - > expr ; cur_expr ! = NULL ; cur_expr = cur_expr - > next )
len + + ;
buf [ 0 ] = cpu_to_le32 ( len ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 1 , fp ) ;
if ( rc )
return rc ;
for ( cur_expr = node - > expr ; cur_expr ! = NULL ; cur_expr = cur_expr - > next ) {
buf [ 0 ] = cpu_to_le32 ( cur_expr - > expr_type ) ;
buf [ 1 ] = cpu_to_le32 ( cur_expr - > bool ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 2 , fp ) ;
if ( rc )
return rc ;
}
rc = cond_write_av_list ( p , node - > true_list , fp ) ;
if ( rc )
return rc ;
rc = cond_write_av_list ( p , node - > false_list , fp ) ;
if ( rc )
return rc ;
return 0 ;
}
int cond_write_list ( struct policydb * p , struct cond_node * list , void * fp )
{
struct cond_node * cur ;
u32 len ;
__le32 buf [ 1 ] ;
int rc ;
len = 0 ;
for ( cur = list ; cur ! = NULL ; cur = cur - > next )
len + + ;
buf [ 0 ] = cpu_to_le32 ( len ) ;
rc = put_entry ( buf , sizeof ( u32 ) , 1 , fp ) ;
if ( rc )
return rc ;
for ( cur = list ; cur ! = NULL ; cur = cur - > next ) {
rc = cond_write_node ( p , cur , fp ) ;
if ( rc )
return rc ;
}
return 0 ;
}
2005-04-17 02:20:36 +04:00
/* Determine whether additional permissions are granted by the conditional
* av table , and if so , add them to the result
*/
void cond_compute_av ( struct avtab * ctab , struct avtab_key * key , struct av_decision * avd )
{
struct avtab_node * node ;
2008-04-19 01:38:29 +04:00
if ( ! ctab | | ! key | | ! avd )
2005-04-17 02:20:36 +04:00
return ;
2008-08-07 04:18:20 +04:00
for ( node = avtab_search_node ( ctab , key ) ; node ;
2005-09-04 02:55:16 +04:00
node = avtab_search_node_next ( node , key - > specified ) ) {
2008-04-19 01:38:29 +04:00
if ( ( u16 ) ( AVTAB_ALLOWED | AVTAB_ENABLED ) = =
( node - > key . specified & ( AVTAB_ALLOWED | AVTAB_ENABLED ) ) )
2005-09-04 02:55:16 +04:00
avd - > allowed | = node - > datum . data ;
2008-04-19 01:38:29 +04:00
if ( ( u16 ) ( AVTAB_AUDITDENY | AVTAB_ENABLED ) = =
( node - > key . specified & ( AVTAB_AUDITDENY | AVTAB_ENABLED ) ) )
2005-04-17 02:20:36 +04:00
/* Since a '0' in an auditdeny mask represents a
* permission we do NOT want to audit ( dontaudit ) , we use
* the ' & ' operand to ensure that all ' 0 ' s in the mask
* are retained ( much unlike the allow and auditallow cases ) .
*/
2005-09-04 02:55:16 +04:00
avd - > auditdeny & = node - > datum . data ;
2008-04-19 01:38:29 +04:00
if ( ( u16 ) ( AVTAB_AUDITALLOW | AVTAB_ENABLED ) = =
( node - > key . specified & ( AVTAB_AUDITALLOW | AVTAB_ENABLED ) ) )
2005-09-04 02:55:16 +04:00
avd - > auditallow | = node - > datum . data ;
2005-04-17 02:20:36 +04:00
}
return ;
}