mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
273df864cf
Asymmetric private keys are used to sign multiple files. The kernel currently supports checking against blacklisted keys. However, if the public key is blacklisted, any file signed by the blacklisted key will automatically fail signature verification. Blacklisting the public key is not fine enough granularity, as we might want to only blacklist a particular file. This patch adds support for checking against the blacklisted hash of the file, without the appended signature, based on the IMA policy. It defines a new policy option "appraise_flag=check_blacklist". In addition to the blacklisted binary hashes stored in the firmware "dbx" variable, the Linux kernel may be configured to load blacklisted binary hashes onto the .blacklist keyring as well. The following example shows how to blacklist a specific kernel module hash. $ sha256sum kernel/kheaders.ko 77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3 kernel/kheaders.ko $ grep BLACKLIST .config CONFIG_SYSTEM_BLACKLIST_KEYRING=y CONFIG_SYSTEM_BLACKLIST_HASH_LIST="blacklist-hash-list" $ cat certs/blacklist-hash-list "bin:77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3" Update the IMA custom measurement and appraisal policy rules (/etc/ima-policy): measure func=MODULE_CHECK template=ima-modsig appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig After building, installing, and rebooting the kernel: 545660333 ---lswrv 0 0 \_ blacklist: bin:77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3 measure func=MODULE_CHECK template=ima-modsig appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig modprobe: ERROR: could not insert 'kheaders': Permission denied 10 0c9834db5a0182c1fb0cdc5d3adcf11a11fd83dd ima-sig sha256:3bc6ed4f0b4d6e31bc1dbc9ef844605abc7afdc6d81a57d77a1ec9407997c40 2 /usr/lib/modules/5.4.0-rc3+/kernel/kernel/kheaders.ko 10 82aad2bcc3fa8ed94762356b5c14838f3bcfa6a0 ima-modsig sha256:3bc6ed4f0b4d6e31bc1dbc9ef844605abc7afdc6d81a57d77a1ec9407997c40 2 /usr/lib/modules/5.4.0rc3+/kernel/kernel/kheaders.ko sha256:77fa889b3 5a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3 3082029a06092a864886f70d010702a082028b30820287020101310d300b0609608648 016503040201300b06092a864886f70d01070131820264.... 10 25b72217cc1152b44b134ce2cd68f12dfb71acb3 ima-buf sha256:8b58427fedcf8f4b20bc8dc007f2e232bf7285d7b93a66476321f9c2a3aa132 b blacklisted-hash 77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3 Signed-off-by: Nayna Jain <nayna@linux.ibm.com> [zohar@linux.ibm.com: updated patch description] Signed-off-by: Mimi Zohar <zohar@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/1572492694-6520-8-git-send-email-zohar@linux.ibm.com
398 lines
12 KiB
C
398 lines
12 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
|
|
*
|
|
* Authors:
|
|
* Reiner Sailer <sailer@watson.ibm.com>
|
|
* Mimi Zohar <zohar@us.ibm.com>
|
|
*
|
|
* File: ima.h
|
|
* internal Integrity Measurement Architecture (IMA) definitions
|
|
*/
|
|
|
|
#ifndef __LINUX_IMA_H
|
|
#define __LINUX_IMA_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/crypto.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/security.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/tpm.h>
|
|
#include <linux/audit.h>
|
|
#include <crypto/hash_info.h>
|
|
|
|
#include "../integrity.h"
|
|
|
|
#ifdef CONFIG_HAVE_IMA_KEXEC
|
|
#include <asm/ima.h>
|
|
#endif
|
|
|
|
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
|
|
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 */
|
|
#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
|
|
#define IMA_EVENT_NAME_LEN_MAX 255
|
|
|
|
#define IMA_HASH_BITS 9
|
|
#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
|
|
|
|
#define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16
|
|
#define IMA_TEMPLATE_NUM_FIELDS_MAX 15
|
|
|
|
#define IMA_TEMPLATE_IMA_NAME "ima"
|
|
#define IMA_TEMPLATE_IMA_FMT "d|n"
|
|
|
|
/* current content of the policy */
|
|
extern int ima_policy_flag;
|
|
|
|
/* set during initialization */
|
|
extern int ima_hash_algo;
|
|
extern int ima_appraise;
|
|
extern struct tpm_chip *ima_tpm_chip;
|
|
|
|
/* IMA event related data */
|
|
struct ima_event_data {
|
|
struct integrity_iint_cache *iint;
|
|
struct file *file;
|
|
const unsigned char *filename;
|
|
struct evm_ima_xattr_data *xattr_value;
|
|
int xattr_len;
|
|
const struct modsig *modsig;
|
|
const char *violation;
|
|
const void *buf;
|
|
int buf_len;
|
|
};
|
|
|
|
/* IMA template field data definition */
|
|
struct ima_field_data {
|
|
u8 *data;
|
|
u32 len;
|
|
};
|
|
|
|
/* IMA template field definition */
|
|
struct ima_template_field {
|
|
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
|
|
int (*field_init)(struct ima_event_data *event_data,
|
|
struct ima_field_data *field_data);
|
|
void (*field_show)(struct seq_file *m, enum ima_show_type show,
|
|
struct ima_field_data *field_data);
|
|
};
|
|
|
|
/* IMA template descriptor definition */
|
|
struct ima_template_desc {
|
|
struct list_head list;
|
|
char *name;
|
|
char *fmt;
|
|
int num_fields;
|
|
const struct ima_template_field **fields;
|
|
};
|
|
|
|
struct ima_template_entry {
|
|
int pcr;
|
|
u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
|
|
struct ima_template_desc *template_desc; /* template descriptor */
|
|
u32 template_data_len;
|
|
struct ima_field_data template_data[0]; /* template related data */
|
|
};
|
|
|
|
struct ima_queue_entry {
|
|
struct hlist_node hnext; /* place in hash collision list */
|
|
struct list_head later; /* place in ima_measurements list */
|
|
struct ima_template_entry *entry;
|
|
};
|
|
extern struct list_head ima_measurements; /* list of all measurements */
|
|
|
|
/* Some details preceding the binary serialized measurement list */
|
|
struct ima_kexec_hdr {
|
|
u16 version;
|
|
u16 _reserved0;
|
|
u32 _reserved1;
|
|
u64 buffer_size;
|
|
u64 count;
|
|
};
|
|
|
|
extern const int read_idmap[];
|
|
|
|
#ifdef CONFIG_HAVE_IMA_KEXEC
|
|
void ima_load_kexec_buffer(void);
|
|
#else
|
|
static inline void ima_load_kexec_buffer(void) {}
|
|
#endif /* CONFIG_HAVE_IMA_KEXEC */
|
|
|
|
/*
|
|
* The default binary_runtime_measurements list format is defined as the
|
|
* platform native format. The canonical format is defined as little-endian.
|
|
*/
|
|
extern bool ima_canonical_fmt;
|
|
|
|
/* Internal IMA function definitions */
|
|
int ima_init(void);
|
|
int ima_fs_init(void);
|
|
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
|
const char *op, struct inode *inode,
|
|
const unsigned char *filename);
|
|
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);
|
|
void ima_add_violation(struct file *file, const unsigned char *filename,
|
|
struct integrity_iint_cache *iint,
|
|
const char *op, const char *cause);
|
|
int ima_init_crypto(void);
|
|
void ima_putc(struct seq_file *m, void *data, int datalen);
|
|
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
|
|
int template_desc_init_fields(const char *template_fmt,
|
|
const struct ima_template_field ***fields,
|
|
int *num_fields);
|
|
struct ima_template_desc *ima_template_desc_current(void);
|
|
struct ima_template_desc *lookup_template_desc(const char *name);
|
|
bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
|
|
int ima_restore_measurement_entry(struct ima_template_entry *entry);
|
|
int ima_restore_measurement_list(loff_t bufsize, void *buf);
|
|
int ima_measurements_show(struct seq_file *m, void *v);
|
|
unsigned long ima_get_binary_runtime_size(void);
|
|
int ima_init_template(void);
|
|
void ima_init_template_list(void);
|
|
int __init ima_init_digests(void);
|
|
int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
|
|
void *lsm_data);
|
|
|
|
/*
|
|
* used to protect h_table and sha_table
|
|
*/
|
|
extern spinlock_t ima_queue_lock;
|
|
|
|
struct ima_h_table {
|
|
atomic_long_t len; /* number of stored measurements in the list */
|
|
atomic_long_t violations;
|
|
struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
|
|
};
|
|
extern struct ima_h_table ima_htable;
|
|
|
|
static inline unsigned long ima_hash_key(u8 *digest)
|
|
{
|
|
return hash_long(*digest, IMA_HASH_BITS);
|
|
}
|
|
|
|
#define __ima_hooks(hook) \
|
|
hook(NONE) \
|
|
hook(FILE_CHECK) \
|
|
hook(MMAP_CHECK) \
|
|
hook(BPRM_CHECK) \
|
|
hook(CREDS_CHECK) \
|
|
hook(POST_SETATTR) \
|
|
hook(MODULE_CHECK) \
|
|
hook(FIRMWARE_CHECK) \
|
|
hook(KEXEC_KERNEL_CHECK) \
|
|
hook(KEXEC_INITRAMFS_CHECK) \
|
|
hook(POLICY_CHECK) \
|
|
hook(KEXEC_CMDLINE) \
|
|
hook(MAX_CHECK)
|
|
#define __ima_hook_enumify(ENUM) ENUM,
|
|
|
|
enum ima_hooks {
|
|
__ima_hooks(__ima_hook_enumify)
|
|
};
|
|
|
|
extern const char *const func_tokens[];
|
|
|
|
struct modsig;
|
|
|
|
/* LIM API function definitions */
|
|
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
|
|
int mask, enum ima_hooks func, int *pcr,
|
|
struct ima_template_desc **template_desc);
|
|
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
|
|
int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|
struct file *file, void *buf, loff_t size,
|
|
enum hash_algo algo, struct modsig *modsig);
|
|
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
|
|
const unsigned char *filename,
|
|
struct evm_ima_xattr_data *xattr_value,
|
|
int xattr_len, const struct modsig *modsig, int pcr,
|
|
struct ima_template_desc *template_desc);
|
|
void process_buffer_measurement(const void *buf, int size,
|
|
const char *eventname, enum ima_hooks func,
|
|
int pcr);
|
|
void ima_audit_measurement(struct integrity_iint_cache *iint,
|
|
const unsigned char *filename);
|
|
int ima_alloc_init_template(struct ima_event_data *event_data,
|
|
struct ima_template_entry **entry,
|
|
struct ima_template_desc *template_desc);
|
|
int ima_store_template(struct ima_template_entry *entry, int violation,
|
|
struct inode *inode,
|
|
const unsigned char *filename, int pcr);
|
|
void ima_free_template_entry(struct ima_template_entry *entry);
|
|
const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
|
|
|
|
/* IMA policy related functions */
|
|
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
|
|
enum ima_hooks func, int mask, int flags, int *pcr,
|
|
struct ima_template_desc **template_desc);
|
|
void ima_init_policy(void);
|
|
void ima_update_policy(void);
|
|
void ima_update_policy_flag(void);
|
|
ssize_t ima_parse_add_rule(char *);
|
|
void ima_delete_rules(void);
|
|
int ima_check_policy(void);
|
|
void *ima_policy_start(struct seq_file *m, loff_t *pos);
|
|
void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos);
|
|
void ima_policy_stop(struct seq_file *m, void *v);
|
|
int ima_policy_show(struct seq_file *m, void *v);
|
|
|
|
/* Appraise integrity measurements */
|
|
#define IMA_APPRAISE_ENFORCE 0x01
|
|
#define IMA_APPRAISE_FIX 0x02
|
|
#define IMA_APPRAISE_LOG 0x04
|
|
#define IMA_APPRAISE_MODULES 0x08
|
|
#define IMA_APPRAISE_FIRMWARE 0x10
|
|
#define IMA_APPRAISE_POLICY 0x20
|
|
#define IMA_APPRAISE_KEXEC 0x40
|
|
|
|
#ifdef CONFIG_IMA_APPRAISE
|
|
int ima_check_blacklist(struct integrity_iint_cache *iint,
|
|
const struct modsig *modsig, int pcr);
|
|
int ima_appraise_measurement(enum ima_hooks func,
|
|
struct integrity_iint_cache *iint,
|
|
struct file *file, const unsigned char *filename,
|
|
struct evm_ima_xattr_data *xattr_value,
|
|
int xattr_len, const struct modsig *modsig);
|
|
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);
|
|
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
|
|
enum ima_hooks func);
|
|
enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
|
|
int xattr_len);
|
|
int ima_read_xattr(struct dentry *dentry,
|
|
struct evm_ima_xattr_data **xattr_value);
|
|
|
|
#else
|
|
static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
|
|
const struct modsig *modsig, int pcr)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int ima_appraise_measurement(enum ima_hooks func,
|
|
struct integrity_iint_cache *iint,
|
|
struct file *file,
|
|
const unsigned char *filename,
|
|
struct evm_ima_xattr_data *xattr_value,
|
|
int xattr_len,
|
|
const struct modsig *modsig)
|
|
{
|
|
return INTEGRITY_UNKNOWN;
|
|
}
|
|
|
|
static inline int ima_must_appraise(struct inode *inode, int mask,
|
|
enum ima_hooks func)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void ima_update_xattr(struct integrity_iint_cache *iint,
|
|
struct file *file)
|
|
{
|
|
}
|
|
|
|
static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache
|
|
*iint,
|
|
enum ima_hooks func)
|
|
{
|
|
return INTEGRITY_UNKNOWN;
|
|
}
|
|
|
|
static inline enum hash_algo
|
|
ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
|
|
{
|
|
return ima_hash_algo;
|
|
}
|
|
|
|
static inline int ima_read_xattr(struct dentry *dentry,
|
|
struct evm_ima_xattr_data **xattr_value)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_IMA_APPRAISE */
|
|
|
|
#ifdef CONFIG_IMA_APPRAISE_MODSIG
|
|
bool ima_hook_supports_modsig(enum ima_hooks func);
|
|
int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
|
|
struct modsig **modsig);
|
|
void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
|
|
int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
|
|
const u8 **digest, u32 *digest_size);
|
|
int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
|
|
u32 *data_len);
|
|
void ima_free_modsig(struct modsig *modsig);
|
|
#else
|
|
static inline bool ima_hook_supports_modsig(enum ima_hooks func)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline int ima_read_modsig(enum ima_hooks func, const void *buf,
|
|
loff_t buf_len, struct modsig **modsig)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void ima_collect_modsig(struct modsig *modsig, const void *buf,
|
|
loff_t size)
|
|
{
|
|
}
|
|
|
|
static inline int ima_get_modsig_digest(const struct modsig *modsig,
|
|
enum hash_algo *algo, const u8 **digest,
|
|
u32 *digest_size)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int ima_get_raw_modsig(const struct modsig *modsig,
|
|
const void **data, u32 *data_len)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void ima_free_modsig(struct modsig *modsig)
|
|
{
|
|
}
|
|
#endif /* CONFIG_IMA_APPRAISE_MODSIG */
|
|
|
|
/* LSM based policy rules require audit */
|
|
#ifdef CONFIG_IMA_LSM_RULES
|
|
|
|
#define security_filter_rule_init security_audit_rule_init
|
|
#define security_filter_rule_match security_audit_rule_match
|
|
|
|
#else
|
|
|
|
static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
|
|
void **lsmrule)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
|
|
void *lsmrule)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
#endif /* CONFIG_IMA_LSM_RULES */
|
|
|
|
#ifdef CONFIG_IMA_READ_POLICY
|
|
#define POLICY_FILE_FLAGS (S_IWUSR | S_IRUSR)
|
|
#else
|
|
#define POLICY_FILE_FLAGS S_IWUSR
|
|
#endif /* CONFIG_IMA_READ_POLICY */
|
|
|
|
#endif /* __LINUX_IMA_H */
|