aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-04-20 10:20:54 -0400
committerJames Morris <jmorris@namei.org>2010-04-20 19:58:13 -0400
commit6ccd045630054c99ba1bb35673db12cfcf1eea58 (patch)
treebce41e39722ae178807abe2213fd94e582842bae /security
parenta200005038955057063fc8ea82129ebc785df41c (diff)
ima: handle multiple rules per write
Currently IMA will only accept one rule per write(). This patch allows IMA to accept writes which contain multiple rules but only processes one rule per write. \n is used as the delimiter between rules. IMA will return a short write indicating that it only accepted up to the first \n. This allows simple userspace utilities like cat to be used to load an IMA policy instead of needing a special userspace utility that understood 'one write per rule' Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_fs.c38
-rw-r--r--security/integrity/ima/ima_policy.c18
3 files changed, 32 insertions, 26 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 47fb65d1fcbd..16d100d3fc38 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -135,7 +135,7 @@ enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
135int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); 135int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
136void ima_init_policy(void); 136void ima_init_policy(void);
137void ima_update_policy(void); 137void ima_update_policy(void);
138int ima_parse_add_rule(char *); 138ssize_t ima_parse_add_rule(char *);
139void ima_delete_rules(void); 139void ima_delete_rules(void);
140 140
141/* LSM based policy rules require audit */ 141/* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 0c72c9c38956..3674a52e1cfb 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -243,32 +243,34 @@ static const struct file_operations ima_ascii_measurements_ops = {
243static ssize_t ima_write_policy(struct file *file, const char __user *buf, 243static ssize_t ima_write_policy(struct file *file, const char __user *buf,
244 size_t datalen, loff_t *ppos) 244 size_t datalen, loff_t *ppos)
245{ 245{
246 char *data; 246 char *data = NULL;
247 int rc; 247 ssize_t result;
248 248
249 if (datalen >= PAGE_SIZE) 249 if (datalen >= PAGE_SIZE)
250 return -ENOMEM; 250 datalen = PAGE_SIZE - 1;
251 if (*ppos != 0) { 251
252 /* No partial writes. */ 252 /* No partial writes. */
253 return -EINVAL; 253 result = -EINVAL;
254 } 254 if (*ppos != 0)
255 goto out;
256
257 result = -ENOMEM;
255 data = kmalloc(datalen + 1, GFP_KERNEL); 258 data = kmalloc(datalen + 1, GFP_KERNEL);
256 if (!data) 259 if (!data)
257 return -ENOMEM; 260 goto out;
258 261
259 if (copy_from_user(data, buf, datalen)) {
260 kfree(data);
261 return -EFAULT;
262 }
263 *(data + datalen) = '\0'; 262 *(data + datalen) = '\0';
264 rc = ima_parse_add_rule(data);
265 if (rc < 0) {
266 datalen = -EINVAL;
267 valid_policy = 0;
268 }
269 263
264 result = -EFAULT;
265 if (copy_from_user(data, buf, datalen))
266 goto out;
267
268 result = ima_parse_add_rule(data);
269out:
270 if (result < 0)
271 valid_policy = 0;
270 kfree(data); 272 kfree(data);
271 return datalen; 273 return result;
272} 274}
273 275
274static struct dentry *ima_dir; 276static struct dentry *ima_dir;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 4759d0f99335..49998f90e441 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -261,7 +261,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
261 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); 261 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
262 262
263 entry->action = -1; 263 entry->action = -1;
264 while ((p = strsep(&rule, " \n")) != NULL) { 264 while ((p = strsep(&rule, " ")) != NULL) {
265 substring_t args[MAX_OPT_ARGS]; 265 substring_t args[MAX_OPT_ARGS];
266 int token; 266 int token;
267 unsigned long lnum; 267 unsigned long lnum;
@@ -269,7 +269,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
269 if (result < 0) 269 if (result < 0)
270 break; 270 break;
271 if (!*p) 271 if (!*p)
272 continue; 272 break;
273 token = match_token(p, policy_tokens, args); 273 token = match_token(p, policy_tokens, args);
274 switch (token) { 274 switch (token) {
275 case Opt_measure: 275 case Opt_measure:
@@ -373,7 +373,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
373 if (entry->action == UNKNOWN) 373 if (entry->action == UNKNOWN)
374 result = -EINVAL; 374 result = -EINVAL;
375 375
376 audit_log_format(ab, "res=%d", !result ? 0 : 1); 376 audit_log_format(ab, "res=%d", !!result);
377 audit_log_end(ab); 377 audit_log_end(ab);
378 return result; 378 return result;
379} 379}
@@ -383,13 +383,14 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
383 * @rule - ima measurement policy rule 383 * @rule - ima measurement policy rule
384 * 384 *
385 * Uses a mutex to protect the policy list from multiple concurrent writers. 385 * Uses a mutex to protect the policy list from multiple concurrent writers.
386 * Returns 0 on success, an error code on failure. 386 * Returns the length of the rule parsed, an error code on failure
387 */ 387 */
388int ima_parse_add_rule(char *rule) 388ssize_t ima_parse_add_rule(char *rule)
389{ 389{
390 const char *op = "update_policy"; 390 const char *op = "update_policy";
391 char *p;
391 struct ima_measure_rule_entry *entry; 392 struct ima_measure_rule_entry *entry;
392 int result = 0; 393 ssize_t result, len;
393 int audit_info = 0; 394 int audit_info = 0;
394 395
395 /* Prevent installed policy from changing */ 396 /* Prevent installed policy from changing */
@@ -409,8 +410,11 @@ int ima_parse_add_rule(char *rule)
409 410
410 INIT_LIST_HEAD(&entry->list); 411 INIT_LIST_HEAD(&entry->list);
411 412
412 result = ima_parse_rule(rule, entry); 413 p = strsep(&rule, "\n");
414 len = strlen(p) + 1;
415 result = ima_parse_rule(p, entry);
413 if (!result) { 416 if (!result) {
417 result = len;
414 mutex_lock(&ima_measure_mutex); 418 mutex_lock(&ima_measure_mutex);
415 list_add_tail(&entry->list, &measure_policy_rules); 419 list_add_tail(&entry->list, &measure_policy_rules);
416 mutex_unlock(&ima_measure_mutex); 420 mutex_unlock(&ima_measure_mutex);