Commit ac60ab4b authored by James Morris's avatar James Morris

Merge branch 'next' of...

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
parents a0cfd75f a2d61ed5
...@@ -3058,7 +3058,7 @@ static int do_last(struct nameidata *nd, struct path *path, ...@@ -3058,7 +3058,7 @@ static int do_last(struct nameidata *nd, struct path *path,
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, ...@@ -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; ...@@ -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) ...@@ -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;
} }
......
# #
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,9 +29,21 @@ config INTEGRITY_SIGNATURE ...@@ -17,9 +29,21 @@ 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_ASYMMETRIC_KEYS
boolean "Enable asymmetric keys support"
depends on INTEGRITY_SIGNATURE
default n
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
select X509_CERTIFICATE_PARSER
help
This option enables digital signature verification using
asymmetric keys.
config INTEGRITY_AUDIT config INTEGRITY_AUDIT
bool "Enables integrity auditing support " bool "Enables integrity auditing support "
depends on INTEGRITY && AUDIT depends on AUDIT
default y default y
help help
In addition to enabling integrity auditing support, this In addition to enabling integrity auditing support, this
...@@ -32,17 +56,7 @@ config INTEGRITY_AUDIT ...@@ -32,17 +56,7 @@ config INTEGRITY_AUDIT
be enabled by specifying 'integrity_audit=1' on the kernel be enabled by specifying 'integrity_audit=1' on the kernel
command line. command line.
config INTEGRITY_ASYMMETRIC_KEYS
boolean "Enable asymmetric keys support"
depends on INTEGRITY_SIGNATURE
default n
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
select X509_CERTIFICATE_PARSER
help
This option enables digital signature verification using
asymmetric keys.
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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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:
......
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 ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 */ ...@@ -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); ...@@ -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, ...@@ -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); ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ static int process_measurement(struct file *file, const char *filename, ...@@ -253,7 +254,7 @@ static int process_measurement(struct file *file, const char *filename,
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int template_desc_init_fields(const char *template_fmt, ...@@ -152,24 +152,6 @@ static int template_desc_init_fields(const char *template_fmt,
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) ...@@ -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();
if (result < 0)
return result;
return 0; return template_desc_init_fields(template->fmt,
&(template->fields),
&(template->num_fields));
} }
...@@ -31,6 +31,7 @@ ...@@ -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 { ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment