2017-01-16 00:42:13 -08:00
/*
* AppArmor security module
*
* This file contains AppArmor lib definitions
*
* 2017 Canonical Ltd .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation , version 2 of the
* License .
*/
# ifndef __AA_LIB_H
# define __AA_LIB_H
# include <linux/slab.h>
# include <linux/fs.h>
# include "match.h"
/*
* DEBUG remains global ( no per profile flag ) since it is mostly used in sysctl
* which is not related to profile accesses .
*/
2017-01-16 00:42:27 -08:00
# define DEBUG_ON (aa_g_debug)
# define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)
2017-01-16 00:42:13 -08:00
# define AA_DEBUG(fmt, args...) \
do { \
2017-01-16 00:42:27 -08:00
if ( DEBUG_ON ) \
2017-01-16 00:42:13 -08:00
pr_debug_ratelimited ( " AppArmor: " fmt , # # args ) ; \
} while ( 0 )
2017-01-16 00:42:27 -08:00
# define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)
# define AA_BUG(X, args...) AA_BUG_FMT((X), "" args)
# ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS
# define AA_BUG_FMT(X, fmt, args...) \
WARN ( ( X ) , " AppArmor WARN %s: ( " # X " ): " fmt , __func__ , # # args )
# else
# define AA_BUG_FMT(X, fmt, args...)
# endif
2017-01-16 00:42:13 -08:00
# define AA_ERROR(fmt, args...) \
pr_err_ratelimited ( " AppArmor: " fmt , # # args )
/* Flag indicating whether initialization completed */
2017-04-06 06:55:23 -07:00
extern int apparmor_initialized ;
2017-01-16 00:42:13 -08:00
/* fn's in lib */
2017-05-22 02:47:22 -07:00
const char * skipn_spaces ( const char * str , size_t n ) ;
2017-01-16 00:42:13 -08:00
char * aa_split_fqname ( char * args , char * * ns_name ) ;
2017-01-16 00:42:23 -08:00
const char * aa_splitn_fqname ( const char * fqname , size_t n , const char * * ns_name ,
size_t * ns_len ) ;
2017-01-16 00:42:13 -08:00
void aa_info_message ( const char * str ) ;
/**
* aa_strneq - compare null terminated @ str to a non null terminated substring
* @ str : a null terminated string
* @ sub : a substring , not necessarily null terminated
* @ len : length of @ sub to compare
*
* The @ str string must be full consumed for this to be considered a match
*/
static inline bool aa_strneq ( const char * str , const char * sub , int len )
{
return ! strncmp ( str , sub , len ) & & ! str [ len ] ;
}
/**
* aa_dfa_null_transition - step to next state after null character
* @ dfa : the dfa to match against
* @ start : the state of the dfa to start matching in
*
* aa_dfa_null_transition transitions to the next state after a null
* character which is not used in standard matching and is only
* used to separate pairs .
*/
static inline unsigned int aa_dfa_null_transition ( struct aa_dfa * dfa ,
unsigned int start )
{
/* the null transition only needs the string's null terminator byte */
return aa_dfa_next ( dfa , start , 0 ) ;
}
2017-01-16 00:42:28 -08:00
static inline bool path_mediated_fs ( struct dentry * dentry )
2017-01-16 00:42:13 -08:00
{
2017-11-27 13:05:09 -08:00
return ! ( dentry - > d_sb - > s_flags & SB_NOUSER ) ;
2017-01-16 00:42:13 -08:00
}
2017-06-09 07:09:05 -07:00
struct counted_str {
struct kref count ;
char name [ ] ;
} ;
# define str_to_counted(str) \
( ( struct counted_str * ) ( str - offsetof ( struct counted_str , name ) ) )
# define __counted /* atm just a notation */
void aa_str_kref ( struct kref * kref ) ;
char * aa_str_alloc ( int size , gfp_t gfp ) ;
static inline __counted char * aa_get_str ( __counted char * str )
{
if ( str )
kref_get ( & ( str_to_counted ( str ) - > count ) ) ;
return str ;
}
static inline void aa_put_str ( __counted char * str )
{
if ( str )
kref_put ( & str_to_counted ( str ) - > count , aa_str_kref ) ;
}
2017-01-16 00:42:14 -08:00
/* struct aa_policy - common part of both namespaces and profiles
* @ name : name of the object
* @ hname - The hierarchical name
* @ list : list policy object is on
* @ profiles : head of the profiles list contained in the object
*/
struct aa_policy {
2017-01-16 00:42:30 -08:00
const char * name ;
2017-06-09 07:09:05 -07:00
__counted char * hname ;
2017-01-16 00:42:14 -08:00
struct list_head list ;
struct list_head profiles ;
} ;
/**
2017-01-16 00:42:29 -08:00
* basename - find the last component of an hname
2017-01-16 00:42:14 -08:00
* @ name : hname to find the base profile name component of ( NOT NULL )
*
* Returns : the tail ( base profile name ) name component of an hname
*/
2017-01-16 00:42:29 -08:00
static inline const char * basename ( const char * hname )
2017-01-16 00:42:14 -08:00
{
char * split ;
hname = strim ( ( char * ) hname ) ;
for ( split = strstr ( hname , " // " ) ; split ; split = strstr ( hname , " // " ) )
hname = split + 2 ;
return hname ;
}
/**
* __policy_find - find a policy by @ name on a policy list
* @ head : list to search ( NOT NULL )
* @ name : name to search for ( NOT NULL )
*
* Requires : rcu_read_lock be held
*
* Returns : unrefcounted policy that match @ name or NULL if not found
*/
static inline struct aa_policy * __policy_find ( struct list_head * head ,
const char * name )
{
struct aa_policy * policy ;
list_for_each_entry_rcu ( policy , head , list ) {
if ( ! strcmp ( policy - > name , name ) )
return policy ;
}
return NULL ;
}
/**
* __policy_strn_find - find a policy that ' s name matches @ len chars of @ str
* @ head : list to search ( NOT NULL )
* @ str : string to search for ( NOT NULL )
* @ len : length of match required
*
* Requires : rcu_read_lock be held
*
* Returns : unrefcounted policy that match @ str or NULL if not found
*
* if @ len = = strlen ( @ strlen ) then this is equiv to __policy_find
* other wise it allows searching for policy by a partial match of name
*/
static inline struct aa_policy * __policy_strn_find ( struct list_head * head ,
const char * str , int len )
{
struct aa_policy * policy ;
list_for_each_entry_rcu ( policy , head , list ) {
if ( aa_strneq ( policy - > name , str , len ) )
return policy ;
}
return NULL ;
}
bool aa_policy_init ( struct aa_policy * policy , const char * prefix ,
2017-01-16 00:42:31 -08:00
const char * name , gfp_t gfp ) ;
2017-01-16 00:42:14 -08:00
void aa_policy_destroy ( struct aa_policy * policy ) ;
2017-06-09 16:55:04 -07:00
/*
* fn_label_build - abstract out the build of a label transition
* @ L : label the transition is being computed for
* @ P : profile parameter derived from L by this macro , can be passed to FN
* @ GFP : memory allocation type to use
* @ FN : fn to call for each profile transition . @ P is set to the profile
*
* Returns : new label on success
* ERR_PTR if build @ FN fails
* NULL if label_build fails due to low memory conditions
*
* @ FN must return a label or ERR_PTR on failure . NULL is not allowed
*/
# define fn_label_build(L, P, GFP, FN) \
( { \
__label__ __cleanup , __done ; \
struct aa_label * __new_ ; \
\
if ( ( L ) - > size > 1 ) { \
/* TODO: add cache of transitions already done */ \
struct label_it __i ; \
int __j , __k , __count ; \
DEFINE_VEC ( label , __lvec ) ; \
DEFINE_VEC ( profile , __pvec ) ; \
if ( vec_setup ( label , __lvec , ( L ) - > size , ( GFP ) ) ) { \
__new_ = NULL ; \
goto __done ; \
} \
__j = 0 ; \
label_for_each ( __i , ( L ) , ( P ) ) { \
__new_ = ( FN ) ; \
AA_BUG ( ! __new_ ) ; \
if ( IS_ERR ( __new_ ) ) \
goto __cleanup ; \
__lvec [ __j + + ] = __new_ ; \
} \
for ( __j = __count = 0 ; __j < ( L ) - > size ; __j + + ) \
__count + = __lvec [ __j ] - > size ; \
if ( ! vec_setup ( profile , __pvec , __count , ( GFP ) ) ) { \
for ( __j = __k = 0 ; __j < ( L ) - > size ; __j + + ) { \
label_for_each ( __i , __lvec [ __j ] , ( P ) ) \
__pvec [ __k + + ] = aa_get_profile ( P ) ; \
} \
__count - = aa_vec_unique ( __pvec , __count , 0 ) ; \
if ( __count > 1 ) { \
__new_ = aa_vec_find_or_create_label ( __pvec , \
__count , ( GFP ) ) ; \
/* only fails if out of Mem */ \
if ( ! __new_ ) \
__new_ = NULL ; \
} else \
__new_ = aa_get_label ( & __pvec [ 0 ] - > label ) ; \
vec_cleanup ( profile , __pvec , __count ) ; \
} else \
__new_ = NULL ; \
__cleanup : \
vec_cleanup ( label , __lvec , ( L ) - > size ) ; \
} else { \
( P ) = labels_profile ( L ) ; \
__new_ = ( FN ) ; \
} \
__done : \
if ( ! __new_ ) \
AA_DEBUG ( " label build failed \n " ) ; \
( __new_ ) ; \
} )
# define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \
( { \
struct aa_label * __new ; \
if ( ( P ) - > ns ! = ( NS ) ) \
__new = ( OTHER_FN ) ; \
else \
__new = ( NS_FN ) ; \
( __new ) ; \
} )
# define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \
( { \
fn_label_build ( ( L ) , ( P ) , ( GFP ) , \
__fn_build_in_ns ( labels_ns ( L ) , ( P ) , ( NS_FN ) , ( OTHER_FN ) ) ) ; \
} )
# endif /* __AA_LIB_H */