From: Stefan Berger <stefanb@linux.ibm.com>
To: Mimi Zohar <zohar@linux.ibm.com>, linux-integrity@vger.kernel.org
Cc: serge@hallyn.com, christian.brauner@ubuntu.com,
containers@lists.linux.dev, dmitry.kasatkin@gmail.com,
ebiederm@xmission.com, krzysztof.struczynski@huawei.com,
roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com,
lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com,
jamjoom@us.ibm.com, linux-kernel@vger.kernel.org,
paul@paul-moore.com, rgb@redhat.com,
linux-security-module@vger.kernel.org, jmorris@namei.org,
Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
Subject: Re: [PATCH v10 18/27] integrity/ima: Define ns_status for storing namespaced iint data
Date: Wed, 23 Feb 2022 21:49:35 -0500 [thread overview]
Message-ID: <b7b0c6bf-225f-dbb8-7a80-4bc9f3e78a53@linux.ibm.com> (raw)
In-Reply-To: <92e1fc33-b97f-b99e-4f28-1d05a07c2f2f@linux.ibm.com>
On 2/23/22 21:21, Stefan Berger wrote:
>
> On 2/23/22 11:12, Mimi Zohar wrote:
>> On Tue, 2022-02-01 at 15:37 -0500, Stefan Berger wrote:
>>> From: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
>>>
>>> Add an rbtree to the IMA namespace structure that stores a namespaced
>>> version of iint->flags in ns_status struct. Similar to the
>>> integrity_iint_cache, both the iint and ns_status are looked up
>>> using the
>>> inode pointer value. The lookup, allocate, and insertion code is also
>>> similar.
>>>
>>> In subsequent patches we will have to find all ns_status entries an
>>> iint
>>> is being used in and reset flags there. To do this, connect a list of
>>> ns_status to the integrity_iint_cache and provide a reader-writer
>>> lock in the integrity_iint_cache to lock access to the list.
>>>
>>> To simplify the code in the non-namespaces case embed an ns_status in
>>> the integrity_iint_cache and have it linked into the iint's
>>> ns_status list
>>> when calling ima_get_ns_status().
>>>
>>> When getting an ns_status first try to find it in the RB tree. Here
>>> we can
>>> run into the situation that an ns_status found in the RB tree has a
>>> different iint associated with it for the same inode. In this case
>>> we need
>>> to delete the ns_status structure and get a new one.
>>>
>>> There are two cases for freeing:
>>> - when the iint is freed (inode deletion): Walk the list of ns_status
>>> entries and disconnect each ns_status from the list; take the
>>> writer lock to protect access to the list; also, take the item
>>> off the
>>> per-namespace rbtree
>>>
>>> - when the ima_namepace is freed: While walking the rbtree, remove the
>>> ns_status from the list while also holding the iint's writer lock;
>>> to be able to grab the lock we have to have a pointer to the iint on
>>> the ns_status structure.
>>>
>>> To avoid an ns_status to be freed by the two cases concurrently,
>>> prevent
>>> these two cases to run concurrently. Therefore, groups of threads
>>> deleting either inodes or ima_namespaces are allowed to run
>>> concurrently
>>> but no two threads may run and one delete an inode and the other an
>>> ima_namespace.
>> The locking involved here is really complex. I'm sure you thought
>> about it a lot, but isn't there a better alternative?
>
> I am afraid this is a difficult question and a short and concise
> answer is not possible...
>
> The complexity of the locking is driven by concurrency and the data
> structures that are involved. The data structures (existing global
> iint rbtree, ns_status structure, and per namespace rbtree for
> ns_status) and how they are organized and connected (via linked lists)
> are a consequence of the fact that we need to be able to handle files
> shared between IMA namespaces (and the host) so that re-auditing,
> re-measuring and re-appraisal of files after file modifications or
> modifications of the security.ima xattr (by any namespaces) can be
> done efficiently. Furthermore, it helps to efficiently remove all the
> status information that an IMA namespace has kept for files it
> audited/measured/appraised. The goal was to make this as scalable as
> possible by having each namespace get out of the way of other
> namespaces by preventing them from locking each other out too much.
> The single biggest problem are files shared between IMA namespaces.
>
> The best argument for the design I can come up with is the 'Big O
> notation' describing the time complexity of operations.
>
>
> The existing global iint rbtree maintains IMA status information for
> each inode. Lookup and insertion of data into the gloab iint rbtree
> is O(log(n)), thus optimal.
>
> To accommodate re-auditing/re-measurement/re-appraisal, which is
> driven by resetting status flags, I connected a list of ns_status
> structures, in which each namespace maintains its status information
> for each inode, to the iint maintained in that global rbtree. The
> resetting of status flags is fast because traversing the list after a
> lookup in the tree is O(n). Lookup + resetting the flags therefore is
> O(log(n) + n). If the list didn't exist we would have to search all
> IMA namespaces for the inode to be able to reset the flags, resulting
> in O(n * log(n)) time complexity, which is of course much worse. So,
> the list of ns_status linked to an iint has a good reason: better time
> complexity to traverse the list and reset status flags. Beside that
> it also supports fast handling of deletion of files where the iint has
> to be delete from the global rbtree and the ns_status list it holds
> must also be deleted (each ns_status also needs to be delete from a
> per IMA-namespace rbtree then)
>
>
> There's also a per-IMA namespace rbtree for each inode that serves two
> purposes:
>
> a) Fast lookup of ns_status (O(log(n)) for an IMA namespace; at least
> to insert an ns_status into this tree we need not write-lock the iint
> tree but the initial iint creation required the write-locking of the
> iint tree
>
> b) Maintaining a collection of inodes that the namespace has
> audited/measured/appraised for efficient deletion upon IMA namespace
> teardown: We can traverse this tree in O(n) time and determine which
> iints have no more namespace users and delete them from the iint tree.
>
>
> Now the dilemma with this is that an ns_status structure is connected
> to a list hanging off the iint and on top of this it is part of an
> rbtree. And this is where the 'group locking' is coming from. What we
> need to prevent is that an ns_status is deleted from its iint list
> (when a file is deleted) while it is also deleted from the per-IMA
> namespace rbtree (when the namespace is deleted). Both must not be
> done concurrently. What is possible is that a group of threads may
> tear down namespaces and the other group may act on file deletion, but
> threads from both groups must not run concurrently.
>
>
> Now we can at least look at two alternatives for the per-IMA namespace
> rbtree.
>
> 1) One alternative is to use a list instead of an rbtree. We would
> loose the fast lookup via the per IMA namespace tree and get O(n)
> lookup times but quick insertion into the list [O(1)]. We still would
> have the collection of inodes. And we would still have the dilemma
> that an ns_status would be connected to two lists, thus requiring the
> group locking. I don't think using a list instead of an rbtree is a
> solution.
>
> 2) We could try to get rid of the per-IMA namespace rbtree altogether
> and just use the global iint rbtree that exists today with a list of
> ns_status connected to its iints. If we do this we would loose the
> knowledge of which inodes a namespace has an ns_status structure for.
> The only way we would find this is by traversing the global iint tree
> (O(n)) and follow each iint list (O(m)) to see whether we find an
> ns_status holding information about the iint. The time complexity for
> this would be O(n*m) but much less than O(n^2). A downside would also
> be that we would have to keep a lock on the global iint rbtree while
> traversing it, thus locking out those that want to add inodes to the
> tree. On the upside it would allow us to get rid of the group locking.
> Lookup of an ns_status in the global iint tree would be O(n) + O(m)
> and insertion would be O(n) + O(1).
>
>
> Certainly, the alternative is 2) with its own trade-offs. My guess is
> some sort of yielding could probably also be helpful there then to
> avoid blocking higher priority operations than deleting of a namespace.
I forgot to mention: It makes a difference if one has to walk the global
iint tree to find the few ns_status for the namespace among possibly
thousands of entries in that tree than having a per-IMA namespace rbtree
that has these few ns_status right there. So walking the iint tree is
more like O(N) versus O(n) walking the per-IMA namespace rbtree.
next prev parent reply other threads:[~2022-02-24 2:50 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-01 20:37 [PATCH v10 00/27] ima: Namespace IMA with audit support in IMA-ns Stefan Berger
2022-02-01 20:37 ` [PATCH v10 01/27] ima: Remove ima_policy file before directory Stefan Berger
2022-02-10 12:02 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 02/27] ima: Do not print policy rule with inactive LSM labels Stefan Berger
2022-02-02 14:17 ` Christian Brauner
2022-02-01 20:37 ` [PATCH v10 03/27] ima: Return error code obtained from securityfs functions Stefan Berger
2022-02-10 12:02 ` Mimi Zohar
2022-02-15 18:09 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 04/27] securityfs: rework dentry creation Stefan Berger
2022-02-10 12:03 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 05/27] ima: Define ima_namespace struct and start moving variables into it Stefan Berger
2022-02-16 14:41 ` Mimi Zohar
2022-02-16 20:25 ` Stefan Berger
2022-02-01 20:37 ` [PATCH v10 06/27] ima: Move arch_policy_entry into ima_namespace Stefan Berger
2022-02-16 16:39 ` Mimi Zohar
2022-02-16 20:48 ` Stefan Berger
2022-02-16 20:56 ` Mimi Zohar
2022-02-16 21:19 ` Stefan Berger
2022-02-01 20:37 ` [PATCH v10 07/27] ima: Move ima_htable " Stefan Berger
2022-02-16 14:41 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 08/27] ima: Move measurement list related variables " Stefan Berger
2022-02-17 14:46 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 09/27] ima: Move some IMA policy and filesystem " Stefan Berger
2022-02-17 14:44 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 10/27] ima: Move IMA securityfs files into ima_namespace or onto stack Stefan Berger
2022-02-17 14:44 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 11/27] ima: Move ima_lsm_policy_notifier into ima_namespace Stefan Berger
2022-02-17 20:30 ` Mimi Zohar
2022-02-17 20:59 ` Stefan Berger
2022-02-17 21:24 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 12/27] ima: Define mac_admin_ns_capable() as a wrapper for ns_capable() Stefan Berger
2022-02-05 5:58 ` Serge E. Hallyn
2022-02-06 17:20 ` Stefan Berger
2022-02-07 18:43 ` Stefan Berger
2022-02-23 17:51 ` Serge E. Hallyn
2022-02-01 20:37 ` [PATCH v10 13/27] ima: Only accept AUDIT rules for non-init_ima_ns namespaces for now Stefan Berger
2022-02-17 21:32 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 14/27] userns: Add pointer to ima_namespace to user_namespace Stefan Berger
2022-02-18 16:26 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 15/27] ima: Implement hierarchical processing of file accesses Stefan Berger
2022-02-18 16:27 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 16/27] ima: Implement ima_free_policy_rules() for freeing of an ima_namespace Stefan Berger
2022-02-18 17:09 ` Mimi Zohar
2022-02-18 19:38 ` Stefan Berger
2022-02-18 20:04 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 17/27] ima: Add functions for creating and " Stefan Berger
2022-02-18 19:49 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 18/27] integrity/ima: Define ns_status for storing namespaced iint data Stefan Berger
2022-02-23 16:12 ` Mimi Zohar
2022-02-24 2:21 ` Stefan Berger
2022-02-24 2:49 ` Stefan Berger [this message]
2022-02-01 20:37 ` [PATCH v10 19/27] integrity: Add optional callback function to integrity_inode_free() Stefan Berger
2022-02-01 20:37 ` [PATCH v10 20/27] ima: Namespace audit status flags Stefan Berger
2022-02-01 20:37 ` [PATCH v10 21/27] ima: Remove unused iints from the integrity_iint_cache Stefan Berger
2022-02-01 20:37 ` [PATCH v10 22/27] securityfs: Extend securityfs with namespacing support Stefan Berger
2022-02-23 1:48 ` Mimi Zohar
2022-02-23 8:14 ` Christian Brauner
2022-02-23 15:44 ` Stefan Berger
2022-02-01 20:37 ` [PATCH v10 23/27] ima: Setup securityfs for IMA namespace Stefan Berger
2022-02-23 11:45 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 24/27] ima: Introduce securityfs file to activate an " Stefan Berger
2022-02-23 13:54 ` Mimi Zohar
2022-02-23 17:08 ` Stefan Berger
2022-02-23 17:12 ` Mimi Zohar
2022-02-23 22:30 ` Stefan Berger
2022-02-01 20:37 ` [PATCH v10 25/27] ima: Show owning user namespace's uid and gid when displaying policy Stefan Berger
2022-02-23 14:06 ` Mimi Zohar
2022-02-01 20:37 ` [PATCH v10 26/27] ima: Limit number of policy rules in non-init_ima_ns Stefan Berger
2022-02-23 15:38 ` Mimi Zohar
2022-02-23 16:37 ` Stefan Berger
2022-02-23 17:04 ` Mimi Zohar
2022-02-23 20:45 ` Stefan Berger
2022-02-23 20:59 ` Mimi Zohar
2022-02-23 21:06 ` Stefan Berger
2022-02-01 20:37 ` [PATCH v10 27/27] ima: Enable IMA namespaces Stefan Berger
2022-02-23 17:58 ` Serge E. Hallyn
2022-02-23 20:53 ` Stefan Berger
2022-02-02 14:13 ` [PATCH v10 00/27] ima: Namespace IMA with audit support in IMA-ns Christian Brauner
2022-02-02 14:40 ` Stefan Berger
2022-02-02 16:04 ` Mimi Zohar
2022-02-02 18:18 ` Stefan Berger
2022-02-02 21:27 ` Stefan Berger
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=b7b0c6bf-225f-dbb8-7a80-4bc9f3e78a53@linux.ibm.com \
--to=stefanb@linux.ibm.com \
--cc=christian.brauner@ubuntu.com \
--cc=containers@lists.linux.dev \
--cc=dmitry.kasatkin@gmail.com \
--cc=ebiederm@xmission.com \
--cc=jamjoom@us.ibm.com \
--cc=jejb@linux.ibm.com \
--cc=jmorris@namei.org \
--cc=krzysztof.struczynski@huawei.com \
--cc=lhinds@redhat.com \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=lsturman@redhat.com \
--cc=mkayaalp@linux.vnet.ibm.com \
--cc=mpeters@redhat.com \
--cc=paul@paul-moore.com \
--cc=puiterwi@redhat.com \
--cc=rgb@redhat.com \
--cc=roberto.sassu@huawei.com \
--cc=serge@hallyn.com \
--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).