2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-07-30 01:47:58 +04:00
/*
* AppArmor security module
*
* This file contains AppArmor auditing functions
*
* Copyright ( C ) 1998 - 2008 Novell / SUSE
* Copyright 2009 - 2010 Canonical Ltd .
*/
# include <linux/audit.h>
# include <linux/socket.h>
# include "include/apparmor.h"
# include "include/audit.h"
# include "include/policy.h"
2017-01-16 11:42:15 +03:00
# include "include/policy_ns.h"
2018-04-16 21:23:58 +03:00
# include "include/secid.h"
2010-07-30 01:47:58 +04:00
2012-03-14 16:30:36 +04:00
const char * const audit_mode_names [ ] = {
2010-07-30 01:47:58 +04:00
" normal " ,
" quiet_denied " ,
" quiet " ,
" noquiet " ,
" all "
} ;
2012-03-14 16:30:36 +04:00
static const char * const aa_audit_type [ ] = {
2010-07-30 01:47:58 +04:00
" AUDIT " ,
" ALLOWED " ,
" DENIED " ,
" HINT " ,
" STATUS " ,
" ERROR " ,
2013-02-19 04:13:34 +04:00
" KILLED " ,
2012-02-22 12:20:26 +04:00
" AUTO "
2010-07-30 01:47:58 +04:00
} ;
/*
* Currently AppArmor auditing is fed straight into the audit framework .
*
* TODO :
* netlink interface for complain mode
* user auditing , - send user auditing to netlink interface
* system control of whether user audit messages go to system log
*/
/**
* audit_base - core AppArmor function .
* @ ab : audit buffer to fill ( NOT NULL )
* @ ca : audit structure containing data to audit ( NOT NULL )
*
* Record common AppArmor audit data from @ sa
*/
static void audit_pre ( struct audit_buffer * ab , void * ca )
{
struct common_audit_data * sa = ca ;
if ( aa_g_audit_header ) {
audit_log_format ( ab , " apparmor= " ) ;
2017-01-16 11:43:02 +03:00
audit_log_string ( ab , aa_audit_type [ aad ( sa ) - > type ] ) ;
2010-07-30 01:47:58 +04:00
}
2017-01-16 11:43:02 +03:00
if ( aad ( sa ) - > op ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " operation= " ) ;
2017-01-16 11:43:02 +03:00
audit_log_string ( ab , aad ( sa ) - > op ) ;
2010-07-30 01:47:58 +04:00
}
2017-01-16 11:43:02 +03:00
if ( aad ( sa ) - > info ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " info= " ) ;
2017-01-16 11:43:02 +03:00
audit_log_string ( ab , aad ( sa ) - > info ) ;
if ( aad ( sa ) - > error )
audit_log_format ( ab , " error=%d " , aad ( sa ) - > error ) ;
2010-07-30 01:47:58 +04:00
}
2017-06-09 18:14:28 +03:00
if ( aad ( sa ) - > label ) {
struct aa_label * label = aad ( sa ) - > label ;
if ( label_isprofile ( label ) ) {
struct aa_profile * profile = labels_profile ( label ) ;
if ( profile - > ns ! = root_ns ) {
audit_log_format ( ab , " namespace= " ) ;
audit_log_untrustedstring ( ab ,
profile - > ns - > base . hname ) ;
}
audit_log_format ( ab , " profile= " ) ;
audit_log_untrustedstring ( ab , profile - > base . hname ) ;
} else {
audit_log_format ( ab , " label= " ) ;
aa_label_xaudit ( ab , root_ns , label , FLAG_VIEW_SUBNS ,
GFP_ATOMIC ) ;
2010-07-30 01:47:58 +04:00
}
}
2017-01-16 11:43:02 +03:00
if ( aad ( sa ) - > name ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " name= " ) ;
2017-01-16 11:43:02 +03:00
audit_log_untrustedstring ( ab , aad ( sa ) - > name ) ;
2010-07-30 01:47:58 +04:00
}
}
/**
* aa_audit_msg - Log a message to the audit subsystem
* @ sa : audit event structure ( NOT NULL )
* @ cb : optional callback fn for type specific fields ( MAYBE NULL )
*/
void aa_audit_msg ( int type , struct common_audit_data * sa ,
void ( * cb ) ( struct audit_buffer * , void * ) )
{
2017-01-16 11:43:02 +03:00
aad ( sa ) - > type = type ;
2012-04-03 02:48:12 +04:00
common_lsm_audit ( sa , audit_pre , cb ) ;
2010-07-30 01:47:58 +04:00
}
/**
* aa_audit - Log a profile based audit event to the audit subsystem
* @ type : audit type for the message
* @ profile : profile to check against ( NOT NULL )
* @ sa : audit event ( NOT NULL )
* @ cb : optional callback fn for type specific fields ( MAYBE NULL )
*
* Handle default message switching based off of audit mode flags
*
* Returns : error on failure
*/
2017-01-16 11:43:02 +03:00
int aa_audit ( int type , struct aa_profile * profile , struct common_audit_data * sa ,
2010-07-30 01:47:58 +04:00
void ( * cb ) ( struct audit_buffer * , void * ) )
{
2017-01-16 11:43:15 +03:00
AA_BUG ( ! profile ) ;
2010-07-30 01:47:58 +04:00
if ( type = = AUDIT_APPARMOR_AUTO ) {
2017-01-16 11:43:02 +03:00
if ( likely ( ! aad ( sa ) - > error ) ) {
2010-07-30 01:47:58 +04:00
if ( AUDIT_MODE ( profile ) ! = AUDIT_ALL )
return 0 ;
type = AUDIT_APPARMOR_AUDIT ;
} else if ( COMPLAIN_MODE ( profile ) )
type = AUDIT_APPARMOR_ALLOWED ;
else
type = AUDIT_APPARMOR_DENIED ;
}
if ( AUDIT_MODE ( profile ) = = AUDIT_QUIET | |
( type = = AUDIT_APPARMOR_DENIED & &
AUDIT_MODE ( profile ) = = AUDIT_QUIET ) )
2017-01-16 11:43:02 +03:00
return aad ( sa ) - > error ;
2010-07-30 01:47:58 +04:00
if ( KILL_MODE ( profile ) & & type = = AUDIT_APPARMOR_DENIED )
type = AUDIT_APPARMOR_KILL ;
2017-06-09 18:14:28 +03:00
aad ( sa ) - > label = & profile - > label ;
2010-07-30 01:47:58 +04:00
aa_audit_msg ( type , sa , cb ) ;
2017-01-16 11:43:02 +03:00
if ( aad ( sa ) - > type = = AUDIT_APPARMOR_KILL )
2012-04-04 23:01:42 +04:00
( void ) send_sig_info ( SIGKILL , NULL ,
2014-06-08 22:20:54 +04:00
sa - > type = = LSM_AUDIT_DATA_TASK & & sa - > u . tsk ?
sa - > u . tsk : current ) ;
2010-07-30 01:47:58 +04:00
2017-01-16 11:43:02 +03:00
if ( aad ( sa ) - > type = = AUDIT_APPARMOR_ALLOWED )
return complain_error ( aad ( sa ) - > error ) ;
2010-07-30 01:47:58 +04:00
2017-01-16 11:43:02 +03:00
return aad ( sa ) - > error ;
2010-07-30 01:47:58 +04:00
}
2018-04-16 21:23:58 +03:00
struct aa_audit_rule {
2018-05-03 10:39:58 +03:00
struct aa_label * label ;
2018-04-16 21:23:58 +03:00
} ;
void aa_audit_rule_free ( void * vrule )
{
struct aa_audit_rule * rule = vrule ;
if ( rule ) {
2018-05-03 10:39:58 +03:00
if ( ! IS_ERR ( rule - > label ) )
aa_put_label ( rule - > label ) ;
2018-04-16 21:23:58 +03:00
kfree ( rule ) ;
}
}
int aa_audit_rule_init ( u32 field , u32 op , char * rulestr , void * * vrule )
{
struct aa_audit_rule * rule ;
switch ( field ) {
case AUDIT_SUBJ_ROLE :
if ( op ! = Audit_equal & & op ! = Audit_not_equal )
return - EINVAL ;
break ;
default :
return - EINVAL ;
}
rule = kzalloc ( sizeof ( struct aa_audit_rule ) , GFP_KERNEL ) ;
if ( ! rule )
return - ENOMEM ;
2018-05-03 10:39:58 +03:00
/* Currently rules are treated as coming from the root ns */
rule - > label = aa_label_parse ( & root_ns - > unconfined - > label , rulestr ,
GFP_KERNEL , true , false ) ;
2018-05-17 22:53:45 +03:00
if ( IS_ERR ( rule - > label ) ) {
aa_audit_rule_free ( rule ) ;
2018-05-03 10:39:58 +03:00
return PTR_ERR ( rule - > label ) ;
2018-05-17 22:53:45 +03:00
}
2018-04-16 21:23:58 +03:00
2018-05-17 22:53:45 +03:00
* vrule = rule ;
2018-04-16 21:23:58 +03:00
return 0 ;
}
int aa_audit_rule_known ( struct audit_krule * rule )
{
int i ;
for ( i = 0 ; i < rule - > field_count ; i + + ) {
struct audit_field * f = & rule - > fields [ i ] ;
switch ( f - > type ) {
case AUDIT_SUBJ_ROLE :
return 1 ;
}
}
return 0 ;
}
2019-01-31 19:52:11 +03:00
int aa_audit_rule_match ( u32 sid , u32 field , u32 op , void * vrule )
2018-04-16 21:23:58 +03:00
{
struct aa_audit_rule * rule = vrule ;
struct aa_label * label ;
int found = 0 ;
label = aa_secid_to_label ( sid ) ;
if ( ! label )
return - ENOENT ;
2018-05-03 10:39:58 +03:00
if ( aa_label_is_subset ( label , rule - > label ) )
found = 1 ;
2018-04-16 21:23:58 +03:00
switch ( field ) {
case AUDIT_SUBJ_ROLE :
switch ( op ) {
case Audit_equal :
return found ;
case Audit_not_equal :
return ! found ;
}
}
return 0 ;
}