// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.3*/45#include <linux/fs.h>6#include <linux/fs_struct.h>7#include <linux/types.h>8#include <linux/binfmts.h>9#include <linux/mman.h>10#include <linux/blk_types.h>1112#include "ipe.h"13#include "hooks.h"14#include "eval.h"15#include "digest.h"1617/**18* ipe_bprm_check_security() - ipe security hook function for bprm check.19* @bprm: Supplies a pointer to a linux_binprm structure to source the file20* being evaluated.21*22* This LSM hook is called when a binary is loaded through the exec23* family of system calls.24*25* Return:26* * %0 - Success27* * %-EACCES - Did not pass IPE policy28*/29int ipe_bprm_check_security(struct linux_binprm *bprm)30{31struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;3233ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC, IPE_HOOK_BPRM_CHECK);34return ipe_evaluate_event(&ctx);35}3637/**38* ipe_mmap_file() - ipe security hook function for mmap check.39* @f: File being mmap'd. Can be NULL in the case of anonymous memory.40* @reqprot: The requested protection on the mmap, passed from usermode.41* @prot: The effective protection on the mmap, resolved from reqprot and42* system configuration.43* @flags: Unused.44*45* This hook is called when a file is loaded through the mmap46* family of system calls.47*48* Return:49* * %0 - Success50* * %-EACCES - Did not pass IPE policy51*/52int ipe_mmap_file(struct file *f, unsigned long reqprot __always_unused,53unsigned long prot, unsigned long flags)54{55struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;5657if (prot & PROT_EXEC) {58ipe_build_eval_ctx(&ctx, f, IPE_OP_EXEC, IPE_HOOK_MMAP);59return ipe_evaluate_event(&ctx);60}6162return 0;63}6465/**66* ipe_file_mprotect() - ipe security hook function for mprotect check.67* @vma: Existing virtual memory area created by mmap or similar.68* @reqprot: The requested protection on the mmap, passed from usermode.69* @prot: The effective protection on the mmap, resolved from reqprot and70* system configuration.71*72* This LSM hook is called when a mmap'd region of memory is changing73* its protections via mprotect.74*75* Return:76* * %0 - Success77* * %-EACCES - Did not pass IPE policy78*/79int ipe_file_mprotect(struct vm_area_struct *vma,80unsigned long reqprot __always_unused,81unsigned long prot)82{83struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;8485/* Already Executable */86if (vma->vm_flags & VM_EXEC)87return 0;8889if (prot & PROT_EXEC) {90ipe_build_eval_ctx(&ctx, vma->vm_file, IPE_OP_EXEC, IPE_HOOK_MPROTECT);91return ipe_evaluate_event(&ctx);92}9394return 0;95}9697/**98* ipe_kernel_read_file() - ipe security hook function for kernel read.99* @file: Supplies a pointer to the file structure being read in from disk.100* @id: Supplies the enumeration identifying the purpose of the read.101* @contents: Unused.102*103* This LSM hook is called when a file is read from disk in the kernel.104*105* Return:106* * %0 - Success107* * %-EACCES - Did not pass IPE policy108*/109int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,110bool contents)111{112struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;113enum ipe_op_type op;114115switch (id) {116case READING_FIRMWARE:117op = IPE_OP_FIRMWARE;118break;119case READING_MODULE:120op = IPE_OP_KERNEL_MODULE;121break;122case READING_KEXEC_INITRAMFS:123op = IPE_OP_KEXEC_INITRAMFS;124break;125case READING_KEXEC_IMAGE:126op = IPE_OP_KEXEC_IMAGE;127break;128case READING_POLICY:129op = IPE_OP_POLICY;130break;131case READING_X509_CERTIFICATE:132op = IPE_OP_X509;133break;134default:135op = IPE_OP_INVALID;136WARN(1, "no rule setup for kernel_read_file enum %d", id);137}138139ipe_build_eval_ctx(&ctx, file, op, IPE_HOOK_KERNEL_READ);140return ipe_evaluate_event(&ctx);141}142143/**144* ipe_kernel_load_data() - ipe security hook function for kernel load data.145* @id: Supplies the enumeration identifying the purpose of the load.146* @contents: Unused.147*148* This LSM hook is called when a data buffer provided by userspace is loading149* into the kernel.150*151* Return:152* * %0 - Success153* * %-EACCES - Did not pass IPE policy154*/155int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)156{157struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;158enum ipe_op_type op;159160switch (id) {161case LOADING_FIRMWARE:162op = IPE_OP_FIRMWARE;163break;164case LOADING_MODULE:165op = IPE_OP_KERNEL_MODULE;166break;167case LOADING_KEXEC_INITRAMFS:168op = IPE_OP_KEXEC_INITRAMFS;169break;170case LOADING_KEXEC_IMAGE:171op = IPE_OP_KEXEC_IMAGE;172break;173case LOADING_POLICY:174op = IPE_OP_POLICY;175break;176case LOADING_X509_CERTIFICATE:177op = IPE_OP_X509;178break;179default:180op = IPE_OP_INVALID;181WARN(1, "no rule setup for kernel_load_data enum %d", id);182}183184ipe_build_eval_ctx(&ctx, NULL, op, IPE_HOOK_KERNEL_LOAD);185return ipe_evaluate_event(&ctx);186}187188/**189* ipe_unpack_initramfs() - Mark the current rootfs as initramfs.190*/191void ipe_unpack_initramfs(void)192{193ipe_sb(current->fs->root.mnt->mnt_sb)->initramfs = true;194}195196#ifdef CONFIG_IPE_PROP_DM_VERITY197/**198* ipe_bdev_free_security() - Free IPE's LSM blob of block_devices.199* @bdev: Supplies a pointer to a block_device that contains the structure200* to free.201*/202void ipe_bdev_free_security(struct block_device *bdev)203{204struct ipe_bdev *blob = ipe_bdev(bdev);205206ipe_digest_free(blob->root_hash);207}208209#ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE210static void ipe_set_dmverity_signature(struct ipe_bdev *blob,211const void *value,212size_t size)213{214blob->dm_verity_signed = size > 0 && value;215}216#else217static inline void ipe_set_dmverity_signature(struct ipe_bdev *blob,218const void *value,219size_t size)220{221}222#endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */223224/**225* ipe_bdev_setintegrity() - Save integrity data from a bdev to IPE's LSM blob.226* @bdev: Supplies a pointer to a block_device that contains the LSM blob.227* @type: Supplies the integrity type.228* @value: Supplies the value to store.229* @size: The size of @value.230*231* This hook is currently used to save dm-verity's root hash or the existence232* of a validated signed dm-verity root hash into LSM blob.233*234* Return: %0 on success. If an error occurs, the function will return the235* -errno.236*/237int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type,238const void *value, size_t size)239{240const struct dm_verity_digest *digest = NULL;241struct ipe_bdev *blob = ipe_bdev(bdev);242struct digest_info *info = NULL;243244if (type == LSM_INT_DMVERITY_SIG_VALID) {245ipe_set_dmverity_signature(blob, value, size);246247return 0;248}249250if (type != LSM_INT_DMVERITY_ROOTHASH)251return -EINVAL;252253if (!value) {254ipe_digest_free(blob->root_hash);255blob->root_hash = NULL;256257return 0;258}259digest = value;260261info = kzalloc(sizeof(*info), GFP_KERNEL);262if (!info)263return -ENOMEM;264265info->digest = kmemdup(digest->digest, digest->digest_len, GFP_KERNEL);266if (!info->digest)267goto err;268269info->alg = kstrdup(digest->alg, GFP_KERNEL);270if (!info->alg)271goto err;272273info->digest_len = digest->digest_len;274275ipe_digest_free(blob->root_hash);276blob->root_hash = info;277278return 0;279err:280ipe_digest_free(info);281282return -ENOMEM;283}284#endif /* CONFIG_IPE_PROP_DM_VERITY */285286#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG287/**288* ipe_inode_setintegrity() - save integrity data from a inode to IPE's LSM blob.289* @inode: The inode to source the security blob from.290* @type: Supplies the integrity type.291* @value: The value to be stored.292* @size: The size of @value.293*294* This hook is currently used to save the existence of a validated fs-verity295* builtin signature into LSM blob.296*297* Return: %0 on success. If an error occurs, the function will return the298* -errno.299*/300int ipe_inode_setintegrity(const struct inode *inode,301enum lsm_integrity_type type,302const void *value, size_t size)303{304struct ipe_inode *inode_sec = ipe_inode(inode);305306if (type == LSM_INT_FSVERITY_BUILTINSIG_VALID) {307inode_sec->fs_verity_signed = size > 0 && value;308return 0;309}310311return -EINVAL;312}313#endif /* CONFIG_CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */314315316