// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( C ) 2020 - 2024 Microsoft Corporation . All rights reserved .
*/
#include <linux/slab.h>
#include <linux/audit.h>
#include <linux/types.h>
#include <crypto/sha2.h>
#include "ipe.h"
#include "eval.h"
#include "hooks.h"
#include "policy.h"
#include "audit.h"
#include "digest.h"
#define ACTSTR(x) ((x) == IPE_ACTION_ALLOW ? "ALLOW" : "DENY" )
#define IPE_AUDIT_HASH_ALG "sha256" /* keep in sync with audit_policy() */
#define AUDIT_POLICY_LOAD_FMT "policy_name=\" %s\" policy_version=%hu.%hu.%hu " \
"policy_digest=" IPE_AUDIT_HASH_ALG ":"
#define AUDIT_POLICY_LOAD_NULL_FMT "policy_name=? policy_version=? " \
"policy_digest=?"
#define AUDIT_OLD_ACTIVE_POLICY_FMT "old_active_pol_name=\" %s\" " \
"old_active_pol_version=%hu.%hu.%hu " \
"old_policy_digest=" IPE_AUDIT_HASH_ALG ":"
#define AUDIT_OLD_ACTIVE_POLICY_NULL_FMT "old_active_pol_name=? " \
"old_active_pol_version=? " \
"old_policy_digest=?"
#define AUDIT_NEW_ACTIVE_POLICY_FMT "new_active_pol_name=\" %s\" " \
"new_active_pol_version=%hu.%hu.%hu " \
"new_policy_digest=" IPE_AUDIT_HASH_ALG ":"
static const char *const audit_op_names[__IPE_OP_MAX + 1 ] = {
"EXECUTE" ,
"FIRMWARE" ,
"KMODULE" ,
"KEXEC_IMAGE" ,
"KEXEC_INITRAMFS" ,
"POLICY" ,
"X509_CERT" ,
"UNKNOWN" ,
};
static const char *const audit_hook_names[__IPE_HOOK_MAX] = {
"BPRM_CHECK" ,
"MMAP" ,
"MPROTECT" ,
"KERNEL_READ" ,
"KERNEL_LOAD" ,
};
static const char *const audit_prop_names[__IPE_PROP_MAX] = {
"boot_verified=FALSE" ,
"boot_verified=TRUE" ,
"dmverity_roothash=" ,
"dmverity_signature=FALSE" ,
"dmverity_signature=TRUE" ,
"fsverity_digest=" ,
"fsverity_signature=FALSE" ,
"fsverity_signature=TRUE" ,
};
/**
* audit_dmv_roothash ( ) - audit the roothash of a dmverity_roothash property .
* @ ab : Supplies a pointer to the audit_buffer to append to .
* @ rh : Supplies a pointer to the digest structure .
*/
static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh)
{
audit_log_format(ab, "%s" , audit_prop_names[IPE_PROP_DMV_ROOTHASH]);
ipe_digest_audit(ab, rh);
}
/**
* audit_fsv_digest ( ) - audit the digest of a fsverity_digest property .
* @ ab : Supplies a pointer to the audit_buffer to append to .
* @ d : Supplies a pointer to the digest structure .
*/
static void audit_fsv_digest(struct audit_buffer *ab, const void *d)
{
audit_log_format(ab, "%s" , audit_prop_names[IPE_PROP_FSV_DIGEST]);
ipe_digest_audit(ab, d);
}
/**
* audit_rule ( ) - audit an IPE policy rule .
* @ ab : Supplies a pointer to the audit_buffer to append to .
* @ r : Supplies a pointer to the ipe_rule to approximate a string form for .
*/
static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r)
{
const struct ipe_prop *ptr;
audit_log_format(ab, " rule=\" op=%s ", audit_op_names[r->op]);
list_for_each_entry(ptr, &r->props, next) {
switch (ptr->type) {
case IPE_PROP_DMV_ROOTHASH:
audit_dmv_roothash(ab, ptr->value);
break ;
case IPE_PROP_FSV_DIGEST:
audit_fsv_digest(ab, ptr->value);
break ;
default :
audit_log_format(ab, "%s" , audit_prop_names[ptr->type]);
break ;
}
audit_log_format(ab, " " );
}
audit_log_format(ab, "action=%s\" ", ACTSTR(r->action));
}
/**
* ipe_audit_match ( ) - Audit a rule match in a policy evaluation .
* @ ctx : Supplies a pointer to the evaluation context that was used in the
* evaluation .
* @ match_type : Supplies the scope of the match : rule , operation default ,
* global default .
* @ act : Supplies the IPE ' s evaluation decision , deny or allow .
* @ r : Supplies a pointer to the rule that was matched , if possible .
*/
void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
enum ipe_match match_type,
enum ipe_action_type act, const struct ipe_rule *const r)
{
const char *op = audit_op_names[ctx->op];
char comm[sizeof (current->comm)];
struct audit_buffer *ab;
struct inode *inode;
if (act != IPE_ACTION_DENY && !READ_ONCE(success_audit))
return ;
ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN,
AUDIT_IPE_ACCESS);
if (!ab)
return ;
audit_log_format(ab, "ipe_op=%s ipe_hook=%s enforcing=%d pid=%d comm=" ,
op, audit_hook_names[ctx->hook], READ_ONCE(enforce),
task_tgid_nr(current));
audit_log_untrustedstring(ab, get_task_comm(comm, current));
if (ctx->file) {
audit_log_d_path(ab, " path=" , &ctx->file->f_path);
inode = file_inode(ctx->file);
if (inode) {
audit_log_format(ab, " dev=" );
audit_log_untrustedstring(ab, inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu" , inode->i_ino);
} else {
audit_log_format(ab, " dev=? ino=?" );
}
} else {
audit_log_format(ab, " path=? dev=? ino=?" );
}
if (match_type == IPE_MATCH_RULE)
audit_rule(ab, r);
else if (match_type == IPE_MATCH_TABLE)
audit_log_format(ab, " rule=\" DEFAULT op=%s action=%s\"" , op,
ACTSTR(act));
else
audit_log_format(ab, " rule=\" DEFAULT action=%s\"" ,
ACTSTR(act));
audit_log_end(ab);
}
/**
* audit_policy ( ) - Audit a policy ' s name , version and thumbprint to @ ab .
* @ ab : Supplies a pointer to the audit buffer to append to .
* @ audit_format : Supplies a pointer to the audit format string
* @ p : Supplies a pointer to the policy to audit .
*/
static void audit_policy(struct audit_buffer *ab,
const char *audit_format,
const struct ipe_policy *const p)
{
u8 digest[SHA256_DIGEST_SIZE];
sha256(p->pkcs7, p->pkcs7len, digest);
audit_log_format(ab, audit_format, p->parsed->name,
p->parsed->version.major, p->parsed->version.minor,
p->parsed->version.rev);
audit_log_n_hex(ab, digest, sizeof (digest));
}
/**
* ipe_audit_policy_activation ( ) - Audit a policy being activated .
* @ op : Supplies a pointer to the previously activated policy to audit .
* @ np : Supplies a pointer to the newly activated policy to audit .
*/
void ipe_audit_policy_activation(const struct ipe_policy *const op,
const struct ipe_policy *const np)
{
struct audit_buffer *ab;
ab = audit_log_start(audit_context(), GFP_KERNEL,
AUDIT_IPE_CONFIG_CHANGE);
if (!ab)
return ;
if (op) {
audit_policy(ab, AUDIT_OLD_ACTIVE_POLICY_FMT, op);
audit_log_format(ab, " " );
} else {
/*
* old active policy can be NULL if there is no kernel
* built - in policy
*/
audit_log_format(ab, AUDIT_OLD_ACTIVE_POLICY_NULL_FMT);
audit_log_format(ab, " " );
}
audit_policy(ab, AUDIT_NEW_ACTIVE_POLICY_FMT, np);
audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1" ,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_end(ab);
}
/**
* ipe_audit_policy_load ( ) - Audit a policy loading event .
* @ p : Supplies a pointer to the policy to audit or an error pointer .
*/
void ipe_audit_policy_load(const struct ipe_policy *const p)
{
struct audit_buffer *ab;
int err = 0 ;
ab = audit_log_start(audit_context(), GFP_KERNEL,
AUDIT_IPE_POLICY_LOAD);
if (!ab)
return ;
if (!IS_ERR(p)) {
audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p);
} else {
audit_log_format(ab, AUDIT_POLICY_LOAD_NULL_FMT);
err = PTR_ERR(p);
}
audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=%d errno=%d" ,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current), !err, err);
audit_log_end(ab);
}
/**
* ipe_audit_enforce ( ) - Audit a change in IPE ' s enforcement state .
* @ new_enforce : The new value enforce to be set .
* @ old_enforce : The old value currently in enforce .
*/
void ipe_audit_enforce(bool new_enforce, bool old_enforce)
{
struct audit_buffer *ab;
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS);
if (!ab)
return ;
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
"enforcing=%d old_enforcing=%d auid=%u ses=%u"
" enabled=1 old-enabled=1 lsm=ipe res=1" ,
new_enforce, old_enforce,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_end(ab);
}
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland