Skip to content

Commit

Permalink
Merge tag 'integrity-v5.8' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/zohar/linux-integrity

Pull integrity updates from Mimi Zohar:
 "The main changes are extending the TPM 2.0 PCR banks with bank
  specific file hashes, calculating the "boot_aggregate" based on other
  TPM PCR banks, using the default IMA hash algorithm, instead of SHA1,
  as the basis for the cache hash table key, and preventing the mprotect
  syscall to circumvent an IMA mmap appraise policy rule.

   - In preparation for extending TPM 2.0 PCR banks with bank specific
     digests, commit 0b6cf6b ("tpm: pass an array of
     tpm_extend_digest structures to tpm_pcr_extend()") modified
     tpm_pcr_extend(). The original SHA1 file digests were
     padded/truncated, before being extended into the other TPM PCR
     banks. This pull request calculates and extends the TPM PCR banks
     with bank specific file hashes completing the above change.

   - The "boot_aggregate", the first IMA measurement list record, is the
     "trusted boot" link between the pre-boot environment and the
     running OS. With TPM 2.0, the "boot_aggregate" record is not
     limited to being based on the SHA1 TPM PCR bank, but can be
     calculated based on any enabled bank, assuming the hash algorithm
     is also enabled in the kernel.

  Other changes include the following and five other bug fixes/code
  clean up:

   - supporting both a SHA1 and a larger "boot_aggregate" digest in a
     custom template format containing both the the SHA1 ('d') and
     larger digests ('d-ng') fields.

   - Initial hash table key fix, but additional changes would be good"

* tag 'integrity-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
  ima: Directly free *entry in ima_alloc_init_template() if digests is NULL
  ima: Call ima_calc_boot_aggregate() in ima_eventdigest_init()
  ima: Directly assign the ima_default_policy pointer to ima_rules
  ima: verify mprotect change is consistent with mmap policy
  evm: Fix possible memory leak in evm_calc_hmac_or_hash()
  ima: Set again build_ima_appraise variable
  ima: Remove redundant policy rule set in add_rules()
  ima: Fix ima digest hash table key calculation
  ima: Use ima_hash_algo for collision detection in the measurement list
  ima: Calculate and extend PCR with digests in ima_template_entry
  ima: Allocate and initialize tfm for each PCR bank
  ima: Switch to dynamically allocated buffer for template digests
  ima: Store template digest directly in ima_template_entry
  ima: Evaluate error in init_ima()
  ima: Switch to ima_hash_algo for boot aggregate
  • Loading branch information
torvalds committed Jun 6, 2020
2 parents aaa2faa + 42413b4 commit 3c0ad98
Show file tree
Hide file tree
Showing 13 changed files with 397 additions and 87 deletions.
7 changes: 7 additions & 0 deletions include/linux/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern int ima_file_check(struct file *file, int mask);
extern void ima_post_create_tmpfile(struct inode *inode);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot);
extern int ima_load_data(enum kernel_load_data_id id);
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
Expand Down Expand Up @@ -70,6 +71,12 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
return 0;
}

static inline int ima_file_mprotect(struct vm_area_struct *vma,
unsigned long prot)
{
return 0;
}

static inline int ima_load_data(enum kernel_load_data_id id)
{
return 0;
Expand Down
2 changes: 1 addition & 1 deletion security/integrity/evm/evm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,

/* Portable EVM signatures must include an IMA hash */
if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
return -EPERM;
error = -EPERM;
out:
kfree(xattr_value);
kfree(desc);
Expand Down
20 changes: 13 additions & 7 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
#define IMA_EVENT_NAME_LEN_MAX 255

#define IMA_HASH_BITS 9
#define IMA_HASH_BITS 10
#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)

#define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16
Expand All @@ -45,13 +45,19 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
#define IMA_TEMPLATE_IMA_NAME "ima"
#define IMA_TEMPLATE_IMA_FMT "d|n"

#define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)

/* current content of the policy */
extern int ima_policy_flag;

/* set during initialization */
extern int ima_hash_algo;
extern int ima_sha1_idx __ro_after_init;
extern int ima_hash_algo_idx __ro_after_init;
extern int ima_extra_slots __ro_after_init;
extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip;
extern const char boot_aggregate_name[];

/* IMA event related data */
struct ima_event_data {
Expand Down Expand Up @@ -92,7 +98,7 @@ struct ima_template_desc {

struct ima_template_entry {
int pcr;
u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
struct tpm_digest *digests;
struct ima_template_desc *template_desc; /* template descriptor */
u32 template_data_len;
struct ima_field_data template_data[0]; /* template related data */
Expand Down Expand Up @@ -138,9 +144,8 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
int ima_calc_buffer_hash(const void *buf, loff_t len,
struct ima_digest_data *hash);
int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_template_desc *desc, int num_fields,
struct ima_digest_data *hash);
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
struct ima_template_entry *entry);
int ima_calc_boot_aggregate(struct ima_digest_data *hash);
void ima_add_violation(struct file *file, const unsigned char *filename,
struct integrity_iint_cache *iint,
const char *op, const char *cause);
Expand Down Expand Up @@ -175,9 +180,10 @@ struct ima_h_table {
};
extern struct ima_h_table ima_htable;

static inline unsigned long ima_hash_key(u8 *digest)
static inline unsigned int ima_hash_key(u8 *digest)
{
return hash_long(*digest, IMA_HASH_BITS);
/* there is no point in taking a hash of part of a digest */
return (digest[0] | digest[1] << 8) % IMA_MEASURE_HTABLE_SIZE;
}

#define __ima_hooks(hook) \
Expand Down
23 changes: 12 additions & 11 deletions security/integrity/ima/ima_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void ima_free_template_entry(struct ima_template_entry *entry)
for (i = 0; i < entry->template_desc->num_fields; i++)
kfree(entry->template_data[i].data);

kfree(entry->digests);
kfree(entry);
}

Expand All @@ -38,6 +39,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
struct ima_template_desc *desc)
{
struct ima_template_desc *template_desc;
struct tpm_digest *digests;
int i, result = 0;

if (desc)
Expand All @@ -50,6 +52,15 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
if (!*entry)
return -ENOMEM;

digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
sizeof(*digests), GFP_NOFS);
if (!digests) {
kfree(*entry);
*entry = NULL;
return -ENOMEM;
}

(*entry)->digests = digests;
(*entry)->template_desc = template_desc;
for (i = 0; i < template_desc->num_fields; i++) {
const struct ima_template_field *field =
Expand Down Expand Up @@ -96,26 +107,16 @@ int ima_store_template(struct ima_template_entry *entry,
static const char audit_cause[] = "hashing_error";
char *template_name = entry->template_desc->name;
int result;
struct {
struct ima_digest_data hdr;
char digest[TPM_DIGEST_SIZE];
} hash;

if (!violation) {
int num_fields = entry->template_desc->num_fields;

/* this function uses default algo */
hash.hdr.algo = HASH_ALGO_SHA1;
result = ima_calc_field_array_hash(&entry->template_data[0],
entry->template_desc,
num_fields, &hash.hdr);
entry);
if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
template_name, op,
audit_cause, result, 0);
return result;
}
memcpy(entry->digest, hash.hdr.digest, hash.hdr.length);
}
entry->pcr = pcr;
result = ima_add_template_entry(entry, violation, op, inode, filename);
Expand Down
Loading

0 comments on commit 3c0ad98

Please sign in to comment.