Path: blob/master/security/integrity/ima/ima_main.c
10817 views
/*1* Copyright (C) 2005,2006,2007,2008 IBM Corporation2*3* Authors:4* Reiner Sailer <[email protected]>5* Serge Hallyn <[email protected]>6* Kylene Hall <[email protected]>7* Mimi Zohar <[email protected]>8*9* This program is free software; you can redistribute it and/or10* modify it under the terms of the GNU General Public License as11* published by the Free Software Foundation, version 2 of the12* License.13*14* File: ima_main.c15* implements the IMA hooks: ima_bprm_check, ima_file_mmap,16* and ima_file_check.17*/18#include <linux/module.h>19#include <linux/file.h>20#include <linux/binfmts.h>21#include <linux/mount.h>22#include <linux/mman.h>23#include <linux/slab.h>2425#include "ima.h"2627int ima_initialized;2829char *ima_hash = "sha1";30static int __init hash_setup(char *str)31{32if (strncmp(str, "md5", 3) == 0)33ima_hash = "md5";34return 1;35}36__setup("ima_hash=", hash_setup);3738/*39* ima_rdwr_violation_check40*41* Only invalidate the PCR for measured files:42* - Opening a file for write when already open for read,43* results in a time of measure, time of use (ToMToU) error.44* - Opening a file for read when already open for write,45* could result in a file measurement error.46*47*/48static void ima_rdwr_violation_check(struct file *file)49{50struct dentry *dentry = file->f_path.dentry;51struct inode *inode = dentry->d_inode;52fmode_t mode = file->f_mode;53int rc;54bool send_tomtou = false, send_writers = false;5556if (!S_ISREG(inode->i_mode) || !ima_initialized)57return;5859mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */6061if (mode & FMODE_WRITE) {62if (atomic_read(&inode->i_readcount) && IS_IMA(inode))63send_tomtou = true;64goto out;65}6667rc = ima_must_measure(inode, MAY_READ, FILE_CHECK);68if (rc < 0)69goto out;7071if (atomic_read(&inode->i_writecount) > 0)72send_writers = true;73out:74mutex_unlock(&inode->i_mutex);7576if (send_tomtou)77ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",78"ToMToU");79if (send_writers)80ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",81"open_writers");82}8384static void ima_check_last_writer(struct ima_iint_cache *iint,85struct inode *inode,86struct file *file)87{88mode_t mode = file->f_mode;8990mutex_lock(&iint->mutex);91if (mode & FMODE_WRITE &&92atomic_read(&inode->i_writecount) == 1 &&93iint->version != inode->i_version)94iint->flags &= ~IMA_MEASURED;95mutex_unlock(&iint->mutex);96}9798/**99* ima_file_free - called on __fput()100* @file: pointer to file structure being freed101*102* Flag files that changed, based on i_version103*/104void ima_file_free(struct file *file)105{106struct inode *inode = file->f_dentry->d_inode;107struct ima_iint_cache *iint;108109if (!iint_initialized || !S_ISREG(inode->i_mode))110return;111112iint = ima_iint_find(inode);113if (!iint)114return;115116ima_check_last_writer(iint, inode, file);117}118119static int process_measurement(struct file *file, const unsigned char *filename,120int mask, int function)121{122struct inode *inode = file->f_dentry->d_inode;123struct ima_iint_cache *iint;124int rc = 0;125126if (!ima_initialized || !S_ISREG(inode->i_mode))127return 0;128129rc = ima_must_measure(inode, mask, function);130if (rc != 0)131return rc;132retry:133iint = ima_iint_find(inode);134if (!iint) {135rc = ima_inode_alloc(inode);136if (!rc || rc == -EEXIST)137goto retry;138return rc;139}140141mutex_lock(&iint->mutex);142143rc = iint->flags & IMA_MEASURED ? 1 : 0;144if (rc != 0)145goto out;146147rc = ima_collect_measurement(iint, file);148if (!rc)149ima_store_measurement(iint, file, filename);150out:151mutex_unlock(&iint->mutex);152return rc;153}154155/**156* ima_file_mmap - based on policy, collect/store measurement.157* @file: pointer to the file to be measured (May be NULL)158* @prot: contains the protection that will be applied by the kernel.159*160* Measure files being mmapped executable based on the ima_must_measure()161* policy decision.162*163* Return 0 on success, an error code on failure.164* (Based on the results of appraise_measurement().)165*/166int ima_file_mmap(struct file *file, unsigned long prot)167{168int rc;169170if (!file)171return 0;172if (prot & PROT_EXEC)173rc = process_measurement(file, file->f_dentry->d_name.name,174MAY_EXEC, FILE_MMAP);175return 0;176}177178/**179* ima_bprm_check - based on policy, collect/store measurement.180* @bprm: contains the linux_binprm structure181*182* The OS protects against an executable file, already open for write,183* from being executed in deny_write_access() and an executable file,184* already open for execute, from being modified in get_write_access().185* So we can be certain that what we verify and measure here is actually186* what is being executed.187*188* Return 0 on success, an error code on failure.189* (Based on the results of appraise_measurement().)190*/191int ima_bprm_check(struct linux_binprm *bprm)192{193int rc;194195rc = process_measurement(bprm->file, bprm->filename,196MAY_EXEC, BPRM_CHECK);197return 0;198}199200/**201* ima_path_check - based on policy, collect/store measurement.202* @file: pointer to the file to be measured203* @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE204*205* Measure files based on the ima_must_measure() policy decision.206*207* Always return 0 and audit dentry_open failures.208* (Return code will be based upon measurement appraisal.)209*/210int ima_file_check(struct file *file, int mask)211{212int rc;213214ima_rdwr_violation_check(file);215rc = process_measurement(file, file->f_dentry->d_name.name,216mask & (MAY_READ | MAY_WRITE | MAY_EXEC),217FILE_CHECK);218return 0;219}220EXPORT_SYMBOL_GPL(ima_file_check);221222static int __init init_ima(void)223{224int error;225226error = ima_init();227ima_initialized = 1;228return error;229}230231static void __exit cleanup_ima(void)232{233ima_cleanup();234}235236late_initcall(init_ima); /* Start IMA after the TPM is available */237238MODULE_DESCRIPTION("Integrity Measurement Architecture");239MODULE_LICENSE("GPL");240241242