linux-security-module.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Roberto Sassu <roberto.sassu@huaweicloud.com>
To: Jarkko Sakkinen <jarkko@kernel.org>,
	corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com,
	paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com
Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-integrity@vger.kernel.org,
	linux-security-module@vger.kernel.org, bpf@vger.kernel.org,
	pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de,
	mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com,
	Roberto Sassu <roberto.sassu@huawei.com>
Subject: Re: [RFC][PATCH v2 03/13] integrity/digest_cache: Add functions to populate and search
Date: Wed, 16 Aug 2023 10:35:56 +0200	[thread overview]
Message-ID: <98959e3d-7543-4a8e-9712-05a3ba04d2c8@huaweicloud.com> (raw)
In-Reply-To: <CUSFPINBGDSS.DQ0I19Z9FNR4@suppilovahvero>

On 8/14/2023 7:13 PM, Jarkko Sakkinen wrote:
> On Sat Aug 12, 2023 at 1:46 PM EEST, Roberto Sassu wrote:
>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>
>> Add digest_cache_init_htable(), to size a hash table depending on the
>> number of digests to be added to the cache.
>>
>> Add digest_cache_add() and digest_cache_lookup() to respectively add and
>> lookup a digest in the digest cache.
>>
>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>> ---
>>   security/integrity/digest_cache.c | 131 ++++++++++++++++++++++++++++++
>>   security/integrity/digest_cache.h |  24 ++++++
>>   2 files changed, 155 insertions(+)
>>
>> diff --git a/security/integrity/digest_cache.c b/security/integrity/digest_cache.c
>> index 4201c68171a..d14d84b804b 100644
>> --- a/security/integrity/digest_cache.c
>> +++ b/security/integrity/digest_cache.c
>> @@ -315,3 +315,134 @@ struct digest_cache *digest_cache_get(struct dentry *dentry,
>>   
>>   	return iint->dig_user;
>>   }
>> +
>> +/**
>> + * digest_cache_init_htable - Allocate and initialize the hash table
>> + * @digest_cache: Digest cache
>> + * @num_digests: Number of digests to add to the digest cache
>> + *
>> + * This function allocates and initializes the hash table. Its size is
>> + * determined by the number of digests to add to the digest cache, known
>> + * at this point by the parser calling this function.
>> + *
>> + * Return: Zero on success, a negative value otherwise.
>> + */
>> +int digest_cache_init_htable(struct digest_cache *digest_cache,
>> +			     u64 num_digests)
>> +{
>> +	int i;
>> +
>> +	if (!digest_cache)
>> +		return 0;
>> +
>> +	digest_cache->num_slots = num_digests / DIGEST_CACHE_HTABLE_DEPTH;
>> +	if (!digest_cache->num_slots)
>> +		digest_cache->num_slots = 1;
>> +
>> +	digest_cache->slots = kmalloc_array(num_digests,
>> +					    sizeof(*digest_cache->slots),
>> +					    GFP_KERNEL);
>> +	if (!digest_cache->slots)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < digest_cache->num_slots; i++)
>> +		INIT_HLIST_HEAD(&digest_cache->slots[i]);
>> +
>> +	pr_debug("Initialized %d hash table slots for digest list %s\n",
>> +		 digest_cache->num_slots, digest_cache->path_str);
>> +	return 0;
>> +}
>> +
>> +/**
>> + * digest_cache_add - Add a new digest to the digest cache
>> + * @digest_cache: Digest cache
>> + * @digest: Digest to add
>> + *
>> + * This function, invoked by a digest list parser, adds a digest extracted
>> + * from a digest list to the digest cache.
>> + *
>> + * Return: Zero on success, a negative value on error.
> 
> Nit: previous had a different phrasing "a negative value otherwise".
> 
> I would suggest "a POSIX error code otherwise" for both.

Ok.

>> + */
>> +int digest_cache_add(struct digest_cache *digest_cache, u8 *digest)
>> +{
>> +	struct digest_cache_entry *entry;
>> +	unsigned int key;
>> +	int digest_len;
>> +
>> +	if (!digest_cache)
>> +		return 0;
>> +
>> +	digest_len = hash_digest_size[digest_cache->algo];
>> +
>> +	entry = kmalloc(sizeof(*entry) + digest_len, GFP_KERNEL);
>> +	if (!entry)
>> +		return -ENOMEM;
>> +
>> +	memcpy(entry->digest, digest, digest_len);
>> +
>> +	key = digest_cache_hash_key(digest, digest_cache->num_slots);
>> +	hlist_add_head(&entry->hnext, &digest_cache->slots[key]);
>> +	pr_debug("Add digest %s:%*phN from digest list %s\n",
>> +		 hash_algo_name[digest_cache->algo], digest_len, digest,
>> +		 digest_cache->path_str);
>> +	return 0;
>> +}
>> +
>> +/**
>> + * digest_cache_lookup - Searches a digest in the digest cache
>> + * @digest_cache: Digest cache
>> + * @digest: Digest to search
>> + * @algo: Algorithm of the digest to search
>> + * @pathname: Path of the file whose digest is looked up
>> + *
>> + * This function, invoked by IMA or EVM, searches the calculated digest of
>> + * a file or file metadata in the digest cache acquired with
>> + * digest_cache_get().
>> + *
>> + * Return: Zero if the digest is found, a negative value if not.
>> + */
>> +int digest_cache_lookup(struct digest_cache *digest_cache, u8 *digest,
>> +			enum hash_algo algo, const char *pathname)
>> +{
>> +	struct digest_cache_entry *entry;
>> +	unsigned int key;
>> +	int digest_len;
>> +	int search_depth = 0;
>> +
>> +	if (!digest_cache)
>> +		return -ENOENT;
>> +
>> +	if (digest_cache->algo == HASH_ALGO__LAST) {
>> +		pr_debug("Algorithm not set for digest list %s\n",
>> +			 digest_cache->path_str);
>> +		return -ENOENT;
>> +	}
>> +
>> +	digest_len = hash_digest_size[digest_cache->algo];
>> +
>> +	if (algo != digest_cache->algo) {
>> +		pr_debug("Algo mismatch for file %s, digest %s:%*phN in digest list %s (%s)\n",
>> +			 pathname, hash_algo_name[algo], digest_len, digest,
>> +			 digest_cache->path_str,
>> +			 hash_algo_name[digest_cache->algo]);
>> +		return -ENOENT;
>> +	}
>> +
>> +	key = digest_cache_hash_key(digest, digest_cache->num_slots);
>> +
>> +	hlist_for_each_entry_rcu(entry, &digest_cache->slots[key], hnext) {
>> +		if (!memcmp(entry->digest, digest, digest_len)) {
>> +			pr_debug("Cache hit at depth %d for file %s, digest %s:%*phN in digest list %s\n",
>> +				 search_depth, pathname, hash_algo_name[algo],
>> +				 digest_len, digest, digest_cache->path_str);
>> +			return 0;
>> +		}
>> +
>> +		search_depth++;
>> +	}
>> +
>> +	pr_debug("Cache miss for file %s, digest %s:%*phN in digest list %s\n",
>> +		 pathname, hash_algo_name[algo], digest_len, digest,
>> +		 digest_cache->path_str);
>> +	return -ENOENT;
>> +}
>> diff --git a/security/integrity/digest_cache.h b/security/integrity/digest_cache.h
>> index ff88e8593c6..01cd70f9850 100644
>> --- a/security/integrity/digest_cache.h
>> +++ b/security/integrity/digest_cache.h
>> @@ -66,6 +66,11 @@ static inline unsigned int digest_cache_hash_key(u8 *digest,
>>   void digest_cache_free(struct digest_cache *digest_cache);
>>   struct digest_cache *digest_cache_get(struct dentry *dentry,
>>   				      struct integrity_iint_cache *iint);
>> +int digest_cache_init_htable(struct digest_cache *digest_cache,
>> +			     u64 num_digests);
>> +int digest_cache_add(struct digest_cache *digest_cache, u8 *digest);
>> +int digest_cache_lookup(struct digest_cache *digest_cache, u8 *digest,
>> +			enum hash_algo algo, const char *pathname);
>>   #else
>>   static inline void digest_cache_free(struct digest_cache *digest_cache)
>>   {
>> @@ -77,5 +82,24 @@ digest_cache_get(struct dentry *dentry, struct integrity_iint_cache *iint)
>>   	return NULL;
>>   }
>>   
>> +static inline int digest_cache_init_htable(struct digest_cache *digest_cache,
>> +					   u64 num_digests)
>> +{
>> +	return -EOPNOTSUPP;
>> +}
>> +
>> +static inline int digest_cache_add(struct digest_cache *digest_cache,
>> +				   u8 *digest)
>> +{
>> +	return -EOPNOTSUPP;
>> +}
>> +
>> +static inline int digest_cache_lookup(struct digest_cache *digest_cache,
>> +				      u8 *digest, enum hash_algo algo,
>> +				      const char *pathname)
>> +{
>> +	return -ENOENT;
>> +}
>> +
>>   #endif /* CONFIG_INTEGRITY_DIGEST_CACHE */
>>   #endif /* _DIGEST_CACHE_H */
>> -- 
>> 2.34.1
> 
> Why all this complexity instead of using xarray?
> 
> https://docs.kernel.org/core-api/xarray.html

Uhm, did I get correctly from the documentation that it isn't the 
optimal solution for hash tables?

Thanks

Roberto


  reply	other threads:[~2023-08-16  8:39 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-12 10:46 [RFC][PATCH v2 00/13] integrity: Introduce a digest cache Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 01/13] ima: Introduce hook DIGEST_LIST_CHECK Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 02/13] integrity: Introduce a digest cache Roberto Sassu
