* [PATCH v3 1/9] KEYS: Defined an IMA hook to measure keys on key create or update
From: Lakshmi Ramasubramanian @ 2019-10-31 1:19 UTC (permalink / raw)
To: zohar, dhowells, matthewgarrett, sashal, jamorris, linux-kernel,
linux-integrity, linux-security-module, keyrings
Cc: prsriva
In-Reply-To: <20191031011910.2574-1-nramas@linux.microsoft.com>
Asymmetric keys used for verifying file signatures or certificates
are currently not included in the IMA measurement list.
This patch defines a new IMA hook namely ima_post_key_create_or_update()
to measure asymmetric keys.
Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
security/integrity/ima/ima.h | 2 ++
security/integrity/ima/ima_main.c | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 997a57137351..22d0628faf56 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -21,6 +21,8 @@
#include <linux/tpm.h>
#include <linux/audit.h>
#include <crypto/hash_info.h>
+#include <crypto/public_key.h>
+#include <keys/asymmetric-type.h>
#include "../integrity.h"
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 492b8f241d39..18e1bc105be7 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -635,6 +635,9 @@ void process_buffer_measurement(const void *buf, int size,
int action = 0;
u32 secid;
+ if (!ima_policy_flag)
+ return;
+
if (func) {
security_task_getsecid(current, &secid);
action = ima_get_action(NULL, current_cred(), secid, 0, func,
@@ -695,6 +698,29 @@ void ima_kexec_cmdline(const void *buf, int size)
}
}
+/**
+ * ima_post_key_create_or_update - measure asymmetric keys
+ * @keyring: keyring to which the key is linked to
+ * @key: created or updated key
+ * @flags: key flags
+ * @create: flag indicating whether the key was created or updated
+ *
+ * Keys can only be measured, not appraised.
+ */
+void ima_post_key_create_or_update(struct key *keyring, struct key *key,
+ unsigned long flags, bool create)
+{
+ const struct public_key *pk;
+
+ if (key->type != &key_type_asymmetric)
+ return;
+
+ pk = key->payload.data[asym_crypto];
+ process_buffer_measurement(pk->key, pk->keylen,
+ keyring->description,
+ NONE, 0);
+}
+
static int __init init_ima(void)
{
int error;
--
2.17.1
^ permalink raw reply related
* Re: [PATCH linux-kselftest/test v1] apparmor: add AppArmor KUnit tests for policy unpack
From: John Johansen @ 2019-10-31 1:37 UTC (permalink / raw)
To: Kees Cook, Luis Chamberlain
Cc: Brendan Higgins, Alan Maguire, Matthias Maennich, shuah, jmorris,
serge, Iurii Zaikin, David Gow, Theodore Ts'o,
Linux Kernel Mailing List, linux-security-module,
KUnit Development, open list:KERNEL SELFTEST FRAMEWORK,
Mike Salvatore
In-Reply-To: <201910301205.74EC2A226D@keescook>
On 10/30/19 12:09 PM, Kees Cook wrote:
> On Thu, Oct 24, 2019 at 10:15:29AM +0000, Luis Chamberlain wrote:
>> On Wed, Oct 23, 2019 at 05:42:18PM -0700, Brendan Higgins wrote:
>>> With that, I think the best solution in this case will be the
>>> "__visible_for_testing" route. It has no overhead when testing is
>>> turned off (in fact it is no different in anyway when testing is
>>> turned off). The downsides I see are:
>>>
>>> 1) You may not be able to test non-module code not compiled for
>>> testing later with the test modules that Alan is working on (But the
>>> only way I think that will work is by preventing the symbol from being
>>> inlined, right?).
>>>
>>> 2) I think "__visible_for_testing" will be prone to abuse. Here, I
>>> think there are reasons why we might want to expose these symbols for
>>> testing, but not otherwise. Nevertheless, I think most symbols that
>>> should be tested should probably be made visible by default. Since you
>>> usually only want to test your public interfaces. I could very well
>>> see this getting used as a kludge that gets used far too frequently.
>>
>> There are two parts to your statement on 2):
>>
>> a) possible abuse of say __visible_for_testing
>
> I really don't like the idea of littering the kernel with these. It'll
> also require chunks in header files wrapped in #ifdefs. This is really
> ugly.
>
>> b) you typically only want to test your public interfaces
>
I would disagree with this. Helper/lib functions benefit from testing,
and ensuring they work as expected. Having tests on these helps catch
errors when you fix bugs or make improvements. If you want its indirect
testing of public interfaces.
> True, but being able to test the little helper functions is a nice
> starting point and a good building block.
>
yeah its a nice building block
> Why can't unit tests live with the code they're testing? They're already
> logically tied together; what's the harm there? This needn't be the case
> for ALL tests, etc. The test driver could still live externally. The
> test in the other .c would just have exported functions... ?
>
they can, its my preference too. Or if the tests must live separate I
don't even mind the abomination of including a test .c that contains
the tests for the private fns only.
In the end though, I just want to see more unit testing and will happily
take what ever the community decides is the way to go.
^ permalink raw reply
* Re: [PATCH linux-kselftest/test v1] apparmor: add AppArmor KUnit tests for policy unpack
From: John Johansen @ 2019-10-31 1:40 UTC (permalink / raw)
To: Iurii Zaikin, Kees Cook
Cc: Luis Chamberlain, Brendan Higgins, Alan Maguire,
Matthias Maennich, shuah, jmorris, serge, David Gow,
Theodore Ts'o, Linux Kernel Mailing List,
linux-security-module, KUnit Development,
open list:KERNEL SELFTEST FRAMEWORK, Mike Salvatore
In-Reply-To: <CAAXuY3o31iCJwZ+WGHMaK1MgpC0qv=JkJWnzv8Lhym9TnZQvcQ@mail.gmail.com>
On 10/30/19 1:11 PM, Iurii Zaikin wrote:
>> Why can't unit tests live with the code they're testing? They're already
>> logically tied together; what's the harm there? This needn't be the case
>> for ALL tests, etc. The test driver could still live externally. The
>> test in the other .c would just have exported functions... ?
>>
> Curiously enough, this approach has been adopted by D 2.0 where unittests are
> members of the class under test: https://digitalmars.com/d/2.0/unittest.html
> but such approach is not mainstream.
> I personally like the idea of testing the lowest level bits in isolation even if
> they are not a part of any interface. I think that specifying the
> interface using
> unit tests and ensuring implementation correctness are complementary but
fwiw this is my preferred approach as well
> I haven't had much luck arguing this with our esteemed colleagues.
>
surprise, surprise /s
^ permalink raw reply
* Re: [PATCH linux-kselftest/test v1] apparmor: add AppArmor KUnit tests for policy unpack
From: Brendan Higgins @ 2019-10-31 9:01 UTC (permalink / raw)
To: Kees Cook
Cc: Theodore Y. Ts'o, shuah, John Johansen, jmorris, serge,
Alan Maguire, Iurii Zaikin, David Gow, Luis Chamberlain,
Linux Kernel Mailing List, linux-security-module,
KUnit Development, open list:KERNEL SELFTEST FRAMEWORK,
Mike Salvatore
In-Reply-To: <201910301201.404F0E3BB@keescook>
On Wed, Oct 30, 2019 at 12:02 PM Kees Cook <keescook@chromium.org> wrote:
>
> On Fri, Oct 18, 2019 at 02:41:38PM -0700, Brendan Higgins wrote:
> > On Fri, Oct 18, 2019 at 9:25 AM Theodore Y. Ts'o <tytso@mit.edu> wrote:
> > >
> > > On Thu, Oct 17, 2019 at 05:43:07PM -0700, Brendan Higgins wrote:
> > > > > +config SECURITY_APPARMOR_TEST
> > > > > + bool "Build KUnit tests for policy_unpack.c"
> > > > > + default n
> > > > > + depends on KUNIT && SECURITY_APPARMOR
> > > >
> > > > Ted, here is an example where doing select on direct dependencies is
> > > > tricky because SECURITY_APPARMOR has a number of indirect dependencies.
> > >
> > > Well, that could be solved by adding a select on all of the indirect
> > > dependencies. I did get your point about the fact that we could have
> >
> > In this particular case that would work.
> >
> > > cases where the indirect dependencies might conflict with one another.
> > > That's going to be a tough situation regardless of whether we have a
> > > sat-solver or a human who has to struggle with that situation.
> >
> > But yeah, that's the real problem.
>
> I think at this stage we want to make it _possible_ to write tests
> sanely without causing all kinds of headaches. I think "build all the
> tests" can just be a function of "allmodconfig" and leave it at that
> until we have cases we really need to deal with.
That...appears to work. I really can't see any reason why that isn't
good enough for now.
I am surprised that this hasn't been suggested yet.
Thanks!
^ permalink raw reply
* Re: [PATCH v3 1/9] KEYS: Defined an IMA hook to measure keys on key create or update
From: Sasha Levin @ 2019-10-31 9:10 UTC (permalink / raw)
To: Lakshmi Ramasubramanian
Cc: zohar, dhowells, matthewgarrett, jamorris, linux-kernel,
linux-integrity, linux-security-module, keyrings, prsriva
In-Reply-To: <20191031011910.2574-2-nramas@linux.microsoft.com>
On Wed, Oct 30, 2019 at 06:19:02PM -0700, Lakshmi Ramasubramanian wrote:
>Asymmetric keys used for verifying file signatures or certificates
>are currently not included in the IMA measurement list.
>
>This patch defines a new IMA hook namely ima_post_key_create_or_update()
>to measure asymmetric keys.
>
>Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
What are the prerequisites for this patch?
--
Thanks,
Sasha
^ permalink raw reply
* Re: [PATCH linux-kselftest/test v1] apparmor: add AppArmor KUnit tests for policy unpack
From: Brendan Higgins @ 2019-10-31 9:17 UTC (permalink / raw)
To: Kees Cook
Cc: Luis Chamberlain, Alan Maguire, Matthias Maennich, shuah,
John Johansen, jmorris, serge, Iurii Zaikin, David Gow,
Theodore Ts'o, Linux Kernel Mailing List,
linux-security-module, KUnit Development,
open list:KERNEL SELFTEST FRAMEWORK, Mike Salvatore
In-Reply-To: <201910301205.74EC2A226D@keescook>
On Wed, Oct 30, 2019 at 12:09 PM Kees Cook <keescook@chromium.org> wrote:
>
> On Thu, Oct 24, 2019 at 10:15:29AM +0000, Luis Chamberlain wrote:
> > On Wed, Oct 23, 2019 at 05:42:18PM -0700, Brendan Higgins wrote:
> > > With that, I think the best solution in this case will be the
> > > "__visible_for_testing" route. It has no overhead when testing is
> > > turned off (in fact it is no different in anyway when testing is
> > > turned off). The downsides I see are:
> > >
> > > 1) You may not be able to test non-module code not compiled for
> > > testing later with the test modules that Alan is working on (But the
> > > only way I think that will work is by preventing the symbol from being
> > > inlined, right?).
> > >
> > > 2) I think "__visible_for_testing" will be prone to abuse. Here, I
> > > think there are reasons why we might want to expose these symbols for
> > > testing, but not otherwise. Nevertheless, I think most symbols that
> > > should be tested should probably be made visible by default. Since you
> > > usually only want to test your public interfaces. I could very well
> > > see this getting used as a kludge that gets used far too frequently.
> >
> > There are two parts to your statement on 2):
> >
> > a) possible abuse of say __visible_for_testing
>
> I really don't like the idea of littering the kernel with these. It'll
Yeah, I kind of hope that it would make people think more
intentionally about what is a public interface so that they wouldn't
litter the kernel with those. But I agree that in the world where
people *didn't* do that. Lots of these sprinkled around would be
annoying.
> also require chunks in header files wrapped in #ifdefs. This is really
Why would it require header files wrapped in #ifdefs?
We could put all the ifdeffery logic in the __visible_for_testing
macro so that nothing in the original code has to change except for
adding an #include and replacing a couple of `static`s with
`__visible_for_testing`.
> ugly.
>
> > b) you typically only want to test your public interfaces
>
> True, but being able to test the little helper functions is a nice
> starting point and a good building block.
Yeah, I think I have come to accept that. We can argue about how this
should change and how people need to learn to be more intentional
about which interfaces are public and many other high minded ideas,
but when it comes down to it, we need to provide a starting point that
is easy.
If our nice starting point becomes a problem, we can always improve it later.
> Why can't unit tests live with the code they're testing? They're already
> logically tied together; what's the harm there? This needn't be the case
> for ALL tests, etc. The test driver could still live externally. The
> test in the other .c would just have exported functions... ?
Well, for one, it totally tanks certain cases for building KUnit tests
as modules. I don't care about this point *too* much personally, but I
accept that there are others that want this, and I don't want to make
these people's lives too difficult.
The main reason I care, however, is just that I think it looks bad to
me. The file that these tests were in was already pretty long, and the
tests made it even longer. So that makes the tests harder to find. If
all tests are in a *-test.c file, then it becomes really easy to find
all of your tests. Admittedly, this is a pretty minor point. Honestly,
the main reason it looks bad to me, is because it is different from
what I am used to, which, I know, is not a great reason.
^ permalink raw reply
* Re: [PATCH linux-kselftest/test v1] apparmor: add AppArmor KUnit tests for policy unpack
From: Brendan Higgins @ 2019-10-31 9:33 UTC (permalink / raw)
To: Iurii Zaikin
Cc: Kees Cook, Luis Chamberlain, Alan Maguire, Matthias Maennich,
shuah, John Johansen, jmorris, serge, David Gow,
Theodore Ts'o, Linux Kernel Mailing List,
linux-security-module, KUnit Development,
open list:KERNEL SELFTEST FRAMEWORK, Mike Salvatore
In-Reply-To: <CAAXuY3o31iCJwZ+WGHMaK1MgpC0qv=JkJWnzv8Lhym9TnZQvcQ@mail.gmail.com>
On Wed, Oct 30, 2019 at 1:12 PM Iurii Zaikin <yzaikin@google.com> wrote:
>
> > Why can't unit tests live with the code they're testing? They're already
> > logically tied together; what's the harm there? This needn't be the case
> > for ALL tests, etc. The test driver could still live externally. The
> > test in the other .c would just have exported functions... ?
> >
> Curiously enough, this approach has been adopted by D 2.0 where unittests are
> members of the class under test: https://digitalmars.com/d/2.0/unittest.html
Thanks for pointing this out, Iurii, that actually looks pretty cool.
I still personally prefer keeping tests and code separate, but if we
decide to go the route of mixing tests and code, maybe we might want
to use this as a model.
> but such approach is not mainstream.
> I personally like the idea of testing the lowest level bits in isolation even if
> they are not a part of any interface. I think that specifying the
> interface using
> unit tests and ensuring implementation correctness are complementary but
> I haven't had much luck arguing this with our esteemed colleagues.
So I think this is a very subtle point which is very widely
misunderstood. Most people write code and then write their tests,
following this practice along with only testing public interfaces
often causes people to just not test all of their code, which is
wrong.
The idea of only testing public interfaces is supposed to make people
think more carefully about what the composite layers of the program
is. If you are having difficulty getting decent coverage by only
testing your public interfaces, then it likely tells you that you have
one of two problems:
1) You have code that you don't need, and you should remove it.
2) One of the layers in your program is too think, and you should
introduce a new layer with a new public interface that you can test
through.
I think the second point here is problematic with how C is written in
the kernel. We don't really have any concept of public vs. private
inside the kernel outside of static vs. not static, which is much more
restricted.
^ permalink raw reply
* [tip: core/rcu] security/safesetid: Replace rcu_swap_protected() with rcu_replace_pointer()
From: tip-bot2 for Paul E. McKenney @ 2019-10-31 11:54 UTC (permalink / raw)
To: linux-tip-commits
Cc: Linus Torvalds, Reported-by: kbuild test robot, Paul E. McKenney,
Micah Morton, James Morris, Serge E. Hallyn,
linux-security-module, Ingo Molnar, Borislav Petkov, linux-kernel
The following commit has been merged into the core/rcu branch of tip:
Commit-ID: a60a5746004d7dbb68cbccd4c16d0529e2b2d1d9
Gitweb: https://git.kernel.org/tip/a60a5746004d7dbb68cbccd4c16d0529e2b2d1d9
Author: Paul E. McKenney <paulmck@kernel.org>
AuthorDate: Fri, 04 Oct 2019 15:07:09 -07:00
Committer: Paul E. McKenney <paulmck@kernel.org>
CommitterDate: Wed, 30 Oct 2019 08:45:57 -07:00
security/safesetid: Replace rcu_swap_protected() with rcu_replace_pointer()
This commit replaces the use of rcu_swap_protected() with the more
intuitively appealing rcu_replace_pointer() as a step towards removing
rcu_swap_protected().
Link: https://lore.kernel.org/lkml/CAHk-=wiAsJLw1egFEE=Z7-GGtM6wcvtyytXZA1+BHqta4gg6Hw@mail.gmail.com/
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: Reported-by: kbuild test robot <lkp@intel.com>
[ paulmck: From rcu_replace() to rcu_replace_pointer() per Ingo Molnar. ]
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Micah Morton <mortonm@chromium.org>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: <linux-security-module@vger.kernel.org>
---
security/safesetid/securityfs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/security/safesetid/securityfs.c b/security/safesetid/securityfs.c
index 74a13d4..f8bc574 100644
--- a/security/safesetid/securityfs.c
+++ b/security/safesetid/securityfs.c
@@ -179,8 +179,8 @@ out_free_rule:
* doesn't currently exist, just use a spinlock for now.
*/
mutex_lock(&policy_update_lock);
- rcu_swap_protected(safesetid_setuid_rules, pol,
- lockdep_is_held(&policy_update_lock));
+ pol = rcu_replace_pointer(safesetid_setuid_rules, pol,
+ lockdep_is_held(&policy_update_lock));
mutex_unlock(&policy_update_lock);
err = len;
^ permalink raw reply related
* Re: [PATCH v3 1/9] KEYS: Defined an IMA hook to measure keys on key create or update
From: Mimi Zohar @ 2019-10-31 12:10 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, dhowells, matthewgarrett, sashal,
jamorris, linux-kernel, linux-integrity, linux-security-module,
keyrings
Cc: prsriva
In-Reply-To: <20191031011910.2574-2-nramas@linux.microsoft.com>
On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
> Asymmetric keys used for verifying file signatures or certificates
> are currently not included in the IMA measurement list.
>
> This patch defines a new IMA hook namely ima_post_key_create_or_update()
> to measure asymmetric keys.
It's not enough for the kernel to be able to compile the kernel after
applying all the patches in a patch set. After applying each patch,
the kernel should build properly, otherwise it is not bi-sect safe.
Refer to "3) Separate your changes" of
"Documentation/process/submitting-patches.rst.
>
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> ---
> security/integrity/ima/ima.h | 2 ++
> security/integrity/ima/ima_main.c | 26 ++++++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 997a57137351..22d0628faf56 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -21,6 +21,8 @@
> #include <linux/tpm.h>
> #include <linux/audit.h>
> #include <crypto/hash_info.h>
> +#include <crypto/public_key.h>
> +#include <keys/asymmetric-type.h>
>
> #include "../integrity.h"
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 492b8f241d39..18e1bc105be7 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -635,6 +635,9 @@ void process_buffer_measurement(const void *buf, int size,
> int action = 0;
> u32 secid;
>
> + if (!ima_policy_flag)
> + return;
> +
> if (func) {
> security_task_getsecid(current, &secid);
> action = ima_get_action(NULL, current_cred(), secid, 0, func,
> @@ -695,6 +698,29 @@ void ima_kexec_cmdline(const void *buf, int size)
> }
> }
>
> +/**
> + * ima_post_key_create_or_update - measure asymmetric keys
> + * @keyring: keyring to which the key is linked to
> + * @key: created or updated key
> + * @flags: key flags
> + * @create: flag indicating whether the key was created or updated
> + *
> + * Keys can only be measured, not appraised.
> + */
> +void ima_post_key_create_or_update(struct key *keyring, struct key *key,
> + unsigned long flags, bool create)
> +{
> + const struct public_key *pk;
> +
> + if (key->type != &key_type_asymmetric)
> + return;
> +
> + pk = key->payload.data[asym_crypto];
> + process_buffer_measurement(pk->key, pk->keylen,
> + keyring->description,
> + NONE, 0);
This patch should also define the new "func".
Mimi
> +}
> +
> static int __init init_ima(void)
> {
> int error;
^ permalink raw reply
* Re: [PATCH v3 2/9] KEYS: Defined functions to queue and dequeue keys for measurement
From: Mimi Zohar @ 2019-10-31 12:10 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, dhowells, matthewgarrett, sashal,
jamorris, linux-kernel, linux-integrity, linux-security-module,
keyrings
Cc: prsriva
In-Reply-To: <20191031011910.2574-3-nramas@linux.microsoft.com>
On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
> Key measurements cannot be done if the IMA hook to measure keys is
> called before IMA is initialized. Key measurement needs to be deferred
> if IMA is not yet initialized. Queued keys need to be processed when
> IMA initialization is completed.
>
> This patch defines functions to queue and de-queue keys for measurement.
I would defer this patch until later in the patch set, after having
the basic measuring of keys in place.
Mimi
^ permalink raw reply
* Re: [PATCH v3 4/9] KEYS: Updated IMA policy functions for handling key measurement
From: Mimi Zohar @ 2019-10-31 12:10 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, dhowells, matthewgarrett, sashal,
jamorris, linux-kernel, linux-integrity, linux-security-module,
keyrings
Cc: prsriva
In-Reply-To: <20191031011910.2574-5-nramas@linux.microsoft.com>
This patch adds support for "keyring=". The patch title should
reflect it.
On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
> Information regarding what keyrings need to be measured is missing.
>
> A new field in the IMA policy, namely, keyrings is added to
> convey what keyrings need to be measured.
>
> This patch updates the IMA function to retrieve keyrings from the policy.
Defining a new policy option should be separate from modifying
functions.
Mimi
^ permalink raw reply
* Re: [PATCH v3 3/9] KEYS: Added KEYRING_CHECK policy for key measurement
From: Mimi Zohar @ 2019-10-31 12:10 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, dhowells, matthewgarrett, sashal,
jamorris, linux-kernel, linux-integrity, linux-security-module,
keyrings
Cc: prsriva
In-Reply-To: <20191031011910.2574-4-nramas@linux.microsoft.com>
On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
> An IMA policy to manage measurement of keys is not supported.
> A new IMA policy is needed to manage the measurement of keys.
> A policy option is also needed to allow measurement of keys
> linked to a given set of keyrings only.
>
> This patch defines KEYRING_CHECK and keyrings in IMA policy
> for this purpose.
"KEYRING_CHECK" and "keyrings" are not related. One is a "func"
name, while the other is an IMA policy option. This should be broken
up into two different patches. When defining a new policy option, the
only code in that patch should be the new policy option.
>
> KEYRING_CHECK can be added in the IMA policy to measure keys.
> keyrings can be, optionally, set to only measure keys
> added or updated to a given set of keyrings. If keyrings is not
> specified for KEYRING_CHECK, keys added or updated in
> all keyrings are measured.
>
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> ---
> Documentation/ABI/testing/ima_policy | 15 +++++++++++++++
> security/integrity/ima/ima.h | 1 +
> security/integrity/ima/ima_main.c | 2 +-
> security/integrity/ima/ima_policy.c | 2 +-
> security/integrity/ima/ima_queue.c | 2 +-
> 5 files changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> index fc376a323908..757faf1a1a27 100644
> --- a/Documentation/ABI/testing/ima_policy
> +++ b/Documentation/ABI/testing/ima_policy
> @@ -25,10 +25,12 @@ Description:
> lsm: [[subj_user=] [subj_role=] [subj_type=]
> [obj_user=] [obj_role=] [obj_type=]]
> option: [[appraise_type=]] [template=] [permit_directio]
> + [keyrings=]
> base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
> [FIRMWARE_CHECK]
> [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
> [KEXEC_CMDLINE]
> + [KEYRING_CHECK]
This patch is measuring keys, not keyrings.
> mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
> [[^]MAY_EXEC]
> fsmagic:= hex value
> @@ -38,6 +40,9 @@ Description:
> fowner:= decimal value
> lsm: are LSM specific
> option: appraise_type:= [imasig]
> + keyrings: = list of keyrings to measure
> + (eg, .builtin_trusted_keys|.ima). Only valid
> + when action is "measure" and func is KEYRING_CHECK.
> template:= name of a defined IMA template type
> (eg, ima-ng). Only valid when action is "measure".
> pcr:= decimal value
> @@ -105,3 +110,13 @@ Description:
>
> measure func=KEXEC_KERNEL_CHECK pcr=4
> measure func=KEXEC_INITRAMFS_CHECK pcr=5
> +
> + Example of measure rules using KEYRING_CHECK
> + To measure keys added to
> + .builtin_trusted_keys or .ima keyring:
> +
> + measure func=KEYRING_CHECK keyrings=.builtin_trusted_keys|.ima
> +
> + To measure keys added to all keyrings:
> +
> + measure func=KEYRING_CHECK
The patch that introduces the new IMA "func" should document the new
IMA "func". The patch that introduces the new "keyring=" policy
option should document the new IMA policy option. Examples could be
included in each of the patches descriptions.
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index b9600070e415..12e9ec6847b5 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -191,6 +191,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
> hook(KEXEC_INITRAMFS_CHECK) \
> hook(POLICY_CHECK) \
> hook(KEXEC_CMDLINE) \
> + hook(KEYRING_CHECK) \
> hook(MAX_CHECK)
> #define __ima_hook_enumify(ENUM) ENUM,
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 18e1bc105be7..72ae0878ec5d 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -718,7 +718,7 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
> pk = key->payload.data[asym_crypto];
> process_buffer_measurement(pk->key, pk->keylen,
> keyring->description,
> - NONE, 0);
> + KEYRING_CHECK, 0);
> }
>
> static int __init init_ima(void)
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 6df7f641ff66..0cc49f2d5233 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -370,7 +370,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
> {
> int i;
>
> - if (func == KEXEC_CMDLINE) {
> + if ((func == KEXEC_CMDLINE) || (func == KEYRING_CHECK)) {
> if ((rule->flags & IMA_FUNC) && (rule->func == func))
> return true;
> return false;
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index f2503f10abf4..5625381c5a97 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -317,7 +317,7 @@ void ima_measure_queued_keys(void)
> process_buffer_measurement(entry->public_key,
> entry->public_key_len,
> entry->keyring_name,
> - NONE, 0);
> + KEYRING_CHECK, 0);
Changing a newly defined call should be an indication that the patch
ordering is wrong. If the new "func" was defined prior or with the
new IMA hook, then this change wouldn't be needed.
Mimi
> list_del(&entry->list);
> ima_free_measure_key_entry(entry);
> }
^ permalink raw reply
* [Patch v3 0/7] Introduce TEE based Trusted Keys support
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
Add support for TEE based trusted keys where TEE provides the functionality
to seal and unseal trusted keys using hardware unique key. Also, this is
an alternative in case platform doesn't possess a TPM device.
This series also adds some TEE features like:
Patch #1, #2 enables support for registered kernel shared memory with TEE.
Patch #3 enables support for private kernel login method required for
cases like trusted keys where we don't wan't user-space to directly access
TEE service to retrieve trusted key contents.
Rest of the patches from #4 to #7 adds support for TEE based trusted keys.
This patch-set has been tested with OP-TEE based pseudo TA which can be
found here [1].
[1] https://github.com/OP-TEE/optee_os/pull/3082
Changes in v3:
1. Update patch #2 to support registration of multiple kernel pages.
2. Incoporate dependency patch #4 in this patch-set:
https://patchwork.kernel.org/patch/11091435/
3. Rebased to latest tpmdd-master.
Changes in v2:
1. Add reviewed-by tags for patch #1 and #2.
2. Incorporate comments from Jens for patch #3.
3. Switch to use generic trusted keys framework.
Sumit Garg (7):
tee: optee: allow kernel pages to register as shm
tee: enable support to register kernel memory
tee: add private login method for kernel clients
KEYS: trusted: Add generic trusted keys framework
KEYS: trusted: Introduce TEE based Trusted Keys
doc: keys: Document usage of TEE based Trusted Keys
MAINTAINERS: Add entry for TEE based Trusted Keys
Documentation/security/keys/index.rst | 1 +
Documentation/security/keys/tee-trusted.rst | 93 ++++++++
MAINTAINERS | 9 +
drivers/tee/optee/call.c | 7 +
drivers/tee/tee_core.c | 6 +
drivers/tee/tee_shm.c | 26 ++-
include/keys/trusted-type.h | 48 ++++
include/keys/trusted_tee.h | 66 ++++++
include/keys/trusted_tpm.h | 15 --
include/linux/tee_drv.h | 1 +
include/uapi/linux/tee.h | 8 +
security/keys/Kconfig | 3 +
security/keys/trusted-keys/Makefile | 2 +
security/keys/trusted-keys/trusted_common.c | 346 ++++++++++++++++++++++++++++
security/keys/trusted-keys/trusted_tee.c | 282 +++++++++++++++++++++++
security/keys/trusted-keys/trusted_tpm1.c | 345 +++++----------------------
16 files changed, 954 insertions(+), 304 deletions(-)
create mode 100644 Documentation/security/keys/tee-trusted.rst
create mode 100644 include/keys/trusted_tee.h
create mode 100644 security/keys/trusted-keys/trusted_common.c
create mode 100644 security/keys/trusted-keys/trusted_tee.c
--
2.7.4
^ permalink raw reply
* [Patch v3 1/7] tee: optee: allow kernel pages to register as shm
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Kernel pages are marked as normal type memory only so allow kernel pages
to be registered as shared memory with OP-TEE.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
---
drivers/tee/optee/call.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index 13b0269..cf2367b 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -554,6 +554,13 @@ static int check_mem_type(unsigned long start, size_t num_pages)
struct mm_struct *mm = current->mm;
int rc;
+ /*
+ * Allow kernel address to register with OP-TEE as kernel
+ * pages are configured as normal memory only.
+ */
+ if (virt_addr_valid(start))
+ return 0;
+
down_read(&mm->mmap_sem);
rc = __check_mem_type(find_vma(mm, start),
start + num_pages * PAGE_SIZE);
--
2.7.4
^ permalink raw reply related
* [Patch v3 2/7] tee: enable support to register kernel memory
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Enable support to register kernel memory reference with TEE. This change
will allow TEE bus drivers to register memory references.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/tee/tee_shm.c | 26 ++++++++++++++++++++++++--
include/linux/tee_drv.h | 1 +
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 09ddcd0..1ec1577 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
+#include <linux/uio.h>
#include "tee_private.h"
static void tee_shm_release(struct tee_shm *shm)
@@ -224,13 +225,14 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
{
struct tee_device *teedev = ctx->teedev;
const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
+ const u32 req_ker_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
struct tee_shm *shm;
void *ret;
int rc;
int num_pages;
unsigned long start;
- if (flags != req_flags)
+ if (flags != req_flags && flags != req_ker_flags)
return ERR_PTR(-ENOTSUPP);
if (!tee_device_get(teedev))
@@ -265,7 +267,27 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
goto err;
}
- rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages);
+ if (flags & TEE_SHM_USER_MAPPED) {
+ rc = get_user_pages_fast(start, num_pages, FOLL_WRITE,
+ shm->pages);
+ } else {
+ struct kvec *kiov;
+ int i;
+
+ kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
+ if (!kiov) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
+ kiov[i].iov_len = PAGE_SIZE;
+ }
+
+ rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
+ kfree(kiov);
+ }
if (rc > 0)
shm->num_pages = rc;
if (rc != num_pages) {
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 7a03f68..dedf8fa 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -26,6 +26,7 @@
#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */
#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */
#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */
+#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */
struct device;
struct tee_device;
--
2.7.4
^ permalink raw reply related
* [Patch v3 3/7] tee: add private login method for kernel clients
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
There are use-cases where user-space shouldn't be allowed to communicate
directly with a TEE device which is dedicated to provide a specific
service for a kernel client. So add a private login method for kernel
clients and disallow user-space to open-session using GP implementation
defined login method range: (0x80000000 - 0xFFFFFFFF).
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/tee/tee_core.c | 6 ++++++
include/uapi/linux/tee.h | 8 ++++++++
2 files changed, 14 insertions(+)
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 0f16d9f..2c2f646 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -334,6 +334,12 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
goto out;
}
+ if (arg.clnt_login & TEE_IOCTL_LOGIN_MASK) {
+ pr_debug("login method not allowed for user-space client\n");
+ rc = -EPERM;
+ goto out;
+ }
+
rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params);
if (rc)
goto out;
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
index 4b9eb06..a0a3d52 100644
--- a/include/uapi/linux/tee.h
+++ b/include/uapi/linux/tee.h
@@ -172,6 +172,14 @@ struct tee_ioctl_buf_data {
#define TEE_IOCTL_LOGIN_APPLICATION 4
#define TEE_IOCTL_LOGIN_USER_APPLICATION 5
#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6
+/*
+ * Disallow user-space to use GP implementation specific login
+ * method range (0x80000000 - 0xFFFFFFFF). This range is rather
+ * being reserved for REE kernel clients or TEE implementation.
+ */
+#define TEE_IOCTL_LOGIN_MASK 0x80000000
+/* Private login method for REE kernel clients */
+#define TEE_IOCTL_LOGIN_REE_KERNEL 0x80000000
/**
* struct tee_ioctl_param - parameter
--
2.7.4
^ permalink raw reply related
* [Patch v3 4/7] KEYS: trusted: Add generic trusted keys framework
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Current trusted keys framework is tightly coupled to use TPM device as
an underlying implementation which makes it difficult for implementations
like Trusted Execution Environment (TEE) etc. to provide trusked keys
support in case platform doesn't posses a TPM device.
So this patch tries to add generic trusted keys framework where underlying
implemtations like TPM, TEE etc. could be easily plugged-in.
Suggested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
include/keys/trusted-type.h | 45 ++++
include/keys/trusted_tpm.h | 15 --
security/keys/trusted-keys/Makefile | 1 +
security/keys/trusted-keys/trusted_common.c | 343 +++++++++++++++++++++++++++
security/keys/trusted-keys/trusted_tpm1.c | 345 +++++-----------------------
5 files changed, 447 insertions(+), 302 deletions(-)
create mode 100644 security/keys/trusted-keys/trusted_common.c
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index a94c03a..5559010 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -40,6 +40,51 @@ struct trusted_key_options {
uint32_t policyhandle;
};
+struct trusted_key_ops {
+ /*
+ * flag to indicate if trusted key implementation supports migration
+ * or not.
+ */
+ unsigned char migratable;
+
+ /* trusted key init */
+ int (*init)(void);
+
+ /* seal a trusted key */
+ int (*seal)(struct trusted_key_payload *p, char *datablob);
+
+ /* unseal a trusted key */
+ int (*unseal)(struct trusted_key_payload *p, char *datablob);
+
+ /* get random trusted key */
+ int (*get_random)(unsigned char *key, size_t key_len);
+
+ /* trusted key cleanup */
+ void (*cleanup)(void);
+};
+
extern struct key_type key_type_trusted;
+#if defined(CONFIG_TCG_TPM)
+extern struct trusted_key_ops tpm_trusted_key_ops;
+#endif
+
+#define TRUSTED_DEBUG 0
+
+#if TRUSTED_DEBUG
+static inline void dump_payload(struct trusted_key_payload *p)
+{
+ pr_info("trusted_key: key_len %d\n", p->key_len);
+ print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE,
+ 16, 1, p->key, p->key_len, 0);
+ pr_info("trusted_key: bloblen %d\n", p->blob_len);
+ print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE,
+ 16, 1, p->blob, p->blob_len, 0);
+ pr_info("trusted_key: migratable %d\n", p->migratable);
+}
+#else
+static inline void dump_payload(struct trusted_key_payload *p)
+{
+}
+#endif
#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h
index a56d8e1..5753231 100644
--- a/include/keys/trusted_tpm.h
+++ b/include/keys/trusted_tpm.h
@@ -60,17 +60,6 @@ static inline void dump_options(struct trusted_key_options *o)
16, 1, o->pcrinfo, o->pcrinfo_len, 0);
}
-static inline void dump_payload(struct trusted_key_payload *p)
-{
- pr_info("trusted_key: key_len %d\n", p->key_len);
- print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE,
- 16, 1, p->key, p->key_len, 0);
- pr_info("trusted_key: bloblen %d\n", p->blob_len);
- print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE,
- 16, 1, p->blob, p->blob_len, 0);
- pr_info("trusted_key: migratable %d\n", p->migratable);
-}
-
static inline void dump_sess(struct osapsess *s)
{
print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
@@ -96,10 +85,6 @@ static inline void dump_options(struct trusted_key_options *o)
{
}
-static inline void dump_payload(struct trusted_key_payload *p)
-{
-}
-
static inline void dump_sess(struct osapsess *s)
{
}
diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile
index 7b73ceb..2b1085b 100644
--- a/security/keys/trusted-keys/Makefile
+++ b/security/keys/trusted-keys/Makefile
@@ -4,5 +4,6 @@
#
obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+trusted-y += trusted_common.o
trusted-y += trusted_tpm1.o
trusted-y += trusted_tpm2.o
diff --git a/security/keys/trusted-keys/trusted_common.c b/security/keys/trusted-keys/trusted_common.c
new file mode 100644
index 0000000..8f00fde
--- /dev/null
+++ b/security/keys/trusted-keys/trusted_common.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2010 IBM Corporation
+ * Copyright (c) 2019, Linaro Limited
+ *
+ * Author:
+ * David Safford <safford@us.ibm.com>
+ * Added generic trusted key framework: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * See Documentation/security/keys/trusted-encrypted.rst
+ */
+
+#include <keys/user-type.h>
+#include <keys/trusted-type.h>
+#include <linux/capability.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/key-type.h>
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+
+static struct trusted_key_ops *available_tk_ops[] = {
+#if defined(CONFIG_TCG_TPM)
+ &tpm_trusted_key_ops,
+#endif
+};
+static struct trusted_key_ops *tk_ops;
+
+enum {
+ Opt_err,
+ Opt_new, Opt_load, Opt_update,
+};
+
+static const match_table_t key_tokens = {
+ {Opt_new, "new"},
+ {Opt_load, "load"},
+ {Opt_update, "update"},
+ {Opt_err, NULL}
+};
+
+/*
+ * datablob_parse - parse the keyctl data and fill in the
+ * payload structure
+ *
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int datablob_parse(char *datablob, struct trusted_key_payload *p)
+{
+ substring_t args[MAX_OPT_ARGS];
+ long keylen;
+ int ret = -EINVAL;
+ int key_cmd;
+ char *c;
+
+ /* main command */
+ c = strsep(&datablob, " \t");
+ if (!c)
+ return -EINVAL;
+ key_cmd = match_token(c, key_tokens, args);
+ switch (key_cmd) {
+ case Opt_new:
+ /* first argument is key size */
+ c = strsep(&datablob, " \t");
+ if (!c)
+ return -EINVAL;
+ ret = kstrtol(c, 10, &keylen);
+ if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
+ return -EINVAL;
+ p->key_len = keylen;
+ ret = Opt_new;
+ break;
+ case Opt_load:
+ /* first argument is sealed blob */
+ c = strsep(&datablob, " \t");
+ if (!c)
+ return -EINVAL;
+ p->blob_len = strlen(c) / 2;
+ if (p->blob_len > MAX_BLOB_SIZE)
+ return -EINVAL;
+ ret = hex2bin(p->blob, c, p->blob_len);
+ if (ret < 0)
+ return -EINVAL;
+ ret = Opt_load;
+ break;
+ case Opt_update:
+ ret = Opt_update;
+ break;
+ case Opt_err:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
+{
+ struct trusted_key_payload *p = NULL;
+ int ret;
+
+ ret = key_payload_reserve(key, sizeof(*p));
+ if (ret < 0)
+ return p;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+
+ p->migratable = tk_ops->migratable;
+
+ return p;
+}
+
+/*
+ * trusted_instantiate - create a new trusted key
+ *
+ * Unseal an existing trusted blob or, for a new key, get a
+ * random key, then seal and create a trusted key-type key,
+ * adding it to the specified keyring.
+ *
+ * On success, return 0. Otherwise return errno.
+ */
+static int trusted_instantiate(struct key *key,
+ struct key_preparsed_payload *prep)
+{
+ struct trusted_key_payload *payload = NULL;
+ size_t datalen = prep->datalen;
+ char *datablob;
+ int ret = 0;
+ int key_cmd;
+ size_t key_len;
+
+ if (datalen <= 0 || datalen > 32767 || !prep->data)
+ return -EINVAL;
+
+ datablob = kmalloc(datalen + 1, GFP_KERNEL);
+ if (!datablob)
+ return -ENOMEM;
+ memcpy(datablob, prep->data, datalen);
+ datablob[datalen] = '\0';
+
+ payload = trusted_payload_alloc(key);
+ if (!payload) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ key_cmd = datablob_parse(datablob, payload);
+ if (key_cmd < 0) {
+ ret = key_cmd;
+ goto out;
+ }
+
+ dump_payload(payload);
+
+ switch (key_cmd) {
+ case Opt_load:
+ ret = tk_ops->unseal(payload, datablob);
+ dump_payload(payload);
+ if (ret < 0)
+ pr_info("trusted_key: key_unseal failed (%d)\n", ret);
+ break;
+ case Opt_new:
+ key_len = payload->key_len;
+ ret = tk_ops->get_random(payload->key, key_len);
+ if (ret != key_len) {
+ pr_info("trusted_key: key_create failed (%d)\n", ret);
+ goto out;
+ }
+
+ ret = tk_ops->seal(payload, datablob);
+ if (ret < 0)
+ pr_info("trusted_key: key_seal failed (%d)\n", ret);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+out:
+ kzfree(datablob);
+ if (!ret)
+ rcu_assign_keypointer(key, payload);
+ else
+ kzfree(payload);
+ return ret;
+}
+
+static void trusted_rcu_free(struct rcu_head *rcu)
+{
+ struct trusted_key_payload *p;
+
+ p = container_of(rcu, struct trusted_key_payload, rcu);
+ kzfree(p);
+}
+
+/*
+ * trusted_update - reseal an existing key with new PCR values
+ */
+static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
+{
+ struct trusted_key_payload *p;
+ struct trusted_key_payload *new_p;
+ size_t datalen = prep->datalen;
+ char *datablob;
+ int ret = 0;
+
+ if (key_is_negative(key))
+ return -ENOKEY;
+ p = key->payload.data[0];
+ if (!p->migratable)
+ return -EPERM;
+ if (datalen <= 0 || datalen > 32767 || !prep->data)
+ return -EINVAL;
+
+ datablob = kmalloc(datalen + 1, GFP_KERNEL);
+ if (!datablob)
+ return -ENOMEM;
+
+ new_p = trusted_payload_alloc(key);
+ if (!new_p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(datablob, prep->data, datalen);
+ datablob[datalen] = '\0';
+ ret = datablob_parse(datablob, new_p);
+ if (ret != Opt_update) {
+ ret = -EINVAL;
+ kzfree(new_p);
+ goto out;
+ }
+
+ /* copy old key values, and reseal with new pcrs */
+ new_p->migratable = p->migratable;
+ new_p->key_len = p->key_len;
+ memcpy(new_p->key, p->key, p->key_len);
+ dump_payload(p);
+ dump_payload(new_p);
+
+ ret = tk_ops->seal(new_p, datablob);
+ if (ret < 0) {
+ pr_info("trusted_key: key_seal failed (%d)\n", ret);
+ kzfree(new_p);
+ goto out;
+ }
+
+ rcu_assign_keypointer(key, new_p);
+ call_rcu(&p->rcu, trusted_rcu_free);
+out:
+ kzfree(datablob);
+ return ret;
+}
+
+/*
+ * trusted_read - copy the sealed blob data to userspace in hex.
+ * On success, return to userspace the trusted key datablob size.
+ */
+static long trusted_read(const struct key *key, char __user *buffer,
+ size_t buflen)
+{
+ const struct trusted_key_payload *p;
+ char *ascii_buf;
+ char *bufp;
+ int i;
+
+ p = dereference_key_locked(key);
+ if (!p)
+ return -EINVAL;
+
+ if (buffer && buflen >= 2 * p->blob_len) {
+ ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL);
+ if (!ascii_buf)
+ return -ENOMEM;
+
+ bufp = ascii_buf;
+ for (i = 0; i < p->blob_len; i++)
+ bufp = hex_byte_pack(bufp, p->blob[i]);
+ if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+ kzfree(ascii_buf);
+ return -EFAULT;
+ }
+ kzfree(ascii_buf);
+ }
+ return 2 * p->blob_len;
+}
+
+/*
+ * trusted_destroy - clear and free the key's payload
+ */
+static void trusted_destroy(struct key *key)
+{
+ kzfree(key->payload.data[0]);
+}
+
+struct key_type key_type_trusted = {
+ .name = "trusted",
+ .instantiate = trusted_instantiate,
+ .update = trusted_update,
+ .destroy = trusted_destroy,
+ .describe = user_describe,
+ .read = trusted_read,
+};
+EXPORT_SYMBOL_GPL(key_type_trusted);
+
+static int __init init_trusted(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < sizeof(available_tk_ops); i++) {
+ tk_ops = available_tk_ops[i];
+
+ if (!(tk_ops && tk_ops->init && tk_ops->seal &&
+ tk_ops->unseal && tk_ops->get_random))
+ continue;
+
+ ret = tk_ops->init();
+ if (ret) {
+ if (tk_ops->cleanup)
+ tk_ops->cleanup();
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * encrypted_keys.ko depends on successful load of this module even if
+ * trusted key implementation is not found.
+ */
+ if (ret == -ENODEV)
+ return 0;
+
+ return ret;
+}
+
+static void __exit cleanup_trusted(void)
+{
+ if (tk_ops->cleanup)
+ tk_ops->cleanup();
+}
+
+late_initcall(init_trusted);
+module_exit(cleanup_trusted);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index d2c5ec1..32fd1ea 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -1,29 +1,26 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2010 IBM Corporation
+ * Copyright (c) 2019, Linaro Limited
*
* Author:
* David Safford <safford@us.ibm.com>
+ * Switch to generic trusted key framework: Sumit Garg <sumit.garg@linaro.org>
*
* See Documentation/security/keys/trusted-encrypted.rst
*/
#include <crypto/hash_info.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/parser.h>
#include <linux/string.h>
#include <linux/err.h>
-#include <keys/user-type.h>
#include <keys/trusted-type.h>
#include <linux/key-type.h>
-#include <linux/rcupdate.h>
#include <linux/crypto.h>
#include <crypto/hash.h>
#include <crypto/sha.h>
-#include <linux/capability.h>
#include <linux/tpm.h>
#include <linux/tpm_command.h>
@@ -703,7 +700,6 @@ static int key_unseal(struct trusted_key_payload *p,
enum {
Opt_err,
- Opt_new, Opt_load, Opt_update,
Opt_keyhandle, Opt_keyauth, Opt_blobauth,
Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
Opt_hash,
@@ -712,9 +708,6 @@ enum {
};
static const match_table_t key_tokens = {
- {Opt_new, "new"},
- {Opt_load, "load"},
- {Opt_update, "update"},
{Opt_keyhandle, "keyhandle=%s"},
{Opt_keyauth, "keyauth=%s"},
{Opt_blobauth, "blobauth=%s"},
@@ -841,71 +834,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return 0;
}
-/*
- * datablob_parse - parse the keyctl data and fill in the
- * payload and options structures
- *
- * On success returns 0, otherwise -EINVAL.
- */
-static int datablob_parse(char *datablob, struct trusted_key_payload *p,
- struct trusted_key_options *o)
-{
- substring_t args[MAX_OPT_ARGS];
- long keylen;
- int ret = -EINVAL;
- int key_cmd;
- char *c;
-
- /* main command */
- c = strsep(&datablob, " \t");
- if (!c)
- return -EINVAL;
- key_cmd = match_token(c, key_tokens, args);
- switch (key_cmd) {
- case Opt_new:
- /* first argument is key size */
- c = strsep(&datablob, " \t");
- if (!c)
- return -EINVAL;
- ret = kstrtol(c, 10, &keylen);
- if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
- return -EINVAL;
- p->key_len = keylen;
- ret = getoptions(datablob, p, o);
- if (ret < 0)
- return ret;
- ret = Opt_new;
- break;
- case Opt_load:
- /* first argument is sealed blob */
- c = strsep(&datablob, " \t");
- if (!c)
- return -EINVAL;
- p->blob_len = strlen(c) / 2;
- if (p->blob_len > MAX_BLOB_SIZE)
- return -EINVAL;
- ret = hex2bin(p->blob, c, p->blob_len);
- if (ret < 0)
- return -EINVAL;
- ret = getoptions(datablob, p, o);
- if (ret < 0)
- return ret;
- ret = Opt_load;
- break;
- case Opt_update:
- /* all arguments are options */
- ret = getoptions(datablob, p, o);
- if (ret < 0)
- return ret;
- ret = Opt_update;
- break;
- case Opt_err:
- return -EINVAL;
- break;
- }
- return ret;
-}
-
static struct trusted_key_options *trusted_options_alloc(void)
{
struct trusted_key_options *options;
@@ -926,258 +854,99 @@ static struct trusted_key_options *trusted_options_alloc(void)
return options;
}
-static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
+static int tpm_tk_seal(struct trusted_key_payload *p, char *datablob)
{
- struct trusted_key_payload *p = NULL;
- int ret;
-
- ret = key_payload_reserve(key, sizeof *p);
- if (ret < 0)
- return p;
- p = kzalloc(sizeof *p, GFP_KERNEL);
- if (p)
- p->migratable = 1; /* migratable by default */
- return p;
-}
-
-/*
- * trusted_instantiate - create a new trusted key
- *
- * Unseal an existing trusted blob or, for a new key, get a
- * random key, then seal and create a trusted key-type key,
- * adding it to the specified keyring.
- *
- * On success, return 0. Otherwise return errno.
- */
-static int trusted_instantiate(struct key *key,
- struct key_preparsed_payload *prep)
-{
- struct trusted_key_payload *payload = NULL;
struct trusted_key_options *options = NULL;
- size_t datalen = prep->datalen;
- char *datablob;
int ret = 0;
- int key_cmd;
- size_t key_len;
int tpm2;
tpm2 = tpm_is_tpm2(chip);
if (tpm2 < 0)
return tpm2;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
- return -EINVAL;
-
- datablob = kmalloc(datalen + 1, GFP_KERNEL);
- if (!datablob)
- return -ENOMEM;
- memcpy(datablob, prep->data, datalen);
- datablob[datalen] = '\0';
-
options = trusted_options_alloc();
- if (!options) {
- ret = -ENOMEM;
- goto out;
- }
- payload = trusted_payload_alloc(key);
- if (!payload) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!options)
+ return -ENOMEM;
- key_cmd = datablob_parse(datablob, payload, options);
- if (key_cmd < 0) {
- ret = key_cmd;
+ ret = getoptions(datablob, p, options);
+ if (ret < 0)
goto out;
- }
+ dump_options(options);
if (!options->keyhandle) {
ret = -EINVAL;
goto out;
}
- dump_payload(payload);
- dump_options(options);
+ if (tpm2)
+ ret = tpm2_seal_trusted(chip, p, options);
+ else
+ ret = key_seal(p, options);
+ if (ret < 0) {
+ pr_info("tpm_trusted_key: key_seal failed (%d)\n", ret);
+ goto out;
+ }
- switch (key_cmd) {
- case Opt_load:
- if (tpm2)
- ret = tpm2_unseal_trusted(chip, payload, options);
- else
- ret = key_unseal(payload, options);
- dump_payload(payload);
- dump_options(options);
- if (ret < 0)
- pr_info("trusted_key: key_unseal failed (%d)\n", ret);
- break;
- case Opt_new:
- key_len = payload->key_len;
- ret = tpm_get_random(chip, payload->key, key_len);
- if (ret != key_len) {
- pr_info("trusted_key: key_create failed (%d)\n", ret);
+ if (options->pcrlock) {
+ ret = pcrlock(options->pcrlock);
+ if (ret < 0) {
+ pr_info("tpm_trusted_key: pcrlock failed (%d)\n", ret);
goto out;
}
- if (tpm2)
- ret = tpm2_seal_trusted(chip, payload, options);
- else
- ret = key_seal(payload, options);
- if (ret < 0)
- pr_info("trusted_key: key_seal failed (%d)\n", ret);
- break;
- default:
- ret = -EINVAL;
- goto out;
}
- if (!ret && options->pcrlock)
- ret = pcrlock(options->pcrlock);
out:
- kzfree(datablob);
kzfree(options);
- if (!ret)
- rcu_assign_keypointer(key, payload);
- else
- kzfree(payload);
return ret;
}
-static void trusted_rcu_free(struct rcu_head *rcu)
-{
- struct trusted_key_payload *p;
-
- p = container_of(rcu, struct trusted_key_payload, rcu);
- kzfree(p);
-}
-
-/*
- * trusted_update - reseal an existing key with new PCR values
- */
-static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
+static int tpm_tk_unseal(struct trusted_key_payload *p, char *datablob)
{
- struct trusted_key_payload *p;
- struct trusted_key_payload *new_p;
- struct trusted_key_options *new_o;
- size_t datalen = prep->datalen;
- char *datablob;
+ struct trusted_key_options *options = NULL;
int ret = 0;
+ int tpm2;
- if (key_is_negative(key))
- return -ENOKEY;
- p = key->payload.data[0];
- if (!p->migratable)
- return -EPERM;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
- return -EINVAL;
+ tpm2 = tpm_is_tpm2(chip);
+ if (tpm2 < 0)
+ return tpm2;
- datablob = kmalloc(datalen + 1, GFP_KERNEL);
- if (!datablob)
+ options = trusted_options_alloc();
+ if (!options)
return -ENOMEM;
- new_o = trusted_options_alloc();
- if (!new_o) {
- ret = -ENOMEM;
- goto out;
- }
- new_p = trusted_payload_alloc(key);
- if (!new_p) {
- ret = -ENOMEM;
- goto out;
- }
- memcpy(datablob, prep->data, datalen);
- datablob[datalen] = '\0';
- ret = datablob_parse(datablob, new_p, new_o);
- if (ret != Opt_update) {
- ret = -EINVAL;
- kzfree(new_p);
+ ret = getoptions(datablob, p, options);
+ if (ret < 0)
goto out;
- }
+ dump_options(options);
- if (!new_o->keyhandle) {
+ if (!options->keyhandle) {
ret = -EINVAL;
- kzfree(new_p);
goto out;
}
- /* copy old key values, and reseal with new pcrs */
- new_p->migratable = p->migratable;
- new_p->key_len = p->key_len;
- memcpy(new_p->key, p->key, p->key_len);
- dump_payload(p);
- dump_payload(new_p);
+ if (tpm2)
+ ret = tpm2_unseal_trusted(chip, p, options);
+ else
+ ret = key_unseal(p, options);
+ if (ret < 0)
+ pr_info("tpm_trusted_key: key_unseal failed (%d)\n", ret);
- ret = key_seal(new_p, new_o);
- if (ret < 0) {
- pr_info("trusted_key: key_seal failed (%d)\n", ret);
- kzfree(new_p);
- goto out;
- }
- if (new_o->pcrlock) {
- ret = pcrlock(new_o->pcrlock);
+ if (options->pcrlock) {
+ ret = pcrlock(options->pcrlock);
if (ret < 0) {
- pr_info("trusted_key: pcrlock failed (%d)\n", ret);
- kzfree(new_p);
+ pr_info("tpm_trusted_key: pcrlock failed (%d)\n", ret);
goto out;
}
}
- rcu_assign_keypointer(key, new_p);
- call_rcu(&p->rcu, trusted_rcu_free);
out:
- kzfree(datablob);
- kzfree(new_o);
+ kzfree(options);
return ret;
}
-/*
- * trusted_read - copy the sealed blob data to userspace in hex.
- * On success, return to userspace the trusted key datablob size.
- */
-static long trusted_read(const struct key *key, char __user *buffer,
- size_t buflen)
-{
- const struct trusted_key_payload *p;
- char *ascii_buf;
- char *bufp;
- int i;
-
- p = dereference_key_locked(key);
- if (!p)
- return -EINVAL;
-
- if (buffer && buflen >= 2 * p->blob_len) {
- ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL);
- if (!ascii_buf)
- return -ENOMEM;
-
- bufp = ascii_buf;
- for (i = 0; i < p->blob_len; i++)
- bufp = hex_byte_pack(bufp, p->blob[i]);
- if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
- kzfree(ascii_buf);
- return -EFAULT;
- }
- kzfree(ascii_buf);
- }
- return 2 * p->blob_len;
-}
-
-/*
- * trusted_destroy - clear and free the key's payload
- */
-static void trusted_destroy(struct key *key)
+int tpm_tk_get_random(unsigned char *key, size_t key_len)
{
- kzfree(key->payload.data[0]);
+ return tpm_get_random(chip, key, key_len);
}
-struct key_type key_type_trusted = {
- .name = "trusted",
- .instantiate = trusted_instantiate,
- .update = trusted_update,
- .destroy = trusted_destroy,
- .describe = user_describe,
- .read = trusted_read,
-};
-
-EXPORT_SYMBOL_GPL(key_type_trusted);
-
static void trusted_shash_release(void)
{
if (hashalg)
@@ -1192,14 +961,14 @@ static int __init trusted_shash_alloc(void)
hmacalg = crypto_alloc_shash(hmac_alg, 0, 0);
if (IS_ERR(hmacalg)) {
- pr_info("trusted_key: could not allocate crypto %s\n",
+ pr_info("tpm_trusted_key: could not allocate crypto %s\n",
hmac_alg);
return PTR_ERR(hmacalg);
}
hashalg = crypto_alloc_shash(hash_alg, 0, 0);
if (IS_ERR(hashalg)) {
- pr_info("trusted_key: could not allocate crypto %s\n",
+ pr_info("tpm_trusted_key: could not allocate crypto %s\n",
hash_alg);
ret = PTR_ERR(hashalg);
goto hashalg_fail;
@@ -1227,16 +996,13 @@ static int __init init_digests(void)
return 0;
}
-static int __init init_trusted(void)
+static int __init init_tpm_trusted(void)
{
int ret;
- /* encrypted_keys.ko depends on successful load of this module even if
- * TPM is not used.
- */
chip = tpm_default_chip();
if (!chip)
- return 0;
+ return -ENODEV;
ret = init_digests();
if (ret < 0)
@@ -1257,7 +1023,7 @@ static int __init init_trusted(void)
return ret;
}
-static void __exit cleanup_trusted(void)
+static void __exit cleanup_tpm_trusted(void)
{
if (chip) {
put_device(&chip->dev);
@@ -1267,7 +1033,12 @@ static void __exit cleanup_trusted(void)
}
}
-late_initcall(init_trusted);
-module_exit(cleanup_trusted);
-
-MODULE_LICENSE("GPL");
+struct trusted_key_ops tpm_trusted_key_ops = {
+ .migratable = 1, /* migratable by default */
+ .init = init_tpm_trusted,
+ .seal = tpm_tk_seal,
+ .unseal = tpm_tk_unseal,
+ .get_random = tpm_tk_get_random,
+ .cleanup = cleanup_tpm_trusted,
+};
+EXPORT_SYMBOL_GPL(tpm_trusted_key_ops);
--
2.7.4
^ permalink raw reply related
* [Patch v3 5/7] KEYS: trusted: Introduce TEE based Trusted Keys
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Add support for TEE based trusted keys where TEE provides the functionality
to seal and unseal trusted keys using hardware unique key.
Refer to Documentation/tee.txt for detailed information about TEE.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
include/keys/trusted-type.h | 3 +
include/keys/trusted_tee.h | 66 +++++++
security/keys/Kconfig | 3 +
security/keys/trusted-keys/Makefile | 1 +
security/keys/trusted-keys/trusted_common.c | 3 +
security/keys/trusted-keys/trusted_tee.c | 282 ++++++++++++++++++++++++++++
6 files changed, 358 insertions(+)
create mode 100644 include/keys/trusted_tee.h
create mode 100644 security/keys/trusted-keys/trusted_tee.c
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 5559010..e0df5df 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -67,6 +67,9 @@ extern struct key_type key_type_trusted;
#if defined(CONFIG_TCG_TPM)
extern struct trusted_key_ops tpm_trusted_key_ops;
#endif
+#if defined(CONFIG_TEE)
+extern struct trusted_key_ops tee_trusted_key_ops;
+#endif
#define TRUSTED_DEBUG 0
diff --git a/include/keys/trusted_tee.h b/include/keys/trusted_tee.h
new file mode 100644
index 0000000..ab58ffd
--- /dev/null
+++ b/include/keys/trusted_tee.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Linaro Ltd.
+ *
+ * Author:
+ * Sumit Garg <sumit.garg@linaro.org>
+ */
+
+#ifndef __TEE_TRUSTED_KEY_H
+#define __TEE_TRUSTED_KEY_H
+
+#include <linux/tee_drv.h>
+
+#define DRIVER_NAME "tee-trusted-key"
+
+/*
+ * Get random data for symmetric key
+ *
+ * [out] memref[0] Random data
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_GET_RANDOM 0x0
+
+/*
+ * Seal trusted key using hardware unique key
+ *
+ * [in] memref[0] Plain key
+ * [out] memref[1] Sealed key datablob
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_SEAL 0x1
+
+/*
+ * Unseal trusted key using hardware unique key
+ *
+ * [in] memref[0] Sealed key datablob
+ * [out] memref[1] Plain key
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_UNSEAL 0x2
+
+/**
+ * struct trusted_key_private - TEE Trusted key private data
+ * @dev: TEE based Trusted key device.
+ * @ctx: TEE context handler.
+ * @session_id: Trusted key TA session identifier.
+ * @shm_pool: Memory pool shared with TEE device.
+ */
+struct trusted_key_private {
+ struct device *dev;
+ struct tee_context *ctx;
+ u32 session_id;
+ u32 data_rate;
+ struct tee_shm *shm_pool;
+};
+
+#endif
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index dd31343..0d5e37c 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -88,6 +88,9 @@ config TRUSTED_KEYS
if the boot PCRs and other criteria match. Userspace will only ever
see encrypted blobs.
+ It also provides support for alternative TEE based Trusted keys
+ generation and sealing in case TPM isn't present.
+
If you are unsure as to whether this is required, answer N.
config ENCRYPTED_KEYS
diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile
index 2b1085b..ea937d3 100644
--- a/security/keys/trusted-keys/Makefile
+++ b/security/keys/trusted-keys/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
trusted-y += trusted_common.o
trusted-y += trusted_tpm1.o
trusted-y += trusted_tpm2.o
+trusted-y += trusted_tee.o
diff --git a/security/keys/trusted-keys/trusted_common.c b/security/keys/trusted-keys/trusted_common.c
index 8f00fde..a0a171f 100644
--- a/security/keys/trusted-keys/trusted_common.c
+++ b/security/keys/trusted-keys/trusted_common.c
@@ -27,6 +27,9 @@ static struct trusted_key_ops *available_tk_ops[] = {
#if defined(CONFIG_TCG_TPM)
&tpm_trusted_key_ops,
#endif
+#if defined(CONFIG_TEE)
+ &tee_trusted_key_ops,
+#endif
};
static struct trusted_key_ops *tk_ops;
diff --git a/security/keys/trusted-keys/trusted_tee.c b/security/keys/trusted-keys/trusted_tee.c
new file mode 100644
index 0000000..724a73c
--- /dev/null
+++ b/security/keys/trusted-keys/trusted_tee.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Linaro Ltd.
+ *
+ * Author:
+ * Sumit Garg <sumit.garg@linaro.org>
+ */
+
+#include <linux/err.h>
+#include <linux/key-type.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/uuid.h>
+
+#include <keys/trusted-type.h>
+#include <keys/trusted_tee.h>
+
+static struct trusted_key_private pvt_data;
+
+/*
+ * Have the TEE seal(encrypt) the symmetric key
+ */
+static int tee_key_seal(struct trusted_key_payload *p, char *datablob)
+{
+ int ret = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+ struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(¶m, 0, sizeof(param));
+
+ reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
+ p->key_len, TEE_SHM_DMA_BUF |
+ TEE_SHM_KERNEL_MAPPED);
+ if (IS_ERR(reg_shm_in)) {
+ dev_err(pvt_data.dev, "key shm register failed\n");
+ return PTR_ERR(reg_shm_in);
+ }
+
+ reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
+ sizeof(p->blob), TEE_SHM_DMA_BUF |
+ TEE_SHM_KERNEL_MAPPED);
+ if (IS_ERR(reg_shm_out)) {
+ dev_err(pvt_data.dev, "blob shm register failed\n");
+ ret = PTR_ERR(reg_shm_out);
+ goto out;
+ }
+
+ inv_arg.func = TA_CMD_SEAL;
+ inv_arg.session = pvt_data.session_id;
+ inv_arg.num_params = 4;
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[0].u.memref.shm = reg_shm_in;
+ param[0].u.memref.size = p->key_len;
+ param[0].u.memref.shm_offs = 0;
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[1].u.memref.shm = reg_shm_out;
+ param[1].u.memref.size = sizeof(p->blob);
+ param[1].u.memref.shm_offs = 0;
+
+ ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
+ if ((ret < 0) || (inv_arg.ret != 0)) {
+ dev_err(pvt_data.dev, "TA_CMD_SEAL invoke err: %x\n",
+ inv_arg.ret);
+ ret = -EFAULT;
+ } else {
+ p->blob_len = param[1].u.memref.size;
+ }
+
+out:
+ if (reg_shm_out)
+ tee_shm_free(reg_shm_out);
+ if (reg_shm_in)
+ tee_shm_free(reg_shm_in);
+
+ return ret;
+}
+
+/*
+ * Have the TEE unseal(decrypt) the symmetric key
+ */
+static int tee_key_unseal(struct trusted_key_payload *p, char *datablob)
+{
+ int ret = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+ struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(¶m, 0, sizeof(param));
+
+ reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
+ p->blob_len, TEE_SHM_DMA_BUF |
+ TEE_SHM_KERNEL_MAPPED);
+ if (IS_ERR(reg_shm_in)) {
+ dev_err(pvt_data.dev, "blob shm register failed\n");
+ return PTR_ERR(reg_shm_in);
+ }
+
+ reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
+ sizeof(p->key), TEE_SHM_DMA_BUF |
+ TEE_SHM_KERNEL_MAPPED);
+ if (IS_ERR(reg_shm_out)) {
+ dev_err(pvt_data.dev, "key shm register failed\n");
+ ret = PTR_ERR(reg_shm_out);
+ goto out;
+ }
+
+ inv_arg.func = TA_CMD_UNSEAL;
+ inv_arg.session = pvt_data.session_id;
+ inv_arg.num_params = 4;
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[0].u.memref.shm = reg_shm_in;
+ param[0].u.memref.size = p->blob_len;
+ param[0].u.memref.shm_offs = 0;
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[1].u.memref.shm = reg_shm_out;
+ param[1].u.memref.size = sizeof(p->key);
+ param[1].u.memref.shm_offs = 0;
+
+ ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
+ if ((ret < 0) || (inv_arg.ret != 0)) {
+ dev_err(pvt_data.dev, "TA_CMD_UNSEAL invoke err: %x\n",
+ inv_arg.ret);
+ ret = -EFAULT;
+ } else {
+ p->key_len = param[1].u.memref.size;
+ }
+
+out:
+ if (reg_shm_out)
+ tee_shm_free(reg_shm_out);
+ if (reg_shm_in)
+ tee_shm_free(reg_shm_in);
+
+ return ret;
+}
+
+/*
+ * Have the TEE generate random symmetric key
+ */
+static int tee_get_random(unsigned char *key, size_t key_len)
+{
+ int ret = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+ struct tee_shm *reg_shm = NULL;
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(¶m, 0, sizeof(param));
+
+ reg_shm = tee_shm_register(pvt_data.ctx, (unsigned long)key, key_len,
+ TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
+ if (IS_ERR(reg_shm)) {
+ dev_err(pvt_data.dev, "random key shm register failed\n");
+ return PTR_ERR(reg_shm);
+ }
+
+ inv_arg.func = TA_CMD_GET_RANDOM;
+ inv_arg.session = pvt_data.session_id;
+ inv_arg.num_params = 4;
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[0].u.memref.shm = reg_shm;
+ param[0].u.memref.size = key_len;
+ param[0].u.memref.shm_offs = 0;
+
+ ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
+ if ((ret < 0) || (inv_arg.ret != 0)) {
+ dev_err(pvt_data.dev, "TA_CMD_GET_RANDOM invoke err: %x\n",
+ inv_arg.ret);
+ ret = -EFAULT;
+ } else {
+ ret = param[0].u.memref.size;
+ }
+
+ tee_shm_free(reg_shm);
+
+ return ret;
+}
+
+static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+ if (ver->impl_id == TEE_IMPL_ID_OPTEE)
+ return 1;
+ else
+ return 0;
+}
+
+static int trusted_key_probe(struct device *dev)
+{
+ struct tee_client_device *rng_device = to_tee_client_device(dev);
+ int ret = 0, err = -ENODEV;
+ struct tee_ioctl_open_session_arg sess_arg;
+
+ memset(&sess_arg, 0, sizeof(sess_arg));
+
+ /* Open context with TEE driver */
+ pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
+ NULL);
+ if (IS_ERR(pvt_data.ctx))
+ return -ENODEV;
+
+ /* Open session with hwrng Trusted App */
+ memcpy(sess_arg.uuid, rng_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
+ sess_arg.num_params = 0;
+
+ ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
+ if ((ret < 0) || (sess_arg.ret != 0)) {
+ dev_err(dev, "tee_client_open_session failed, err: %x\n",
+ sess_arg.ret);
+ err = -EINVAL;
+ goto out_ctx;
+ }
+ pvt_data.session_id = sess_arg.session;
+
+ ret = register_key_type(&key_type_trusted);
+ if (ret < 0)
+ goto out_sess;
+
+ pvt_data.dev = dev;
+
+ return 0;
+
+out_sess:
+ tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
+out_ctx:
+ tee_client_close_context(pvt_data.ctx);
+
+ return err;
+}
+
+static int trusted_key_remove(struct device *dev)
+{
+ unregister_key_type(&key_type_trusted);
+ tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
+ tee_client_close_context(pvt_data.ctx);
+
+ return 0;
+}
+
+static const struct tee_client_device_id trusted_key_id_table[] = {
+ {UUID_INIT(0xf04a0fe7, 0x1f5d, 0x4b9b,
+ 0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(tee, trusted_key_id_table);
+
+static struct tee_client_driver trusted_key_driver = {
+ .id_table = trusted_key_id_table,
+ .driver = {
+ .name = DRIVER_NAME,
+ .bus = &tee_bus_type,
+ .probe = trusted_key_probe,
+ .remove = trusted_key_remove,
+ },
+};
+
+static int __init init_tee_trusted(void)
+{
+ return driver_register(&trusted_key_driver.driver);
+}
+
+static void __exit cleanup_tee_trusted(void)
+{
+ driver_unregister(&trusted_key_driver.driver);
+}
+
+struct trusted_key_ops tee_trusted_key_ops = {
+ .migratable = 0, /* non-migratable */
+ .init = init_tee_trusted,
+ .seal = tee_key_seal,
+ .unseal = tee_key_unseal,
+ .get_random = tee_get_random,
+ .cleanup = cleanup_tee_trusted,
+};
+EXPORT_SYMBOL_GPL(tee_trusted_key_ops);
--
2.7.4
^ permalink raw reply related
* [Patch v3 6/7] doc: keys: Document usage of TEE based Trusted Keys
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Provide documentation for usage of TEE based Trusted Keys via existing
user-space "keyctl" utility. Also, document various use-cases.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
Documentation/security/keys/index.rst | 1 +
Documentation/security/keys/tee-trusted.rst | 93 +++++++++++++++++++++++++++++
2 files changed, 94 insertions(+)
create mode 100644 Documentation/security/keys/tee-trusted.rst
diff --git a/Documentation/security/keys/index.rst b/Documentation/security/keys/index.rst
index 647d58f..f9ef557 100644
--- a/Documentation/security/keys/index.rst
+++ b/Documentation/security/keys/index.rst
@@ -9,3 +9,4 @@ Kernel Keys
ecryptfs
request-key
trusted-encrypted
+ tee-trusted
diff --git a/Documentation/security/keys/tee-trusted.rst b/Documentation/security/keys/tee-trusted.rst
new file mode 100644
index 0000000..ef03745
--- /dev/null
+++ b/Documentation/security/keys/tee-trusted.rst
@@ -0,0 +1,93 @@
+======================
+TEE based Trusted Keys
+======================
+
+TEE based Trusted Keys provides an alternative approach for providing Trusted
+Keys in case TPM chip isn't present.
+
+Trusted Keys use a TEE service/device both to generate and to seal the keys.
+Keys are sealed under a hardware unique key in the TEE, and only unsealed by
+the TEE.
+
+For more information about TEE, refer to ``Documentation/tee.txt``.
+
+Usage::
+
+ keyctl add trusted name "new keylen" ring
+ keyctl add trusted name "load hex_blob" ring
+ keyctl print keyid
+
+"keyctl print" returns an ascii hex copy of the sealed key, which is in format
+specific to TEE device implementation. The key length for new keys are always
+in bytes. Trusted Keys can be 32 - 128 bytes (256 - 1024 bits).
+
+Examples of trusted key and its usage as 'master' key for encrypted key usage:
+
+More details about encrypted keys can be found here:
+``Documentation/security/keys/trusted-encrypted.rst``
+
+Create and save a trusted key named "kmk" of length 32 bytes::
+
+ $ keyctl add trusted kmk "new 32" @u
+ 754414669
+
+ $ keyctl show
+ Session Keyring
+ 827385718 --alswrv 0 65534 keyring: _uid_ses.0
+ 274124851 --alswrv 0 65534 \_ keyring: _uid.0
+ 754414669 --als-rv 0 0 \_ trusted: kmk
+
+ $ keyctl print 754414669
+ 15676790697861b422175596ae001c2f505cea2c6f3ebbc5fb08eeb1f343a07e
+
+ $ keyctl pipe 754414669 > kmk.blob
+
+Load a trusted key from the saved blob::
+
+ $ keyctl add trusted kmk "load `cat kmk.blob`" @u
+ 491638700
+
+ $ keyctl print 491638700
+ 15676790697861b422175596ae001c2f505cea2c6f3ebbc5fb08eeb1f343a07e
+
+The initial consumer of trusted keys is EVM, which at boot time needs a high
+quality symmetric key for HMAC protection of file metadata. The use of a
+TEE based trusted key provides security that the EVM key has not been
+compromised by a user level problem and tied to particular hardware.
+
+Create and save an encrypted key "evm" using the above trusted key "kmk":
+
+option 1: omitting 'format'::
+
+ $ keyctl add encrypted evm "new trusted:kmk 32" @u
+ 608915065
+
+option 2: explicitly defining 'format' as 'default'::
+
+ $ keyctl add encrypted evm "new default trusted:kmk 32" @u
+ 608915065
+
+ $ keyctl print 608915065
+ default trusted:kmk 32 f380ac588a925f488d5be007cf23e4c900b8b652ab62241c8
+ ed54906189b6659d139d619d4b51752a2645537b11fd44673f13154a65b3f595d5fb2131
+ 2fe45529ea0407c644ea4026f2a1a75661f2c9b66
+
+ $ keyctl pipe 608915065 > evm.blob
+
+Load an encrypted key "evm" from saved blob::
+
+ $ keyctl add encrypted evm "load `cat evm.blob`" @u
+ 831684262
+
+ $ keyctl print 831684262
+ default trusted:kmk 32 f380ac588a925f488d5be007cf23e4c900b8b652ab62241c8
+ ed54906189b6659d139d619d4b51752a2645537b11fd44673f13154a65b3f595d5fb2131
+ 2fe45529ea0407c644ea4026f2a1a75661f2c9b66
+
+Other uses for trusted and encrypted keys, such as for disk and file encryption
+are anticipated. In particular the 'ecryptfs' encrypted keys format can be used
+to mount an eCryptfs filesystem. More details about the usage can be found in
+the file ``Documentation/security/keys/ecryptfs.rst``.
+
+Another format 'enc32' can be used to support encrypted keys with payload size
+of 32 bytes.
--
2.7.4
^ permalink raw reply related
* [Patch v3 7/7] MAINTAINERS: Add entry for TEE based Trusted Keys
From: Sumit Garg @ 2019-10-31 13:58 UTC (permalink / raw)
To: jens.wiklander, jarkko.sakkinen, dhowells
Cc: corbet, jejb, zohar, jmorris, serge, casey, ard.biesheuvel,
daniel.thompson, stuart.yoder, janne.karhunen, keyrings,
linux-integrity, linux-security-module, linux-doc, linux-kernel,
linux-arm-kernel, tee-dev, Sumit Garg
In-Reply-To: <1572530323-14802-1-git-send-email-sumit.garg@linaro.org>
Add MAINTAINERS entry for TEE based Trusted Keys framework.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c6c34d0..08d0282 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9059,6 +9059,15 @@ F: include/keys/trusted-type.h
F: security/keys/trusted.c
F: include/keys/trusted.h
+KEYS-TEE-TRUSTED
+M: Sumit Garg <sumit.garg@linaro.org>
+L: linux-integrity@vger.kernel.org
+L: keyrings@vger.kernel.org
+S: Supported
+F: Documentation/security/keys/tee-trusted.rst
+F: include/keys/trusted_tee.h
+F: security/keys/trusted-keys/trusted_tee.c
+
KEYS/KEYRINGS:
M: David Howells <dhowells@redhat.com>
M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
--
2.7.4
^ permalink raw reply related
* Re: [RFC PATCH 04/10] pipe: Use head and tail pointers for the ring, not cursor and length [ver #2]
From: David Howells @ 2019-10-31 14:57 UTC (permalink / raw)
To: Linus Torvalds
Cc: dhowells, Rasmus Villemoes, Greg Kroah-Hartman, Peter Zijlstra,
Nicolas Dichtel, raven, Christian Brauner, keyrings, linux-usb,
linux-block, LSM List, linux-fsdevel, Linux API,
Linux Kernel Mailing List
In-Reply-To: <CAHk-=wh7cf3ANq-G9MmwSQiUK2d-=083C0HV_8hTGe2Mb4X7JA@mail.gmail.com>
Linus Torvalds <torvalds@linux-foundation.org> wrote:
> It's shorter and more obvious to just write
>
> pipe->head = head;
>
> than it is to write
>
> pipe_commit_write(pipe, head);
But easier to find the latter. But whatever.
David
^ permalink raw reply
* Re: [PATCH v3 1/9] KEYS: Defined an IMA hook to measure keys on key create or update
From: Lakshmi Ramasubramanian @ 2019-10-31 15:08 UTC (permalink / raw)
To: Mimi Zohar, dhowells, matthewgarrett, sashal, jamorris,
linux-kernel, linux-integrity, linux-security-module, keyrings
Cc: prsriva
In-Reply-To: <1572523831.5028.43.camel@linux.ibm.com>
On 10/31/19 5:10 AM, Mimi Zohar wrote:
> On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
>> Asymmetric keys used for verifying file signatures or certificates
>> are currently not included in the IMA measurement list.
>>
>> This patch defines a new IMA hook namely ima_post_key_create_or_update()
>> to measure asymmetric keys.
>
> It's not enough for the kernel to be able to compile the kernel after
> applying all the patches in a patch set. After applying each patch,
> the kernel should build properly, otherwise it is not bi-sect safe.
> Refer to "3) Separate your changes" of
> "Documentation/process/submitting-patches.rst.
I started with kernel version 5.3 for this patch set.
I applied Nayna's process_buffer_measurement() patch and then built my
changes on top of that.
This patch has no other dependency as far as I know.
Are you seeing a build break after applying this patch alone?
(PATCH v3 1/9) KEYS: Defined an IMA hook to measure keys on key create
or update
>
> This patch should also define the new "func".
>
Ok - I'll make that change.
thanks,
-lakshmi
^ permalink raw reply
* Re: [PATCH v3 2/9] KEYS: Defined functions to queue and dequeue keys for measurement
From: Lakshmi Ramasubramanian @ 2019-10-31 15:09 UTC (permalink / raw)
To: Mimi Zohar, dhowells, matthewgarrett, sashal, jamorris,
linux-kernel, linux-integrity, linux-security-module, keyrings
Cc: prsriva
In-Reply-To: <1572523841.5028.44.camel@linux.ibm.com>
On 10/31/19 5:10 AM, Mimi Zohar wrote:
> On Wed, 2019-10-30 at 18:19 -0700, Lakshmi Ramasubramanian wrote:
>> Key measurements cannot be done if the IMA hook to measure keys is
>> called before IMA is initialized. Key measurement needs to be deferred
>> if IMA is not yet initialized. Queued keys need to be processed when
>> IMA initialization is completed.
>>
>> This patch defines functions to queue and de-queue keys for measurement.
>
> I would defer this patch until later in the patch set, after having
> the basic measuring of keys in place.
Ok - I'll move this this patch.
thanks,
-lakshmi
^ permalink raw reply
* Re: [RFC PATCH 04/10] pipe: Use head and tail pointers for the ring, not cursor and length [ver #2]
From: David Howells @ 2019-10-31 15:11 UTC (permalink / raw)
To: Rasmus Villemoes
Cc: dhowells, Ilya Dryomov, Linus Torvalds, Greg Kroah-Hartman,
Peter Zijlstra, nicolas.dichtel, raven, Christian Brauner,
keyrings, linux-usb, linux-block, linux-security-module,
linux-fsdevel, linux-api, LKML
In-Reply-To: <4892d186-8eb0-a282-e7e6-e79958431a54@rasmusvillemoes.dk>
How about:
* We use head and tail indices that aren't masked off, except at the
* point of dereference, but rather they're allowed to wrap naturally.
* This means there isn't a dead spot in the buffer, provided the ring
* size is a power of two and <= 2^31.
David
^ permalink raw reply
* Re: [RFC PATCH 11/10] pipe: Add fsync() support [ver #2]
From: David Howells @ 2019-10-31 15:13 UTC (permalink / raw)
To: Christoph Hellwig
Cc: dhowells, torvalds, Rasmus Villemoes, Greg Kroah-Hartman,
Peter Zijlstra, nicolas.dichtel, raven, Christian Brauner,
keyrings, linux-usb, linux-block, linux-security-module,
linux-fsdevel, linux-api, linux-kernel
In-Reply-To: <20191027152223.GA21194@infradead.org>
Christoph Hellwig <hch@infradead.org> wrote:
> I am _really_ worried about overloading fsync for this behavior. fsync
> hasn't done anything for 50 years, and suddenly adding any action
> is not helpful. If you can't use FIONREAD please add a new ioctls
> instead, and document it properly.
Okay.
David
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox