Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull integrity updates from James Morris:
 "From Mimi:

   - add run time support for specifying additional security xattrs
     included in the security.evm HMAC/signature

   - some code clean up and bug fixes"

* 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  EVM: unlock on error path in evm_read_xattrs()
  EVM: prevent array underflow in evm_write_xattrs()
  EVM: Fix null dereference on xattr when xattr fails to allocate
  EVM: fix memory leak of temporary buffer 'temp'
  IMA: use list_splice_tail_init_rcu() instead of its open coded variant
  ima: use match_string() helper
  ima: fix updating the ima_appraise flag
  ima: based on policy verify firmware signatures (pre-allocated buffer)
  ima: define a new policy condition based on the filesystem name
  EVM: Allow runtime modification of the set of verified xattrs
  EVM: turn evm_config_xattrnames into a list
  integrity: Add an integrity directory in securityfs
  ima: Remove unused variable ima_initialized
  ima: Unify logging
  ima: Reflect correct permissions for policy
This commit is contained in:
Linus Torvalds
2018-06-07 15:40:37 -07:00
16 changed files with 378 additions and 85 deletions

View File

@@ -42,6 +42,17 @@ config EVM_EXTRA_SMACK_XATTRS
additional info to the calculation, requires existing EVM
labeled file systems to be relabeled.
config EVM_ADD_XATTRS
bool "Add additional EVM extended attributes at runtime"
depends on EVM
default n
help
Allow userland to provide additional xattrs for HMAC calculation.
When this option is enabled, root can add additional xattrs to the
list used by EVM by writing them into
/sys/kernel/security/integrity/evm/evm_xattrs.
config EVM_LOAD_X509
bool "Load an X509 certificate onto the '.evm' trusted keyring"
depends on EVM && INTEGRITY_TRUSTED_KEYRING

View File

