Merge branch 'next-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
This commit is contained in:
commit
33b2533518
20 changed files with 169 additions and 145 deletions
17
MAINTAINERS
17
MAINTAINERS
|
@ -3325,7 +3325,9 @@ F: Documentation/filesystems/ext4.txt
|
|||
F: fs/ext4/
|
||||
|
||||
Extended Verification Module (EVM)
|
||||
M: Mimi Zohar <zohar@us.ibm.com>
|
||||
M: Mimi Zohar <zohar@linux.vnet.ibm.com>
|
||||
L: linux-ima-devel@lists.sourceforge.net
|
||||
L: linux-security-module@vger.kernel.org
|
||||
S: Supported
|
||||
F: security/integrity/evm/
|
||||
|
||||
|
@ -4339,8 +4341,11 @@ S: Maintained
|
|||
F: drivers/ipack/
|
||||
|
||||
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
|
||||
M: Mimi Zohar <zohar@us.ibm.com>
|
||||
M: Mimi Zohar <zohar@linux.vnet.ibm.com>
|
||||
M: Dmitry Kasatkin <d.kasatkin@samsung.com>
|
||||
L: linux-ima-devel@lists.sourceforge.net
|
||||
L: linux-ima-user@lists.sourceforge.net
|
||||
L: linux-security-module@vger.kernel.org
|
||||
S: Supported
|
||||
F: security/integrity/ima/
|
||||
|
||||
|
@ -5003,8 +5008,8 @@ F: include/keys/
|
|||
F: security/keys/
|
||||
|
||||
KEYS-TRUSTED
|
||||
M: David Safford <safford@watson.ibm.com>
|
||||
M: Mimi Zohar <zohar@us.ibm.com>
|
||||
M: David Safford <safford@us.ibm.com>
|
||||
M: Mimi Zohar <zohar@linux.vnet.ibm.com>
|
||||
L: linux-security-module@vger.kernel.org
|
||||
L: keyrings@linux-nfs.org
|
||||
S: Supported
|
||||
|
@ -5014,8 +5019,8 @@ F: security/keys/trusted.c
|
|||
F: security/keys/trusted.h
|
||||
|
||||
KEYS-ENCRYPTED
|
||||
M: Mimi Zohar <zohar@us.ibm.com>
|
||||
M: David Safford <safford@watson.ibm.com>
|
||||
M: Mimi Zohar <zohar@linux.vnet.ibm.com>
|
||||
M: David Safford <safford@us.ibm.com>
|
||||
L: linux-security-module@vger.kernel.org
|
||||
L: keyrings@linux-nfs.org
|
||||
S: Supported
|
||||
|
|
|
@ -586,6 +586,9 @@ struct inode {
|
|||
atomic_t i_count;
|
||||
atomic_t i_dio_count;
|
||||
atomic_t i_writecount;
|
||||
#ifdef CONFIG_IMA
|
||||
atomic_t i_readcount; /* struct files open RO */
|
||||
#endif
|
||||
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
|
||||
struct file_lock *i_flock;
|
||||
struct address_space i_data;
|
||||
|
@ -606,9 +609,6 @@ struct inode {
|
|||
struct hlist_head i_fsnotify_marks;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IMA
|
||||
atomic_t i_readcount; /* struct files open RO */
|
||||
#endif
|
||||
void *i_private; /* fs or device private pointer */
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
config EVM
|
||||
boolean "EVM support"
|
||||
depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n)
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_MD5
|
||||
select CRYPTO_SHA1
|
||||
depends on SECURITY
|
||||
select KEYS
|
||||
select ENCRYPTED_KEYS
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_SHA1
|
||||
default n
|
||||
help
|
||||
EVM protects a file's security extended attributes against
|
||||
|
|
|
@ -32,19 +32,19 @@ extern struct crypto_shash *hash_tfm;
|
|||
/* List of EVM protected security xattrs */
|
||||
extern char *evm_config_xattrnames[];
|
||||
|
||||
extern int evm_init_key(void);
|
||||
extern int evm_update_evmxattr(struct dentry *dentry,
|
||||
const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len);
|
||||
extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len, char *digest);
|
||||
extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len, char *digest);
|
||||
extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
|
||||
char *hmac_val);
|
||||
extern int evm_init_secfs(void);
|
||||
int evm_init_key(void);
|
||||
int evm_update_evmxattr(struct dentry *dentry,
|
||||
const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len);
|
||||
int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len, char *digest);
|
||||
int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
|
||||
const char *req_xattr_value,
|
||||
size_t req_xattr_value_len, char *digest);
|
||||
int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
|
||||
char *hmac_val);
|
||||
int evm_init_secfs(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
* Using root's kernel master key (kmk), calculate the HMAC
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/xattr.h>
|
||||
|
@ -103,13 +105,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
|
|||
umode_t mode;
|
||||
} hmac_misc;
|
||||
|
||||
memset(&hmac_misc, 0, sizeof hmac_misc);
|
||||
memset(&hmac_misc, 0, sizeof(hmac_misc));
|
||||
hmac_misc.ino = inode->i_ino;
|
||||
hmac_misc.generation = inode->i_generation;
|
||||
hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid);
|
||||
hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
|
||||
hmac_misc.mode = inode->i_mode;
|
||||
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
|
||||
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
|
||||
if (evm_hmac_version > 1)
|
||||
crypto_shash_update(desc, inode->i_sb->s_uuid,
|
||||
sizeof(inode->i_sb->s_uuid));
|
||||
|
@ -221,7 +223,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
|
|||
|
||||
desc = init_desc(EVM_XATTR_HMAC);
|
||||
if (IS_ERR(desc)) {
|
||||
printk(KERN_INFO "init_desc failed\n");
|
||||
pr_info("init_desc failed\n");
|
||||
return PTR_ERR(desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* evm_inode_removexattr, and evm_verifyxattr
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/audit.h>
|
||||
|
@ -432,7 +434,7 @@ static int __init init_evm(void)
|
|||
|
||||
error = evm_init_secfs();
|
||||
if (error < 0) {
|
||||
printk(KERN_INFO "EVM: Error registering secfs\n");
|
||||
pr_info("Error registering secfs\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -449,7 +451,7 @@ static int __init evm_display_config(void)
|
|||
char **xattrname;
|
||||
|
||||
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
|
||||
printk(KERN_INFO "EVM: %s\n", *xattrname);
|
||||
pr_info("%s\n", *xattrname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
* - Get the key and enable EVM
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include "evm.h"
|
||||
|
@ -79,9 +81,9 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf,
|
|||
error = evm_init_key();
|
||||
if (!error) {
|
||||
evm_initialized = 1;
|
||||
pr_info("EVM: initialized\n");
|
||||
pr_info("initialized\n");
|
||||
} else
|
||||
pr_err("EVM: initialization failed\n");
|
||||
pr_err("initialization failed\n");
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ static void init_once(void *foo)
|
|||
{
|
||||
struct integrity_iint_cache *iint = foo;
|
||||
|
||||
memset(iint, 0, sizeof *iint);
|
||||
memset(iint, 0, sizeof(*iint));
|
||||
iint->version = 0;
|
||||
iint->flags = 0UL;
|
||||
iint->ima_file_status = INTEGRITY_UNKNOWN;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "../integrity.h"
|
||||
|
||||
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
|
||||
IMA_SHOW_ASCII };
|
||||
IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
|
||||
enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
|
||||
|
||||
/* digest size for IMA, fits SHA1 or MD5 */
|
||||
|
|
|
@ -92,8 +92,8 @@ int ima_store_template(struct ima_template_entry *entry,
|
|||
int violation, struct inode *inode,
|
||||
const unsigned char *filename)
|
||||
{
|
||||
const char *op = "add_template_measure";
|
||||
const char *audit_cause = "hashing_error";
|
||||
static const char op[] = "add_template_measure";
|
||||
static const char audit_cause[] = "hashing_error";
|
||||
char *template_name = entry->template_desc->name;
|
||||
int result;
|
||||
struct {
|
||||
|
@ -132,7 +132,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
|
|||
const char *op, const char *cause)
|
||||
{
|
||||
struct ima_template_entry *entry;
|
||||
struct inode *inode = file->f_dentry->d_inode;
|
||||
struct inode *inode = file_inode(file);
|
||||
int violation = 1;
|
||||
int result;
|
||||
|
||||
|
@ -160,10 +160,10 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
|
|||
* @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK)
|
||||
*
|
||||
* The policy is defined in terms of keypairs:
|
||||
* subj=, obj=, type=, func=, mask=, fsmagic=
|
||||
* subj=, obj=, type=, func=, mask=, fsmagic=
|
||||
* subj,obj, and type: are LSM specific.
|
||||
* func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
|
||||
* mask: contains the permission mask
|
||||
* func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
|
||||
* mask: contains the permission mask
|
||||
* fsmagic: hex value
|
||||
*
|
||||
* Returns IMA_MEASURE, IMA_APPRAISE mask.
|
||||
|
@ -248,7 +248,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|||
*
|
||||
* We only get here if the inode has not already been measured,
|
||||
* but the measurement could already exist:
|
||||
* - multiple copies of the same file on either the same or
|
||||
* - multiple copies of the same file on either the same or
|
||||
* different filesystems.
|
||||
* - the inode was previously flushed as well as the iint info,
|
||||
* containing the hashing info.
|
||||
|
@ -260,8 +260,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
|
|||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len)
|
||||
{
|
||||
const char *op = "add_template_measure";
|
||||
const char *audit_cause = "ENOMEM";
|
||||
static const char op[] = "add_template_measure";
|
||||
static const char audit_cause[] = "ENOMEM";
|
||||
int result = -ENOMEM;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct ima_template_entry *entry;
|
||||
|
@ -332,5 +332,5 @@ const char *ima_d_path(struct path *path, char **pathbuf)
|
|||
pathname = NULL;
|
||||
}
|
||||
}
|
||||
return pathname;
|
||||
return pathname ?: (const char *)path->dentry->d_name.name;
|
||||
}
|
||||
|
|
|
@ -177,11 +177,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
|
|||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len)
|
||||
{
|
||||
static const char op[] = "appraise_data";
|
||||
char *cause = "unknown";
|
||||
struct dentry *dentry = file->f_dentry;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
enum integrity_status status = INTEGRITY_UNKNOWN;
|
||||
const char *op = "appraise_data";
|
||||
char *cause = "unknown";
|
||||
int rc = xattr_len, hash_start = 0;
|
||||
|
||||
if (!ima_appraise)
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
* the Free Software Foundation, version 2 of the License.
|
||||
*
|
||||
* File: ima_crypto.c
|
||||
* Calculates md5/sha1 file hash, template hash, boot-aggreate hash
|
||||
* Calculates md5/sha1 file hash, template hash, boot-aggreate hash
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/crypto.h>
|
||||
|
@ -85,16 +87,20 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
|||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!rbuf) {
|
||||
rc = -ENOMEM;
|
||||
i_size = i_size_read(file_inode(file));
|
||||
|
||||
if (i_size == 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!rbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(file->f_mode & FMODE_READ)) {
|
||||
file->f_mode |= FMODE_READ;
|
||||
read = 1;
|
||||
}
|
||||
i_size = i_size_read(file_inode(file));
|
||||
|
||||
while (offset < i_size) {
|
||||
int rbuf_len;
|
||||
|
||||
|
@ -111,12 +117,12 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
|||
if (rc)
|
||||
break;
|
||||
}
|
||||
kfree(rbuf);
|
||||
if (!rc)
|
||||
rc = crypto_shash_final(&desc.shash, hash->digest);
|
||||
if (read)
|
||||
file->f_mode &= ~FMODE_READ;
|
||||
kfree(rbuf);
|
||||
out:
|
||||
if (!rc)
|
||||
rc = crypto_shash_final(&desc.shash, hash->digest);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -161,15 +167,22 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
|
|||
return rc;
|
||||
|
||||
for (i = 0; i < num_fields; i++) {
|
||||
u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
|
||||
u8 *data_to_hash = field_data[i].data;
|
||||
u32 datalen = field_data[i].len;
|
||||
|
||||
if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
|
||||
rc = crypto_shash_update(&desc.shash,
|
||||
(const u8 *) &field_data[i].len,
|
||||
sizeof(field_data[i].len));
|
||||
if (rc)
|
||||
break;
|
||||
} else if (strcmp(td->fields[i]->field_id, "n") == 0) {
|
||||
memcpy(buffer, data_to_hash, datalen);
|
||||
data_to_hash = buffer;
|
||||
datalen = IMA_EVENT_NAME_LEN_MAX + 1;
|
||||
}
|
||||
rc = crypto_shash_update(&desc.shash, field_data[i].data,
|
||||
field_data[i].len);
|
||||
rc = crypto_shash_update(&desc.shash, data_to_hash, datalen);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
@ -205,7 +218,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
|
|||
return;
|
||||
|
||||
if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
|
||||
pr_err("IMA: Error Communicating to TPM chip\n");
|
||||
pr_err("Error Communicating to TPM chip\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -133,14 +133,14 @@ static int ima_measurements_show(struct seq_file *m, void *v)
|
|||
* PCR used is always the same (config option) in
|
||||
* little-endian format
|
||||
*/
|
||||
ima_putc(m, &pcr, sizeof pcr);
|
||||
ima_putc(m, &pcr, sizeof(pcr));
|
||||
|
||||
/* 2nd: template digest */
|
||||
ima_putc(m, e->digest, TPM_DIGEST_SIZE);
|
||||
|
||||
/* 3rd: template name size */
|
||||
namelen = strlen(e->template_desc->name);
|
||||
ima_putc(m, &namelen, sizeof namelen);
|
||||
ima_putc(m, &namelen, sizeof(namelen));
|
||||
|
||||
/* 4th: template name */
|
||||
ima_putc(m, e->template_desc->name, namelen);
|
||||
|
@ -160,6 +160,8 @@ static int ima_measurements_show(struct seq_file *m, void *v)
|
|||
|
||||
if (is_ima_template && strcmp(field->field_id, "d") == 0)
|
||||
show = IMA_SHOW_BINARY_NO_FIELD_LEN;
|
||||
if (is_ima_template && strcmp(field->field_id, "n") == 0)
|
||||
show = IMA_SHOW_BINARY_OLD_STRING_FMT;
|
||||
field->field_show(m, show, &e->template_data[i]);
|
||||
}
|
||||
return 0;
|
||||
|
@ -290,7 +292,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
|
|||
/*
|
||||
* ima_open_policy: sequentialize access to the policy file
|
||||
*/
|
||||
static int ima_open_policy(struct inode * inode, struct file * filp)
|
||||
static 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))
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
* File: ima_init.c
|
||||
* initialization and cleanup functions
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -42,10 +45,10 @@ int ima_used_chip;
|
|||
*/
|
||||
static void __init ima_add_boot_aggregate(void)
|
||||
{
|
||||
static const char op[] = "add_boot_aggregate";
|
||||
const char *audit_cause = "ENOMEM";
|
||||
struct ima_template_entry *entry;
|
||||
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
|
||||
const char *op = "add_boot_aggregate";
|
||||
const char *audit_cause = "ENOMEM";
|
||||
int result = -ENOMEM;
|
||||
int violation = 0;
|
||||
struct {
|
||||
|
@ -93,7 +96,7 @@ int __init ima_init(void)
|
|||
ima_used_chip = 1;
|
||||
|
||||
if (!ima_used_chip)
|
||||
pr_info("IMA: No TPM chip found, activating TPM-bypass!\n");
|
||||
pr_info("No TPM chip found, activating TPM-bypass!\n");
|
||||
|
||||
rc = ima_init_crypto();
|
||||
if (rc)
|
||||
|
|
|
@ -71,15 +71,14 @@ __setup("ima_hash=", hash_setup);
|
|||
* ima_rdwr_violation_check
|
||||
*
|
||||
* Only invalidate the PCR for measured files:
|
||||
* - Opening a file for write when already open for read,
|
||||
* - Opening a file for write when already open for read,
|
||||
* results in a time of measure, time of use (ToMToU) error.
|
||||
* - Opening a file for read when already open for write,
|
||||
* could result in a file measurement error.
|
||||
* could result in a file measurement error.
|
||||
*
|
||||
*/
|
||||
static void ima_rdwr_violation_check(struct file *file)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct inode *inode = file_inode(file);
|
||||
fmode_t mode = file->f_mode;
|
||||
int must_measure;
|
||||
|
@ -111,8 +110,6 @@ static void ima_rdwr_violation_check(struct file *file)
|
|||
return;
|
||||
|
||||
pathname = ima_d_path(&file->f_path, &pathbuf);
|
||||
if (!pathname || strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
|
||||
pathname = dentry->d_name.name;
|
||||
|
||||
if (send_tomtou)
|
||||
ima_add_violation(file, pathname, "invalid_pcr", "ToMToU");
|
||||
|
@ -220,9 +217,7 @@ static int process_measurement(struct file *file, const char *filename,
|
|||
if (rc != 0)
|
||||
goto out_digsig;
|
||||
|
||||
pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename;
|
||||
if (!pathname)
|
||||
pathname = (const char *)file->f_dentry->d_name.name;
|
||||
pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
|
||||
|
||||
if (action & IMA_MEASURE)
|
||||
ima_store_measurement(iint, file, pathname,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* the Free Software Foundation, version 2 of the License.
|
||||
*
|
||||
* ima_policy.c
|
||||
* - initialize default measure policy rules
|
||||
* - initialize default measure policy rules
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
|
@ -21,8 +21,8 @@
|
|||
#include "ima.h"
|
||||
|
||||
/* flags definitions */
|
||||
#define IMA_FUNC 0x0001
|
||||
#define IMA_MASK 0x0002
|
||||
#define IMA_FUNC 0x0001
|
||||
#define IMA_MASK 0x0002
|
||||
#define IMA_FSMAGIC 0x0004
|
||||
#define IMA_UID 0x0008
|
||||
#define IMA_FOWNER 0x0010
|
||||
|
@ -69,35 +69,35 @@ struct ima_rule_entry {
|
|||
* and running executables.
|
||||
*/
|
||||
static struct ima_rule_entry default_rules[] = {
|
||||
{.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 = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = MEASURE,.func = MMAP_CHECK,.mask = MAY_EXEC,
|
||||
{.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 = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
|
||||
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
|
||||
{.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},
|
||||
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
||||
};
|
||||
|
||||
static struct ima_rule_entry default_appraise_rules[] = {
|
||||
{.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = APPRAISE,.fowner = GLOBAL_ROOT_UID,.flags = IMA_FOWNER},
|
||||
{.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
|
||||
};
|
||||
|
||||
static LIST_HEAD(ima_default_rules);
|
||||
|
@ -122,12 +122,12 @@ static int __init default_appraise_policy_setup(char *str)
|
|||
}
|
||||
__setup("ima_appraise_tcb", default_appraise_policy_setup);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Although the IMA policy does not change, the LSM policy can be
|
||||
* reloaded, leaving the IMA LSM based rules referring to the old,
|
||||
* stale LSM policy.
|
||||
*
|
||||
* Update the IMA LSM based rules to reflect the reloaded LSM policy.
|
||||
* Update the IMA LSM based rules to reflect the reloaded LSM policy.
|
||||
* We assume the rules still exist; and BUG_ON() if they don't.
|
||||
*/
|
||||
static void ima_lsm_update_rules(void)
|
||||
|
@ -167,9 +167,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
|||
const struct cred *cred = current_cred();
|
||||
int i;
|
||||
|
||||
if ((rule->flags & IMA_FUNC) && rule->func != func)
|
||||
if ((rule->flags & IMA_FUNC) &&
|
||||
(rule->func != func && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_MASK) && rule->mask != mask)
|
||||
if ((rule->flags & IMA_MASK) &&
|
||||
(rule->mask != mask && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_FSMAGIC)
|
||||
&& rule->fsmagic != inode->i_sb->s_magic)
|
||||
|
@ -216,7 +218,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
|||
retried = 1;
|
||||
ima_lsm_update_rules();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
if (!rc)
|
||||
return false;
|
||||
}
|
||||
|
@ -232,7 +234,7 @@ static int get_subaction(struct ima_rule_entry *rule, int func)
|
|||
if (!(rule->flags & IMA_FUNC))
|
||||
return IMA_FILE_APPRAISE;
|
||||
|
||||
switch(func) {
|
||||
switch (func) {
|
||||
case MMAP_CHECK:
|
||||
return IMA_MMAP_APPRAISE;
|
||||
case BPRM_CHECK:
|
||||
|
@ -304,7 +306,7 @@ void __init ima_init_policy(void)
|
|||
measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
|
||||
appraise_entries = ima_use_appraise_tcb ?
|
||||
ARRAY_SIZE(default_appraise_rules) : 0;
|
||||
|
||||
|
||||
for (i = 0; i < measure_entries + appraise_entries; i++) {
|
||||
if (i < measure_entries)
|
||||
list_add_tail(&default_rules[i].list,
|
||||
|
@ -329,7 +331,7 @@ void __init ima_init_policy(void)
|
|||
*/
|
||||
void ima_update_policy(void)
|
||||
{
|
||||
const char *op = "policy_update";
|
||||
static const char op[] = "policy_update";
|
||||
const char *cause = "already exists";
|
||||
int result = 1;
|
||||
int audit_info = 0;
|
||||
|
@ -520,8 +522,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
|||
break;
|
||||
}
|
||||
|
||||
result = kstrtoul(args[0].from, 16,
|
||||
&entry->fsmagic);
|
||||
result = kstrtoul(args[0].from, 16, &entry->fsmagic);
|
||||
if (!result)
|
||||
entry->flags |= IMA_FSMAGIC;
|
||||
break;
|
||||
|
@ -645,7 +646,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
|||
*/
|
||||
ssize_t ima_parse_add_rule(char *rule)
|
||||
{
|
||||
const char *op = "update_policy";
|
||||
static const char op[] = "update_policy";
|
||||
char *p;
|
||||
struct ima_rule_entry *entry;
|
||||
ssize_t result, len;
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
* The measurement list is append-only. No entry is
|
||||
* ever removed or changed during the boot-cycle.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -72,7 +75,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
|
|||
|
||||
qe = kmalloc(sizeof(*qe), GFP_KERNEL);
|
||||
if (qe == NULL) {
|
||||
pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n");
|
||||
pr_err("OUT OF MEMORY ERROR creating queue entry\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
qe->entry = entry;
|
||||
|
@ -95,8 +98,7 @@ static int ima_pcr_extend(const u8 *hash)
|
|||
|
||||
result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
|
||||
if (result != 0)
|
||||
pr_err("IMA: Error Communicating to TPM chip, result: %d\n",
|
||||
result);
|
||||
pr_err("Error Communicating to TPM chip, result: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -115,7 +117,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
|||
|
||||
mutex_lock(&ima_extend_list_mutex);
|
||||
if (!violation) {
|
||||
memcpy(digest, entry->digest, sizeof digest);
|
||||
memcpy(digest, entry->digest, sizeof(digest));
|
||||
if (ima_lookup_digest_entry(digest)) {
|
||||
audit_cause = "hash_exists";
|
||||
result = -EEXIST;
|
||||
|
@ -131,7 +133,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
|||
}
|
||||
|
||||
if (violation) /* invalidate pcr */
|
||||
memset(digest, 0xff, sizeof digest);
|
||||
memset(digest, 0xff, sizeof(digest));
|
||||
|
||||
tpmresult = ima_pcr_extend(digest);
|
||||
if (tpmresult != 0) {
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
* File: ima_template.c
|
||||
* Helpers to manage template descriptors.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
#include "ima.h"
|
||||
|
@ -19,20 +22,20 @@
|
|||
|
||||
static struct ima_template_desc defined_templates[] = {
|
||||
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
|
||||
{.name = "ima-ng",.fmt = "d-ng|n-ng"},
|
||||
{.name = "ima-sig",.fmt = "d-ng|n-ng|sig"},
|
||||
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
|
||||
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
|
||||
};
|
||||
|
||||
static struct ima_template_field supported_fields[] = {
|
||||
{.field_id = "d",.field_init = ima_eventdigest_init,
|
||||
{.field_id = "d", .field_init = ima_eventdigest_init,
|
||||
.field_show = ima_show_template_digest},
|
||||
{.field_id = "n",.field_init = ima_eventname_init,
|
||||
{.field_id = "n", .field_init = ima_eventname_init,
|
||||
.field_show = ima_show_template_string},
|
||||
{.field_id = "d-ng",.field_init = ima_eventdigest_ng_init,
|
||||
{.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
|
||||
.field_show = ima_show_template_digest_ng},
|
||||
{.field_id = "n-ng",.field_init = ima_eventname_ng_init,
|
||||
{.field_id = "n-ng", .field_init = ima_eventname_ng_init,
|
||||
.field_show = ima_show_template_string},
|
||||
{.field_id = "sig",.field_init = ima_eventsig_init,
|
||||
{.field_id = "sig", .field_init = ima_eventsig_init,
|
||||
.field_show = ima_show_template_sig},
|
||||
};
|
||||
|
||||
|
@ -58,7 +61,7 @@ static int __init ima_template_setup(char *str)
|
|||
*/
|
||||
if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
|
||||
ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
|
||||
pr_err("IMA: template does not support hash alg\n");
|
||||
pr_err("template does not support hash alg\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ static bool ima_template_hash_algo_allowed(u8 algo)
|
|||
enum data_formats {
|
||||
DATA_FMT_DIGEST = 0,
|
||||
DATA_FMT_DIGEST_WITH_ALGO,
|
||||
DATA_FMT_EVENT_NAME,
|
||||
DATA_FMT_STRING,
|
||||
DATA_FMT_HEX
|
||||
};
|
||||
|
@ -37,18 +36,10 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
|
|||
struct ima_field_data *field_data)
|
||||
{
|
||||
u8 *buf, *buf_ptr;
|
||||
u32 buflen;
|
||||
u32 buflen = datalen;
|
||||
|
||||
switch (datafmt) {
|
||||
case DATA_FMT_EVENT_NAME:
|
||||
buflen = IMA_EVENT_NAME_LEN_MAX + 1;
|
||||
break;
|
||||
case DATA_FMT_STRING:
|
||||
if (datafmt == DATA_FMT_STRING)
|
||||
buflen = datalen + 1;
|
||||
break;
|
||||
default:
|
||||
buflen = datalen;
|
||||
}
|
||||
|
||||
buf = kzalloc(buflen, GFP_KERNEL);
|
||||
if (!buf)
|
||||
|
@ -63,7 +54,7 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
|
|||
* split into multiple template fields (the space is the delimitator
|
||||
* character for measurements lists in ASCII format).
|
||||
*/
|
||||
if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) {
|
||||
if (datafmt == DATA_FMT_STRING) {
|
||||
for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
|
||||
if (*buf_ptr == ' ')
|
||||
*buf_ptr = '_';
|
||||
|
@ -109,13 +100,16 @@ static void ima_show_template_data_binary(struct seq_file *m,
|
|||
enum data_formats datafmt,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
|
||||
ima_putc(m, &field_data->len, sizeof(u32));
|
||||
u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
|
||||
strlen(field_data->data) : field_data->len;
|
||||
|
||||
if (!field_data->len)
|
||||
if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
|
||||
ima_putc(m, &len, sizeof(len));
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
ima_putc(m, field_data->data, field_data->len);
|
||||
ima_putc(m, field_data->data, len);
|
||||
}
|
||||
|
||||
static void ima_show_template_field_data(struct seq_file *m,
|
||||
|
@ -129,6 +123,7 @@ static void ima_show_template_field_data(struct seq_file *m,
|
|||
break;
|
||||
case IMA_SHOW_BINARY:
|
||||
case IMA_SHOW_BINARY_NO_FIELD_LEN:
|
||||
case IMA_SHOW_BINARY_OLD_STRING_FMT:
|
||||
ima_show_template_data_binary(m, show, datafmt, field_data);
|
||||
break;
|
||||
default:
|
||||
|
@ -277,8 +272,6 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
|
|||
{
|
||||
const char *cur_filename = NULL;
|
||||
u32 cur_filename_len = 0;
|
||||
enum data_formats fmt = size_limit ?
|
||||
DATA_FMT_EVENT_NAME : DATA_FMT_STRING;
|
||||
|
||||
BUG_ON(filename == NULL && file == NULL);
|
||||
|
||||
|
@ -301,7 +294,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
|
|||
cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
|
||||
out:
|
||||
return ima_write_template_field_data(cur_filename, cur_filename_len,
|
||||
fmt, field_data);
|
||||
DATA_FMT_STRING, field_data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* the Free Software Foundation, version 2 of the License.
|
||||
*
|
||||
* File: integrity_audit.c
|
||||
* Audit calls for the integrity subsystem
|
||||
* Audit calls for the integrity subsystem
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
@ -33,6 +33,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
|
|||
const char *cause, int result, int audit_info)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
char name[TASK_COMM_LEN];
|
||||
|
||||
if (!integrity_audit_info && audit_info == 1) /* Skip info messages */
|
||||
return;
|
||||
|
@ -49,7 +50,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
|
|||
audit_log_format(ab, " cause=");
|
||||
audit_log_string(ab, cause);
|
||||
audit_log_format(ab, " comm=");
|
||||
audit_log_untrustedstring(ab, current->comm);
|
||||
audit_log_untrustedstring(ab, get_task_comm(name, current));
|
||||
if (fname) {
|
||||
audit_log_format(ab, " name=");
|
||||
audit_log_untrustedstring(ab, fname);
|
||||
|
|
Loading…
Reference in a new issue