diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index cb850e5290c2..89670c5e7c8e 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2394,23 +2394,6 @@ Kernel parameters [IMA] Define a custom template format. Format: { "field1|...|fieldN" } - ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage - Format: - Set the minimal file size for using asynchronous hash. - If left unspecified, ahash usage is disabled. - - ahash performance varies for different data sizes on - different crypto accelerators. This option can be used - to achieve the best performance for a particular HW. - - ima.ahash_bufsize= [IMA] Asynchronous hash buffer size - Format: - Set hashing buffer size. Default: 4k. - - ahash performance varies for different chunk sizes on - different crypto accelerators. This option can be used - to achieve best performance for particular HW. - ima= [IMA] Enable or disable IMA Format: { "off" | "on" } Default: "on" diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 8f680ef18d8c..0d72b48249ee 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -11,51 +11,15 @@ */ #include -#include -#include #include #include -#include #include #include #include #include "ima.h" -/* 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_PAGE_ORDER) - return -EINVAL; - ima_maxorder = order; - ima_bufsize = PAGE_SIZE << order; - return 0; -} - -static const 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; int ima_sha1_idx __ro_after_init; int ima_hash_algo_idx __ro_after_init; @@ -226,234 +190,6 @@ static void ima_free_tfm(struct crypto_shash *tfm) crypto_free_shash(tfm); } -/** - * 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_RECLAIM | __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 < 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); - 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 inline int ahash_wait(int err, struct crypto_wait *wait) -{ - - err = crypto_wait_req(err, wait); - - if (err) - 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, rbuf_len, active = 0, ahash_rc = 0; - struct ahash_request *req; - struct scatterlist sg[1]; - struct crypto_wait wait; - size_t rbuf_size[2]; - - hash->length = crypto_ahash_digestsize(tfm); - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) - return -ENOMEM; - - crypto_init_wait(&wait); - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &wait); - - rc = ahash_wait(crypto_ahash_init(req), &wait); - 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); - } - - 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, &wait); - if (rc) - goto out3; - } - /* read buffer */ - rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); - rc = integrity_kernel_read(file, offset, rbuf[active], - rbuf_len); - if (rc != rbuf_len) { - if (rc >= 0) - rc = -EINVAL; - /* - * Forward current rc, do not overwrite with return value - * from ahash_wait() - */ - ahash_wait(ahash_rc, &wait); - 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, &wait); - 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, &wait); -out3: - 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), &wait); - } -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) @@ -505,41 +241,15 @@ out: return rc; } -static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash) -{ - struct crypto_shash *tfm; - int rc; - - tfm = ima_alloc_tfm(hash->algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = ima_calc_file_hash_tfm(file, hash, tfm); - - ima_free_tfm(tfm); - - return rc; -} - /* * 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; struct file *f = file; bool new_file_instance = false; + struct crypto_shash *tfm; /* * For consistency, fail file's opened with the O_DIRECT flag on @@ -563,16 +273,13 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) new_file_instance = true; } - i_size = i_size_read(file_inode(f)); - - if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { - rc = ima_calc_file_ahash(f, hash); - if (!rc) - goto out; + tfm = ima_alloc_tfm(hash->algo); + if (IS_ERR(tfm)) { + rc = PTR_ERR(tfm); + } else { + rc = ima_calc_file_hash_tfm(f, hash, tfm); + ima_free_tfm(tfm); } - - rc = ima_calc_file_shash(f, hash); -out: if (new_file_instance) fput(f); return rc; @@ -661,63 +368,6 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, return rc; } -static int calc_buffer_ahash_atfm(const void *buf, loff_t len, - struct ima_digest_data *hash, - struct crypto_ahash *tfm) -{ - struct ahash_request *req; - struct scatterlist sg; - struct crypto_wait wait; - int rc, ahash_rc = 0; - - hash->length = crypto_ahash_digestsize(tfm); - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) - return -ENOMEM; - - crypto_init_wait(&wait); - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &wait); - - rc = ahash_wait(crypto_ahash_init(req), &wait); - if (rc) - goto out; - - sg_init_one(&sg, buf, len); - ahash_request_set_crypt(req, &sg, NULL, len); - - ahash_rc = crypto_ahash_update(req); - - /* wait for the update request to complete */ - rc = ahash_wait(ahash_rc, &wait); - if (!rc) { - ahash_request_set_crypt(req, NULL, hash->digest, 0); - rc = ahash_wait(crypto_ahash_final(req), &wait); - } -out: - ahash_request_free(req); - return rc; -} - -static int calc_buffer_ahash(const void *buf, loff_t len, - 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 = calc_buffer_ahash_atfm(buf, len, hash, tfm); - - ima_free_atfm(tfm); - - return rc; -} - static int calc_buffer_shash_tfm(const void *buf, loff_t size, struct ima_digest_data *hash, struct crypto_shash *tfm) @@ -748,8 +398,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t size, return rc; } -static int calc_buffer_shash(const void *buf, loff_t len, - struct ima_digest_data *hash) +int ima_calc_buffer_hash(const void *buf, loff_t len, + struct ima_digest_data *hash) { struct crypto_shash *tfm; int rc; @@ -764,20 +414,6 @@ static int calc_buffer_shash(const void *buf, loff_t len, return rc; } -int ima_calc_buffer_hash(const void *buf, loff_t len, - struct ima_digest_data *hash) -{ - int rc; - - if (ima_ahash_minsize && len >= ima_ahash_minsize) { - rc = calc_buffer_ahash(buf, len, hash); - if (!rc) - return 0; - } - - return calc_buffer_shash(buf, len, hash); -} - static void ima_pcrread(u32 idx, struct tpm_digest *d) { if (!ima_tpm_chip)