2023-08-14 17:03   ` Jarkko Sakkinen
2023-08-16  8:21     ` Roberto Sassu
2023-08-16 20:39       ` Jarkko Sakkinen
2023-08-12 10:46 ` [RFC][PATCH v2 03/13] integrity/digest_cache: Add functions to populate and search Roberto Sassu
2023-08-14 17:13   ` Jarkko Sakkinen
2023-08-16  8:35     ` Roberto Sassu [this message]
2023-08-16 21:00       ` Jarkko Sakkinen
2023-08-12 10:46 ` [RFC][PATCH v2 04/13] integrity/digest_cache: Prefetch digest lists in a directory Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 05/13] integrity/digest_cache: Parse tlv digest lists Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 06/13] integrity/digest_cache: Parse rpm " Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 07/13] ima: Add digest_cache policy keyword Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 08/13] ima: Use digest cache for measurement Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 09/13] ima: Use digest cache for appraisal Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 10/13] tools: Add tool to manage digest lists Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 11/13] tools/digest-lists: Add tlv digest list generator and parser Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 12/13] tools/digest-lists: Add rpm " Roberto Sassu
2023-08-12 10:46 ` [RFC][PATCH v2 13/13] docs: Add documentation of the integrity digest cache Roberto Sassu
2023-09-05 15:46 ` [RFC][PATCH v2 00/13] integrity: Introduce a " Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=98959e3d-7543-4a8e-9712-05a3ba04d2c8@huaweicloud.com \
    --to=roberto.sassu@huaweicloud.com \
    --cc=bpf@vger.kernel.org \
    --cc=corbet@lwn.net \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=hch@lst.de \
    --cc=jannh@google.com \
    --cc=jarkko@kernel.org \
    --cc=jmorris@namei.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mjg59@srcf.ucam.org \
    --cc=paul@paul-moore.com \
    --cc=pbrobinson@gmail.com \
    --cc=pmatilai@redhat.com \
    --cc=roberto.sassu@huawei.com \
    --cc=serge@hallyn.com \
    --cc=zbyszek@in.waw.pl \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).