2010-07-30 01:47:57 +04:00
/*
* AppArmor security module
*
* This file contains basic common functions used in AppArmor
*
* Copyright ( C ) 1998 - 2008 Novell / SUSE
* Copyright 2009 - 2010 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 .
*/
2017-01-16 11:42:23 +03:00
# include <linux/ctype.h>
2011-06-16 15:01:34 +04:00
# include <linux/mm.h>
2010-07-30 01:47:57 +04:00
# include <linux/slab.h>
# include <linux/string.h>
# include <linux/vmalloc.h>
# include "include/audit.h"
2011-08-29 05:15:25 +04:00
# include "include/apparmor.h"
2017-01-16 11:42:13 +03:00
# include "include/lib.h"
2017-01-16 11:42:14 +03:00
# include "include/policy.h"
2010-07-30 01:47:57 +04:00
/**
* aa_split_fqname - split a fqname into a profile and namespace name
* @ fqname : a full qualified name in namespace profile format ( NOT NULL )
* @ ns_name : pointer to portion of the string containing the ns name ( NOT NULL )
*
* Returns : profile name or NULL if one is not specified
*
* Split a namespace name from a profile name ( see policy . c for naming
* description ) . If a portion of the name is missing it returns NULL for
* that portion .
*
* NOTE : may modify the @ fqname string . The pointers returned point
* into the @ fqname string .
*/
char * aa_split_fqname ( char * fqname , char * * ns_name )
{
char * name = strim ( fqname ) ;
* ns_name = NULL ;
if ( name [ 0 ] = = ' : ' ) {
char * split = strchr ( & name [ 1 ] , ' : ' ) ;
2010-08-28 05:33:28 +04:00
* ns_name = skip_spaces ( & name [ 1 ] ) ;
2010-07-30 01:47:57 +04:00
if ( split ) {
/* overwrite ':' with \0 */
2013-02-27 15:45:05 +04:00
* split + + = 0 ;
if ( strncmp ( split , " // " , 2 ) = = 0 )
split + = 2 ;
name = skip_spaces ( split ) ;
2010-07-30 01:47:57 +04:00
} else
/* a ns name without a following profile is allowed */
name = NULL ;
}
if ( name & & * name = = 0 )
name = NULL ;
return name ;
}
2017-01-16 11:42:23 +03:00
/**
* skipn_spaces - Removes leading whitespace from @ str .
* @ str : The string to be stripped .
*
* Returns a pointer to the first non - whitespace character in @ str .
* if all whitespace will return NULL
*/
2017-05-22 12:47:22 +03:00
const char * skipn_spaces ( const char * str , size_t n )
2017-01-16 11:42:23 +03:00
{
for ( ; n & & isspace ( * str ) ; - - n )
+ + str ;
if ( n )
return ( char * ) str ;
return NULL ;
}
const char * aa_splitn_fqname ( const char * fqname , size_t n , const char * * ns_name ,
size_t * ns_len )
{
const char * end = fqname + n ;
const char * name = skipn_spaces ( fqname , n ) ;
if ( ! name )
return NULL ;
* ns_name = NULL ;
* ns_len = 0 ;
if ( name [ 0 ] = = ' : ' ) {
char * split = strnchr ( & name [ 1 ] , end - & name [ 1 ] , ' : ' ) ;
* ns_name = skipn_spaces ( & name [ 1 ] , end - & name [ 1 ] ) ;
if ( ! * ns_name )
return NULL ;
if ( split ) {
* ns_len = split - * ns_name ;
if ( * ns_len = = 0 )
* ns_name = NULL ;
split + + ;
if ( end - split > 1 & & strncmp ( split , " // " , 2 ) = = 0 )
split + = 2 ;
name = skipn_spaces ( split , end - split ) ;
} else {
/* a ns name without a following profile is allowed */
name = NULL ;
* ns_len = end - * ns_name ;
}
}
if ( name & & * name = = 0 )
name = NULL ;
return name ;
}
2010-07-30 01:47:57 +04:00
/**
* aa_info_message - log a none profile related status message
* @ str : message to log
*/
void aa_info_message ( const char * str )
{
if ( audit_enabled ) {
2017-01-16 11:43:02 +03:00
DEFINE_AUDIT_DATA ( sa , LSM_AUDIT_DATA_NONE , NULL ) ;
aad ( & sa ) - > info = str ;
2010-07-30 01:47:57 +04:00
aa_audit_msg ( AUDIT_APPARMOR_STATUS , & sa , NULL ) ;
}
printk ( KERN_INFO " AppArmor: %s \n " , str ) ;
}
2017-01-16 11:42:14 +03:00
/**
* aa_policy_init - initialize a policy structure
* @ policy : policy to initialize ( NOT NULL )
* @ prefix : prefix name if any is required . ( MAYBE NULL )
* @ name : name of the policy , init will make a copy of it ( NOT NULL )
*
* Note : this fn creates a copy of strings passed in
*
* Returns : true if policy init successful
*/
bool aa_policy_init ( struct aa_policy * policy , const char * prefix ,
2017-01-16 11:42:31 +03:00
const char * name , gfp_t gfp )
2017-01-16 11:42:14 +03:00
{
/* freed by policy_free */
if ( prefix ) {
policy - > hname = kmalloc ( strlen ( prefix ) + strlen ( name ) + 3 ,
2017-01-16 11:42:31 +03:00
gfp ) ;
2017-01-16 11:42:14 +03:00
if ( policy - > hname )
2017-01-16 11:42:30 +03:00
sprintf ( ( char * ) policy - > hname , " %s//%s " , prefix , name ) ;
2017-01-16 11:42:14 +03:00
} else
2017-01-16 11:42:31 +03:00
policy - > hname = kstrdup ( name , gfp ) ;
2017-01-16 11:42:14 +03:00
if ( ! policy - > hname )
2017-04-06 16:55:19 +03:00
return false ;
2017-01-16 11:42:14 +03:00
/* base.name is a substring of fqname */
2017-01-16 11:42:31 +03:00
policy - > name = basename ( policy - > hname ) ;
2017-01-16 11:42:14 +03:00
INIT_LIST_HEAD ( & policy - > list ) ;
INIT_LIST_HEAD ( & policy - > profiles ) ;
2017-04-06 16:55:19 +03:00
return true ;
2017-01-16 11:42:14 +03:00
}
/**
* aa_policy_destroy - free the elements referenced by @ policy
* @ policy : policy that is to have its elements freed ( NOT NULL )
*/
void aa_policy_destroy ( struct aa_policy * policy )
{
2017-01-16 11:42:32 +03:00
AA_BUG ( on_list_rcu ( & policy - > profiles ) ) ;
AA_BUG ( on_list_rcu ( & policy - > list ) ) ;
2017-01-16 11:42:14 +03:00
/* don't free name as its a subset of hname */
kzfree ( policy - > hname ) ;
}