@@ -30,6 +30,11 @@
#define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP_COMPLETE | \
EVM_ALLOW_METADATA_WRITES)
struct xattr_list {
struct list_head list;
char *name;
};
extern int evm_initialized;
#define EVM_ATTR_FSUUID 0x0001
@@ -40,7 +45,7 @@ extern struct crypto_shash *hmac_tfm;
extern struct crypto_shash *hash_tfm;
/* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[];
extern struct list_head evm_config_xattrnames;
int evm_init_key(void);
int evm_update_evmxattr(struct dentry *dentry,

View File

@@ -192,8 +192,8 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
char type, char *digest)
{
struct inode *inode = d_backing_inode(dentry);
struct xattr_list *xattr;
struct shash_desc *desc;
char **xattrname;
size_t xattr_size = 0;
char *xattr_value = NULL;
int error;
@@ -209,14 +209,14 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
return PTR_ERR(desc);
error = -ENODATA;
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
bool is_ima = false;
if (strcmp(*xattrname, XATTR_NAME_IMA) == 0)
if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
is_ima = true;
if ((req_xattr_name && req_xattr_value)
&& !strcmp(*xattrname, req_xattr_name)) {
&& !strcmp(xattr->name, req_xattr_name)) {
error = 0;
crypto_shash_update(desc, (const u8 *)req_xattr_value,
req_xattr_value_len);
@@ -224,7 +224,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
ima_present = true;
continue;
}
size = vfs_getxattr_alloc(dentry, *xattrname,
size = vfs_getxattr_alloc(dentry, xattr->name,
&xattr_value, xattr_size, GFP_NOFS);
if (size == -ENOMEM) {
error = -ENOMEM;

View File

@@ -35,28 +35,29 @@ static const char * const integrity_status_msg[] = {
};
int evm_hmac_attrs;
char *evm_config_xattrnames[] = {
static struct xattr_list evm_config_default_xattrnames[] = {
#ifdef CONFIG_SECURITY_SELINUX
XATTR_NAME_SELINUX,
{.name = XATTR_NAME_SELINUX},
#endif
#ifdef CONFIG_SECURITY_SMACK
XATTR_NAME_SMACK,
{.name = XATTR_NAME_SMACK},
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
XATTR_NAME_SMACKEXEC,
XATTR_NAME_SMACKTRANSMUTE,
XATTR_NAME_SMACKMMAP,
{.name = XATTR_NAME_SMACKEXEC},
{.name = XATTR_NAME_SMACKTRANSMUTE},
{.name = XATTR_NAME_SMACKMMAP},
#endif
#endif
#ifdef CONFIG_SECURITY_APPARMOR
XATTR_NAME_APPARMOR,
{.name = XATTR_NAME_APPARMOR},
#endif
#ifdef CONFIG_IMA_APPRAISE
XATTR_NAME_IMA,
{.name = XATTR_NAME_IMA},
#endif
XATTR_NAME_CAPS,
NULL
{.name = XATTR_NAME_CAPS},
};
LIST_HEAD(evm_config_xattrnames);
static int evm_fixmode;
static int __init evm_set_fixmode(char *str)
{
@@ -68,6 +69,17 @@ __setup("evm=", evm_set_fixmode);
static void __init evm_init_config(void)
{
int i, xattrs;
xattrs = ARRAY_SIZE(evm_config_default_xattrnames);
pr_info("Initialising EVM extended attributes:\n");
for (i = 0; i < xattrs; i++) {
pr_info("%s\n", evm_config_default_xattrnames[i].name);
list_add_tail(&evm_config_default_xattrnames[i].list,
&evm_config_xattrnames);
}
#ifdef CONFIG_EVM_ATTR_FSUUID
evm_hmac_attrs |= EVM_ATTR_FSUUID;
#endif
@@ -82,15 +94,15 @@ static bool evm_key_loaded(void)
static int evm_find_protected_xattrs(struct dentry *dentry)
{
struct inode *inode = d_backing_inode(dentry);
char **xattr;
struct xattr_list *xattr;
int error;
int count = 0;
if (!(inode->i_opflags & IOP_XATTR))
return -EOPNOTSUPP;
for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
if (error < 0) {
if (error == -ENODATA)
continue;
@@ -211,24 +223,25 @@ out:
static int evm_protected_xattr(const char *req_xattr_name)
{
char **xattrname;
int namelen;
int found = 0;
struct xattr_list *xattr;
namelen = strlen(req_xattr_name);
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
if ((strlen(*xattrname) == namelen)
&& (strncmp(req_xattr_name, *xattrname, namelen) == 0)) {
list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
if ((strlen(xattr->name) == namelen)
&& (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
found = 1;
break;
}
if (strncmp(req_xattr_name,
*xattrname + XATTR_SECURITY_PREFIX_LEN,
xattr->name + XATTR_SECURITY_PREFIX_LEN,
strlen(req_xattr_name)) == 0) {
found = 1;
break;
}
}
return found;
}
@@ -544,35 +557,35 @@ void __init evm_load_x509(void)
static int __init init_evm(void)
{
int error;
struct list_head *pos, *q;
struct xattr_list *xattr;
evm_init_config();
error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
if (error)
return error;
goto error;
error = evm_init_secfs();
if (error < 0) {
pr_info("Error registering secfs\n");
return error;
goto error;
}
return 0;
error:
if (error != 0) {
if (!list_empty(&evm_config_xattrnames)) {
list_for_each_safe(pos, q, &evm_config_xattrnames) {
xattr = list_entry(pos, struct xattr_list,
list);
list_del(pos);
}
}
}
return error;
}
/*
* evm_display_config - list the EVM protected security extended attributes
*/
static int __init evm_display_config(void)
{
char **xattrname;
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
pr_info("%s\n", *xattrname);
return 0;
}
pure_initcall(evm_display_config);
late_initcall(init_evm);
MODULE_DESCRIPTION("Extended Verification Module");

View File

@@ -15,11 +15,21 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/audit.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include "evm.h"
static struct dentry *evm_dir;
static struct dentry *evm_init_tpm;
static struct dentry *evm_symlink;
#ifdef CONFIG_EVM_ADD_XATTRS
static struct dentry *evm_xattrs;
static DEFINE_MUTEX(xattr_list_mutex);
static int evm_xattrs_locked;
#endif
/**
* evm_read_key - read() for <securityfs>/evm
@@ -107,13 +117,203 @@ static const struct file_operations evm_key_ops = {
.write = evm_write_key,
};
#ifdef CONFIG_EVM_ADD_XATTRS
/**
* evm_read_xattrs - read() for <securityfs>/evm_xattrs
*
* @filp: file pointer, not actually used
* @buf: where to put the result
* @count: maximum to send along
* @ppos: where to start
*
* Returns number of bytes read or error code, as appropriate
*/
static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
char *temp;
int offset = 0;
ssize_t rc, size = 0;
struct xattr_list *xattr;
if (*ppos != 0)
return 0;
rc = mutex_lock_interruptible(&xattr_list_mutex);
if (rc)
return -ERESTARTSYS;
list_for_each_entry(xattr, &evm_config_xattrnames, list)
size += strlen(xattr->name) + 1;
temp = kmalloc(size + 1, GFP_KERNEL);
if (!temp) {
mutex_unlock(&xattr_list_mutex);
return -ENOMEM;
}
list_for_each_entry(xattr, &evm_config_xattrnames, list) {
sprintf(temp + offset, "%s\n", xattr->name);
offset += strlen(xattr->name) + 1;
}
mutex_unlock(&xattr_list_mutex);
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
kfree(temp);
return rc;
}
/**
* evm_write_xattrs - write() for <securityfs>/evm_xattrs
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Returns number of bytes written or error code, as appropriate
*/
static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
int len, err;
struct xattr_list *xattr, *tmp;
struct audit_buffer *ab;
struct iattr newattrs;
struct inode *inode;
if (!capable(CAP_SYS_ADMIN) || evm_xattrs_locked)
return -EPERM;
if (*ppos != 0)
return -EINVAL;
if (count > XATTR_NAME_MAX)
return -E2BIG;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_EVM_XATTR);
if (IS_ERR(ab))
return PTR_ERR(ab);
xattr = kmalloc(sizeof(struct xattr_list), GFP_KERNEL);
if (!xattr) {
err = -ENOMEM;
goto out;
}
xattr->name = memdup_user_nul(buf, count);
if (IS_ERR(xattr->name)) {
err = PTR_ERR(xattr->name);
xattr->name = NULL;
goto out;
}
/* Remove any trailing newline */
len = strlen(xattr->name);
if (len && xattr->name[len-1] == '\n')
xattr->name[len-1] = '\0';
if (strcmp(xattr->name, ".") == 0) {
evm_xattrs_locked = 1;
newattrs.ia_mode = S_IFREG | 0440;
newattrs.ia_valid = ATTR_MODE;
inode = evm_xattrs->d_inode;
inode_lock(inode);
err = simple_setattr(evm_xattrs, &newattrs);
inode_unlock(inode);
audit_log_format(ab, "locked");
if (!err)
err = count;
goto out;
}
audit_log_format(ab, "xattr=");
audit_log_untrustedstring(ab, xattr->name);
if (strncmp(xattr->name, XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN) != 0) {
err = -EINVAL;
goto out;
}
/* Guard against races in evm_read_xattrs */
mutex_lock(&xattr_list_mutex);
list_for_each_entry(tmp, &evm_config_xattrnames, list) {
if (strcmp(xattr->name, tmp->name) == 0) {
err = -EEXIST;
mutex_unlock(&xattr_list_mutex);
goto out;
}
}
list_add_tail_rcu(&xattr->list, &evm_config_xattrnames);
mutex_unlock(&xattr_list_mutex);
audit_log_format(ab, " res=0");
audit_log_end(ab);
return count;
out:
audit_log_format(ab, " res=%d", err);
audit_log_end(ab);
if (xattr) {
kfree(xattr->name);
kfree(xattr);
}
return err;
}
static const struct file_operations evm_xattr_ops = {
.read = evm_read_xattrs,
.write = evm_write_xattrs,
};
static int evm_init_xattrs(void)
{
evm_xattrs = securityfs_create_file("evm_xattrs", 0660, evm_dir, NULL,
&evm_xattr_ops);
if (!evm_xattrs || IS_ERR(evm_xattrs))
return -EFAULT;
return 0;
}
#else
static int evm_init_xattrs(void)
{
return 0;
}
#endif
int __init evm_init_secfs(void)
{
int error = 0;
evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP,
NULL, NULL, &evm_key_ops);
if (!evm_init_tpm || IS_ERR(evm_init_tpm))
evm_dir = securityfs_create_dir("evm", integrity_dir);
if (!evm_dir || IS_ERR(evm_dir))
return -EFAULT;
evm_init_tpm = securityfs_create_file("evm", 0660,
evm_dir, NULL, &evm_key_ops);
if (!evm_init_tpm || IS_ERR(evm_init_tpm)) {
error = -EFAULT;
goto out;
}
evm_symlink = securityfs_create_symlink("evm", NULL,
"integrity/evm/evm", NULL);
if (!evm_symlink || IS_ERR(evm_symlink)) {
error = -EFAULT;
goto out;
}
if (evm_init_xattrs() != 0) {
error = -EFAULT;
goto out;
}
return 0;
out:
securityfs_remove(evm_symlink);
securityfs_remove(evm_init_tpm);
securityfs_remove(evm_dir);
return error;
}

View File

@@ -21,12 +21,15 @@
#include <linux/rbtree.h>
#include <linux/file.h>
#include <linux/uaccess.h>
#include <linux/security.h>
#include "integrity.h"
static struct rb_root integrity_iint_tree = RB_ROOT;
static DEFINE_RWLOCK(integrity_iint_lock);
static struct kmem_cache *iint_cache __read_mostly;
struct dentry *integrity_dir;
/*
* __integrity_iint_find - return the iint associated with an inode
*/
@@ -211,3 +214,18 @@ void __init integrity_load_keys(void)
ima_load_x509();
evm_load_x509();
}
static int __init integrity_fs_init(void)
{
integrity_dir = securityfs_create_dir("integrity", NULL);
if (IS_ERR(integrity_dir)) {
pr_err("Unable to create integrity sysfs dir: %ld\n",
PTR_ERR(integrity_dir));
integrity_dir = NULL;
return PTR_ERR(integrity_dir);
}
return 0;
}
late_initcall(integrity_fs_init)

View File

@@ -53,7 +53,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
extern int ima_policy_flag;
/* set during initialization */
extern int ima_initialized;
extern int ima_used_chip;
extern int ima_hash_algo;
extern int ima_appraise;

View File

@@ -15,6 +15,9 @@
* implemenents security file system for reporting
* current measurement list and IMA statistics
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -336,7 +339,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
if (data[0] == '/') {
result = ima_read_policy(data);
} else if (ima_appraise & IMA_APPRAISE_POLICY) {
pr_err("IMA: signed policy file (specified as an absolute pathname) required\n");
pr_err("signed policy file (specified as an absolute pathname) required\n");
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
"policy_update", "signed policy required",
1, 0);
@@ -356,6 +359,7 @@ out:
}
static struct dentry *ima_dir;
static struct dentry *ima_symlink;
static struct dentry *binary_runtime_measurements;
static struct dentry *ascii_runtime_measurements;
static struct dentry *runtime_measurements_count;
@@ -417,7 +421,7 @@ static int ima_release_policy(struct inode *inode, struct file *file)
valid_policy = 0;
}
pr_info("IMA: policy update %s\n", cause);
pr_info("policy update %s\n", cause);
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
"policy_update", cause, !valid_policy, 0);
@@ -434,6 +438,8 @@ static int ima_release_policy(struct inode *inode, struct file *file)
ima_policy = NULL;
#elif defined(CONFIG_IMA_WRITE_POLICY)
clear_bit(IMA_FS_BUSY, &ima_fs_flags);
#elif defined(CONFIG_IMA_READ_POLICY)
inode->i_mode &= ~S_IWUSR;
#endif
return 0;
}
@@ -448,10 +454,15 @@ static const struct file_operations ima_measure_policy_ops = {
int __init ima_fs_init(void)
{
ima_dir = securityfs_create_dir("ima", NULL);
ima_dir = securityfs_create_dir("ima", integrity_dir);
if (IS_ERR(ima_dir))
return -1;
ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima",
NULL);
if (IS_ERR(ima_symlink))
goto out;
binary_runtime_measurements =
securityfs_create_file("binary_runtime_measurements",
S_IRUSR | S_IRGRP, ima_dir, NULL,
@@ -491,6 +502,7 @@ out:
securityfs_remove(runtime_measurements_count);
securityfs_remove(ascii_runtime_measurements);
securityfs_remove(binary_runtime_measurements);
securityfs_remove(ima_symlink);
securityfs_remove(ima_dir);
securityfs_remove(ima_policy);
return -1;

View File

@@ -10,6 +10,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
#include <linux/kexec.h>

View File

@@ -32,8 +32,6 @@
#include "ima.h"
int ima_initialized;
#ifdef CONFIG_IMA_APPRAISE
int ima_appraise = IMA_APPRAISE_ENFORCE;
#else
@@ -61,14 +59,11 @@ static int __init hash_setup(char *str)
goto out;
}
for (i = 0; i < HASH_ALGO__LAST; i++) {
if (strcmp(str, hash_algo_name[i]) == 0) {
ima_hash_algo = i;
break;
}
}
if (i == HASH_ALGO__LAST)
i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
if (i < 0)
return 1;
ima_hash_algo = i;
out:
hash_setup_done = 1;
return 1;
@@ -449,6 +444,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
static int read_idmap[READING_MAX_ID] = {
[READING_FIRMWARE] = FIRMWARE_CHECK,
[READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK,
[READING_MODULE] = MODULE_CHECK,
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
@@ -517,10 +513,9 @@ static int __init init_ima(void)
error = ima_init();
}
if (!error) {
ima_initialized = 1;
if (!error)
ima_update_policy_flag();
}
return error;
}

View File

@@ -33,6 +33,7 @@
#define IMA_INMASK 0x0040
#define IMA_EUID 0x0080
#define IMA_PCR 0x0100
#define IMA_FSNAME 0x0200
#define UNKNOWN 0
#define MEASURE 0x0001 /* same as IMA_MEASURE */
@@ -74,6 +75,7 @@ struct ima_rule_entry {
void *args_p; /* audit value */
int type; /* audit type */
} lsm[MAX_LSM_RULES];
char *fsname;
};
/*
@@ -273,6 +275,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
if ((rule->flags & IMA_FSMAGIC)
&& rule->fsmagic != inode->i_sb->s_magic)
return false;
if ((rule->flags & IMA_FSNAME)
&& strcmp(rule->fsname, inode->i_sb->s_type->name))
return false;
if ((rule->flags & IMA_FSUUID) &&
!uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
return false;
@@ -435,6 +440,17 @@ void ima_update_policy_flag(void)
ima_policy_flag &= ~IMA_APPRAISE;
}
static int ima_appraise_flag(enum ima_hooks func)
{
if (func == MODULE_CHECK)
return IMA_APPRAISE_MODULES;
else if (func == FIRMWARE_CHECK)
return IMA_APPRAISE_FIRMWARE;
else if (func == POLICY_CHECK)
return IMA_APPRAISE_POLICY;
return 0;
}
/**
* ima_init_policy - initialize the default measure rules.
*
@@ -473,9 +489,11 @@ void __init ima_init_policy(void)
* Insert the appraise rules requiring file signatures, prior to
* any other appraise rules.
*/
for (i = 0; i < secure_boot_entries; i++)
list_add_tail(&secure_boot_rules[i].list,
&ima_default_rules);
for (i = 0; i < secure_boot_entries; i++) {
list_add_tail(&secure_boot_rules[i].list, &ima_default_rules);
temp_ima_appraise |=
ima_appraise_flag(secure_boot_rules[i].func);
}
for (i = 0; i < appraise_entries; i++) {
list_add_tail(&default_appraise_rules[i].list,
@@ -509,22 +527,9 @@ int ima_check_policy(void)
*/
void ima_update_policy(void)
{
struct list_head *first, *last, *policy;
struct list_head *policy = &ima_policy_rules;
/* append current policy with the new rules */
first = (&ima_temp_rules)->next;
last = (&ima_temp_rules)->prev;
policy = &ima_policy_rules;
synchronize_rcu();
last->next = policy;
rcu_assign_pointer(list_next_rcu(policy->prev), first);
first->prev = policy->prev;
policy->prev = last;
/* prepare for the next policy rules addition */
INIT_LIST_HEAD(&ima_temp_rules);
list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
if (ima_rules != policy) {
ima_policy_flag = 0;
@@ -540,7 +545,7 @@ enum {
Opt_audit, Opt_hash, Opt_dont_hash,
Opt_obj_user, Opt_obj_role, Opt_obj_type,
Opt_subj_user, Opt_subj_role, Opt_subj_type,
Opt_func, Opt_mask, Opt_fsmagic,
Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname,
Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
@@ -565,6 +570,7 @@ static match_table_t policy_tokens = {
{Opt_func, "func=%s"},
{Opt_mask, "mask=%s"},
{Opt_fsmagic, "fsmagic=%s"},
{Opt_fsname, "fsname=%s"},
{Opt_fsuuid, "fsuuid=%s"},
{Opt_uid_eq, "uid=%s"},
{Opt_euid_eq, "euid=%s"},
@@ -776,6 +782,17 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
if (!result)
entry->flags |= IMA_FSMAGIC;
break;
case Opt_fsname:
ima_log_string(ab, "fsname", args[0].from);
entry->fsname = kstrdup(args[0].from, GFP_KERNEL);
if (!entry->fsname) {
result = -ENOMEM;
break;
}
result = 0;
entry->flags |= IMA_FSNAME;
break;
case Opt_fsuuid:
ima_log_string(ab, "fsuuid", args[0].from);
@@ -917,12 +934,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
}
if (!result && (entry->action == UNKNOWN))
result = -EINVAL;
else if (entry->func == MODULE_CHECK)
temp_ima_appraise |= IMA_APPRAISE_MODULES;
else if (entry->func == FIRMWARE_CHECK)
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
else if (entry->func == POLICY_CHECK)
temp_ima_appraise |= IMA_APPRAISE_POLICY;
else if (entry->action == APPRAISE)
temp_ima_appraise |= ima_appraise_flag(entry->func);
audit_log_format(ab, "res=%d", !result);
audit_log_end(ab);
return result;
@@ -1104,6 +1118,12 @@ int ima_policy_show(struct seq_file *m, void *v)
seq_puts(m, " ");
}
if (entry->flags & IMA_FSNAME) {
snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname);
seq_printf(m, pt(Opt_fsname), tbuf);
seq_puts(m, " ");
}
if (entry->flags & IMA_PCR) {
snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr);
seq_printf(m, pt(Opt_pcr), tbuf);

View File

@@ -13,6 +13,8 @@
* Library of supported template fields.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include "ima_template_lib.h"
static bool ima_template_hash_algo_allowed(u8 algo)

View File

@@ -143,6 +143,8 @@ int integrity_kernel_read(struct file *file, loff_t offset,
#define INTEGRITY_KEYRING_MODULE 2
#define INTEGRITY_KEYRING_MAX 3
extern struct dentry *integrity_dir;
#ifdef CONFIG_INTEGRITY_SIGNATURE
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,