diff options
Diffstat (limited to 'security/integrity')
-rw-r--r-- | security/integrity/digsig.c | 28 | ||||
-rw-r--r-- | security/integrity/ima/Kconfig | 10 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 15 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 10 | ||||
-rw-r--r-- | security/integrity/ima/ima_crypto.c | 312 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 28 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 13 | ||||
-rw-r--r-- | security/integrity/integrity.h | 14 |
8 files changed, 413 insertions, 17 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index b4af4ebc5be2..8d4fbff8b87c 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -13,7 +13,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/err.h> +#include <linux/sched.h> #include <linux/rbtree.h> +#include <linux/cred.h> #include <linux/key-type.h> #include <linux/digsig.h> @@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX]; static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { "_evm", "_module", +#ifndef CONFIG_IMA_TRUSTED_KEYRING "_ima", +#else + ".ima", +#endif }; int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, @@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, return -EOPNOTSUPP; } + +int integrity_init_keyring(const unsigned int id) +{ + const struct cred *cred = current_cred(); + int err = 0; + + keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), + KGIDT_INIT(0), cred, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ | + KEY_USR_WRITE | KEY_USR_SEARCH), + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (!IS_ERR(keyring[id])) + set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); + else { + err = PTR_ERR(keyring[id]); + pr_info("Can't allocate %s keyring (%d)\n", + keyring_name[id], err); + keyring[id] = NULL; + } + return err; +} diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 81a27971d884..08758fbd496f 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -123,3 +123,13 @@ config IMA_APPRAISE For more information on integrity appraisal refer to: <http://linux-ima.sourceforge.net> If unsure, say N. + +config IMA_TRUSTED_KEYRING + bool "Require all keys on the .ima keyring be signed" + depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING + depends on INTEGRITY_ASYMMETRIC_KEYS + select KEYS_DEBUG_PROC_KEYS + default y + help + This option requires that all keys added to the .ima + keyring be signed by a key on the system trusted keyring. diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f79fa8be203c..57da4bd7ba0c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -158,7 +158,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); struct integrity_iint_cache *integrity_iint_find(struct inode *inode); /* IMA policy related functions */ -enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; +enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, int flags); @@ -171,6 +171,7 @@ void ima_delete_rules(void); #define IMA_APPRAISE_ENFORCE 0x01 #define IMA_APPRAISE_FIX 0x02 #define IMA_APPRAISE_MODULES 0x04 +#define IMA_APPRAISE_FIRMWARE 0x08 #ifdef CONFIG_IMA_APPRAISE int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, @@ -249,4 +250,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, return -EINVAL; } #endif /* CONFIG_IMA_LSM_RULES */ + +#ifdef CONFIG_IMA_TRUSTED_KEYRING +static inline int ima_init_keyring(const unsigned int id) +{ + return integrity_init_keyring(id); +} +#else +static inline int ima_init_keyring(const unsigned int id) +{ + return 0; +} +#endif /* CONFIG_IMA_TRUSTED_KEYRING */ #endif diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index d3113d4aaa3c..86bfd5c5df85 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -75,6 +75,8 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, return iint->ima_bprm_status; case MODULE_CHECK: return iint->ima_module_status; + case FIRMWARE_CHECK: + return iint->ima_firmware_status; case FILE_CHECK: default: return iint->ima_file_status; @@ -94,6 +96,9 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, case MODULE_CHECK: iint->ima_module_status = status; break; + case FIRMWARE_CHECK: + iint->ima_firmware_status = status; + break; case FILE_CHECK: default: iint->ima_file_status = status; @@ -113,6 +118,9 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) case MODULE_CHECK: iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); break; + case FIRMWARE_CHECK: + iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED); + break; case FILE_CHECK: default: iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); @@ -214,7 +222,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, hash_start = 1; case IMA_XATTR_DIGEST: if (iint->flags & IMA_DIGSIG_REQUIRED) { - cause = "IMA signature required"; + cause = "IMA-signature-required"; status = INTEGRITY_FAIL; break; } diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index ccd0ac8fa9a0..0bd732843fe7 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -16,6 +16,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/kernel.h> +#include <linux/moduleparam.h> +#include <linux/ratelimit.h> #include <linux/file.h> #include <linux/crypto.h> #include <linux/scatterlist.h> @@ -25,7 +27,45 @@ #include <crypto/hash_info.h> #include "ima.h" +struct ahash_completion { + struct completion completion; + int err; +}; + +/* minimum file size for ahash use */ +static unsigned long ima_ahash_minsize; +module_param_named(ahash_minsize, ima_ahash_minsize, ulong, 0644); +MODULE_PARM_DESC(ahash_minsize, "Minimum file size for ahash use"); + +/* default is 0 - 1 page. */ +static int ima_maxorder; +static unsigned int ima_bufsize = PAGE_SIZE; + +static int param_set_bufsize(const char *val, const struct kernel_param *kp) +{ + unsigned long long size; + int order; + + size = memparse(val, NULL); + order = get_order(size); + if (order >= MAX_ORDER) + return -EINVAL; + ima_maxorder = order; + ima_bufsize = PAGE_SIZE << order; + return 0; +} + +static struct kernel_param_ops param_ops_bufsize = { + .set = param_set_bufsize, + .get = param_get_uint, +}; +#define param_check_bufsize(name, p) __param_check(name, p, unsigned int) + +module_param_named(ahash_bufsize, ima_bufsize, bufsize, 0644); +MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); + static struct crypto_shash *ima_shash_tfm; +static struct crypto_ahash *ima_ahash_tfm; /** * ima_kernel_read - read file content @@ -93,9 +133,246 @@ static void ima_free_tfm(struct crypto_shash *tfm) crypto_free_shash(tfm); } -/* - * Calculate the MD5/SHA1 file digest +/** + * ima_alloc_pages() - Allocate contiguous pages. + * @max_size: Maximum amount of memory to allocate. + * @allocated_size: Returned size of actual allocation. + * @last_warn: Should the min_size allocation warn or not. + * + * Tries to do opportunistic allocation for memory first trying to allocate + * max_size amount of memory and then splitting that until zero order is + * reached. Allocation is tried without generating allocation warnings unless + * last_warn is set. Last_warn set affects only last allocation of zero order. + * + * By default, ima_maxorder is 0 and it is equivalent to kmalloc(GFP_KERNEL) + * + * Return pointer to allocated memory, or NULL on failure. + */ +static void *ima_alloc_pages(loff_t max_size, size_t *allocated_size, + int last_warn) +{ + void *ptr; + int order = ima_maxorder; + gfp_t gfp_mask = __GFP_WAIT | __GFP_NOWARN | __GFP_NORETRY; + + if (order) + order = min(get_order(max_size), order); + + for (; order; order--) { + ptr = (void *)__get_free_pages(gfp_mask, order); + if (ptr) { + *allocated_size = PAGE_SIZE << order; + return ptr; + } + } + + /* order is zero - one page */ + + gfp_mask = GFP_KERNEL; + + if (!last_warn) + gfp_mask |= __GFP_NOWARN; + + ptr = (void *)__get_free_pages(gfp_mask, 0); + if (ptr) { + *allocated_size = PAGE_SIZE; + return ptr; + } + + *allocated_size = 0; + return NULL; +} + +/** + * ima_free_pages() - Free pages allocated by ima_alloc_pages(). + * @ptr: Pointer to allocated pages. + * @size: Size of allocated buffer. */ +static void ima_free_pages(void *ptr, size_t size) +{ + if (!ptr) + return; + free_pages((unsigned long)ptr, get_order(size)); +} + +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo) +{ + struct crypto_ahash *tfm = ima_ahash_tfm; + int rc; + + if ((algo != ima_hash_algo && algo < HASH_ALGO__LAST) || !tfm) { + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); + if (!IS_ERR(tfm)) { + if (algo == ima_hash_algo) + ima_ahash_tfm = tfm; + } else { + rc = PTR_ERR(tfm); + pr_err("Can not allocate %s (reason: %d)\n", + hash_algo_name[algo], rc); + } + } + return tfm; +} + +static void ima_free_atfm(struct crypto_ahash *tfm) +{ + if (tfm != ima_ahash_tfm) + crypto_free_ahash(tfm); +} + +static void ahash_complete(struct crypto_async_request *req, int err) +{ + struct ahash_completion *res = req->data; + + if (err == -EINPROGRESS) + return; + res->err = err; + complete(&res->completion); +} + +static int ahash_wait(int err, struct ahash_completion *res) +{ + switch (err) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + wait_for_completion(&res->completion); + reinit_completion(&res->completion); + err = res->err; + /* fall through */ + default: + pr_crit_ratelimited("ahash calculation failed: err: %d\n", err); + } + + return err; +} + +static int ima_calc_file_hash_atfm(struct file *file, + struct ima_digest_data *hash, + struct crypto_ahash *tfm) +{ + loff_t i_size, offset; + char *rbuf[2] = { NULL, }; + int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; + struct ahash_request *req; + struct scatterlist sg[1]; + struct ahash_completion res; + size_t rbuf_size[2]; + + hash->length = crypto_ahash_digestsize(tfm); + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) + return -ENOMEM; + + init_completion(&res.completion); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + ahash_complete, &res); + + rc = ahash_wait(crypto_ahash_init(req), &res); + if (rc) + goto out1; + + i_size = i_size_read(file_inode(file)); + + if (i_size == 0) + goto out2; + + /* + * Try to allocate maximum size of memory. + * Fail if even a single page cannot be allocated. + */ + rbuf[0] = ima_alloc_pages(i_size, &rbuf_size[0], 1); + if (!rbuf[0]) { + rc = -ENOMEM; + goto out1; + } + + /* Only allocate one buffer if that is enough. */ + if (i_size > rbuf_size[0]) { + /* + * Try to allocate secondary buffer. If that fails fallback to + * using single buffering. Use previous memory allocation size + * as baseline for possible allocation size. + */ + rbuf[1] = ima_alloc_pages(i_size - rbuf_size[0], + &rbuf_size[1], 0); + } + + if (!(file->f_mode & FMODE_READ)) { + file->f_mode |= FMODE_READ; + read = 1; + } + + for (offset = 0; offset < i_size; offset += rbuf_len) { + if (!rbuf[1] && offset) { + /* Not using two buffers, and it is not the first + * read/request, wait for the completion of the + * previous ahash_update() request. + */ + rc = ahash_wait(ahash_rc, &res); + if (rc) + goto out3; + } + /* read buffer */ + rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); + rc = ima_kernel_read(file, offset, rbuf[active], rbuf_len); + if (rc != rbuf_len) + goto out3; + + if (rbuf[1] && offset) { + /* Using two buffers, and it is not the first + * read/request, wait for the completion of the + * previous ahash_update() request. + */ + rc = ahash_wait(ahash_rc, &res); + if (rc) + goto out3; + } + + sg_init_one(&sg[0], rbuf[active], rbuf_len); + ahash_request_set_crypt(req, sg, NULL, rbuf_len); + + ahash_rc = crypto_ahash_update(req); + + if (rbuf[1]) + active = !active; /* swap buffers, if we use two */ + } + /* wait for the last update request to complete */ + rc = ahash_wait(ahash_rc, &res); +out3: + if (read) + file->f_mode &= ~FMODE_READ; + ima_free_pages(rbuf[0], rbuf_size[0]); + ima_free_pages(rbuf[1], rbuf_size[1]); +out2: + if (!rc) { + ahash_request_set_crypt(req, NULL, hash->digest, 0); + rc = ahash_wait(crypto_ahash_final(req), &res); + } +out1: + ahash_request_free(req); + return rc; +} + +static int ima_calc_file_ahash(struct file *file, struct ima_digest_data *hash) +{ + struct crypto_ahash *tfm; + int rc; + + tfm = ima_alloc_atfm(hash->algo); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + rc = ima_calc_file_hash_atfm(file, hash, tfm); + + ima_free_atfm(tfm); + + return rc; +} + static int ima_calc_file_hash_tfm(struct file *file, struct ima_digest_data *hash, struct crypto_shash *tfm) @@ -156,7 +433,7 @@ out: return rc; } -int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) +static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash) { struct crypto_shash *tfm; int rc; @@ -173,6 +450,35 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) } /* + * ima_calc_file_hash - calculate file hash + * + * Asynchronous hash (ahash) allows using HW acceleration for calculating + * a hash. ahash performance varies for different data sizes on different + * crypto accelerators. shash performance might be better for smaller files. + * The 'ima.ahash_minsize' module parameter allows specifying the best + * minimum file size for using ahash on the system. + * + * If the ima.ahash_minsize parameter is not specified, this function uses + * shash for the hash calculation. If ahash fails, it falls back to using + * shash. + */ +int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) +{ + loff_t i_size; + int rc; + + i_size = i_size_read(file_inode(file)); + + if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { + rc = ima_calc_file_ahash(file, hash); + if (!rc) + return 0; + } + + return ima_calc_file_shash(file, hash); +} + +/* * Calculate the hash of template data */ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 09baa335ebc7..2917f980bf30 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -88,8 +88,6 @@ static void ima_rdwr_violation_check(struct file *file) if (!S_ISREG(inode->i_mode) || !ima_initialized) return; - mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ - if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { struct integrity_iint_cache *iint; @@ -104,8 +102,6 @@ static void ima_rdwr_violation_check(struct file *file) send_writers = true; } - mutex_unlock(&inode->i_mutex); - if (!send_tomtou && !send_writers) return; @@ -163,7 +159,7 @@ static int process_measurement(struct file *file, const char *filename, { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - struct ima_template_desc *template_desc = ima_template_desc_current(); + struct ima_template_desc *template_desc; char *pathbuf = NULL; const char *pathname = NULL; int rc = -ENOMEM, action, must_appraise, _func; @@ -207,6 +203,7 @@ static int process_measurement(struct file *file, const char *filename, goto out_digsig; } + template_desc = ima_template_desc_current(); if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { if (action & IMA_APPRAISE_SUBMASK) xattr_ptr = &xattr_value; @@ -322,14 +319,31 @@ int ima_module_check(struct file *file) return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); } +int ima_fw_from_file(struct file *file, char *buf, size_t size) +{ + if (!file) { + if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && + (ima_appraise & IMA_APPRAISE_ENFORCE)) + return -EACCES; /* INTEGRITY_UNKNOWN */ + return 0; + } + return process_measurement(file, NULL, MAY_EXEC, FIRMWARE_CHECK); +} + static int __init init_ima(void) { int error; hash_setup(CONFIG_IMA_DEFAULT_HASH); error = ima_init(); - if (!error) - ima_initialized = 1; + if (error) + goto out; + + error = ima_init_keyring(INTEGRITY_KEYRING_IMA); + if (error) + goto out; + ima_initialized = 1; +out: return error; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 40a7488f6721..07099a8bc283 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -84,6 +84,7 @@ static struct ima_rule_entry default_rules[] = { {.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 = FIRMWARE_CHECK, .flags = IMA_FUNC}, }; static struct ima_rule_entry default_appraise_rules[] = { @@ -241,6 +242,8 @@ static int get_subaction(struct ima_rule_entry *rule, int func) return IMA_BPRM_APPRAISE; case MODULE_CHECK: return IMA_MODULE_APPRAISE; + case FIRMWARE_CHECK: + return IMA_FIRMWARE_APPRAISE; case FILE_CHECK: default: return IMA_FILE_APPRAISE; @@ -332,7 +335,7 @@ void __init ima_init_policy(void) void ima_update_policy(void) { static const char op[] = "policy_update"; - const char *cause = "already exists"; + const char *cause = "already-exists"; int result = 1; int audit_info = 0; @@ -486,6 +489,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) entry->func = FILE_CHECK; else if (strcmp(args[0].from, "MODULE_CHECK") == 0) entry->func = MODULE_CHECK; + else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0) + entry->func = FIRMWARE_CHECK; else if ((strcmp(args[0].from, "FILE_MMAP") == 0) || (strcmp(args[0].from, "MMAP_CHECK") == 0)) entry->func = MMAP_CHECK; @@ -636,6 +641,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) result = -EINVAL; else if (entry->func == MODULE_CHECK) ima_appraise |= IMA_APPRAISE_MODULES; + else if (entry->func == FIRMWARE_CHECK) + ima_appraise |= IMA_APPRAISE_FIRMWARE; audit_log_format(ab, "res=%d", !result); audit_log_end(ab); return result; @@ -659,7 +666,7 @@ ssize_t ima_parse_add_rule(char *rule) /* Prevent installed policy from changing */ if (ima_rules != &ima_default_rules) { integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "already exists", + NULL, op, "already-exists", -EACCES, audit_info); return -EACCES; } @@ -685,7 +692,7 @@ ssize_t ima_parse_add_rule(char *rule) if (result) { kfree(entry); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "invalid policy", result, + NULL, op, "invalid-policy", result, audit_info); return result; } diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 33c0a70f6b15..19b8e314ca96 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -46,10 +46,14 @@ #define IMA_BPRM_APPRAISED 0x00002000 #define IMA_MODULE_APPRAISE 0x00004000 #define IMA_MODULE_APPRAISED 0x00008000 +#define IMA_FIRMWARE_APPRAISE 0x00010000 +#define IMA_FIRMWARE_APPRAISED 0x00020000 #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ - IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE) + IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \ + IMA_FIRMWARE_APPRAISE) #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ - IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED) + IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \ + IMA_FIRMWARE_APPRAISED) enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, @@ -104,6 +108,7 @@ struct integrity_iint_cache { enum integrity_status ima_mmap_status:4; enum integrity_status ima_bprm_status:4; enum integrity_status ima_module_status:4; + enum integrity_status ima_firmware_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; }; @@ -124,6 +129,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode); int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen); +int integrity_init_keyring(const unsigned int id); #else static inline int integrity_digsig_verify(const unsigned int id, @@ -133,6 +139,10 @@ static inline int integrity_digsig_verify(const unsigned int id, return -EOPNOTSUPP; } +static inline int integrity_init_keyring(const unsigned int id) +{ + return 0; +} #endif /* CONFIG_INTEGRITY_SIGNATURE */ #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |