ima: support new kernel module syscall
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Tue, 16 Oct 2012 02:10:08 +0000 (12:40 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 14 Dec 2012 02:35:26 +0000 (13:05 +1030)
With the addition of the new kernel module syscall, which defines two
arguments - a file descriptor to the kernel module and a pointer to a NULL
terminated string of module arguments - it is now possible to measure and
appraise kernel modules like any other file on the file system.

This patch adds support to measure and appraise kernel modules in an
extensible and consistent manner.

To support filesystems without extended attribute support, additional
patches could pass the signature as the first parameter.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Documentation/ABI/testing/ima_policy
include/linux/ima.h
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/security.c

index 9869466..ec0a38e 100644 (file)
@@ -23,7 +23,7 @@ Description:
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
 
-               base:   func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK]
+               base:   func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK]
                        mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
                        fsmagic:= hex value
                        uid:= decimal value
@@ -53,6 +53,7 @@ Description:
                        measure func=BPRM_CHECK
                        measure func=FILE_MMAP mask=MAY_EXEC
                        measure func=FILE_CHECK mask=MAY_READ uid=0
+                       measure func=MODULE_CHECK uid=0
                        appraise fowner=0
 
                The default policy measures all executables in bprm_check,
index 2c7223d..86c361e 100644 (file)
@@ -18,6 +18,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern int ima_module_check(struct file *file);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -40,6 +41,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
        return 0;
 }
 
+static inline int ima_module_check(struct file *file)
+{
+       return 0;
+}
+
 #endif /* CONFIG_IMA_H */
 
 #ifdef CONFIG_IMA_APPRAISE
index 6ee8826..3b2adb7 100644 (file)
@@ -127,7 +127,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
 struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR };
+enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, MODULE_CHECK, POST_SETATTR };
 
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
                     int flags);
index b356884..0cea3db 100644 (file)
@@ -100,12 +100,12 @@ err_out:
  * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
- * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
+ * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP, MODULE_CHECK)
  *
  * The policy is defined in terms of keypairs:
  *             subj=, obj=, type=, func=, mask=, fsmagic=
  *     subj,obj, and type: are LSM specific.
- *     func: FILE_CHECK | BPRM_CHECK | FILE_MMAP
+ *     func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | MODULE_CHECK
  *     mask: contains the permission mask
  *     fsmagic: hex value
  *
index 73c9a26..45de18e 100644 (file)
@@ -280,6 +280,27 @@ int ima_file_check(struct file *file, int mask)
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
+/**
+ * ima_module_check - based on policy, collect/store/appraise measurement.
+ * @file: pointer to the file to be measured/appraised
+ *
+ * Measure/appraise kernel modules based on policy.
+ *
+ * Always return 0 and audit dentry_open failures.
+ * Return code is based upon measurement appraisal.
+ */
+int ima_module_check(struct file *file)
+{
+       int rc;
+
+       if (!file)
+               rc = INTEGRITY_UNKNOWN;
+       else
+               rc = process_measurement(file, file->f_dentry->d_name.name,
+                                        MAY_EXEC, MODULE_CHECK);
+       return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
+}
+
 static int __init init_ima(void)
 {
        int error;
index c7dacd2..af7d182 100644 (file)
@@ -80,6 +80,7 @@ static struct ima_rule_entry default_rules[] = {
         .flags = IMA_FUNC | IMA_MASK},
        {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
         .flags = IMA_FUNC | IMA_MASK | IMA_UID},
+       {.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -401,6 +402,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        /* PATH_CHECK is for backwards compat */
                        else if (strcmp(args[0].from, "PATH_CHECK") == 0)
                                entry->func = FILE_CHECK;
+                       else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
+                               entry->func = MODULE_CHECK;
                        else if (strcmp(args[0].from, "FILE_MMAP") == 0)
                                entry->func = FILE_MMAP;
                        else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
index ce88630..daa97f4 100644 (file)
@@ -822,7 +822,12 @@ int security_kernel_module_request(char *kmod_name)
 
 int security_kernel_module_from_file(struct file *file)
 {
-       return security_ops->kernel_module_from_file(file);
+       int ret;
+
+       ret = security_ops->kernel_module_from_file(file);
+       if (ret)
+               return ret;
+       return ima_module_check(file);
 }
 
 int security_task_fix_setuid(struct cred *new, const struct cred *old,