2010-07-30 01:48:07 +04:00
/*
* AppArmor security module
*
* This file contains AppArmor LSM hooks .
*
* 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 .
*/
2015-05-03 01:10:46 +03:00
# include <linux/lsm_hooks.h>
2010-07-30 01:48:07 +04:00
# include <linux/moduleparam.h>
# include <linux/mm.h>
# include <linux/mman.h>
# include <linux/mount.h>
# include <linux/namei.h>
# include <linux/ptrace.h>
# include <linux/ctype.h>
# include <linux/sysctl.h>
# include <linux/audit.h>
userns: security: make capabilities relative to the user namespace
- Introduce ns_capable to test for a capability in a non-default
user namespace.
- Teach cap_capable to handle capabilities in a non-default
user namespace.
The motivation is to get to the unprivileged creation of new
namespaces. It looks like this gets us 90% of the way there, with
only potential uid confusion issues left.
I still need to handle getting all caps after creation but otherwise I
think I have a good starter patch that achieves all of your goals.
Changelog:
11/05/2010: [serge] add apparmor
12/14/2010: [serge] fix capabilities to created user namespaces
Without this, if user serge creates a user_ns, he won't have
capabilities to the user_ns he created. THis is because we
were first checking whether his effective caps had the caps
he needed and returning -EPERM if not, and THEN checking whether
he was the creator. Reverse those checks.
12/16/2010: [serge] security_real_capable needs ns argument in !security case
01/11/2011: [serge] add task_ns_capable helper
01/11/2011: [serge] add nsown_capable() helper per Bastian Blank suggestion
02/16/2011: [serge] fix a logic bug: the root user is always creator of
init_user_ns, but should not always have capabilities to
it! Fix the check in cap_capable().
02/21/2011: Add the required user_ns parameter to security_capable,
fixing a compile failure.
02/23/2011: Convert some macros to functions as per akpm comments. Some
couldn't be converted because we can't easily forward-declare
them (they are inline if !SECURITY, extern if SECURITY). Add
a current_user_ns function so we can use it in capability.h
without #including cred.h. Move all forward declarations
together to the top of the #ifdef __KERNEL__ section, and use
kernel-doc format.
02/23/2011: Per dhowells, clean up comment in cap_capable().
02/23/2011: Per akpm, remove unreachable 'return -EPERM' in cap_capable.
(Original written and signed off by Eric; latest, modified version
acked by him)
[akpm@linux-foundation.org: fix build]
[akpm@linux-foundation.org: export current_user_ns() for ecryptfs]
[serge.hallyn@canonical.com: remove unneeded extra argument in selinux's task_has_capability]
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Acked-by: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-03-24 02:43:17 +03:00
# include <linux/user_namespace.h>
2017-01-16 03:49:28 +03:00
# include <linux/kmemleak.h>
2010-07-30 01:48:07 +04:00
# include <net/sock.h>
# include "include/apparmor.h"
# include "include/apparmorfs.h"
# include "include/audit.h"
# include "include/capability.h"
# include "include/context.h"
# include "include/file.h"
# include "include/ipc.h"
# include "include/path.h"
# include "include/policy.h"
2017-01-16 11:42:15 +03:00
# include "include/policy_ns.h"
2010-07-30 01:48:07 +04:00
# include "include/procattr.h"
/* Flag indicating whether initialization completed */
2017-04-06 16:55:23 +03:00
int apparmor_initialized ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:10 +03:00
DEFINE_PER_CPU ( struct aa_buffers , aa_buffers ) ;
2010-07-30 01:48:07 +04:00
/*
* LSM hook functions
*/
/*
2017-01-16 11:43:00 +03:00
* free the associated aa_task_ctx and put its profiles
2010-07-30 01:48:07 +04:00
*/
static void apparmor_cred_free ( struct cred * cred )
{
2017-01-16 11:43:00 +03:00
aa_free_task_context ( cred_ctx ( cred ) ) ;
cred_ctx ( cred ) = NULL ;
2010-07-30 01:48:07 +04:00
}
/*
* allocate the apparmor part of blank credentials
*/
static int apparmor_cred_alloc_blank ( struct cred * cred , gfp_t gfp )
{
/* freed by apparmor_cred_free */
2017-01-16 11:43:00 +03:00
struct aa_task_ctx * ctx = aa_alloc_task_context ( gfp ) ;
if ( ! ctx )
2010-07-30 01:48:07 +04:00
return - ENOMEM ;
2017-01-16 11:43:00 +03:00
cred_ctx ( cred ) = ctx ;
2010-07-30 01:48:07 +04:00
return 0 ;
}
/*
2017-01-16 11:43:00 +03:00
* prepare new aa_task_ctx for modification by prepare_cred block
2010-07-30 01:48:07 +04:00
*/
static int apparmor_cred_prepare ( struct cred * new , const struct cred * old ,
gfp_t gfp )
{
/* freed by apparmor_cred_free */
2017-01-16 11:43:00 +03:00
struct aa_task_ctx * ctx = aa_alloc_task_context ( gfp ) ;
if ( ! ctx )
2010-07-30 01:48:07 +04:00
return - ENOMEM ;
2017-01-16 11:43:00 +03:00
aa_dup_task_context ( ctx , cred_ctx ( old ) ) ;
cred_ctx ( new ) = ctx ;
2010-07-30 01:48:07 +04:00
return 0 ;
}
/*
* transfer the apparmor data to a blank set of creds
*/
static void apparmor_cred_transfer ( struct cred * new , const struct cred * old )
{
2017-01-16 11:43:00 +03:00
const struct aa_task_ctx * old_ctx = cred_ctx ( old ) ;
struct aa_task_ctx * new_ctx = cred_ctx ( new ) ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:00 +03:00
aa_dup_task_context ( new_ctx , old_ctx ) ;
2010-07-30 01:48:07 +04:00
}
static int apparmor_ptrace_access_check ( struct task_struct * child ,
unsigned int mode )
{
return aa_ptrace ( current , child , mode ) ;
}
static int apparmor_ptrace_traceme ( struct task_struct * parent )
{
return aa_ptrace ( parent , current , PTRACE_MODE_ATTACH ) ;
}
/* Derived from security/commoncap.c:cap_capget */
static int apparmor_capget ( struct task_struct * target , kernel_cap_t * effective ,
kernel_cap_t * inheritable , kernel_cap_t * permitted )
{
struct aa_profile * profile ;
const struct cred * cred ;
rcu_read_lock ( ) ;
cred = __task_cred ( target ) ;
profile = aa_cred_profile ( cred ) ;
2015-05-03 01:11:42 +03:00
/*
* cap_capget is stacked ahead of this and will
* initialize effective and permitted .
*/
2011-06-25 19:57:07 +04:00
if ( ! unconfined ( profile ) & & ! COMPLAIN_MODE ( profile ) ) {
2010-07-30 01:48:07 +04:00
* effective = cap_intersect ( * effective , profile - > caps . allow ) ;
* permitted = cap_intersect ( * permitted , profile - > caps . allow ) ;
}
rcu_read_unlock ( ) ;
return 0 ;
}
2012-01-03 21:25:14 +04:00
static int apparmor_capable ( const struct cred * cred , struct user_namespace * ns ,
int cap , int audit )
2010-07-30 01:48:07 +04:00
{
struct aa_profile * profile ;
2015-05-03 01:11:42 +03:00
int error = 0 ;
profile = aa_cred_profile ( cred ) ;
if ( ! unconfined ( profile ) )
error = aa_capable ( profile , cap , audit ) ;
2010-07-30 01:48:07 +04:00
return error ;
}
/**
* common_perm - basic common permission check wrapper fn for paths
* @ op : operation being checked
* @ path : path to check permission of ( NOT NULL )
* @ mask : requested permissions mask
* @ cond : conditional info for the permission request ( NOT NULL )
*
* Returns : % 0 else error code if error or permission denied
*/
2017-01-16 11:43:01 +03:00
static int common_perm ( const char * op , const struct path * path , u32 mask ,
2010-07-30 01:48:07 +04:00
struct path_cond * cond )
{
struct aa_profile * profile ;
int error = 0 ;
profile = __aa_current_profile ( ) ;
if ( ! unconfined ( profile ) )
error = aa_path_perm ( op , profile , path , 0 , mask , cond ) ;
return error ;
}
/**
2017-01-16 11:43:07 +03:00
* common_perm_cond - common permission wrapper around inode cond
2010-07-30 01:48:07 +04:00
* @ op : operation being checked
2017-01-16 11:43:07 +03:00
* @ path : location to check ( NOT NULL )
2010-07-30 01:48:07 +04:00
* @ mask : requested permissions mask
*
* Returns : % 0 else error code if error or permission denied
*/
2017-01-16 11:43:07 +03:00
static int common_perm_cond ( const char * op , const struct path * path , u32 mask )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:07 +03:00
struct path_cond cond = { d_backing_inode ( path - > dentry ) - > i_uid ,
d_backing_inode ( path - > dentry ) - > i_mode
} ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:07 +03:00
if ( ! path_mediated_fs ( path - > dentry ) )
return 0 ;
return common_perm ( op , path , mask , & cond ) ;
2010-07-30 01:48:07 +04:00
}
/**
2017-01-16 11:43:07 +03:00
* common_perm_dir_dentry - common permission wrapper when path is dir , dentry
2010-07-30 01:48:07 +04:00
* @ op : operation being checked
2017-01-16 11:43:07 +03:00
* @ dir : directory of the dentry ( NOT NULL )
* @ dentry : dentry to check ( NOT NULL )
2010-07-30 01:48:07 +04:00
* @ mask : requested permissions mask
2017-01-16 11:43:07 +03:00
* @ cond : conditional info for the permission request ( NOT NULL )
2010-07-30 01:48:07 +04:00
*
* Returns : % 0 else error code if error or permission denied
*/
2017-01-16 11:43:07 +03:00
static int common_perm_dir_dentry ( const char * op , const struct path * dir ,
struct dentry * dentry , u32 mask ,
struct path_cond * cond )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:07 +03:00
struct path path = { . mnt = dir - > mnt , . dentry = dentry } ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:07 +03:00
return common_perm ( op , & path , mask , cond ) ;
2010-07-30 01:48:07 +04:00
}
/**
* common_perm_rm - common permission wrapper for operations doing rm
* @ op : operation being checked
* @ dir : directory that the dentry is in ( NOT NULL )
* @ dentry : dentry being rm ' d ( NOT NULL )
* @ mask : requested permission mask
*
* Returns : % 0 else error code if error or permission denied
*/
2017-01-16 11:43:01 +03:00
static int common_perm_rm ( const char * op , const struct path * dir ,
2010-07-30 01:48:07 +04:00
struct dentry * dentry , u32 mask )
{
2015-03-18 01:26:22 +03:00
struct inode * inode = d_backing_inode ( dentry ) ;
2010-07-30 01:48:07 +04:00
struct path_cond cond = { } ;
2017-01-16 11:42:28 +03:00
if ( ! inode | | ! path_mediated_fs ( dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
cond . uid = inode - > i_uid ;
cond . mode = inode - > i_mode ;
return common_perm_dir_dentry ( op , dir , dentry , mask , & cond ) ;
}
/**
* common_perm_create - common permission wrapper for operations doing create
* @ op : operation being checked
* @ dir : directory that dentry will be created in ( NOT NULL )
* @ dentry : dentry to create ( NOT NULL )
* @ mask : request permission mask
* @ mode : created file mode
*
* Returns : % 0 else error code if error or permission denied
*/
2017-01-16 11:43:01 +03:00
static int common_perm_create ( const char * op , const struct path * dir ,
2016-03-25 22:10:04 +03:00
struct dentry * dentry , u32 mask , umode_t mode )
2010-07-30 01:48:07 +04:00
{
struct path_cond cond = { current_fsuid ( ) , mode } ;
2017-01-16 11:42:28 +03:00
if ( ! path_mediated_fs ( dir - > dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
return common_perm_dir_dentry ( op , dir , dentry , mask , & cond ) ;
}
2016-03-25 22:13:39 +03:00
static int apparmor_path_unlink ( const struct path * dir , struct dentry * dentry )
2010-07-30 01:48:07 +04:00
{
return common_perm_rm ( OP_UNLINK , dir , dentry , AA_MAY_DELETE ) ;
}
2016-03-25 22:21:09 +03:00
static int apparmor_path_mkdir ( const struct path * dir , struct dentry * dentry ,
2011-11-21 23:56:21 +04:00
umode_t mode )
2010-07-30 01:48:07 +04:00
{
return common_perm_create ( OP_MKDIR , dir , dentry , AA_MAY_CREATE ,
S_IFDIR ) ;
}
2016-03-25 22:13:39 +03:00
static int apparmor_path_rmdir ( const struct path * dir , struct dentry * dentry )
2010-07-30 01:48:07 +04:00
{
return common_perm_rm ( OP_RMDIR , dir , dentry , AA_MAY_DELETE ) ;
}
2016-03-25 22:21:09 +03:00
static int apparmor_path_mknod ( const struct path * dir , struct dentry * dentry ,
2011-11-21 23:58:38 +04:00
umode_t mode , unsigned int dev )
2010-07-30 01:48:07 +04:00
{
return common_perm_create ( OP_MKNOD , dir , dentry , AA_MAY_CREATE , mode ) ;
}
2016-03-25 21:22:01 +03:00
static int apparmor_path_truncate ( const struct path * path )
2010-07-30 01:48:07 +04:00
{
2017-05-27 01:07:22 +03:00
return common_perm_cond ( OP_TRUNC , path , MAY_WRITE | AA_MAY_SETATTR ) ;
2010-07-30 01:48:07 +04:00
}
2016-03-25 22:21:09 +03:00
static int apparmor_path_symlink ( const struct path * dir , struct dentry * dentry ,
2010-07-30 01:48:07 +04:00
const char * old_name )
{
return common_perm_create ( OP_SYMLINK , dir , dentry , AA_MAY_CREATE ,
S_IFLNK ) ;
}
2016-03-25 22:27:45 +03:00
static int apparmor_path_link ( struct dentry * old_dentry , const struct path * new_dir ,
2010-07-30 01:48:07 +04:00
struct dentry * new_dentry )
{
struct aa_profile * profile ;
int error = 0 ;
2017-01-16 11:42:28 +03:00
if ( ! path_mediated_fs ( old_dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
profile = aa_current_profile ( ) ;
if ( ! unconfined ( profile ) )
error = aa_path_link ( profile , old_dentry , new_dir , new_dentry ) ;
return error ;
}
2016-03-25 22:27:45 +03:00
static int apparmor_path_rename ( const struct path * old_dir , struct dentry * old_dentry ,
const struct path * new_dir , struct dentry * new_dentry )
2010-07-30 01:48:07 +04:00
{
struct aa_profile * profile ;
int error = 0 ;
2017-01-16 11:42:28 +03:00
if ( ! path_mediated_fs ( old_dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
profile = aa_current_profile ( ) ;
if ( ! unconfined ( profile ) ) {
2016-12-17 04:04:13 +03:00
struct path old_path = { . mnt = old_dir - > mnt ,
. dentry = old_dentry } ;
struct path new_path = { . mnt = new_dir - > mnt ,
. dentry = new_dentry } ;
2015-03-18 01:26:22 +03:00
struct path_cond cond = { d_backing_inode ( old_dentry ) - > i_uid ,
d_backing_inode ( old_dentry ) - > i_mode
2010-07-30 01:48:07 +04:00
} ;
error = aa_path_perm ( OP_RENAME_SRC , profile , & old_path , 0 ,
2017-05-27 01:07:22 +03:00
MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
AA_MAY_SETATTR | AA_MAY_DELETE ,
2010-07-30 01:48:07 +04:00
& cond ) ;
if ( ! error )
error = aa_path_perm ( OP_RENAME_DEST , profile , & new_path ,
2017-05-27 01:07:22 +03:00
0 , MAY_WRITE | AA_MAY_SETATTR |
2010-07-30 01:48:07 +04:00
AA_MAY_CREATE , & cond ) ;
}
return error ;
}
2016-03-25 21:56:23 +03:00
static int apparmor_path_chmod ( const struct path * path , umode_t mode )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:07 +03:00
return common_perm_cond ( OP_CHMOD , path , AA_MAY_CHMOD ) ;
2010-07-30 01:48:07 +04:00
}
2016-03-25 21:44:41 +03:00
static int apparmor_path_chown ( const struct path * path , kuid_t uid , kgid_t gid )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:07 +03:00
return common_perm_cond ( OP_CHOWN , path , AA_MAY_CHOWN ) ;
2010-07-30 01:48:07 +04:00
}
2015-03-09 02:28:30 +03:00
static int apparmor_inode_getattr ( const struct path * path )
2010-07-30 01:48:07 +04:00
{
2017-05-27 01:07:22 +03:00
return common_perm_cond ( OP_GETATTR , path , AA_MAY_GETATTR ) ;
2010-07-30 01:48:07 +04:00
}
2012-04-04 21:45:40 +04:00
static int apparmor_file_open ( struct file * file , const struct cred * cred )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:00 +03:00
struct aa_file_ctx * fctx = file - > f_security ;
2010-07-30 01:48:07 +04:00
struct aa_profile * profile ;
int error = 0 ;
2017-01-16 11:42:28 +03:00
if ( ! path_mediated_fs ( file - > f_path . dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
/* If in exec, permission is handled by bprm hooks.
* Cache permissions granted by the previous exec check , with
* implicit read and executable mmap which are required to
* actually execute the image .
*/
if ( current - > in_execve ) {
2017-01-16 11:43:00 +03:00
fctx - > allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP ;
2010-07-30 01:48:07 +04:00
return 0 ;
}
profile = aa_cred_profile ( cred ) ;
if ( ! unconfined ( profile ) ) {
2013-01-24 02:07:38 +04:00
struct inode * inode = file_inode ( file ) ;
2010-07-30 01:48:07 +04:00
struct path_cond cond = { inode - > i_uid , inode - > i_mode } ;
error = aa_path_perm ( OP_OPEN , profile , & file - > f_path , 0 ,
aa_map_file_to_perms ( file ) , & cond ) ;
/* todo cache full allowed permissions set and state */
2017-01-16 11:43:00 +03:00
fctx - > allow = aa_map_file_to_perms ( file ) ;
2010-07-30 01:48:07 +04:00
}
return error ;
}
static int apparmor_file_alloc_security ( struct file * file )
{
/* freed by apparmor_file_free_security */
file - > f_security = aa_alloc_file_context ( GFP_KERNEL ) ;
if ( ! file - > f_security )
return - ENOMEM ;
return 0 ;
}
static void apparmor_file_free_security ( struct file * file )
{
2017-01-16 11:43:00 +03:00
struct aa_file_ctx * ctx = file - > f_security ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:00 +03:00
aa_free_file_context ( ctx ) ;
2010-07-30 01:48:07 +04:00
}
2017-01-16 11:43:01 +03:00
static int common_file_perm ( const char * op , struct file * file , u32 mask )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:00 +03:00
struct aa_file_ctx * fctx = file - > f_security ;
2010-07-30 01:48:07 +04:00
struct aa_profile * profile , * fprofile = aa_cred_profile ( file - > f_cred ) ;
int error = 0 ;
2017-01-16 11:43:15 +03:00
AA_BUG ( ! fprofile ) ;
2010-07-30 01:48:07 +04:00
if ( ! file - > f_path . mnt | |
2017-01-16 11:42:28 +03:00
! path_mediated_fs ( file - > f_path . dentry ) )
2010-07-30 01:48:07 +04:00
return 0 ;
profile = __aa_current_profile ( ) ;
/* revalidate access, if task is unconfined, or the cached cred
* doesn ' t match or if the request is for more permissions than
* was granted .
*
* Note : the test for ! unconfined ( fprofile ) is to handle file
* delegation from unconfined tasks
*/
if ( ! unconfined ( profile ) & & ! unconfined ( fprofile ) & &
2017-01-16 11:43:00 +03:00
( ( fprofile ! = profile ) | | ( mask & ~ fctx - > allow ) ) )
2010-07-30 01:48:07 +04:00
error = aa_file_perm ( op , profile , file , mask ) ;
return error ;
}
static int apparmor_file_permission ( struct file * file , int mask )
{
return common_file_perm ( OP_FPERM , file , mask ) ;
}
static int apparmor_file_lock ( struct file * file , unsigned int cmd )
{
u32 mask = AA_MAY_LOCK ;
if ( cmd = = F_WRLCK )
mask | = MAY_WRITE ;
return common_file_perm ( OP_FLOCK , file , mask ) ;
}
2017-01-16 11:43:01 +03:00
static int common_mmap ( const char * op , struct file * file , unsigned long prot ,
2010-07-30 01:48:07 +04:00
unsigned long flags )
{
int mask = 0 ;
if ( ! file | | ! file - > f_security )
return 0 ;
if ( prot & PROT_READ )
mask | = MAY_READ ;
/*
* Private mappings don ' t require write perms since they don ' t
* write back to the files
*/
if ( ( prot & PROT_WRITE ) & & ! ( flags & MAP_PRIVATE ) )
mask | = MAY_WRITE ;
if ( prot & PROT_EXEC )
mask | = AA_EXEC_MMAP ;
return common_file_perm ( op , file , mask ) ;
}
2012-05-30 21:30:51 +04:00
static int apparmor_mmap_file ( struct file * file , unsigned long reqprot ,
unsigned long prot , unsigned long flags )
2010-07-30 01:48:07 +04:00
{
return common_mmap ( OP_FMMAP , file , prot , flags ) ;
}
static int apparmor_file_mprotect ( struct vm_area_struct * vma ,
unsigned long reqprot , unsigned long prot )
{
return common_mmap ( OP_FMPROT , vma - > vm_file , prot ,
! ( vma - > vm_flags & VM_SHARED ) ? MAP_PRIVATE : 0 ) ;
}
static int apparmor_getprocattr ( struct task_struct * task , char * name ,
char * * value )
{
int error = - ENOENT ;
/* released below */
const struct cred * cred = get_task_cred ( task ) ;
2017-01-16 11:43:00 +03:00
struct aa_task_ctx * ctx = cred_ctx ( cred ) ;
2013-07-11 08:07:43 +04:00
struct aa_profile * profile = NULL ;
2010-07-30 01:48:07 +04:00
if ( strcmp ( name , " current " ) = = 0 )
2017-01-16 11:43:00 +03:00
profile = aa_get_newest_profile ( ctx - > profile ) ;
else if ( strcmp ( name , " prev " ) = = 0 & & ctx - > previous )
profile = aa_get_newest_profile ( ctx - > previous ) ;
else if ( strcmp ( name , " exec " ) = = 0 & & ctx - > onexec )
profile = aa_get_newest_profile ( ctx - > onexec ) ;
2010-07-30 01:48:07 +04:00
else
error = - EINVAL ;
2013-07-11 08:07:43 +04:00
if ( profile )
error = aa_getprocattr ( profile , value ) ;
aa_put_profile ( profile ) ;
2010-07-30 01:48:07 +04:00
put_cred ( cred ) ;
return error ;
}
2017-01-09 18:07:31 +03:00
static int apparmor_setprocattr ( const char * name , void * value ,
size_t size )
2010-07-30 01:48:07 +04:00
{
2016-07-07 23:41:11 +03:00
char * command , * largs = NULL , * args = value ;
2010-07-30 01:48:07 +04:00
size_t arg_size ;
int error ;
2017-01-16 11:43:02 +03:00
DEFINE_AUDIT_DATA ( sa , LSM_AUDIT_DATA_NONE , OP_SETPROCATTR ) ;
2010-07-30 01:48:07 +04:00
if ( size = = 0 )
return - EINVAL ;
2016-07-07 23:41:11 +03:00
/* AppArmor requires that the buffer must be null terminated atm */
if ( args [ size - 1 ] ! = ' \0 ' ) {
/* null terminate */
largs = args = kmalloc ( size + 1 , GFP_KERNEL ) ;
if ( ! args )
return - ENOMEM ;
memcpy ( args , value , size ) ;
args [ size ] = ' \0 ' ;
}
error = - EINVAL ;
2010-07-30 01:48:07 +04:00
args = strim ( args ) ;
command = strsep ( & args , " " ) ;
if ( ! args )
2016-07-07 23:41:11 +03:00
goto out ;
2010-07-30 01:48:07 +04:00
args = skip_spaces ( args ) ;
if ( ! * args )
2016-07-07 23:41:11 +03:00
goto out ;
2010-07-30 01:48:07 +04:00
2016-07-10 09:46:33 +03:00
arg_size = size - ( args - ( largs ? largs : ( char * ) value ) ) ;
2010-07-30 01:48:07 +04:00
if ( strcmp ( name , " current " ) = = 0 ) {
if ( strcmp ( command , " changehat " ) = = 0 ) {
error = aa_setprocattr_changehat ( args , arg_size ,
! AA_DO_TEST ) ;
} else if ( strcmp ( command , " permhat " ) = = 0 ) {
error = aa_setprocattr_changehat ( args , arg_size ,
AA_DO_TEST ) ;
} else if ( strcmp ( command , " changeprofile " ) = = 0 ) {
2017-01-16 11:43:06 +03:00
error = aa_change_profile ( args , ! AA_ONEXEC ,
! AA_DO_TEST , false ) ;
2010-07-30 01:48:07 +04:00
} else if ( strcmp ( command , " permprofile " ) = = 0 ) {
2017-01-16 11:43:06 +03:00
error = aa_change_profile ( args , ! AA_ONEXEC , AA_DO_TEST ,
false ) ;
2013-02-27 15:44:40 +04:00
} else
goto fail ;
2010-07-30 01:48:07 +04:00
} else if ( strcmp ( name , " exec " ) = = 0 ) {
2013-02-27 15:44:40 +04:00
if ( strcmp ( command , " exec " ) = = 0 )
2017-01-16 11:43:06 +03:00
error = aa_change_profile ( args , AA_ONEXEC , ! AA_DO_TEST ,
false ) ;
2013-02-27 15:44:40 +04:00
else
goto fail ;
} else
2010-07-30 01:48:07 +04:00
/* only support the "current" and "exec" process attributes */
2016-07-07 23:41:11 +03:00
goto fail ;
2013-02-27 15:44:40 +04:00
2010-07-30 01:48:07 +04:00
if ( ! error )
error = size ;
2016-07-07 23:41:11 +03:00
out :
kfree ( largs ) ;
2010-07-30 01:48:07 +04:00
return error ;
2013-02-27 15:44:40 +04:00
fail :
2017-01-16 11:43:02 +03:00
aad ( & sa ) - > profile = aa_current_profile ( ) ;
aad ( & sa ) - > info = name ;
aad ( & sa ) - > error = error = - EINVAL ;
2013-02-27 15:44:40 +04:00
aa_audit_msg ( AUDIT_APPARMOR_DENIED , & sa , NULL ) ;
2016-07-07 23:41:11 +03:00
goto out ;
2010-07-30 01:48:07 +04:00
}
2017-06-09 15:27:50 +03:00
/**
* apparmor_bprm_committing_creds - do task cleanup on committing new creds
* @ bprm : binprm for the exec ( NOT NULL )
*/
static void apparmor_bprm_committing_creds ( struct linux_binprm * bprm )
{
struct aa_profile * profile = __aa_current_profile ( ) ;
struct aa_task_ctx * new_ctx = cred_ctx ( bprm - > cred ) ;
/* bail out if unconfined or not changing profile */
if ( ( new_ctx - > profile = = profile ) | |
( unconfined ( new_ctx - > profile ) ) )
return ;
current - > pdeath_signal = 0 ;
/* reset soft limits and set hard limits for the new profile */
__aa_transition_rlimits ( profile , new_ctx - > profile ) ;
}
/**
* apparmor_bprm_committed_cred - do cleanup after new creds committed
* @ bprm : binprm for the exec ( NOT NULL )
*/
static void apparmor_bprm_committed_creds ( struct linux_binprm * bprm )
{
/* TODO: cleanup signals - ipc mediation */
return ;
}
2010-08-11 13:28:02 +04:00
static int apparmor_task_setrlimit ( struct task_struct * task ,
unsigned int resource , struct rlimit * new_rlim )
2010-07-30 01:48:07 +04:00
{
2011-06-09 02:07:47 +04:00
struct aa_profile * profile = __aa_current_profile ( ) ;
2010-07-30 01:48:07 +04:00
int error = 0 ;
if ( ! unconfined ( profile ) )
2010-09-06 21:10:20 +04:00
error = aa_task_setrlimit ( profile , task , resource , new_rlim ) ;
2010-07-30 01:48:07 +04:00
return error ;
}
2017-02-14 16:18:51 +03:00
static struct security_hook_list apparmor_hooks [ ] __lsm_ro_after_init = {
2015-05-03 01:11:36 +03:00
LSM_HOOK_INIT ( ptrace_access_check , apparmor_ptrace_access_check ) ,
LSM_HOOK_INIT ( ptrace_traceme , apparmor_ptrace_traceme ) ,
LSM_HOOK_INIT ( capget , apparmor_capget ) ,
LSM_HOOK_INIT ( capable , apparmor_capable ) ,
LSM_HOOK_INIT ( path_link , apparmor_path_link ) ,
LSM_HOOK_INIT ( path_unlink , apparmor_path_unlink ) ,
LSM_HOOK_INIT ( path_symlink , apparmor_path_symlink ) ,
LSM_HOOK_INIT ( path_mkdir , apparmor_path_mkdir ) ,
LSM_HOOK_INIT ( path_rmdir , apparmor_path_rmdir ) ,
LSM_HOOK_INIT ( path_mknod , apparmor_path_mknod ) ,
LSM_HOOK_INIT ( path_rename , apparmor_path_rename ) ,
LSM_HOOK_INIT ( path_chmod , apparmor_path_chmod ) ,
LSM_HOOK_INIT ( path_chown , apparmor_path_chown ) ,
LSM_HOOK_INIT ( path_truncate , apparmor_path_truncate ) ,
LSM_HOOK_INIT ( inode_getattr , apparmor_inode_getattr ) ,
LSM_HOOK_INIT ( file_open , apparmor_file_open ) ,
LSM_HOOK_INIT ( file_permission , apparmor_file_permission ) ,
LSM_HOOK_INIT ( file_alloc_security , apparmor_file_alloc_security ) ,
LSM_HOOK_INIT ( file_free_security , apparmor_file_free_security ) ,
LSM_HOOK_INIT ( mmap_file , apparmor_mmap_file ) ,
LSM_HOOK_INIT ( file_mprotect , apparmor_file_mprotect ) ,
LSM_HOOK_INIT ( file_lock , apparmor_file_lock ) ,
LSM_HOOK_INIT ( getprocattr , apparmor_getprocattr ) ,
LSM_HOOK_INIT ( setprocattr , apparmor_setprocattr ) ,
LSM_HOOK_INIT ( cred_alloc_blank , apparmor_cred_alloc_blank ) ,
LSM_HOOK_INIT ( cred_free , apparmor_cred_free ) ,
LSM_HOOK_INIT ( cred_prepare , apparmor_cred_prepare ) ,
LSM_HOOK_INIT ( cred_transfer , apparmor_cred_transfer ) ,
LSM_HOOK_INIT ( bprm_set_creds , apparmor_bprm_set_creds ) ,
LSM_HOOK_INIT ( bprm_committing_creds , apparmor_bprm_committing_creds ) ,
LSM_HOOK_INIT ( bprm_committed_creds , apparmor_bprm_committed_creds ) ,
LSM_HOOK_INIT ( bprm_secureexec , apparmor_bprm_secureexec ) ,
LSM_HOOK_INIT ( task_setrlimit , apparmor_task_setrlimit ) ,
2010-07-30 01:48:07 +04:00
} ;
/*
* AppArmor sysfs module parameters
*/
2010-08-02 06:00:43 +04:00
static int param_set_aabool ( const char * val , const struct kernel_param * kp ) ;
static int param_get_aabool ( char * buffer , const struct kernel_param * kp ) ;
2011-12-15 07:11:32 +04:00
# define param_check_aabool param_check_bool
2015-05-27 04:39:38 +03:00
static const struct kernel_param_ops param_ops_aabool = {
2014-08-27 00:51:23 +04:00
. flags = KERNEL_PARAM_OPS_FL_NOARG ,
2010-08-02 06:00:43 +04:00
. set = param_set_aabool ,
. get = param_get_aabool
} ;
2010-07-30 01:48:07 +04:00
2010-08-02 06:00:43 +04:00
static int param_set_aauint ( const char * val , const struct kernel_param * kp ) ;
static int param_get_aauint ( char * buffer , const struct kernel_param * kp ) ;
2011-12-15 07:11:32 +04:00
# define param_check_aauint param_check_uint
2015-05-27 04:39:38 +03:00
static const struct kernel_param_ops param_ops_aauint = {
2010-08-02 06:00:43 +04:00
. set = param_set_aauint ,
. get = param_get_aauint
} ;
2010-07-30 01:48:07 +04:00
2010-08-02 06:00:43 +04:00
static int param_set_aalockpolicy ( const char * val , const struct kernel_param * kp ) ;
static int param_get_aalockpolicy ( char * buffer , const struct kernel_param * kp ) ;
2011-12-15 07:11:32 +04:00
# define param_check_aalockpolicy param_check_bool
2015-05-27 04:39:38 +03:00
static const struct kernel_param_ops param_ops_aalockpolicy = {
2014-08-27 00:51:23 +04:00
. flags = KERNEL_PARAM_OPS_FL_NOARG ,
2010-08-02 06:00:43 +04:00
. set = param_set_aalockpolicy ,
. get = param_get_aalockpolicy
} ;
2010-07-30 01:48:07 +04:00
static int param_set_audit ( const char * val , struct kernel_param * kp ) ;
static int param_get_audit ( char * buffer , struct kernel_param * kp ) ;
static int param_set_mode ( const char * val , struct kernel_param * kp ) ;
static int param_get_mode ( char * buffer , struct kernel_param * kp ) ;
/* Flag values, also controllable via /sys/module/apparmor/parameters
* We define special types as we want to do additional mediation .
*/
/* AppArmor global enforcement switch - complain, enforce, kill */
enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE ;
module_param_call ( mode , param_set_mode , param_get_mode ,
& aa_g_profile_mode , S_IRUSR | S_IWUSR ) ;
2014-10-24 20:16:14 +04:00
/* whether policy verification hashing is enabled */
2016-07-25 20:59:07 +03:00
bool aa_g_hash_policy = IS_ENABLED ( CONFIG_SECURITY_APPARMOR_HASH_DEFAULT ) ;
2017-01-17 00:21:27 +03:00
# ifdef CONFIG_SECURITY_APPARMOR_HASH
2014-10-24 20:16:14 +04:00
module_param_named ( hash_policy , aa_g_hash_policy , aabool , S_IRUSR | S_IWUSR ) ;
2016-07-25 20:59:07 +03:00
# endif
2014-10-24 20:16:14 +04:00
2010-07-30 01:48:07 +04:00
/* Debug mode */
2017-04-06 16:55:20 +03:00
bool aa_g_debug = IS_ENABLED ( CONFIG_SECURITY_APPARMOR_DEBUG_MESSAGES ) ;
2010-07-30 01:48:07 +04:00
module_param_named ( debug , aa_g_debug , aabool , S_IRUSR | S_IWUSR ) ;
/* Audit mode */
enum audit_mode aa_g_audit ;
module_param_call ( audit , param_set_audit , param_get_audit ,
& aa_g_audit , S_IRUSR | S_IWUSR ) ;
/* Determines if audit header is included in audited messages. This
* provides more context if the audit daemon is not running
*/
2012-01-13 03:02:20 +04:00
bool aa_g_audit_header = 1 ;
2010-07-30 01:48:07 +04:00
module_param_named ( audit_header , aa_g_audit_header , aabool ,
S_IRUSR | S_IWUSR ) ;
/* lock out loading/removal of policy
* TODO : add in at boot loading of policy , which is the only way to
* load policy , if lock_policy is set
*/
2012-01-13 03:02:20 +04:00
bool aa_g_lock_policy ;
2010-07-30 01:48:07 +04:00
module_param_named ( lock_policy , aa_g_lock_policy , aalockpolicy ,
S_IRUSR | S_IWUSR ) ;
/* Syscall logging mode */
2012-01-13 03:02:20 +04:00
bool aa_g_logsyscall ;
2010-07-30 01:48:07 +04:00
module_param_named ( logsyscall , aa_g_logsyscall , aabool , S_IRUSR | S_IWUSR ) ;
/* Maximum pathname length before accesses will start getting rejected */
unsigned int aa_g_path_max = 2 * PATH_MAX ;
2017-04-06 16:55:24 +03:00
module_param_named ( path_max , aa_g_path_max , aauint , S_IRUSR ) ;
2010-07-30 01:48:07 +04:00
/* Determines how paranoid loading of policy is and how much verification
* on the loaded policy is done .
2017-01-16 11:42:37 +03:00
* DEPRECATED : read only as strict checking of load is always done now
* that none root users ( user namespaces ) can load policy .
2010-07-30 01:48:07 +04:00
*/
2012-01-13 03:02:20 +04:00
bool aa_g_paranoid_load = 1 ;
2017-01-16 11:42:37 +03:00
module_param_named ( paranoid_load , aa_g_paranoid_load , aabool , S_IRUGO ) ;
2010-07-30 01:48:07 +04:00
/* Boot time disable flag */
2012-01-13 03:02:20 +04:00
static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE ;
2013-07-11 08:03:43 +04:00
module_param_named ( enabled , apparmor_enabled , bool , S_IRUGO ) ;
2010-07-30 01:48:07 +04:00
static int __init apparmor_enabled_setup ( char * str )
{
unsigned long enabled ;
2014-02-05 10:13:14 +04:00
int error = kstrtoul ( str , 0 , & enabled ) ;
2010-07-30 01:48:07 +04:00
if ( ! error )
apparmor_enabled = enabled ? 1 : 0 ;
return 1 ;
}
__setup ( " apparmor= " , apparmor_enabled_setup ) ;
/* set global flag turning off the ability to load policy */
2010-08-02 06:00:43 +04:00
static int param_set_aalockpolicy ( const char * val , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-04-06 16:55:23 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
if ( apparmor_initialized & & ! policy_admin_capable ( NULL ) )
2010-07-30 01:48:07 +04:00
return - EPERM ;
return param_set_bool ( val , kp ) ;
}
2010-08-02 06:00:43 +04:00
static int param_get_aalockpolicy ( char * buffer , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:11 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_view_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
return param_get_bool ( buffer , kp ) ;
}
2010-08-02 06:00:43 +04:00
static int param_set_aabool ( const char * val , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:11 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_admin_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
return param_set_bool ( val , kp ) ;
}
2010-08-02 06:00:43 +04:00
static int param_get_aabool ( char * buffer , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:11 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_view_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
return param_get_bool ( buffer , kp ) ;
}
2010-08-02 06:00:43 +04:00
static int param_set_aauint ( const char * val , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-03-30 15:25:23 +03:00
int error ;
2017-01-16 11:43:11 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
2017-03-30 15:25:23 +03:00
/* file is ro but enforce 2nd line check */
if ( apparmor_initialized )
2017-04-06 16:55:23 +03:00
return - EPERM ;
2017-03-30 15:25:23 +03:00
error = param_set_uint ( val , kp ) ;
pr_info ( " AppArmor: buffer size set to %d bytes \n " , aa_g_path_max ) ;
return error ;
2010-07-30 01:48:07 +04:00
}
2010-08-02 06:00:43 +04:00
static int param_get_aauint ( char * buffer , const struct kernel_param * kp )
2010-07-30 01:48:07 +04:00
{
2017-01-16 11:43:11 +03:00
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_view_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
return param_get_uint ( buffer , kp ) ;
}
static int param_get_audit ( char * buffer , struct kernel_param * kp )
{
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_view_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
return sprintf ( buffer , " %s " , audit_mode_names [ aa_g_audit ] ) ;
}
static int param_set_audit ( const char * val , struct kernel_param * kp )
{
int i ;
if ( ! apparmor_enabled )
return - EINVAL ;
if ( ! val )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_admin_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
for ( i = 0 ; i < AUDIT_MAX_INDEX ; i + + ) {
if ( strcmp ( val , audit_mode_names [ i ] ) = = 0 ) {
aa_g_audit = i ;
return 0 ;
}
}
return - EINVAL ;
}
static int param_get_mode ( char * buffer , struct kernel_param * kp )
{
if ( ! apparmor_enabled )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_view_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
2013-07-11 08:13:43 +04:00
return sprintf ( buffer , " %s " , aa_profile_mode_names [ aa_g_profile_mode ] ) ;
2010-07-30 01:48:07 +04:00
}
static int param_set_mode ( const char * val , struct kernel_param * kp )
{
int i ;
if ( ! apparmor_enabled )
return - EINVAL ;
if ( ! val )
return - EINVAL ;
2017-04-06 16:55:23 +03:00
if ( apparmor_initialized & & ! policy_admin_capable ( NULL ) )
return - EPERM ;
2010-07-30 01:48:07 +04:00
2013-07-11 08:13:43 +04:00
for ( i = 0 ; i < APPARMOR_MODE_NAMES_MAX_INDEX ; i + + ) {
if ( strcmp ( val , aa_profile_mode_names [ i ] ) = = 0 ) {
2010-07-30 01:48:07 +04:00
aa_g_profile_mode = i ;
return 0 ;
}
}
return - EINVAL ;
}
/*
* AppArmor init functions
*/
/**
2017-01-16 11:43:00 +03:00
* set_init_ctx - set a task context and profile on the first task .
2010-07-30 01:48:07 +04:00
*
* TODO : allow setting an alternate profile than unconfined
*/
2017-01-16 11:43:00 +03:00
static int __init set_init_ctx ( void )
2010-07-30 01:48:07 +04:00
{
struct cred * cred = ( struct cred * ) current - > real_cred ;
2017-01-16 11:43:00 +03:00
struct aa_task_ctx * ctx ;
2010-07-30 01:48:07 +04:00
2017-01-16 11:43:00 +03:00
ctx = aa_alloc_task_context ( GFP_KERNEL ) ;
if ( ! ctx )
2010-07-30 01:48:07 +04:00
return - ENOMEM ;
2017-01-16 11:43:00 +03:00
ctx - > profile = aa_get_profile ( root_ns - > unconfined ) ;
cred_ctx ( cred ) = ctx ;
2010-07-30 01:48:07 +04:00
return 0 ;
}
2017-01-16 11:43:10 +03:00
static void destroy_buffers ( void )
{
u32 i , j ;
for_each_possible_cpu ( i ) {
for_each_cpu_buffer ( j ) {
kfree ( per_cpu ( aa_buffers , i ) . buf [ j ] ) ;
per_cpu ( aa_buffers , i ) . buf [ j ] = NULL ;
}
}
}
static int __init alloc_buffers ( void )
{
u32 i , j ;
for_each_possible_cpu ( i ) {
for_each_cpu_buffer ( j ) {
char * buffer ;
if ( cpu_to_node ( i ) > num_online_nodes ( ) )
/* fallback to kmalloc for offline nodes */
buffer = kmalloc ( aa_g_path_max , GFP_KERNEL ) ;
else
buffer = kmalloc_node ( aa_g_path_max , GFP_KERNEL ,
cpu_to_node ( i ) ) ;
if ( ! buffer ) {
destroy_buffers ( ) ;
return - ENOMEM ;
}
per_cpu ( aa_buffers , i ) . buf [ j ] = buffer ;
}
}
return 0 ;
}
2016-03-17 03:19:10 +03:00
# ifdef CONFIG_SYSCTL
static int apparmor_dointvec ( struct ctl_table * table , int write ,
void __user * buffer , size_t * lenp , loff_t * ppos )
{
if ( ! policy_admin_capable ( NULL ) )
return - EPERM ;
if ( ! apparmor_enabled )
return - EINVAL ;
return proc_dointvec ( table , write , buffer , lenp , ppos ) ;
}
static struct ctl_path apparmor_sysctl_path [ ] = {
{ . procname = " kernel " , } ,
{ }
} ;
static struct ctl_table apparmor_sysctl_table [ ] = {
{
. procname = " unprivileged_userns_apparmor_policy " ,
. data = & unprivileged_userns_apparmor_policy ,
. maxlen = sizeof ( int ) ,
. mode = 0600 ,
. proc_handler = apparmor_dointvec ,
} ,
{ }
} ;
static int __init apparmor_init_sysctl ( void )
{
return register_sysctl_paths ( apparmor_sysctl_path ,
apparmor_sysctl_table ) ? 0 : - ENOMEM ;
}
# else
static inline int apparmor_init_sysctl ( void )
{
return 0 ;
}
# endif /* CONFIG_SYSCTL */
2010-07-30 01:48:07 +04:00
static int __init apparmor_init ( void )
{
int error ;
2015-05-03 01:11:42 +03:00
if ( ! apparmor_enabled | | ! security_module_enable ( " apparmor " ) ) {
2010-07-30 01:48:07 +04:00
aa_info_message ( " AppArmor disabled by boot time parameter " ) ;
apparmor_enabled = 0 ;
return 0 ;
}
2017-01-16 11:42:42 +03:00
error = aa_setup_dfa_engine ( ) ;
if ( error ) {
AA_ERROR ( " Unable to setup dfa engine \n " ) ;
goto alloc_out ;
}
2010-07-30 01:48:07 +04:00
error = aa_alloc_root_ns ( ) ;
if ( error ) {
AA_ERROR ( " Unable to allocate default profile namespace \n " ) ;
goto alloc_out ;
}
2016-03-17 03:19:10 +03:00
error = apparmor_init_sysctl ( ) ;
if ( error ) {
AA_ERROR ( " Unable to register sysctls \n " ) ;
goto alloc_out ;
}
2017-01-16 11:43:10 +03:00
error = alloc_buffers ( ) ;
if ( error ) {
AA_ERROR ( " Unable to allocate work buffers \n " ) ;
goto buffers_out ;
}
2017-01-16 11:43:00 +03:00
error = set_init_ctx ( ) ;
2010-07-30 01:48:07 +04:00
if ( error ) {
AA_ERROR ( " Failed to set context on init task \n " ) ;
2015-05-03 01:11:42 +03:00
aa_free_root_ns ( ) ;
2017-01-16 11:43:10 +03:00
goto buffers_out ;
2010-07-30 01:48:07 +04:00
}
2017-01-19 04:09:05 +03:00
security_add_hooks ( apparmor_hooks , ARRAY_SIZE ( apparmor_hooks ) ,
" apparmor " ) ;
2010-07-30 01:48:07 +04:00
/* Report that AppArmor successfully initialized */
apparmor_initialized = 1 ;
if ( aa_g_profile_mode = = APPARMOR_COMPLAIN )
aa_info_message ( " AppArmor initialized: complain mode enabled " ) ;
else if ( aa_g_profile_mode = = APPARMOR_KILL )
aa_info_message ( " AppArmor initialized: kill mode enabled " ) ;
else
aa_info_message ( " AppArmor initialized " ) ;
return error ;
2017-01-16 11:43:10 +03:00
buffers_out :
destroy_buffers ( ) ;
2010-07-30 01:48:07 +04:00
alloc_out :
aa_destroy_aafs ( ) ;
2017-01-16 11:42:42 +03:00
aa_teardown_dfa_engine ( ) ;
2010-07-30 01:48:07 +04:00
apparmor_enabled = 0 ;
return error ;
}
security_initcall ( apparmor_init ) ;