Blame view
security/integrity/ima/ima_main.c
5.77 KB
3323eec92 integrity: IMA as... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * Copyright (C) 2005,2006,2007,2008 IBM Corporation * * Authors: * Reiner Sailer <sailer@watson.ibm.com> * Serge Hallyn <serue@us.ibm.com> * Kylene Hall <kylene@us.ibm.com> * Mimi Zohar <zohar@us.ibm.com> * * 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. * * File: ima_main.c |
e0d5bd2ae IMA: clean up the... |
16 |
* implements the IMA hooks: ima_bprm_check, ima_file_mmap, |
9bbb6cad0 ima: rename ima_p... |
17 |
* and ima_file_check. |
3323eec92 integrity: IMA as... |
18 19 20 21 22 23 |
*/ #include <linux/module.h> #include <linux/file.h> #include <linux/binfmts.h> #include <linux/mount.h> #include <linux/mman.h> |
5a0e3ad6a include cleanup: ... |
24 |
#include <linux/slab.h> |
d5813a571 ima: sparse fix: ... |
25 |
#include <linux/ima.h> |
3323eec92 integrity: IMA as... |
26 27 28 29 30 31 32 33 |
#include "ima.h" int ima_initialized; char *ima_hash = "sha1"; static int __init hash_setup(char *str) { |
07ff7a0b1 integrity: remove... |
34 35 |
if (strncmp(str, "md5", 3) == 0) ima_hash = "md5"; |
3323eec92 integrity: IMA as... |
36 37 38 |
return 1; } __setup("ima_hash=", hash_setup); |
e0d5bd2ae IMA: clean up the... |
39 |
/* |
890275b5e IMA: maintain i_r... |
40 |
* ima_rdwr_violation_check |
8eb988c70 fix ima breakage |
41 |
* |
890275b5e IMA: maintain i_r... |
42 |
* Only invalidate the PCR for measured files: |
8eb988c70 fix ima breakage |
43 44 45 46 47 48 |
* - Opening a file for write when already open for read, * results in a time of measure, time of use (ToMToU) error. * - Opening a file for read when already open for write, * could result in a file measurement error. * */ |
890275b5e IMA: maintain i_r... |
49 |
static void ima_rdwr_violation_check(struct file *file) |
8eb988c70 fix ima breakage |
50 51 52 53 |
{ struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; fmode_t mode = file->f_mode; |
8eb988c70 fix ima breakage |
54 |
int rc; |
ad16ad00c IMA: use inode->i... |
55 |
bool send_tomtou = false, send_writers = false; |
8eb988c70 fix ima breakage |
56 |
|
890275b5e IMA: maintain i_r... |
57 |
if (!S_ISREG(inode->i_mode) || !ima_initialized) |
8eb988c70 fix ima breakage |
58 |
return; |
a178d2027 IMA: move read co... |
59 |
|
890275b5e IMA: maintain i_r... |
60 |
mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ |
ad16ad00c IMA: use inode->i... |
61 |
|
8eb988c70 fix ima breakage |
62 |
if (mode & FMODE_WRITE) { |
a68a27b6f IMA: convert i_re... |
63 |
if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) |
ad16ad00c IMA: use inode->i... |
64 |
send_tomtou = true; |
8eb988c70 fix ima breakage |
65 66 |
goto out; } |
ad16ad00c IMA: use inode->i... |
67 |
|
1adace9bb ima: remove unnec... |
68 |
rc = ima_must_measure(inode, MAY_READ, FILE_CHECK); |
bade72d60 IMA: fix the ToMT... |
69 70 |
if (rc < 0) goto out; |
ad16ad00c IMA: use inode->i... |
71 72 |
if (atomic_read(&inode->i_writecount) > 0) send_writers = true; |
8eb988c70 fix ima breakage |
73 |
out: |
890275b5e IMA: maintain i_r... |
74 |
mutex_unlock(&inode->i_mutex); |
ad16ad00c IMA: use inode->i... |
75 76 77 78 79 80 81 |
if (send_tomtou) ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", "ToMToU"); if (send_writers) ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", "open_writers"); |
8eb988c70 fix ima breakage |
82 |
} |
f381c2722 integrity: move i... |
83 |
static void ima_check_last_writer(struct integrity_iint_cache *iint, |
bc7d2a3e6 IMA: only allocat... |
84 85 86 |
struct inode *inode, struct file *file) { |
4b2a2c674 ima: fmode_t miss... |
87 |
fmode_t mode = file->f_mode; |
bc7d2a3e6 IMA: only allocat... |
88 |
|
854fdd55b IMA: remove IMA i... |
89 |
mutex_lock(&iint->mutex); |
bc7d2a3e6 IMA: only allocat... |
90 91 92 93 |
if (mode & FMODE_WRITE && atomic_read(&inode->i_writecount) == 1 && iint->version != inode->i_version) iint->flags &= ~IMA_MEASURED; |
bc7d2a3e6 IMA: only allocat... |
94 |
mutex_unlock(&iint->mutex); |
bc7d2a3e6 IMA: only allocat... |
95 |
} |
3323eec92 integrity: IMA as... |
96 97 98 99 |
/** * ima_file_free - called on __fput() * @file: pointer to file structure being freed * |
890275b5e IMA: maintain i_r... |
100 |
* Flag files that changed, based on i_version |
3323eec92 integrity: IMA as... |
101 102 103 104 |
*/ void ima_file_free(struct file *file) { struct inode *inode = file->f_dentry->d_inode; |
f381c2722 integrity: move i... |
105 |
struct integrity_iint_cache *iint; |
3323eec92 integrity: IMA as... |
106 |
|
e950598d4 ima: always maint... |
107 |
if (!iint_initialized || !S_ISREG(inode->i_mode)) |
3323eec92 integrity: IMA as... |
108 |
return; |
196f51812 IMA: explicit IMA... |
109 |
|
f381c2722 integrity: move i... |
110 |
iint = integrity_iint_find(inode); |
854fdd55b IMA: remove IMA i... |
111 112 |
if (!iint) return; |
3323eec92 integrity: IMA as... |
113 |
|
854fdd55b IMA: remove IMA i... |
114 |
ima_check_last_writer(iint, inode, file); |
3323eec92 integrity: IMA as... |
115 |
} |
3323eec92 integrity: IMA as... |
116 117 118 119 |
static int process_measurement(struct file *file, const unsigned char *filename, int mask, int function) { struct inode *inode = file->f_dentry->d_inode; |
f381c2722 integrity: move i... |
120 |
struct integrity_iint_cache *iint; |
e950598d4 ima: always maint... |
121 |
int rc = 0; |
3323eec92 integrity: IMA as... |
122 123 124 |
if (!ima_initialized || !S_ISREG(inode->i_mode)) return 0; |
bc7d2a3e6 IMA: only allocat... |
125 |
|
1adace9bb ima: remove unnec... |
126 |
rc = ima_must_measure(inode, mask, function); |
bc7d2a3e6 IMA: only allocat... |
127 128 129 |
if (rc != 0) return rc; retry: |
f381c2722 integrity: move i... |
130 |
iint = integrity_iint_find(inode); |
bc7d2a3e6 IMA: only allocat... |
131 |
if (!iint) { |
f381c2722 integrity: move i... |
132 |
rc = integrity_inode_alloc(inode); |
bc7d2a3e6 IMA: only allocat... |
133 134 135 136 |
if (!rc || rc == -EEXIST) goto retry; return rc; } |
3323eec92 integrity: IMA as... |
137 138 |
mutex_lock(&iint->mutex); |
bc7d2a3e6 IMA: only allocat... |
139 |
|
1adace9bb ima: remove unnec... |
140 |
rc = iint->flags & IMA_MEASURED ? 1 : 0; |
3323eec92 integrity: IMA as... |
141 142 143 144 145 146 147 148 |
if (rc != 0) goto out; rc = ima_collect_measurement(iint, file); if (!rc) ima_store_measurement(iint, file, filename); out: mutex_unlock(&iint->mutex); |
3323eec92 integrity: IMA as... |
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
return rc; } /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) * @prot: contains the protection that will be applied by the kernel. * * Measure files being mmapped executable based on the ima_must_measure() * policy decision. * * Return 0 on success, an error code on failure. * (Based on the results of appraise_measurement().) */ int ima_file_mmap(struct file *file, unsigned long prot) { int rc; if (!file) return 0; if (prot & PROT_EXEC) rc = process_measurement(file, file->f_dentry->d_name.name, MAY_EXEC, FILE_MMAP); return 0; } /** * ima_bprm_check - based on policy, collect/store measurement. * @bprm: contains the linux_binprm structure * * The OS protects against an executable file, already open for write, * from being executed in deny_write_access() and an executable file, * already open for execute, from being modified in get_write_access(). * So we can be certain that what we verify and measure here is actually * what is being executed. * * Return 0 on success, an error code on failure. * (Based on the results of appraise_measurement().) */ int ima_bprm_check(struct linux_binprm *bprm) { int rc; rc = process_measurement(bprm->file, bprm->filename, MAY_EXEC, BPRM_CHECK); return 0; } |
8eb988c70 fix ima breakage |
196 197 198 199 200 201 202 203 204 205 |
/** * ima_path_check - based on policy, collect/store measurement. * @file: pointer to the file to be measured * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE * * Measure files based on the ima_must_measure() policy decision. * * Always return 0 and audit dentry_open failures. * (Return code will be based upon measurement appraisal.) */ |
9bbb6cad0 ima: rename ima_p... |
206 |
int ima_file_check(struct file *file, int mask) |
8eb988c70 fix ima breakage |
207 208 |
{ int rc; |
890275b5e IMA: maintain i_r... |
209 |
ima_rdwr_violation_check(file); |
8eb988c70 fix ima breakage |
210 211 |
rc = process_measurement(file, file->f_dentry->d_name.name, mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
1e93d0052 ima: rename PATH_... |
212 |
FILE_CHECK); |
8eb988c70 fix ima breakage |
213 214 |
return 0; } |
9bbb6cad0 ima: rename ima_p... |
215 |
EXPORT_SYMBOL_GPL(ima_file_check); |
8eb988c70 fix ima breakage |
216 |
|
3323eec92 integrity: IMA as... |
217 218 219 |
static int __init init_ima(void) { int error; |
3323eec92 integrity: IMA as... |
220 221 222 223 |
error = ima_init(); ima_initialized = 1; return error; } |
bab739378 integrity: IMA di... |
224 225 226 227 |
static void __exit cleanup_ima(void) { ima_cleanup(); } |
3323eec92 integrity: IMA as... |
228 229 230 231 |
late_initcall(init_ima); /* Start IMA after the TPM is available */ MODULE_DESCRIPTION("Integrity Measurement Architecture"); MODULE_LICENSE("GPL"); |