// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright ( C ) 2008 IBM Corporation
*
* Authors :
* Mimi Zohar < zohar @ us . ibm . com >
*
* File : ima_iint . c
* - implements the IMA hook : ima_inode_free
* - cache integrity information in the inode security blob
*/
#include <linux/slab.h>
#include "ima.h"
static struct kmem_cache *ima_iint_cache __ro_after_init;
/**
* ima_iint_find - Return the iint associated with an inode
* @ inode : Pointer to the inode
*
* Return the IMA integrity information ( iint ) associated with an inode , if the
* inode was processed by IMA .
*
* Return : Found iint or NULL .
*/
struct ima_iint_cache *ima_iint_find(struct inode *inode)
{
if (!IS_IMA(inode))
return NULL;
return ima_inode_get_iint(inode);
}
#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH + 1 )
/*
* It is not clear that IMA should be nested at all , but as long is it measures
* files both on overlayfs and on underlying fs , we need to annotate the iint
* mutex to avoid lockdep false positives related to IMA + overlayfs .
* See ovl_lockdep_annotate_inode_mutex_key ( ) for more details .
*/
static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint,
struct inode *inode)
{
#ifdef CONFIG_LOCKDEP
static struct lock_class_key ima_iint_mutex_key[IMA_MAX_NESTING];
int depth = inode->i_sb->s_stack_depth;
if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING))
depth = 0 ;
lockdep_set_class(&iint->mutex, &ima_iint_mutex_key[depth]);
#endif
}
static void ima_iint_init_always(struct ima_iint_cache *iint,
struct inode *inode)
{
iint->ima_hash = NULL;
iint->real_inode.version = 0 ;
iint->flags = 0 UL;
iint->atomic_flags = 0 UL;
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->ima_creds_status = INTEGRITY_UNKNOWN;
iint->measured_pcrs = 0 ;
mutex_init(&iint->mutex);
ima_iint_lockdep_annotate(iint, inode);
}
static void ima_iint_free(struct ima_iint_cache *iint)
{
kfree(iint->ima_hash);
mutex_destroy(&iint->mutex);
kmem_cache_free(ima_iint_cache, iint);
}
/**
* ima_inode_get - Find or allocate an iint associated with an inode
* @ inode : Pointer to the inode
*
* Find an iint associated with an inode , and allocate a new one if not found .
* Caller must lock i_mutex .
*
* Return : An iint on success , NULL on error .
*/
struct ima_iint_cache *ima_inode_get(struct inode *inode)
{
struct ima_iint_cache *iint;
iint = ima_iint_find(inode);
if (iint)
return iint;
iint = kmem_cache_alloc(ima_iint_cache, GFP_NOFS);
if (!iint)
return NULL;
ima_iint_init_always(iint, inode);
inode->i_flags |= S_IMA;
ima_inode_set_iint(inode, iint);
return iint;
}
/**
* ima_inode_free_rcu - Called to free an inode via a RCU callback
* @ inode_security : The inode - > i_security pointer
*
* Free the IMA data associated with an inode .
*/
void ima_inode_free_rcu(void *inode_security)
{
struct ima_iint_cache **iint_p = inode_security + ima_blob_sizes.lbs_inode;
/* *iint_p should be NULL if !IS_IMA(inode) */
if (*iint_p)
ima_iint_free(*iint_p);
}
static void ima_iint_init_once(void *foo)
{
struct ima_iint_cache *iint = (struct ima_iint_cache *)foo;
memset(iint, 0 , sizeof (*iint));
}
void __init ima_iintcache_init(void )
{
ima_iint_cache =
kmem_cache_create("ima_iint_cache" , sizeof (struct ima_iint_cache),
0 , SLAB_PANIC, ima_iint_init_once);
}
Messung V0.5 in Prozent C=95 H=95 G=94
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland