mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-27 00:51:35 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
This commit is contained in:
commit
ac60ab4b49
16 changed files with 107 additions and 124 deletions
|
@ -3058,7 +3058,7 @@ opened:
|
||||||
error = open_check_o_direct(file);
|
error = open_check_o_direct(file);
|
||||||
if (error)
|
if (error)
|
||||||
goto exit_fput;
|
goto exit_fput;
|
||||||
error = ima_file_check(file, op->acc_mode);
|
error = ima_file_check(file, op->acc_mode, *opened);
|
||||||
if (error)
|
if (error)
|
||||||
goto exit_fput;
|
goto exit_fput;
|
||||||
|
|
||||||
|
|
|
@ -709,7 +709,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
|
||||||
host_err = PTR_ERR(*filp);
|
host_err = PTR_ERR(*filp);
|
||||||
*filp = NULL;
|
*filp = NULL;
|
||||||
} else {
|
} else {
|
||||||
host_err = ima_file_check(*filp, may_flags);
|
host_err = ima_file_check(*filp, may_flags, 0);
|
||||||
|
|
||||||
if (may_flags & NFSD_MAY_64BIT_COOKIE)
|
if (may_flags & NFSD_MAY_64BIT_COOKIE)
|
||||||
(*filp)->f_mode |= FMODE_64BITHASH;
|
(*filp)->f_mode |= FMODE_64BITHASH;
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct linux_binprm;
|
||||||
|
|
||||||
#ifdef CONFIG_IMA
|
#ifdef CONFIG_IMA
|
||||||
extern int ima_bprm_check(struct linux_binprm *bprm);
|
extern int ima_bprm_check(struct linux_binprm *bprm);
|
||||||
extern int ima_file_check(struct file *file, int mask);
|
extern int ima_file_check(struct file *file, int mask, int opened);
|
||||||
extern void ima_file_free(struct file *file);
|
extern void ima_file_free(struct file *file);
|
||||||
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
||||||
extern int ima_module_check(struct file *file);
|
extern int ima_module_check(struct file *file);
|
||||||
|
@ -27,7 +27,7 @@ static inline int ima_bprm_check(struct linux_binprm *bprm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ima_file_check(struct file *file, int mask)
|
static inline int ima_file_check(struct file *file, int mask, int opened)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
#
|
#
|
||||||
config INTEGRITY
|
config INTEGRITY
|
||||||
def_bool y
|
bool "Integrity subsystem"
|
||||||
depends on IMA || EVM
|
depends on SECURITY
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This option enables the integrity subsystem, which is comprised
|
||||||
|
of a number of different components including the Integrity
|
||||||
|
Measurement Architecture (IMA), Extended Verification Module
|
||||||
|
(EVM), IMA-appraisal extension, digital signature verification
|
||||||
|
extension and audit measurement log support.
|
||||||
|
|
||||||
|
Each of these components can be enabled/disabled separately.
|
||||||
|
Refer to the individual components for additional details.
|
||||||
|
|
||||||
|
if INTEGRITY
|
||||||
|
|
||||||
config INTEGRITY_SIGNATURE
|
config INTEGRITY_SIGNATURE
|
||||||
boolean "Digital signature verification using multiple keyrings"
|
boolean "Digital signature verification using multiple keyrings"
|
||||||
depends on INTEGRITY && KEYS
|
depends on KEYS
|
||||||
default n
|
default n
|
||||||
select SIGNATURE
|
select SIGNATURE
|
||||||
help
|
help
|
||||||
|
@ -17,21 +29,6 @@ config INTEGRITY_SIGNATURE
|
||||||
This is useful for evm and module keyrings, when keys are
|
This is useful for evm and module keyrings, when keys are
|
||||||
usually only added from initramfs.
|
usually only added from initramfs.
|
||||||
|
|
||||||
config INTEGRITY_AUDIT
|
|
||||||
bool "Enables integrity auditing support "
|
|
||||||
depends on INTEGRITY && AUDIT
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
In addition to enabling integrity auditing support, this
|
|
||||||
option adds a kernel parameter 'integrity_audit', which
|
|
||||||
controls the level of integrity auditing messages.
|
|
||||||
0 - basic integrity auditing messages (default)
|
|
||||||
1 - additional integrity auditing messages
|
|
||||||
|
|
||||||
Additional informational integrity auditing messages would
|
|
||||||
be enabled by specifying 'integrity_audit=1' on the kernel
|
|
||||||
command line.
|
|
||||||
|
|
||||||
config INTEGRITY_ASYMMETRIC_KEYS
|
config INTEGRITY_ASYMMETRIC_KEYS
|
||||||
boolean "Enable asymmetric keys support"
|
boolean "Enable asymmetric keys support"
|
||||||
depends on INTEGRITY_SIGNATURE
|
depends on INTEGRITY_SIGNATURE
|
||||||
|
@ -44,5 +41,22 @@ config INTEGRITY_ASYMMETRIC_KEYS
|
||||||
This option enables digital signature verification using
|
This option enables digital signature verification using
|
||||||
asymmetric keys.
|
asymmetric keys.
|
||||||
|
|
||||||
|
config INTEGRITY_AUDIT
|
||||||
|
bool "Enables integrity auditing support "
|
||||||
|
depends on AUDIT
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
In addition to enabling integrity auditing support, this
|
||||||
|
option adds a kernel parameter 'integrity_audit', which
|
||||||
|
controls the level of integrity auditing messages.
|
||||||
|
0 - basic integrity auditing messages (default)
|
||||||
|
1 - additional integrity auditing messages
|
||||||
|
|
||||||
|
Additional informational integrity auditing messages would
|
||||||
|
be enabled by specifying 'integrity_audit=1' on the kernel
|
||||||
|
command line.
|
||||||
|
|
||||||
source security/integrity/ima/Kconfig
|
source security/integrity/ima/Kconfig
|
||||||
source security/integrity/evm/Kconfig
|
source security/integrity/evm/Kconfig
|
||||||
|
|
||||||
|
endif # if INTEGRITY
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-$(CONFIG_INTEGRITY) += integrity.o
|
obj-$(CONFIG_INTEGRITY) += integrity.o
|
||||||
obj-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
|
|
||||||
obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
|
|
||||||
obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
|
|
||||||
|
|
||||||
integrity-y := iint.o
|
integrity-y := iint.o
|
||||||
|
integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
|
||||||
|
integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
|
||||||
|
integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
|
||||||
|
|
||||||
subdir-$(CONFIG_IMA) += ima
|
subdir-$(CONFIG_IMA) += ima
|
||||||
obj-$(CONFIG_IMA) += ima/
|
obj-$(CONFIG_IMA) += ima/
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/key-type.h>
|
#include <linux/key-type.h>
|
||||||
#include <crypto/public_key.h>
|
#include <crypto/public_key.h>
|
||||||
#include <keys/asymmetric-type.h>
|
#include <keys/asymmetric-type.h>
|
||||||
|
@ -45,8 +46,8 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ERR(key)) {
|
if (IS_ERR(key)) {
|
||||||
pr_warn("Request for unknown key '%s' err %ld\n",
|
pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
|
||||||
name, PTR_ERR(key));
|
name, PTR_ERR(key));
|
||||||
switch (PTR_ERR(key)) {
|
switch (PTR_ERR(key)) {
|
||||||
/* Hide some search errors */
|
/* Hide some search errors */
|
||||||
case -EACCES:
|
case -EACCES:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
config EVM
|
config EVM
|
||||||
boolean "EVM support"
|
boolean "EVM support"
|
||||||
depends on SECURITY
|
|
||||||
select KEYS
|
select KEYS
|
||||||
select ENCRYPTED_KEYS
|
select ENCRYPTED_KEYS
|
||||||
select CRYPTO_HMAC
|
select CRYPTO_HMAC
|
||||||
|
@ -12,10 +11,6 @@ config EVM
|
||||||
|
|
||||||
If you are unsure how to answer this question, answer N.
|
If you are unsure how to answer this question, answer N.
|
||||||
|
|
||||||
if EVM
|
|
||||||
|
|
||||||
menu "EVM options"
|
|
||||||
|
|
||||||
config EVM_ATTR_FSUUID
|
config EVM_ATTR_FSUUID
|
||||||
bool "FSUUID (version 2)"
|
bool "FSUUID (version 2)"
|
||||||
default y
|
default y
|
||||||
|
@ -47,6 +42,3 @@ config EVM_EXTRA_SMACK_XATTRS
|
||||||
additional info to the calculation, requires existing EVM
|
additional info to the calculation, requires existing EVM
|
||||||
labeled file systems to be relabeled.
|
labeled file systems to be relabeled.
|
||||||
|
|
||||||
endmenu
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
|
@ -126,14 +126,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
|
||||||
rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
|
rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
if (rc == 0)
|
evm_status = INTEGRITY_FAIL;
|
||||||
evm_status = INTEGRITY_FAIL; /* empty */
|
if (rc == -ENODATA) {
|
||||||
else if (rc == -ENODATA) {
|
|
||||||
rc = evm_find_protected_xattrs(dentry);
|
rc = evm_find_protected_xattrs(dentry);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
evm_status = INTEGRITY_NOLABEL;
|
evm_status = INTEGRITY_NOLABEL;
|
||||||
else if (rc == 0)
|
else if (rc == 0)
|
||||||
evm_status = INTEGRITY_NOXATTRS; /* new file */
|
evm_status = INTEGRITY_NOXATTRS; /* new file */
|
||||||
|
} else if (rc == -EOPNOTSUPP) {
|
||||||
|
evm_status = INTEGRITY_UNKNOWN;
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +285,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
evm_status = evm_verify_current_integrity(dentry);
|
evm_status = evm_verify_current_integrity(dentry);
|
||||||
|
if (evm_status == INTEGRITY_NOXATTRS) {
|
||||||
|
struct integrity_iint_cache *iint;
|
||||||
|
|
||||||
|
iint = integrity_iint_find(dentry->d_inode);
|
||||||
|
if (iint && (iint->flags & IMA_NEW_FILE))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
if (evm_status != INTEGRITY_PASS)
|
if (evm_status != INTEGRITY_PASS)
|
||||||
integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
|
integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
|
||||||
|
@ -352,7 +360,6 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
|
evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -372,7 +379,6 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
evm_update_evmxattr(dentry, xattr_name, NULL, 0);
|
evm_update_evmxattr(dentry, xattr_name, NULL, 0);
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -414,7 +420,6 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
|
||||||
|
|
||||||
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
|
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
|
||||||
evm_update_evmxattr(dentry, NULL, NULL, 0);
|
evm_update_evmxattr(dentry, NULL, NULL, 0);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
#
|
#
|
||||||
config IMA
|
config IMA
|
||||||
bool "Integrity Measurement Architecture(IMA)"
|
bool "Integrity Measurement Architecture(IMA)"
|
||||||
depends on SECURITY
|
|
||||||
select INTEGRITY
|
|
||||||
select SECURITYFS
|
select SECURITYFS
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_HMAC
|
select CRYPTO_HMAC
|
||||||
|
|
|
@ -90,10 +90,7 @@ extern struct list_head ima_measurements; /* list of all measurements */
|
||||||
|
|
||||||
/* Internal IMA function definitions */
|
/* Internal IMA function definitions */
|
||||||
int ima_init(void);
|
int ima_init(void);
|
||||||
void ima_cleanup(void);
|
|
||||||
int ima_fs_init(void);
|
int ima_fs_init(void);
|
||||||
void ima_fs_cleanup(void);
|
|
||||||
int ima_inode_alloc(struct inode *inode);
|
|
||||||
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
||||||
const char *op, struct inode *inode,
|
const char *op, struct inode *inode,
|
||||||
const unsigned char *filename);
|
const unsigned char *filename);
|
||||||
|
@ -110,8 +107,6 @@ void ima_print_digest(struct seq_file *m, u8 *digest, int size);
|
||||||
struct ima_template_desc *ima_template_desc_current(void);
|
struct ima_template_desc *ima_template_desc_current(void);
|
||||||
int ima_init_template(void);
|
int ima_init_template(void);
|
||||||
|
|
||||||
int ima_init_template(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* used to protect h_table and sha_table
|
* used to protect h_table and sha_table
|
||||||
*/
|
*/
|
||||||
|
@ -151,12 +146,6 @@ int ima_store_template(struct ima_template_entry *entry, int violation,
|
||||||
void ima_free_template_entry(struct ima_template_entry *entry);
|
void ima_free_template_entry(struct ima_template_entry *entry);
|
||||||
const char *ima_d_path(struct path *path, char **pathbuf);
|
const char *ima_d_path(struct path *path, char **pathbuf);
|
||||||
|
|
||||||
/* rbtree tree calls to lookup, insert, delete
|
|
||||||
* integrity data associated with an inode.
|
|
||||||
*/
|
|
||||||
struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
|
|
||||||
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
|
||||||
|
|
||||||
/* IMA policy related functions */
|
/* IMA policy related functions */
|
||||||
enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR };
|
enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR };
|
||||||
|
|
||||||
|
@ -177,7 +166,7 @@ void ima_delete_rules(void);
|
||||||
int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
||||||
struct file *file, const unsigned char *filename,
|
struct file *file, const unsigned char *filename,
|
||||||
struct evm_ima_xattr_data *xattr_value,
|
struct evm_ima_xattr_data *xattr_value,
|
||||||
int xattr_len);
|
int xattr_len, int opened);
|
||||||
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
|
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
|
||||||
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
|
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
|
||||||
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
|
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
|
||||||
|
@ -193,7 +182,7 @@ static inline int ima_appraise_measurement(int func,
|
||||||
struct file *file,
|
struct file *file,
|
||||||
const unsigned char *filename,
|
const unsigned char *filename,
|
||||||
struct evm_ima_xattr_data *xattr_value,
|
struct evm_ima_xattr_data *xattr_value,
|
||||||
int xattr_len)
|
int xattr_len, int opened)
|
||||||
{
|
{
|
||||||
return INTEGRITY_UNKNOWN;
|
return INTEGRITY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,10 +330,9 @@ const char *ima_d_path(struct path *path, char **pathbuf)
|
||||||
{
|
{
|
||||||
char *pathname = NULL;
|
char *pathname = NULL;
|
||||||
|
|
||||||
/* We will allow 11 spaces for ' (deleted)' to be appended */
|
*pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||||
*pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
|
|
||||||
if (*pathbuf) {
|
if (*pathbuf) {
|
||||||
pathname = d_path(path, *pathbuf, PATH_MAX + 11);
|
pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
|
||||||
if (IS_ERR(pathname)) {
|
if (IS_ERR(pathname)) {
|
||||||
kfree(*pathbuf);
|
kfree(*pathbuf);
|
||||||
*pathbuf = NULL;
|
*pathbuf = NULL;
|
||||||
|
|
|
@ -183,7 +183,7 @@ int ima_read_xattr(struct dentry *dentry,
|
||||||
int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
||||||
struct file *file, const unsigned char *filename,
|
struct file *file, const unsigned char *filename,
|
||||||
struct evm_ima_xattr_data *xattr_value,
|
struct evm_ima_xattr_data *xattr_value,
|
||||||
int xattr_len)
|
int xattr_len, int opened)
|
||||||
{
|
{
|
||||||
static const char op[] = "appraise_data";
|
static const char op[] = "appraise_data";
|
||||||
char *cause = "unknown";
|
char *cause = "unknown";
|
||||||
|
@ -192,8 +192,6 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
||||||
enum integrity_status status = INTEGRITY_UNKNOWN;
|
enum integrity_status status = INTEGRITY_UNKNOWN;
|
||||||
int rc = xattr_len, hash_start = 0;
|
int rc = xattr_len, hash_start = 0;
|
||||||
|
|
||||||
if (!ima_appraise)
|
|
||||||
return 0;
|
|
||||||
if (!inode->i_op->getxattr)
|
if (!inode->i_op->getxattr)
|
||||||
return INTEGRITY_UNKNOWN;
|
return INTEGRITY_UNKNOWN;
|
||||||
|
|
||||||
|
@ -202,8 +200,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
cause = "missing-hash";
|
cause = "missing-hash";
|
||||||
status =
|
status = INTEGRITY_NOLABEL;
|
||||||
(inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL;
|
if (opened & FILE_CREATED) {
|
||||||
|
iint->flags |= IMA_NEW_FILE;
|
||||||
|
status = INTEGRITY_PASS;
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,24 +80,24 @@ static int ima_kernel_read(struct file *file, loff_t offset,
|
||||||
{
|
{
|
||||||
mm_segment_t old_fs;
|
mm_segment_t old_fs;
|
||||||
char __user *buf = addr;
|
char __user *buf = addr;
|
||||||
ssize_t ret;
|
ssize_t ret = -EINVAL;
|
||||||
|
|
||||||
if (!(file->f_mode & FMODE_READ))
|
if (!(file->f_mode & FMODE_READ))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
if (!file->f_op->read && !file->f_op->aio_read)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
old_fs = get_fs();
|
old_fs = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
if (file->f_op->read)
|
if (file->f_op->read)
|
||||||
ret = file->f_op->read(file, buf, count, &offset);
|
ret = file->f_op->read(file, buf, count, &offset);
|
||||||
else
|
else if (file->f_op->aio_read)
|
||||||
ret = do_sync_read(file, buf, count, &offset);
|
ret = do_sync_read(file, buf, count, &offset);
|
||||||
|
else if (file->f_op->read_iter)
|
||||||
|
ret = new_sync_read(file, buf, count, &offset);
|
||||||
set_fs(old_fs);
|
set_fs(old_fs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ima_init_crypto(void)
|
int __init ima_init_crypto(void)
|
||||||
{
|
{
|
||||||
long rc;
|
long rc;
|
||||||
|
|
||||||
|
@ -116,7 +116,10 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
|
||||||
struct crypto_shash *tfm = ima_shash_tfm;
|
struct crypto_shash *tfm = ima_shash_tfm;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) {
|
if (algo < 0 || algo >= HASH_ALGO__LAST)
|
||||||
|
algo = ima_hash_algo;
|
||||||
|
|
||||||
|
if (algo != ima_hash_algo) {
|
||||||
tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
|
tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
|
||||||
if (IS_ERR(tfm)) {
|
if (IS_ERR(tfm)) {
|
||||||
rc = PTR_ERR(tfm);
|
rc = PTR_ERR(tfm);
|
||||||
|
@ -200,7 +203,10 @@ static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
|
||||||
struct crypto_ahash *tfm = ima_ahash_tfm;
|
struct crypto_ahash *tfm = ima_ahash_tfm;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((algo != ima_hash_algo && algo < HASH_ALGO__LAST) || !tfm) {
|
if (algo < 0 || algo >= HASH_ALGO__LAST)
|
||||||
|
algo = ima_hash_algo;
|
||||||
|
|
||||||
|
if (algo != ima_hash_algo || !tfm) {
|
||||||
tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
|
tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
|
||||||
if (!IS_ERR(tfm)) {
|
if (!IS_ERR(tfm)) {
|
||||||
if (algo == ima_hash_algo)
|
if (algo == ima_hash_algo)
|
||||||
|
|
|
@ -124,11 +124,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
if (atomic_read(&inode->i_writecount) == 1 &&
|
if (atomic_read(&inode->i_writecount) == 1) {
|
||||||
iint->version != inode->i_version) {
|
if ((iint->version != inode->i_version) ||
|
||||||
iint->flags &= ~IMA_DONE_MASK;
|
(iint->flags & IMA_NEW_FILE)) {
|
||||||
if (iint->flags & IMA_APPRAISE)
|
iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
|
||||||
ima_update_xattr(iint, file);
|
if (iint->flags & IMA_APPRAISE)
|
||||||
|
ima_update_xattr(iint, file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
}
|
}
|
||||||
|
@ -154,15 +156,15 @@ void ima_file_free(struct file *file)
|
||||||
ima_check_last_writer(iint, inode, file);
|
ima_check_last_writer(iint, inode, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_measurement(struct file *file, const char *filename,
|
static int process_measurement(struct file *file, int mask, int function,
|
||||||
int mask, int function)
|
int opened)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
struct integrity_iint_cache *iint;
|
struct integrity_iint_cache *iint;
|
||||||
struct ima_template_desc *template_desc;
|
struct ima_template_desc *template_desc;
|
||||||
char *pathbuf = NULL;
|
char *pathbuf = NULL;
|
||||||
const char *pathname = NULL;
|
const char *pathname = NULL;
|
||||||
int rc = -ENOMEM, action, must_appraise, _func;
|
int rc = -ENOMEM, action, must_appraise;
|
||||||
struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
|
struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
|
||||||
int xattr_len = 0;
|
int xattr_len = 0;
|
||||||
|
|
||||||
|
@ -180,7 +182,8 @@ static int process_measurement(struct file *file, const char *filename,
|
||||||
must_appraise = action & IMA_APPRAISE;
|
must_appraise = action & IMA_APPRAISE;
|
||||||
|
|
||||||
/* Is the appraise rule hook specific? */
|
/* Is the appraise rule hook specific? */
|
||||||
_func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function;
|
if (action & IMA_FILE_APPRAISE)
|
||||||
|
function = FILE_CHECK;
|
||||||
|
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
|
|
||||||
|
@ -199,15 +202,13 @@ static int process_measurement(struct file *file, const char *filename,
|
||||||
/* Nothing to do, just return existing appraised status */
|
/* Nothing to do, just return existing appraised status */
|
||||||
if (!action) {
|
if (!action) {
|
||||||
if (must_appraise)
|
if (must_appraise)
|
||||||
rc = ima_get_cache_status(iint, _func);
|
rc = ima_get_cache_status(iint, function);
|
||||||
goto out_digsig;
|
goto out_digsig;
|
||||||
}
|
}
|
||||||
|
|
||||||
template_desc = ima_template_desc_current();
|
template_desc = ima_template_desc_current();
|
||||||
if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) {
|
if ((action & IMA_APPRAISE_SUBMASK) ||
|
||||||
if (action & IMA_APPRAISE_SUBMASK)
|
strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
|
||||||
xattr_ptr = &xattr_value;
|
|
||||||
} else
|
|
||||||
xattr_ptr = &xattr_value;
|
xattr_ptr = &xattr_value;
|
||||||
|
|
||||||
rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
|
rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
|
||||||
|
@ -217,14 +218,14 @@ static int process_measurement(struct file *file, const char *filename,
|
||||||
goto out_digsig;
|
goto out_digsig;
|
||||||
}
|
}
|
||||||
|
|
||||||
pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
|
pathname = ima_d_path(&file->f_path, &pathbuf);
|
||||||
|
|
||||||
if (action & IMA_MEASURE)
|
if (action & IMA_MEASURE)
|
||||||
ima_store_measurement(iint, file, pathname,
|
ima_store_measurement(iint, file, pathname,
|
||||||
xattr_value, xattr_len);
|
xattr_value, xattr_len);
|
||||||
if (action & IMA_APPRAISE_SUBMASK)
|
if (action & IMA_APPRAISE_SUBMASK)
|
||||||
rc = ima_appraise_measurement(_func, iint, file, pathname,
|
rc = ima_appraise_measurement(function, iint, file, pathname,
|
||||||
xattr_value, xattr_len);
|
xattr_value, xattr_len, opened);
|
||||||
if (action & IMA_AUDIT)
|
if (action & IMA_AUDIT)
|
||||||
ima_audit_measurement(iint, pathname);
|
ima_audit_measurement(iint, pathname);
|
||||||
kfree(pathbuf);
|
kfree(pathbuf);
|
||||||
|
@ -253,7 +254,7 @@ out:
|
||||||
int ima_file_mmap(struct file *file, unsigned long prot)
|
int ima_file_mmap(struct file *file, unsigned long prot)
|
||||||
{
|
{
|
||||||
if (file && (prot & PROT_EXEC))
|
if (file && (prot & PROT_EXEC))
|
||||||
return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK);
|
return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,10 +273,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
|
||||||
*/
|
*/
|
||||||
int ima_bprm_check(struct linux_binprm *bprm)
|
int ima_bprm_check(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
return process_measurement(bprm->file,
|
return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0);
|
||||||
(strcmp(bprm->filename, bprm->interp) == 0) ?
|
|
||||||
bprm->filename : bprm->interp,
|
|
||||||
MAY_EXEC, BPRM_CHECK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -288,12 +286,12 @@ int ima_bprm_check(struct linux_binprm *bprm)
|
||||||
* On success return 0. On integrity appraisal error, assuming the file
|
* On success return 0. On integrity appraisal error, assuming the file
|
||||||
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
||||||
*/
|
*/
|
||||||
int ima_file_check(struct file *file, int mask)
|
int ima_file_check(struct file *file, int mask, int opened)
|
||||||
{
|
{
|
||||||
ima_rdwr_violation_check(file);
|
ima_rdwr_violation_check(file);
|
||||||
return process_measurement(file, NULL,
|
return process_measurement(file,
|
||||||
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
|
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
|
||||||
FILE_CHECK);
|
FILE_CHECK, opened);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ima_file_check);
|
EXPORT_SYMBOL_GPL(ima_file_check);
|
||||||
|
|
||||||
|
@ -316,7 +314,7 @@ int ima_module_check(struct file *file)
|
||||||
#endif
|
#endif
|
||||||
return 0; /* We rely on module signature checking */
|
return 0; /* We rely on module signature checking */
|
||||||
}
|
}
|
||||||
return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK);
|
return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ima_fw_from_file(struct file *file, char *buf, size_t size)
|
int ima_fw_from_file(struct file *file, char *buf, size_t size)
|
||||||
|
@ -327,7 +325,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t size)
|
||||||
return -EACCES; /* INTEGRITY_UNKNOWN */
|
return -EACCES; /* INTEGRITY_UNKNOWN */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return process_measurement(file, NULL, MAY_EXEC, FIRMWARE_CHECK);
|
return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init init_ima(void)
|
static int __init init_ima(void)
|
||||||
|
|
|
@ -152,24 +152,6 @@ out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_defined_templates(void)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
/* Init defined templates. */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
|
|
||||||
struct ima_template_desc *template = &defined_templates[i];
|
|
||||||
|
|
||||||
result = template_desc_init_fields(template->fmt,
|
|
||||||
&(template->fields),
|
|
||||||
&(template->num_fields));
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ima_template_desc *ima_template_desc_current(void)
|
struct ima_template_desc *ima_template_desc_current(void)
|
||||||
{
|
{
|
||||||
if (!ima_template)
|
if (!ima_template)
|
||||||
|
@ -178,13 +160,11 @@ struct ima_template_desc *ima_template_desc_current(void)
|
||||||
return ima_template;
|
return ima_template;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ima_init_template(void)
|
int __init ima_init_template(void)
|
||||||
{
|
{
|
||||||
int result;
|
struct ima_template_desc *template = ima_template_desc_current();
|
||||||
|
|
||||||
result = init_defined_templates();
|
return template_desc_init_fields(template->fmt,
|
||||||
if (result < 0)
|
&(template->fields),
|
||||||
return result;
|
&(template->num_fields));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#define IMA_DIGSIG 0x01000000
|
#define IMA_DIGSIG 0x01000000
|
||||||
#define IMA_DIGSIG_REQUIRED 0x02000000
|
#define IMA_DIGSIG_REQUIRED 0x02000000
|
||||||
#define IMA_PERMIT_DIRECTIO 0x04000000
|
#define IMA_PERMIT_DIRECTIO 0x04000000
|
||||||
|
#define IMA_NEW_FILE 0x08000000
|
||||||
|
|
||||||
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
|
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
|
||||||
IMA_APPRAISE_SUBMASK)
|
IMA_APPRAISE_SUBMASK)
|
||||||
|
@ -116,7 +117,6 @@ struct integrity_iint_cache {
|
||||||
/* rbtree tree calls to lookup, insert, delete
|
/* rbtree tree calls to lookup, insert, delete
|
||||||
* integrity data associated with an inode.
|
* integrity data associated with an inode.
|
||||||
*/
|
*/
|
||||||
struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
|
|
||||||
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
||||||
|
|
||||||
#define INTEGRITY_KEYRING_EVM 0
|
#define INTEGRITY_KEYRING_EVM 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue