aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2009-06-10 21:03:14 -0400
committerJames Morris <jmorris@namei.org>2009-06-10 21:03:14 -0400
commit73fbad283cfbbcf02939bdbda31fc4a30e729cca (patch)
tree7c89fe13e1b4a2c7f2d60f4ea6eaf69c14bccab7 /security/integrity
parent769f3e8c384795cc350e2aae27de2a12374d19d4 (diff)
parent35f2c2f6f6ae13ef23c4f68e6d3073753077ca43 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/ima_audit.c32
-rw-r--r--security/integrity/ima/ima_crypto.c4
-rw-r--r--security/integrity/ima/ima_fs.c8
-rw-r--r--security/integrity/ima/ima_iint.c2
-rw-r--r--security/integrity/ima/ima_init.c4
-rw-r--r--security/integrity/ima/ima_main.c86
-rw-r--r--security/integrity/ima/ima_policy.c48
7 files changed, 98 insertions, 86 deletions
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index 1e082bb987be..ff513ff737f5 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -22,18 +22,9 @@ static int ima_audit;
22static int __init ima_audit_setup(char *str) 22static int __init ima_audit_setup(char *str)
23{ 23{
24 unsigned long audit; 24 unsigned long audit;
25 int rc, result = 0;
26 char *op = "ima_audit";
27 char *cause;
28 25
29 rc = strict_strtoul(str, 0, &audit); 26 if (!strict_strtoul(str, 0, &audit))
30 if (rc || audit > 1) 27 ima_audit = audit ? 1 : 0;
31 result = 1;
32 else
33 ima_audit = audit;
34 cause = ima_audit ? "enabled" : "not_enabled";
35 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
36 op, cause, result, 0);
37 return 1; 28 return 1;
38} 29}
39__setup("ima_audit=", ima_audit_setup); 30__setup("ima_audit=", ima_audit_setup);
@@ -50,23 +41,14 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
50 41
51 ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); 42 ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
52 audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u", 43 audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u",
53 current->pid, current->cred->uid, 44 current->pid, current_cred()->uid,
54 audit_get_loginuid(current), 45 audit_get_loginuid(current),
55 audit_get_sessionid(current)); 46 audit_get_sessionid(current));
56 audit_log_task_context(ab); 47 audit_log_task_context(ab);
57 switch (audit_msgno) { 48 audit_log_format(ab, " op=");
58 case AUDIT_INTEGRITY_DATA: 49 audit_log_string(ab, op);
59 case AUDIT_INTEGRITY_METADATA: 50 audit_log_format(ab, " cause=");
60 case AUDIT_INTEGRITY_PCR: 51 audit_log_string(ab, cause);
61 case AUDIT_INTEGRITY_STATUS:
62 audit_log_format(ab, " op=%s cause=%s", op, cause);
63 break;
64 case AUDIT_INTEGRITY_HASH:
65 audit_log_format(ab, " op=%s hash=%s", op, cause);
66 break;
67 default:
68 audit_log_format(ab, " op=%s", op);
69 }
70 audit_log_format(ab, " comm="); 52 audit_log_format(ab, " comm=");
71 audit_log_untrustedstring(ab, current->comm); 53 audit_log_untrustedstring(ab, current->comm);
72 if (fname) { 54 if (fname) {
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 50d572b74caf..63003a63aaee 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -103,7 +103,7 @@ int ima_calc_template_hash(int template_len, void *template, char *digest)
103 return rc; 103 return rc;
104} 104}
105 105
106static void ima_pcrread(int idx, u8 *pcr) 106static void __init ima_pcrread(int idx, u8 *pcr)
107{ 107{
108 if (!ima_used_chip) 108 if (!ima_used_chip)
109 return; 109 return;
@@ -115,7 +115,7 @@ static void ima_pcrread(int idx, u8 *pcr)
115/* 115/*
116 * Calculate the boot aggregate hash 116 * Calculate the boot aggregate hash
117 */ 117 */
118int ima_calc_boot_aggregate(char *digest) 118int __init ima_calc_boot_aggregate(char *digest)
119{ 119{
120 struct hash_desc desc; 120 struct hash_desc desc;
121 struct scatterlist sg; 121 struct scatterlist sg;
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index ffbe259700b1..7039b14e1f73 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -15,6 +15,7 @@
15 * implemenents security file system for reporting 15 * implemenents security file system for reporting
16 * current measurement list and IMA statistics 16 * current measurement list and IMA statistics
17 */ 17 */
18#include <linux/fcntl.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/seq_file.h> 20#include <linux/seq_file.h>
20#include <linux/rculist.h> 21#include <linux/rculist.h>
@@ -283,6 +284,9 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
283 */ 284 */
284int ima_open_policy(struct inode * inode, struct file * filp) 285int ima_open_policy(struct inode * inode, struct file * filp)
285{ 286{
287 /* No point in being allowed to open it if you aren't going to write */
288 if (!(filp->f_flags & O_WRONLY))
289 return -EACCES;
286 if (atomic_dec_and_test(&policy_opencount)) 290 if (atomic_dec_and_test(&policy_opencount))
287 return 0; 291 return 0;
288 return -EBUSY; 292 return -EBUSY;
@@ -315,7 +319,7 @@ static struct file_operations ima_measure_policy_ops = {
315 .release = ima_release_policy 319 .release = ima_release_policy
316}; 320};
317 321
318int ima_fs_init(void) 322int __init ima_fs_init(void)
319{ 323{
320 ima_dir = securityfs_create_dir("ima", NULL); 324 ima_dir = securityfs_create_dir("ima", NULL);
321 if (IS_ERR(ima_dir)) 325 if (IS_ERR(ima_dir))
@@ -349,7 +353,7 @@ int ima_fs_init(void)
349 goto out; 353 goto out;
350 354
351 ima_policy = securityfs_create_file("policy", 355 ima_policy = securityfs_create_file("policy",
352 S_IRUSR | S_IRGRP | S_IWUSR, 356 S_IWUSR,
353 ima_dir, NULL, 357 ima_dir, NULL,
354 &ima_measure_policy_ops); 358 &ima_measure_policy_ops);
355 if (IS_ERR(ima_policy)) 359 if (IS_ERR(ima_policy))
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index ec79f1ee992c..b8dd693f8790 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -196,7 +196,7 @@ static void init_once(void *foo)
196 kref_set(&iint->refcount, 1); 196 kref_set(&iint->refcount, 1);
197} 197}
198 198
199void ima_iintcache_init(void) 199void __init ima_iintcache_init(void)
200{ 200{
201 iint_cache = 201 iint_cache =
202 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 202 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 0b0bb8c978cc..a40da7ae5900 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -38,7 +38,7 @@ int ima_used_chip;
38 * a different value.) Violations add a zero entry to the measurement 38 * a different value.) Violations add a zero entry to the measurement
39 * list and extend the aggregate PCR value with ff...ff's. 39 * list and extend the aggregate PCR value with ff...ff's.
40 */ 40 */
41static void ima_add_boot_aggregate(void) 41static void __init ima_add_boot_aggregate(void)
42{ 42{
43 struct ima_template_entry *entry; 43 struct ima_template_entry *entry;
44 const char *op = "add_boot_aggregate"; 44 const char *op = "add_boot_aggregate";
@@ -71,7 +71,7 @@ err_out:
71 audit_cause, result, 0); 71 audit_cause, result, 0);
72} 72}
73 73
74int ima_init(void) 74int __init ima_init(void)
75{ 75{
76 u8 pcr_i[IMA_DIGEST_SIZE]; 76 u8 pcr_i[IMA_DIGEST_SIZE];
77 int rc; 77 int rc;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f4e7266f5aee..6f611874d10e 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -29,20 +29,8 @@ int ima_initialized;
29char *ima_hash = "sha1"; 29char *ima_hash = "sha1";
30static int __init hash_setup(char *str) 30static int __init hash_setup(char *str)
31{ 31{
32 const char *op = "hash_setup"; 32 if (strncmp(str, "md5", 3) == 0)
33 const char *hash = "sha1"; 33 ima_hash = "md5";
34 int result = 0;
35 int audit_info = 0;
36
37 if (strncmp(str, "md5", 3) == 0) {
38 hash = "md5";
39 ima_hash = str;
40 } else if (strncmp(str, "sha1", 4) != 0) {
41 hash = "invalid_hash_type";
42 result = 1;
43 }
44 integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
45 result, audit_info);
46 return 1; 34 return 1;
47} 35}
48__setup("ima_hash=", hash_setup); 36__setup("ima_hash=", hash_setup);
@@ -128,10 +116,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
128{ 116{
129 int rc = 0; 117 int rc = 0;
130 118
131 if (IS_ERR(file)) {
132 pr_info("%s dentry_open failed\n", filename);
133 return rc;
134 }
135 iint->opencount++; 119 iint->opencount++;
136 iint->readcount++; 120 iint->readcount++;
137 121
@@ -141,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
141 return rc; 125 return rc;
142} 126}
143 127
128static void ima_update_counts(struct ima_iint_cache *iint, int mask)
129{
130 iint->opencount++;
131 if ((mask & MAY_WRITE) || (mask == 0))
132 iint->writecount++;
133 else if (mask & (MAY_READ | MAY_EXEC))
134 iint->readcount++;
135}
136
144/** 137/**
145 * ima_path_check - based on policy, collect/store measurement. 138 * ima_path_check - based on policy, collect/store measurement.
146 * @path: contains a pointer to the path to be measured 139 * @path: contains a pointer to the path to be measured
@@ -156,10 +149,10 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
156 * - Opening a file for read when already open for write, 149 * - Opening a file for read when already open for write,
157 * could result in a file measurement error. 150 * could result in a file measurement error.
158 * 151 *
159 * Return 0 on success, an error code on failure. 152 * Always return 0 and audit dentry_open failures.
160 * (Based on the results of appraise_measurement().) 153 * (Return code will be based upon measurement appraisal.)
161 */ 154 */
162int ima_path_check(struct path *path, int mask) 155int ima_path_check(struct path *path, int mask, int update_counts)
163{ 156{
164 struct inode *inode = path->dentry->d_inode; 157 struct inode *inode = path->dentry->d_inode;
165 struct ima_iint_cache *iint; 158 struct ima_iint_cache *iint;
@@ -173,11 +166,8 @@ int ima_path_check(struct path *path, int mask)
173 return 0; 166 return 0;
174 167
175 mutex_lock(&iint->mutex); 168 mutex_lock(&iint->mutex);
176 iint->opencount++; 169 if (update_counts)
177 if ((mask & MAY_WRITE) || (mask == 0)) 170 ima_update_counts(iint, mask);
178 iint->writecount++;
179 else if (mask & (MAY_READ | MAY_EXEC))
180 iint->readcount++;
181 171
182 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); 172 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
183 if (rc < 0) 173 if (rc < 0)
@@ -196,7 +186,19 @@ int ima_path_check(struct path *path, int mask)
196 struct dentry *dentry = dget(path->dentry); 186 struct dentry *dentry = dget(path->dentry);
197 struct vfsmount *mnt = mntget(path->mnt); 187 struct vfsmount *mnt = mntget(path->mnt);
198 188
199 file = dentry_open(dentry, mnt, O_RDONLY, current->cred); 189 file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
190 current_cred());
191 if (IS_ERR(file)) {
192 int audit_info = 0;
193
194 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
195 dentry->d_name.name,
196 "add_measurement",
197 "dentry_open failed",
198 1, audit_info);
199 file = NULL;
200 goto out;
201 }
200 rc = get_path_measurement(iint, file, dentry->d_name.name); 202 rc = get_path_measurement(iint, file, dentry->d_name.name);
201 } 203 }
202out: 204out:
@@ -206,6 +208,7 @@ out:
206 kref_put(&iint->refcount, iint_free); 208 kref_put(&iint->refcount, iint_free);
207 return 0; 209 return 0;
208} 210}
211EXPORT_SYMBOL_GPL(ima_path_check);
209 212
210static int process_measurement(struct file *file, const unsigned char *filename, 213static int process_measurement(struct file *file, const unsigned char *filename,
211 int mask, int function) 214 int mask, int function)
@@ -234,7 +237,16 @@ out:
234 return rc; 237 return rc;
235} 238}
236 239
237static void opencount_get(struct file *file) 240/*
241 * ima_opens_get - increment file counts
242 *
243 * - for IPC shm and shmat file.
244 * - for nfsd exported files.
245 *
246 * Increment the counts for these files to prevent unnecessary
247 * imbalance messages.
248 */
249void ima_counts_get(struct file *file)
238{ 250{
239 struct inode *inode = file->f_dentry->d_inode; 251 struct inode *inode = file->f_dentry->d_inode;
240 struct ima_iint_cache *iint; 252 struct ima_iint_cache *iint;
@@ -246,8 +258,14 @@ static void opencount_get(struct file *file)
246 return; 258 return;
247 mutex_lock(&iint->mutex); 259 mutex_lock(&iint->mutex);
248 iint->opencount++; 260 iint->opencount++;
261 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
262 iint->readcount++;
263
264 if (file->f_mode & FMODE_WRITE)
265 iint->writecount++;
249 mutex_unlock(&iint->mutex); 266 mutex_unlock(&iint->mutex);
250} 267}
268EXPORT_SYMBOL_GPL(ima_counts_get);
251 269
252/** 270/**
253 * ima_file_mmap - based on policy, collect/store measurement. 271 * ima_file_mmap - based on policy, collect/store measurement.
@@ -272,18 +290,6 @@ int ima_file_mmap(struct file *file, unsigned long prot)
272 return 0; 290 return 0;
273} 291}
274 292
275/*
276 * ima_shm_check - IPC shm and shmat create/fput a file
277 *
278 * Maintain the opencount for these files to prevent unnecessary
279 * imbalance messages.
280 */
281void ima_shm_check(struct file *file)
282{
283 opencount_get(file);
284 return;
285}
286
287/** 293/**
288 * ima_bprm_check - based on policy, collect/store measurement. 294 * ima_bprm_check - based on policy, collect/store measurement.
289 * @bprm: contains the linux_binprm structure 295 * @bprm: contains the linux_binprm structure
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index b5291ad5ef56..e1278399b345 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -45,24 +45,30 @@ struct ima_measure_rule_entry {
45 } lsm[MAX_LSM_RULES]; 45 } lsm[MAX_LSM_RULES];
46}; 46};
47 47
48/* Without LSM specific knowledge, the default policy can only be 48/*
49 * Without LSM specific knowledge, the default policy can only be
49 * written in terms of .action, .func, .mask, .fsmagic, and .uid 50 * written in terms of .action, .func, .mask, .fsmagic, and .uid
50 */ 51 */
52
53/*
54 * The minimum rule set to allow for full TCB coverage. Measures all files
55 * opened or mmap for exec and everything read by root. Dangerous because
56 * normal users can easily run the machine out of memory simply building
57 * and running executables.
58 */
51static struct ima_measure_rule_entry default_rules[] = { 59static struct ima_measure_rule_entry default_rules[] = {
52 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC, 60 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
53 .flags = IMA_FSMAGIC},
54 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, 61 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
55 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, 62 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
56 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, 63 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
57 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC, 64 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
58 .flags = IMA_FSMAGIC}, 65 {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
59 {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
60 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, 66 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
61 .flags = IMA_FUNC | IMA_MASK}, 67 .flags = IMA_FUNC | IMA_MASK},
62 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, 68 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
63 .flags = IMA_FUNC | IMA_MASK}, 69 .flags = IMA_FUNC | IMA_MASK},
64 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, 70 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
65 .flags = IMA_FUNC | IMA_MASK | IMA_UID} 71 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
66}; 72};
67 73
68static LIST_HEAD(measure_default_rules); 74static LIST_HEAD(measure_default_rules);
@@ -71,6 +77,14 @@ static struct list_head *ima_measure;
71 77
72static DEFINE_MUTEX(ima_measure_mutex); 78static DEFINE_MUTEX(ima_measure_mutex);
73 79
80static bool ima_use_tcb __initdata;
81static int __init default_policy_setup(char *str)
82{
83 ima_use_tcb = 1;
84 return 1;
85}
86__setup("ima_tcb", default_policy_setup);
87
74/** 88/**
75 * ima_match_rules - determine whether an inode matches the measure rule. 89 * ima_match_rules - determine whether an inode matches the measure rule.
76 * @rule: a pointer to a rule 90 * @rule: a pointer to a rule
@@ -96,7 +110,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
96 if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) 110 if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
97 return false; 111 return false;
98 for (i = 0; i < MAX_LSM_RULES; i++) { 112 for (i = 0; i < MAX_LSM_RULES; i++) {
99 int rc; 113 int rc = 0;
100 u32 osid, sid; 114 u32 osid, sid;
101 115
102 if (!rule->lsm[i].rule) 116 if (!rule->lsm[i].rule)
@@ -109,7 +123,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
109 security_inode_getsecid(inode, &osid); 123 security_inode_getsecid(inode, &osid);
110 rc = security_filter_rule_match(osid, 124 rc = security_filter_rule_match(osid,
111 rule->lsm[i].type, 125 rule->lsm[i].type,
112 AUDIT_EQUAL, 126 Audit_equal,
113 rule->lsm[i].rule, 127 rule->lsm[i].rule,
114 NULL); 128 NULL);
115 break; 129 break;
@@ -119,7 +133,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
119 security_task_getsecid(tsk, &sid); 133 security_task_getsecid(tsk, &sid);
120 rc = security_filter_rule_match(sid, 134 rc = security_filter_rule_match(sid,
121 rule->lsm[i].type, 135 rule->lsm[i].type,
122 AUDIT_EQUAL, 136 Audit_equal,
123 rule->lsm[i].rule, 137 rule->lsm[i].rule,
124 NULL); 138 NULL);
125 default: 139 default:
@@ -164,11 +178,17 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
164 * ima_measure points to either the measure_default_rules or the 178 * ima_measure points to either the measure_default_rules or the
165 * the new measure_policy_rules. 179 * the new measure_policy_rules.
166 */ 180 */
167void ima_init_policy(void) 181void __init ima_init_policy(void)
168{ 182{
169 int i; 183 int i, entries;
184
185 /* if !ima_use_tcb set entries = 0 so we load NO default rules */
186 if (ima_use_tcb)
187 entries = ARRAY_SIZE(default_rules);
188 else
189 entries = 0;
170 190
171 for (i = 0; i < ARRAY_SIZE(default_rules); i++) 191 for (i = 0; i < entries; i++)
172 list_add_tail(&default_rules[i].list, &measure_default_rules); 192 list_add_tail(&default_rules[i].list, &measure_default_rules);
173 ima_measure = &measure_default_rules; 193 ima_measure = &measure_default_rules;
174} 194}
@@ -227,7 +247,7 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
227 247
228 entry->lsm[lsm_rule].type = audit_type; 248 entry->lsm[lsm_rule].type = audit_type;
229 result = security_filter_rule_init(entry->lsm[lsm_rule].type, 249 result = security_filter_rule_init(entry->lsm[lsm_rule].type,
230 AUDIT_EQUAL, args, 250 Audit_equal, args,
231 &entry->lsm[lsm_rule].rule); 251 &entry->lsm[lsm_rule].rule);
232 return result; 252 return result;
233} 253}