From 53fc0e2259f261602a2750dcc82b8d7bf04d3c35 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 5 May 2009 13:12:48 -0400 Subject: integrity: lsm audit rule matching fix An audit subsystem change replaced AUDIT_EQUAL with Audit_equal. Update calls to security_filter_rule_init()/match() to reflect the change. Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index b5291ad5ef5..b168c1d595c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -96,7 +96,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) return false; for (i = 0; i < MAX_LSM_RULES; i++) { - int rc; + int rc = 0; u32 osid, sid; if (!rule->lsm[i].rule) @@ -109,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, security_inode_getsecid(inode, &osid); rc = security_filter_rule_match(osid, rule->lsm[i].type, - AUDIT_EQUAL, + Audit_equal, rule->lsm[i].rule, NULL); break; @@ -119,7 +119,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, security_task_getsecid(tsk, &sid); rc = security_filter_rule_match(sid, rule->lsm[i].type, - AUDIT_EQUAL, + Audit_equal, rule->lsm[i].rule, NULL); default: @@ -227,7 +227,7 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, entry->lsm[lsm_rule].type = audit_type; result = security_filter_rule_init(entry->lsm[lsm_rule].type, - AUDIT_EQUAL, args, + Audit_equal, args, &entry->lsm[lsm_rule].rule); return result; } -- cgit v1.2.3-70-g09d2 From e5e520a715dcea6b72f6b9417b203a4b1e813a8b Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 5 May 2009 13:13:00 -0400 Subject: integrity: use audit_log_string Based on a request from Eric Paris to simplify parsing, replace audit_log_format statements containing "%s" with audit_log_string(). Signed-off-by: Mimi Zohar Acked-by: Eric Paris Signed-off-by: James Morris --- security/integrity/ima/ima_audit.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index 1e082bb987b..c1461150691 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -54,19 +54,10 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, audit_get_loginuid(current), audit_get_sessionid(current)); audit_log_task_context(ab); - switch (audit_msgno) { - case AUDIT_INTEGRITY_DATA: - case AUDIT_INTEGRITY_METADATA: - case AUDIT_INTEGRITY_PCR: - case AUDIT_INTEGRITY_STATUS: - audit_log_format(ab, " op=%s cause=%s", op, cause); - break; - case AUDIT_INTEGRITY_HASH: - audit_log_format(ab, " op=%s hash=%s", op, cause); - break; - default: - audit_log_format(ab, " op=%s", op); - } + audit_log_format(ab, " op="); + audit_log_string(ab, op); + audit_log_format(ab, " cause="); + audit_log_string(ab, cause); audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, current->comm); if (fname) { -- cgit v1.2.3-70-g09d2 From 07ff7a0b187f3951788f64ae1f30e8109bc8e9eb Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 5 May 2009 13:13:10 -0400 Subject: integrity: remove __setup auditing msgs Remove integrity audit messages from __setup() Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_audit.c | 13 ++----------- security/integrity/ima/ima_main.c | 16 ++-------------- 2 files changed, 4 insertions(+), 25 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index c1461150691..b628eea477a 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -22,18 +22,9 @@ static int ima_audit; static int __init ima_audit_setup(char *str) { unsigned long audit; - int rc, result = 0; - char *op = "ima_audit"; - char *cause; - rc = strict_strtoul(str, 0, &audit); - if (rc || audit > 1) - result = 1; - else - ima_audit = audit; - cause = ima_audit ? "enabled" : "not_enabled"; - integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, - op, cause, result, 0); + if (!strict_strtoul(str, 0, &audit)) + ima_audit = audit ? 1 : 0; return 1; } __setup("ima_audit=", ima_audit_setup); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f4e7266f5ae..122f17fc7fc 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -29,20 +29,8 @@ int ima_initialized; char *ima_hash = "sha1"; static int __init hash_setup(char *str) { - const char *op = "hash_setup"; - const char *hash = "sha1"; - int result = 0; - int audit_info = 0; - - if (strncmp(str, "md5", 3) == 0) { - hash = "md5"; - ima_hash = str; - } else if (strncmp(str, "sha1", 4) != 0) { - hash = "invalid_hash_type"; - result = 1; - } - integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash, - result, audit_info); + if (strncmp(str, "md5", 3) == 0) + ima_hash = "md5"; return 1; } __setup("ima_hash=", hash_setup); -- cgit v1.2.3-70-g09d2 From 37bcbf13d32e4e453e9def79ee72bd953b88302f Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 11 May 2009 13:59:10 -0400 Subject: IMA: use current_cred() instead of current->cred Proper invocation of the current credentials is to use current_cred() not current->cred. This patches makes IMA use the new method. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_audit.c | 2 +- security/integrity/ima/ima_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index b628eea477a..ff513ff737f 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -41,7 +41,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u", - current->pid, current->cred->uid, + current->pid, current_cred()->uid, audit_get_loginuid(current), audit_get_sessionid(current)); audit_log_task_context(ab); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 122f17fc7fc..cdae13c5ae0 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -184,7 +184,7 @@ int ima_path_check(struct path *path, int mask) struct dentry *dentry = dget(path->dentry); struct vfsmount *mnt = mntget(path->mnt); - file = dentry_open(dentry, mnt, O_RDONLY, current->cred); + file = dentry_open(dentry, mnt, O_RDONLY, current_cred()); rc = get_path_measurement(iint, file, dentry->d_name.name); } out: -- cgit v1.2.3-70-g09d2 From f06dd16a03f6f7f72fab4db03be36e28c28c6fd6 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 11 May 2009 13:59:16 -0400 Subject: IMA: Handle dentry_open failures Currently IMA does not handle failures from dentry_open(). This means that we leave a pointer set to ERR_PTR(errno) and then try to use it just a few lines later in fput(). Oops. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index cdae13c5ae0..1987424623c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -116,10 +116,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, { int rc = 0; - if (IS_ERR(file)) { - pr_info("%s dentry_open failed\n", filename); - return rc; - } iint->opencount++; iint->readcount++; @@ -185,6 +181,12 @@ int ima_path_check(struct path *path, int mask) struct vfsmount *mnt = mntget(path->mnt); file = dentry_open(dentry, mnt, O_RDONLY, current_cred()); + if (IS_ERR(file)) { + pr_info("%s dentry_open failed\n", dentry->d_name.name); + rc = PTR_ERR(file); + file = NULL; + goto out; + } rc = get_path_measurement(iint, file, dentry->d_name.name); } out: -- cgit v1.2.3-70-g09d2 From 1a62e958fa4aaeeb752311b4f5e16b2a86737b23 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 11 May 2009 13:59:22 -0400 Subject: IMA: open all files O_LARGEFILE If IMA tried to measure a file which was larger than 4G dentry_open would fail with -EOVERFLOW since IMA wasn't passing O_LARGEFILE. This patch passes O_LARGEFILE to all IMA opens to avoid this problem. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 1987424623c..c4228c0eb2d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -180,7 +180,8 @@ int ima_path_check(struct path *path, int mask) struct dentry *dentry = dget(path->dentry); struct vfsmount *mnt = mntget(path->mnt); - file = dentry_open(dentry, mnt, O_RDONLY, current_cred()); + file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, + current_cred()); if (IS_ERR(file)) { pr_info("%s dentry_open failed\n", dentry->d_name.name); rc = PTR_ERR(file); -- cgit v1.2.3-70-g09d2 From f850a7c040d9faafb41bceb0a05d6bb7432c8c7a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 12 May 2009 15:13:55 -0400 Subject: IMA: remove read permissions on the ima policy file The IMA policy file does not implement read. Trying to just open/read/close the file will load a blank policy and you cannot then change the policy without a reboot. This removes the read permission from the file so one must at least be attempting to write... Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_fs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ffbe259700b..3305a961586 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -15,6 +15,7 @@ * implemenents security file system for reporting * current measurement list and IMA statistics */ +#include #include #include #include @@ -283,6 +284,9 @@ static atomic_t policy_opencount = ATOMIC_INIT(1); */ int ima_open_policy(struct inode * inode, struct file * filp) { + /* No point in being allowed to open it if you aren't going to write */ + if (!(filp->f_flags & O_WRONLY)) + return -EACCES; if (atomic_dec_and_test(&policy_opencount)) return 0; return -EBUSY; @@ -349,7 +353,7 @@ int ima_fs_init(void) goto out; ima_policy = securityfs_create_file("policy", - S_IRUSR | S_IRGRP | S_IWUSR, + S_IWUSR, ima_dir, NULL, &ima_measure_policy_ops); if (IS_ERR(ima_policy)) -- cgit v1.2.3-70-g09d2 From c3d20103d08e5c0b6738fbd0acf3ca004e5356c5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 12 May 2009 15:14:23 -0400 Subject: IMA: do not measure everything opened by root by default The IMA default policy measures every single file opened by root. This is terrible for most users. Consider a system (like mine) with virtual machine images. When those images are touched (which happens at boot for me) those images are measured. This is just way too much for the default case. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index b168c1d595c..dec6dcb1c8d 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -61,8 +61,6 @@ static struct ima_measure_rule_entry default_rules[] = { .flags = IMA_FUNC | IMA_MASK}, {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, .flags = IMA_FUNC | IMA_MASK}, - {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, - .flags = IMA_FUNC | IMA_MASK | IMA_UID} }; static LIST_HEAD(measure_default_rules); -- cgit v1.2.3-70-g09d2 From 75834fc3b6fcff00327f5d2a18760c1e8e0179c5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 18 May 2009 10:26:10 -0400 Subject: SELinux: move SELINUX_MAGIC into magic.h The selinuxfs superblock magic is used inside the IMA code, but is being defined in two places and could someday get out of sync. This patch moves the declaration into magic.h so it is only done once. Signed-off-by: Eric Paris Signed-off-by: James Morris --- include/linux/magic.h | 1 + security/integrity/ima/ima_policy.c | 8 +++----- security/selinux/include/security.h | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'security/integrity') diff --git a/include/linux/magic.h b/include/linux/magic.h index 5b4e28bcb78..927138cf305 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -9,6 +9,7 @@ #define DEBUGFS_MAGIC 0x64626720 #define SYSFS_MAGIC 0x62656572 #define SECURITYFS_MAGIC 0x73636673 +#define SELINUX_MAGIC 0xf97cff8c #define TMPFS_MAGIC 0x01021994 #define SQUASHFS_MAGIC 0x73717368 #define EFS_SUPER_MAGIC 0x414A53 diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index dec6dcb1c8d..31d677f7c65 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,14 +49,12 @@ struct ima_measure_rule_entry { * written in terms of .action, .func, .mask, .fsmagic, and .uid */ static struct ima_measure_rule_entry default_rules[] = { - {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC, - .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC, - .flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, .flags = IMA_FUNC | IMA_MASK}, {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a7be3f01fb0..ca835795a8b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -8,14 +8,13 @@ #ifndef _SELINUX_SECURITY_H_ #define _SELINUX_SECURITY_H_ +#include #include "flask.h" #define SECSID_NULL 0x00000000 /* unspecified SID */ #define SECSID_WILD 0xffffffff /* wildcard SID */ #define SECCLASS_NULL 0x0000 /* no class */ -#define SELINUX_MAGIC 0xf97cff8c - /* Identify specific policy version changes */ #define POLICYDB_VERSION_BASE 15 #define POLICYDB_VERSION_BOOL 16 -- cgit v1.2.3-70-g09d2 From 5789ba3bd0a3cd20df5980ebf03358f2eb44fd67 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 21 May 2009 15:47:06 -0400 Subject: IMA: Minimal IMA policy and boot param for TCB IMA policy The IMA TCB policy is dangerous. A normal use can use all of a system's memory (which cannot be freed) simply by building and running lots of executables. The TCB policy is also nearly useless because logging in as root often causes a policy violation when dealing with utmp, thus rendering the measurements meaningless. There is no good fix for this in the kernel. A full TCB policy would need to be loaded in userspace using LSM rule matching to get both a protected and useful system. But, if too little is measured before userspace can load a real policy one again ends up with a meaningless set of measurements. One option would be to put the policy load inside the initrd in order to get it early enough in the boot sequence to be useful, but this runs into trouble with the LSM. For IMA to measure the LSM policy and the LSM policy loading mechanism it needs rules to do so, but we already talked about problems with defaulting to such broad rules.... IMA also depends on the files being measured to be on an FS which implements and supports i_version. Since the only FS with this support (ext4) doesn't even use it by default it seems silly to have any IMA rules by default. This should reduce the performance overhead of IMA to near 0 while still letting users who choose to configure their machine as such to inclue the ima_tcb kernel paramenter and get measurements during boot before they can load a customized, reasonable policy in userspace. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- Documentation/kernel-parameters.txt | 6 ++++++ security/integrity/ima/ima_policy.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'security/integrity') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e87bdbfbcc7..d9a24a04cfb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -914,6 +914,12 @@ and is between 256 and 4096 characters. It is defined in the file Formt: { "sha1" | "md5" } default: "sha1" + ima_tcb [IMA] + Load a policy which meets the needs of the Trusted + Computing Base. This means IMA will measure all + programs exec'd, files mmap'd for exec, and all files + opened for read by uid=0. + in2000= [HW,SCSI] See header of drivers/scsi/in2000.c. diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 31d677f7c65..4719bbf1641 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -45,9 +45,17 @@ struct ima_measure_rule_entry { } lsm[MAX_LSM_RULES]; }; -/* Without LSM specific knowledge, the default policy can only be +/* + * Without LSM specific knowledge, the default policy can only be * written in terms of .action, .func, .mask, .fsmagic, and .uid */ + +/* + * The minimum rule set to allow for full TCB coverage. Measures all files + * opened or mmap for exec and everything read by root. Dangerous because + * normal users can easily run the machine out of memory simply building + * and running executables. + */ static struct ima_measure_rule_entry default_rules[] = { {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, @@ -59,6 +67,8 @@ static struct ima_measure_rule_entry default_rules[] = { .flags = IMA_FUNC | IMA_MASK}, {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, .flags = IMA_FUNC | IMA_MASK}, + {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, + .flags = IMA_FUNC | IMA_MASK | IMA_UID}, }; static LIST_HEAD(measure_default_rules); @@ -67,6 +77,14 @@ static struct list_head *ima_measure; static DEFINE_MUTEX(ima_measure_mutex); +static bool ima_use_tcb __initdata; +static int __init default_policy_setup(char *str) +{ + ima_use_tcb = 1; + return 1; +} +__setup("ima_tcb", default_policy_setup); + /** * ima_match_rules - determine whether an inode matches the measure rule. * @rule: a pointer to a rule @@ -162,9 +180,15 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) */ void ima_init_policy(void) { - int i; + int i, entries; + + /* if !ima_use_tcb set entries = 0 so we load NO default rules */ + if (ima_use_tcb) + entries = ARRAY_SIZE(default_rules); + else + entries = 0; - for (i = 0; i < ARRAY_SIZE(default_rules); i++) + for (i = 0; i < entries; i++) list_add_tail(&default_rules[i].list, &measure_default_rules); ima_measure = &measure_default_rules; } -- cgit v1.2.3-70-g09d2 From 932995f0ce52525b32ff5127b522c2c164de3810 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 21 May 2009 15:43:32 -0400 Subject: IMA: Add __init notation to ima functions A number of IMA functions only used during init are not marked with __init. Add those notations so they are freed automatically. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_crypto.c | 4 ++-- security/integrity/ima/ima_fs.c | 2 +- security/integrity/ima/ima_iint.c | 2 +- security/integrity/ima/ima_init.c | 4 ++-- security/integrity/ima/ima_policy.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 50d572b74ca..63003a63aae 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) return rc; } -static void ima_pcrread(int idx, u8 *pcr) +static void __init ima_pcrread(int idx, u8 *pcr) { if (!ima_used_chip) return; @@ -115,7 +115,7 @@ static void ima_pcrread(int idx, u8 *pcr) /* * Calculate the boot aggregate hash */ -int ima_calc_boot_aggregate(char *digest) +int __init ima_calc_boot_aggregate(char *digest) { struct hash_desc desc; struct scatterlist sg; diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 3305a961586..7039b14e1f7 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -319,7 +319,7 @@ static struct file_operations ima_measure_policy_ops = { .release = ima_release_policy }; -int ima_fs_init(void) +int __init ima_fs_init(void) { ima_dir = securityfs_create_dir("ima", NULL); if (IS_ERR(ima_dir)) diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index ec79f1ee992..b8dd693f879 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) kref_set(&iint->refcount, 1); } -void ima_iintcache_init(void) +void __init ima_iintcache_init(void) { iint_cache = 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 0b0bb8c978c..a40da7ae590 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -38,7 +38,7 @@ int ima_used_chip; * a different value.) Violations add a zero entry to the measurement * list and extend the aggregate PCR value with ff...ff's. */ -static void ima_add_boot_aggregate(void) +static void __init ima_add_boot_aggregate(void) { struct ima_template_entry *entry; const char *op = "add_boot_aggregate"; @@ -71,7 +71,7 @@ err_out: audit_cause, result, 0); } -int ima_init(void) +int __init ima_init(void) { u8 pcr_i[IMA_DIGEST_SIZE]; int rc; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4719bbf1641..e1278399b34 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -178,7 +178,7 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) * ima_measure points to either the measure_default_rules or the * the new measure_policy_rules. */ -void ima_init_policy(void) +void __init ima_init_policy(void) { int i, entries; -- cgit v1.2.3-70-g09d2 From b9fc745db833bbf74b4988493b8cd902a84c9415 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 19 May 2009 13:25:57 -0400 Subject: integrity: path_check update - Add support in ima_path_check() for integrity checking without incrementing the counts. (Required for nfsd.) - rename and export opencount_get to ima_counts_get - replace ima_shm_check calls with ima_counts_get - export ima_path_check Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- fs/exec.c | 5 ++-- fs/namei.c | 6 +++-- include/linux/ima.h | 11 +++++---- ipc/shm.c | 4 ++-- mm/shmem.c | 2 +- security/integrity/ima/ima_main.c | 48 +++++++++++++++++++++++---------------- 6 files changed, 46 insertions(+), 30 deletions(-) (limited to 'security/integrity') diff --git a/fs/exec.c b/fs/exec.c index 998e856c307..618d6d1e2c5 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -130,7 +130,8 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) MAY_READ | MAY_EXEC | MAY_OPEN); if (error) goto exit; - error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); + error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN, + IMA_COUNT_UPDATE); if (error) goto exit; @@ -680,7 +681,7 @@ struct file *open_exec(const char *name) err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); if (err) goto out_path_put; - err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); + err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN, IMA_COUNT_UPDATE); if (err) goto out_path_put; diff --git a/fs/namei.c b/fs/namei.c index 78f253cd2d4..b05a2b1dea6 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -853,7 +853,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); if (!err) - err = ima_path_check(&nd->path, MAY_EXEC); + err = ima_path_check(&nd->path, MAY_EXEC, + IMA_COUNT_UPDATE); if (err) break; @@ -1515,7 +1516,8 @@ int may_open(struct path *path, int acc_mode, int flag) return error; error = ima_path_check(path, - acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); + acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC), + IMA_COUNT_UPDATE); if (error) return error; /* diff --git a/include/linux/ima.h b/include/linux/ima.h index 0e2aa45cb0c..b1b827d091a 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -13,14 +13,17 @@ #include struct linux_binprm; +#define IMA_COUNT_UPDATE 1 +#define IMA_COUNT_LEAVE 0 + #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_inode_alloc(struct inode *inode); extern void ima_inode_free(struct inode *inode); -extern int ima_path_check(struct path *path, int mask); +extern int ima_path_check(struct path *path, int mask, int update_counts); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); -extern void ima_shm_check(struct file *file); +extern void ima_counts_get(struct file *file); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -38,7 +41,7 @@ static inline void ima_inode_free(struct inode *inode) return; } -static inline int ima_path_check(struct path *path, int mask) +static inline int ima_path_check(struct path *path, int mask, int update_counts) { return 0; } @@ -53,7 +56,7 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) return 0; } -static inline void ima_shm_check(struct file *file) +static inline void ima_counts_get(struct file *file) { return; } diff --git a/ipc/shm.c b/ipc/shm.c index faa46da99eb..47b464229cd 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -384,7 +384,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) error = PTR_ERR(file); if (IS_ERR(file)) goto no_file; - ima_shm_check(file); + ima_counts_get(file); id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); if (id < 0) { @@ -891,7 +891,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); if (!file) goto out_free; - ima_shm_check(file); + ima_counts_get(file); file->private_data = sfd; file->f_mapping = shp->shm_file->f_mapping; diff --git a/mm/shmem.c b/mm/shmem.c index b25f95ce3db..a817f75f144 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2684,7 +2684,7 @@ int shmem_zero_setup(struct vm_area_struct *vma) if (IS_ERR(file)) return PTR_ERR(file); - ima_shm_check(file); + ima_counts_get(file); if (vma->vm_file) fput(vma->vm_file); vma->vm_file = file; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index c4228c0eb2d..a2eb23310ea 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -125,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, return rc; } +static void ima_update_counts(struct ima_iint_cache *iint, int mask) +{ + iint->opencount++; + if ((mask & MAY_WRITE) || (mask == 0)) + iint->writecount++; + else if (mask & (MAY_READ | MAY_EXEC)) + iint->readcount++; +} + /** * ima_path_check - based on policy, collect/store measurement. * @path: contains a pointer to the path to be measured @@ -143,7 +152,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, * Return 0 on success, an error code on failure. * (Based on the results of appraise_measurement().) */ -int ima_path_check(struct path *path, int mask) +int ima_path_check(struct path *path, int mask, int update_counts) { struct inode *inode = path->dentry->d_inode; struct ima_iint_cache *iint; @@ -157,11 +166,8 @@ int ima_path_check(struct path *path, int mask) return 0; mutex_lock(&iint->mutex); - iint->opencount++; - if ((mask & MAY_WRITE) || (mask == 0)) - iint->writecount++; - else if (mask & (MAY_READ | MAY_EXEC)) - iint->readcount++; + if (update_counts) + ima_update_counts(iint, mask); rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); if (rc < 0) @@ -197,6 +203,7 @@ out: kref_put(&iint->refcount, iint_free); return 0; } +EXPORT_SYMBOL_GPL(ima_path_check); static int process_measurement(struct file *file, const unsigned char *filename, int mask, int function) @@ -225,7 +232,16 @@ out: return rc; } -static void opencount_get(struct file *file) +/* + * ima_opens_get - increment file counts + * + * - for IPC shm and shmat file. + * - for nfsd exported files. + * + * Increment the counts for these files to prevent unnecessary + * imbalance messages. + */ +void ima_counts_get(struct file *file) { struct inode *inode = file->f_dentry->d_inode; struct ima_iint_cache *iint; @@ -237,8 +253,14 @@ static void opencount_get(struct file *file) return; mutex_lock(&iint->mutex); iint->opencount++; + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) + iint->readcount++; + + if (file->f_mode & FMODE_WRITE) + iint->writecount++; mutex_unlock(&iint->mutex); } +EXPORT_SYMBOL_GPL(ima_counts_get); /** * ima_file_mmap - based on policy, collect/store measurement. @@ -263,18 +285,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) return 0; } -/* - * ima_shm_check - IPC shm and shmat create/fput a file - * - * Maintain the opencount for these files to prevent unnecessary - * imbalance messages. - */ -void ima_shm_check(struct file *file) -{ - opencount_get(file); - return; -} - /** * ima_bprm_check - based on policy, collect/store measurement. * @bprm: contains the linux_binprm structure -- cgit v1.2.3-70-g09d2 From 04288f42033607099cebf5ca15ce8dcec3a9688b Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 4 Jun 2009 13:53:10 -0400 Subject: integrity: ima audit dentry_open failure Until we start appraising measurements, the ima_path_check() return code should always be 0. - Update the ima_path_check() return code comment - Instead of the pr_info, audit the dentry_open failure Signed-off-by: Mimi Zohar Acked-by: Eric Paris Signed-off-by: James Morris --- security/integrity/ima/ima_main.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'security/integrity') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index a2eb23310ea..6f611874d10 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -149,8 +149,8 @@ static void ima_update_counts(struct ima_iint_cache *iint, int mask) * - Opening a file for read when already open for write, * could result in a file measurement error. * - * Return 0 on success, an error code on failure. - * (Based on the results of appraise_measurement().) + * Always return 0 and audit dentry_open failures. + * (Return code will be based upon measurement appraisal.) */ int ima_path_check(struct path *path, int mask, int update_counts) { @@ -189,8 +189,13 @@ int ima_path_check(struct path *path, int mask, int update_counts) file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, current_cred()); if (IS_ERR(file)) { - pr_info("%s dentry_open failed\n", dentry->d_name.name); - rc = PTR_ERR(file); + int audit_info = 0; + + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, + dentry->d_name.name, + "add_measurement", + "dentry_open failed", + 1, audit_info); file = NULL; goto out; } -- cgit v1.2.3-70-g09d2