2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2017-07-19 09:18:33 +03:00
/*
* AppArmor security module
*
* This file contains AppArmor network mediation
*
* Copyright ( C ) 1998 - 2008 Novell / SUSE
* Copyright 2009 - 2017 Canonical Ltd .
*/
# include "include/apparmor.h"
# include "include/audit.h"
# include "include/cred.h"
# include "include/label.h"
# include "include/net.h"
# include "include/policy.h"
2018-05-24 23:27:47 +03:00
# include "include/secid.h"
2017-07-19 09:18:33 +03:00
# include "net_names.h"
struct aa_sfs_entry aa_sfs_entry_network [ ] = {
AA_SFS_FILE_STRING ( " af_mask " , AA_SFS_AF_MASK ) ,
{ }
} ;
static const char * const net_mask_names [ ] = {
" unknown " ,
" send " ,
" receive " ,
" unknown " ,
" create " ,
" shutdown " ,
" connect " ,
" unknown " ,
" setattr " ,
" getattr " ,
" setcred " ,
" getcred " ,
" chmod " ,
" chown " ,
" chgrp " ,
" lock " ,
" mmap " ,
" mprot " ,
" unknown " ,
" unknown " ,
" accept " ,
" bind " ,
" listen " ,
" unknown " ,
" setopt " ,
" getopt " ,
" unknown " ,
" unknown " ,
" unknown " ,
" unknown " ,
" unknown " ,
" unknown " ,
} ;
/* audit callback for net specific fields */
void audit_net_cb ( struct audit_buffer * ab , void * va )
{
struct common_audit_data * sa = va ;
2022-09-14 10:20:12 +03:00
struct apparmor_audit_data * ad = aad ( sa ) ;
2017-07-19 09:18:33 +03:00
if ( address_family_names [ sa - > u . net - > family ] )
2020-07-13 22:51:59 +03:00
audit_log_format ( ab , " family= \" %s \" " ,
address_family_names [ sa - > u . net - > family ] ) ;
2017-07-19 09:18:33 +03:00
else
2020-07-13 22:51:59 +03:00
audit_log_format ( ab , " family= \" unknown(%d) \" " ,
sa - > u . net - > family ) ;
2022-09-14 10:20:12 +03:00
if ( sock_type_names [ ad - > net . type ] )
2020-07-13 22:51:59 +03:00
audit_log_format ( ab , " sock_type= \" %s \" " ,
2022-09-14 10:20:12 +03:00
sock_type_names [ ad - > net . type ] ) ;
2017-07-19 09:18:33 +03:00
else
2020-07-13 22:51:59 +03:00
audit_log_format ( ab , " sock_type= \" unknown(%d) \" " ,
2022-09-14 10:20:12 +03:00
ad - > net . type ) ;
audit_log_format ( ab , " protocol=%d " , ad - > net . protocol ) ;
2017-07-19 09:18:33 +03:00
2022-09-14 10:20:12 +03:00
if ( ad - > request & NET_PERMS_MASK ) {
2017-07-19 09:18:33 +03:00
audit_log_format ( ab , " requested_mask= " ) ;
2022-09-14 10:20:12 +03:00
aa_audit_perm_mask ( ab , ad - > request , NULL , 0 ,
2017-07-19 09:18:33 +03:00
net_mask_names , NET_PERMS_MASK ) ;
2022-09-14 10:20:12 +03:00
if ( ad - > denied & NET_PERMS_MASK ) {
2017-07-19 09:18:33 +03:00
audit_log_format ( ab , " denied_mask= " ) ;
2022-09-14 10:20:12 +03:00
aa_audit_perm_mask ( ab , ad - > denied , NULL , 0 ,
2017-07-19 09:18:33 +03:00
net_mask_names , NET_PERMS_MASK ) ;
}
}
2022-09-14 10:20:12 +03:00
if ( ad - > peer ) {
2017-07-19 09:18:33 +03:00
audit_log_format ( ab , " peer= " ) ;
2022-09-19 10:46:09 +03:00
aa_label_xaudit ( ab , labels_ns ( ad - > subj_label ) , ad - > peer ,
2017-07-19 09:18:33 +03:00
FLAGS_NONE , GFP_ATOMIC ) ;
}
}
/* Generic af perm */
2022-09-14 10:20:12 +03:00
int aa_profile_af_perm ( struct aa_profile * profile ,
struct apparmor_audit_data * ad , u32 request , u16 family ,
int type )
2017-07-19 09:18:33 +03:00
{
2022-09-06 06:47:36 +03:00
struct aa_ruleset * rules = list_first_entry ( & profile - > rules ,
typeof ( * rules ) , list ) ;
2017-07-19 09:18:33 +03:00
struct aa_perms perms = { } ;
2022-01-18 00:43:49 +03:00
aa_state_t state ;
2017-07-19 09:18:33 +03:00
__be16 buffer [ 2 ] ;
AA_BUG ( family > = AF_MAX ) ;
AA_BUG ( type < 0 | | type > = SOCK_MAX ) ;
if ( profile_unconfined ( profile ) )
return 0 ;
2022-07-30 03:17:31 +03:00
state = RULE_MEDIATES ( rules , AA_CLASS_NET ) ;
2017-07-19 09:18:33 +03:00
if ( ! state )
return 0 ;
buffer [ 0 ] = cpu_to_be16 ( family ) ;
buffer [ 1 ] = cpu_to_be16 ( ( u16 ) type ) ;
2023-04-28 15:32:52 +03:00
state = aa_dfa_match_len ( rules - > policy - > dfa , state , ( char * ) & buffer ,
2017-07-19 09:18:33 +03:00
4 ) ;
2023-04-28 15:32:52 +03:00
perms = * aa_lookup_perms ( rules - > policy , state ) ;
2017-07-19 09:18:33 +03:00
aa_apply_modes_to_perms ( profile , & perms ) ;
2022-09-14 10:20:12 +03:00
return aa_check_perms ( profile , & perms , request , ad , audit_net_cb ) ;
2017-07-19 09:18:33 +03:00
}
2022-09-20 06:48:48 +03:00
int aa_af_perm ( const struct cred * subj_cred , struct aa_label * label ,
const char * op , u32 request , u16 family , int type , int protocol )
2017-07-19 09:18:33 +03:00
{
struct aa_profile * profile ;
2022-09-14 10:20:12 +03:00
DEFINE_AUDIT_NET ( ad , op , NULL , family , type , protocol ) ;
2017-07-19 09:18:33 +03:00
return fn_for_each_confined ( label , profile ,
2022-09-14 10:20:12 +03:00
aa_profile_af_perm ( profile , & ad , request , family ,
2017-07-19 09:18:33 +03:00
type ) ) ;
}
2022-09-20 06:48:48 +03:00
static int aa_label_sk_perm ( const struct cred * subj_cred ,
struct aa_label * label ,
const char * op , u32 request ,
2017-07-19 09:18:33 +03:00
struct sock * sk )
{
2022-05-24 12:38:12 +03:00
struct aa_sk_ctx * ctx = SK_CTX ( sk ) ;
2018-09-07 07:33:57 +03:00
int error = 0 ;
2017-07-19 09:18:33 +03:00
AA_BUG ( ! label ) ;
AA_BUG ( ! sk ) ;
2022-05-24 12:38:12 +03:00
if ( ctx - > label ! = kernel_t & & ! unconfined ( label ) ) {
2018-09-07 07:33:57 +03:00
struct aa_profile * profile ;
2022-09-14 10:20:12 +03:00
DEFINE_AUDIT_SK ( ad , op , sk ) ;
2017-07-19 09:18:33 +03:00
2022-09-20 06:48:48 +03:00
ad . subj_cred = subj_cred ;
2018-09-07 07:33:57 +03:00
error = fn_for_each_confined ( label , profile ,
2022-09-14 10:20:12 +03:00
aa_profile_af_sk_perm ( profile , & ad , request , sk ) ) ;
2018-09-07 07:33:57 +03:00
}
return error ;
2017-07-19 09:18:33 +03:00
}
int aa_sk_perm ( const char * op , u32 request , struct sock * sk )
{
struct aa_label * label ;
int error ;
AA_BUG ( ! sk ) ;
AA_BUG ( in_interrupt ( ) ) ;
/* TODO: switch to begin_current_label ???? */
label = begin_current_label_crit_section ( ) ;
2022-09-20 06:48:48 +03:00
error = aa_label_sk_perm ( current_cred ( ) , label , op , request , sk ) ;
2017-07-19 09:18:33 +03:00
end_current_label_crit_section ( label ) ;
return error ;
}
2022-09-20 06:48:48 +03:00
int aa_sock_file_perm ( const struct cred * subj_cred , struct aa_label * label ,
const char * op , u32 request , struct socket * sock )
2017-07-19 09:18:33 +03:00
{
AA_BUG ( ! label ) ;
AA_BUG ( ! sock ) ;
AA_BUG ( ! sock - > sk ) ;
2022-09-20 06:48:48 +03:00
return aa_label_sk_perm ( subj_cred , label , op , request , sock - > sk ) ;
2017-07-19 09:18:33 +03:00
}
2018-05-24 23:27:47 +03:00
2018-10-05 19:11:47 +03:00
# ifdef CONFIG_NETWORK_SECMARK
2018-05-24 23:27:47 +03:00
static int apparmor_secmark_init ( struct aa_secmark * secmark )
{
struct aa_label * label ;
if ( secmark - > label [ 0 ] = = ' * ' ) {
secmark - > secid = AA_SECID_WILDCARD ;
return 0 ;
}
label = aa_label_strn_parse ( & root_ns - > unconfined - > label ,
secmark - > label , strlen ( secmark - > label ) ,
GFP_ATOMIC , false , false ) ;
if ( IS_ERR ( label ) )
return PTR_ERR ( label ) ;
secmark - > secid = label - > secid ;
return 0 ;
}
static int aa_secmark_perm ( struct aa_profile * profile , u32 request , u32 secid ,
2022-09-14 10:20:12 +03:00
struct apparmor_audit_data * ad )
2018-05-24 23:27:47 +03:00
{
int i , ret ;
struct aa_perms perms = { } ;
2022-09-06 06:47:36 +03:00
struct aa_ruleset * rules = list_first_entry ( & profile - > rules ,
typeof ( * rules ) , list ) ;
2018-05-24 23:27:47 +03:00
2022-07-30 03:17:31 +03:00
if ( rules - > secmark_count = = 0 )
2018-05-24 23:27:47 +03:00
return 0 ;
2022-07-30 03:17:31 +03:00
for ( i = 0 ; i < rules - > secmark_count ; i + + ) {
if ( ! rules - > secmark [ i ] . secid ) {
ret = apparmor_secmark_init ( & rules - > secmark [ i ] ) ;
2018-05-24 23:27:47 +03:00
if ( ret )
return ret ;
}
2022-07-30 03:17:31 +03:00
if ( rules - > secmark [ i ] . secid = = secid | |
rules - > secmark [ i ] . secid = = AA_SECID_WILDCARD ) {
if ( rules - > secmark [ i ] . deny )
2018-05-24 23:27:47 +03:00
perms . deny = ALL_PERMS_MASK ;
else
perms . allow = ALL_PERMS_MASK ;
2022-07-30 03:17:31 +03:00
if ( rules - > secmark [ i ] . audit )
2018-05-24 23:27:47 +03:00
perms . audit = ALL_PERMS_MASK ;
}
}
aa_apply_modes_to_perms ( profile , & perms ) ;
2022-09-14 10:20:12 +03:00
return aa_check_perms ( profile , & perms , request , ad , audit_net_cb ) ;
2018-05-24 23:27:47 +03:00
}
int apparmor_secmark_check ( struct aa_label * label , char * op , u32 request ,
2020-11-30 18:36:29 +03:00
u32 secid , const struct sock * sk )
2018-05-24 23:27:47 +03:00
{
struct aa_profile * profile ;
2022-09-14 10:20:12 +03:00
DEFINE_AUDIT_SK ( ad , op , sk ) ;
2018-05-24 23:27:47 +03:00
return fn_for_each_confined ( label , profile ,
aa_secmark_perm ( profile , request , secid ,
2022-09-14 10:20:12 +03:00
& ad ) ) ;
2018-05-24 23:27:47 +03:00
}
2018-10-05 19:11:47 +03:00
# endif