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 .
*
* 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 .
*/
# include <linux/audit.h>
# include <linux/socket.h>
# include "include/apparmor.h"
# include "include/audit.h"
# include "include/policy.h"
2012-03-14 16:30:36 +04:00
const char * const op_table [ ] = {
2010-07-30 01:47:58 +04:00
" null " ,
" sysctl " ,
" capable " ,
" unlink " ,
" mkdir " ,
" rmdir " ,
" mknod " ,
" truncate " ,
" link " ,
" symlink " ,
" rename_src " ,
" rename_dest " ,
" chmod " ,
" chown " ,
" getattr " ,
" open " ,
" file_perm " ,
" file_lock " ,
" file_mmap " ,
" file_mprotect " ,
" create " ,
" post_create " ,
" bind " ,
" connect " ,
" listen " ,
" accept " ,
" sendmsg " ,
" recvmsg " ,
" getsockname " ,
" getpeername " ,
" getsockopt " ,
" setsockopt " ,
" socket_shutdown " ,
" ptrace " ,
" exec " ,
" change_hat " ,
" change_profile " ,
" change_onexec " ,
" setprocattr " ,
" setrlimit " ,
" profile_replace " ,
" profile_load " ,
" profile_remove "
} ;
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= " ) ;
2012-04-03 20:37:02 +04:00
audit_log_string ( ab , aa_audit_type [ sa - > aad - > type ] ) ;
2010-07-30 01:47:58 +04:00
}
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > op ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " operation= " ) ;
2012-04-03 20:37:02 +04:00
audit_log_string ( ab , op_table [ sa - > aad - > op ] ) ;
2010-07-30 01:47:58 +04:00
}
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > info ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " info= " ) ;
2012-04-03 20:37:02 +04:00
audit_log_string ( ab , sa - > aad - > info ) ;
if ( sa - > aad - > error )
audit_log_format ( ab , " error=%d " , sa - > aad - > error ) ;
2010-07-30 01:47:58 +04:00
}
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > profile ) {
struct aa_profile * profile = sa - > aad - > profile ;
2010-07-30 01:47:58 +04:00
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 ) ;
}
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > name ) {
2010-07-30 01:47:58 +04:00
audit_log_format ( ab , " name= " ) ;
2012-04-03 20:37:02 +04:00
audit_log_untrustedstring ( ab , sa - > aad - > 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 * ) )
{
2012-04-03 20:37:02 +04:00
sa - > aad - > 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 )
* @ gfp : allocation flags to use
* @ 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
*/
int aa_audit ( int type , struct aa_profile * profile , gfp_t gfp ,
struct common_audit_data * sa ,
void ( * cb ) ( struct audit_buffer * , void * ) )
{
BUG_ON ( ! profile ) ;
if ( type = = AUDIT_APPARMOR_AUTO ) {
2012-04-03 20:37:02 +04:00
if ( likely ( ! sa - > aad - > 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 ) )
2012-04-03 20:37:02 +04:00
return sa - > aad - > error ;
2010-07-30 01:47:58 +04:00
if ( KILL_MODE ( profile ) & & type = = AUDIT_APPARMOR_DENIED )
type = AUDIT_APPARMOR_KILL ;
if ( ! unconfined ( profile ) )
2012-04-03 20:37:02 +04:00
sa - > aad - > profile = profile ;
2010-07-30 01:47:58 +04:00
aa_audit_msg ( type , sa , cb ) ;
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > type = = AUDIT_APPARMOR_KILL )
2012-04-04 23:01:42 +04:00
( void ) send_sig_info ( SIGKILL , NULL ,
2013-10-08 16:37:26 +04:00
sa - > u . tsk ? sa - > u . tsk : current ) ;
2010-07-30 01:47:58 +04:00
2012-04-03 20:37:02 +04:00
if ( sa - > aad - > type = = AUDIT_APPARMOR_ALLOWED )
return complain_error ( sa - > aad - > error ) ;
2010-07-30 01:47:58 +04:00
2012-04-03 20:37:02 +04:00
return sa - > aad - > error ;
2010-07-30 01:47:58 +04:00
}