mbox series

[RFC,v5,0/1] Add dm verity root hash pkcs7 sig validation.

Message ID 20190619191048.20365-1-jaskarankhurana@linux.microsoft.com (mailing list archive)
Headers show
Series Add dm verity root hash pkcs7 sig validation. | expand

Message

Jaskaran Singh Khurana June 19, 2019, 7:10 p.m. UTC
This patch set adds in-kernel pkcs7 signature checking for the roothash of
the dm-verity hash tree.
The verification is to support cases where the roothash is not secured by
Trusted Boot, UEFI Secureboot or similar technologies.
One of the use cases for this is for dm-verity volumes mounted after boot,
the root hash provided during the creation of the dm-verity volume has to
be secure and thus in-kernel validation implemented here will be used
before we trust the root hash and allow the block device to be created.

Why we are doing validation in the Kernel?

The reason is to still be secure in cases where the attacker is able to
compromise the user mode application in which case the user mode validation
could not have been trusted.
The root hash signature validation in the kernel along with existing
dm-verity implementation gives a higher level of confidence in the
executable code or the protected data. Before allowing the creation of
the device mapper block device the kernel code will check that the detached
pkcs7 signature passed to it validates the roothash and the signature is
trusted by builtin keys set at kernel creation. The kernel should be
secured using Verified boot, UEFI Secure Boot or similar technologies so we
can trust it.

What about attacker mounting non dm-verity volumes to run executable
code?

This verification can be used to have a security architecture where a LSM
can enforce this verification for all the volumes and by doing this it can
ensure that all executable code runs from signed and trusted dm-verity
volumes.

Further patches will be posted that build on this and enforce this
verification based on policy for all the volumes on the system.

How are these changes tested?

To generate and sign the roothash, dump the roothash returned by 
veritysetup format in a text file, say roothash.txt and then sign using
the openssl command:

openssl smime -sign -nocerts -noattr -binary -in <roothash.txt> 
-inkey <keyfile> -signer <certfile> -outform der -out <out_sigfile>

To pass the roothash signature to dm-verity, veritysetup part of cryptsetup
library was modified to take a optional root-hash-sig parameter.

Commandline used to test the changes:

Use the signature file from above step as a parameter to veritysetup.

veritysetup open  <data_device> <name> <hash_device> <root_hash>
 --root-hash-sig=<root_hash_pkcs7_detached_sig>

The changes for veritysetup are in a topic branch for now at:
https://github.com/jaskarankhurana/veritysetup/tree/veritysetup_add_sig

Set kernel commandline dm_verity.verify_sig=1 or 2 for check/force
dm-verity to do root hash signature validation.

Changelog:

v5 (since previous):
  - Code review feedback given by Milan Broz.
  - Remove the Kconfig for root hash verification and instead add a
    commandline parameter(dm_verity.verify_sig) that determines whether to
    check or enforce root hash signature validation.
  - Fixed a small issue when dm-verity was built sepaerately as a module.
  - Added the openssl commandline that can be used to sign the roothash
    in the cover letter.

v4:
  - Code review feedback given by Milan Broz.
  - Add documentation about the root hash signature parameter.
  - Bump up the dm-verity target version.
  - Provided way to sign and test with veritysetup in cover letter.

v3:
  - Code review feedback given by Sasha Levin.
  - Removed EXPORT_SYMBOL_GPL since this was not required.
  - Removed "This file is released under the GPLv2" since we have SPDX
    identifier.
  - Inside verity_verify_root_hash changed EINVAL to ENOKEY when the key
    descriptor is not specified but due to force option being set it is
    expected.
  - Moved CONFIG check to inside verity_verify_get_sig_from_key.
     (Did not move the sig_opts_cleanup to inside verity_dtr as the
     sig_opts do not need to be allocated for the entire duration the block
     device is active unlike the verity structure, note verity_dtr is
     called      only if verity_ctr fails or after the lifetime of the
     block device.)

v2:
  - Code review feedback to pass the signature binary blob as a key that
    can be looked up in the kernel and be used to verify the roothash.
    [Suggested by Milan Broz]
  - Made the code related change suggested in review of v1.
    [Suggested by Balbir Singh]

v1:
  - Add kconfigs to control dm-verity root has signature verification and
    use the signature if specified to verify the root hash.


Jaskaran Khurana (1):
  Adds in-kernel pkcs7 sig check dmverity roothash

 Documentation/device-mapper/verity.txt |   7 ++
 drivers/md/Kconfig                     |   1 +
 drivers/md/Makefile                    |   2 +-
 drivers/md/dm-verity-target.c          |  36 ++++++-
 drivers/md/dm-verity-verify-sig.c      | 139 +++++++++++++++++++++++++
 drivers/md/dm-verity-verify-sig.h      |  37 +++++++
 6 files changed, 216 insertions(+), 6 deletions(-)
 create mode 100644 drivers/md/dm-verity-verify-sig.c
 create mode 100644 drivers/md/dm-verity-verify-sig.h

Comments

Eric Biggers June 28, 2019, 4 a.m. UTC | #1
On Wed, Jun 19, 2019 at 12:10:47PM -0700, Jaskaran Khurana wrote:
> This patch set adds in-kernel pkcs7 signature checking for the roothash of
> the dm-verity hash tree.
> The verification is to support cases where the roothash is not secured by
> Trusted Boot, UEFI Secureboot or similar technologies.
> One of the use cases for this is for dm-verity volumes mounted after boot,
> the root hash provided during the creation of the dm-verity volume has to
> be secure and thus in-kernel validation implemented here will be used
> before we trust the root hash and allow the block device to be created.
> 
> Why we are doing validation in the Kernel?
> 
> The reason is to still be secure in cases where the attacker is able to
> compromise the user mode application in which case the user mode validation
> could not have been trusted.
> The root hash signature validation in the kernel along with existing
> dm-verity implementation gives a higher level of confidence in the
> executable code or the protected data. Before allowing the creation of
> the device mapper block device the kernel code will check that the detached
> pkcs7 signature passed to it validates the roothash and the signature is
> trusted by builtin keys set at kernel creation. The kernel should be
> secured using Verified boot, UEFI Secure Boot or similar technologies so we
> can trust it.
> 
> What about attacker mounting non dm-verity volumes to run executable
> code?
> 
> This verification can be used to have a security architecture where a LSM
> can enforce this verification for all the volumes and by doing this it can
> ensure that all executable code runs from signed and trusted dm-verity
> volumes.
> 
> Further patches will be posted that build on this and enforce this
> verification based on policy for all the volumes on the system.
> 

I don't understand your justification for this feature.

If userspace has already been pwned severely enough for the attacker to be
executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
ioctls need), what good are restrictions on loading more binaries from disk?

Please explain your security model.

- Eric
Jaskaran Singh Khurana June 28, 2019, 7:45 p.m. UTC | #2
Hello Eric,
On Thu, 27 Jun 2019, Eric Biggers wrote:

> On Wed, Jun 19, 2019 at 12:10:47PM -0700, Jaskaran Khurana wrote:
>> This patch set adds in-kernel pkcs7 signature checking for the roothash of
>> the dm-verity hash tree.
>> The verification is to support cases where the roothash is not secured by
>> Trusted Boot, UEFI Secureboot or similar technologies.
>> One of the use cases for this is for dm-verity volumes mounted after boot,
>> the root hash provided during the creation of the dm-verity volume has to
>> be secure and thus in-kernel validation implemented here will be used
>> before we trust the root hash and allow the block device to be created.
>>
>> Why we are doing validation in the Kernel?
>>
>> The reason is to still be secure in cases where the attacker is able to
>> compromise the user mode application in which case the user mode validation
>> could not have been trusted.
>> The root hash signature validation in the kernel along with existing
>> dm-verity implementation gives a higher level of confidence in the
>> executable code or the protected data. Before allowing the creation of
>> the device mapper block device the kernel code will check that the detached
>> pkcs7 signature passed to it validates the roothash and the signature is
>> trusted by builtin keys set at kernel creation. The kernel should be
>> secured using Verified boot, UEFI Secure Boot or similar technologies so we
>> can trust it.
>>
>> What about attacker mounting non dm-verity volumes to run executable
>> code?
>>
>> This verification can be used to have a security architecture where a LSM
>> can enforce this verification for all the volumes and by doing this it can
>> ensure that all executable code runs from signed and trusted dm-verity
>> volumes.
>>
>> Further patches will be posted that build on this and enforce this
>> verification based on policy for all the volumes on the system.
>>
>
> I don't understand your justification for this feature.
>
> If userspace has already been pwned severely enough for the attacker to be
> executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
> ioctls need), what good are restrictions on loading more binaries from disk?
>
> Please explain your security model.
>
> - Eric
>

In a datacenter like environment, this will protect the system from below 
attacks:

1.Prevents attacker from deploying scripts that run arbitrary executables on the system.
2.Prevents physically present malicious admin to run arbitrary code on the
   machine.

Regards,
Jaskaran
Eric Biggers June 28, 2019, 8:34 p.m. UTC | #3
On Fri, Jun 28, 2019 at 12:45:11PM -0700, Jaskaran Singh Khurana wrote:
> 
> Hello Eric,
> On Thu, 27 Jun 2019, Eric Biggers wrote:
> 
> > On Wed, Jun 19, 2019 at 12:10:47PM -0700, Jaskaran Khurana wrote:
> > > This patch set adds in-kernel pkcs7 signature checking for the roothash of
> > > the dm-verity hash tree.
> > > The verification is to support cases where the roothash is not secured by
> > > Trusted Boot, UEFI Secureboot or similar technologies.
> > > One of the use cases for this is for dm-verity volumes mounted after boot,
> > > the root hash provided during the creation of the dm-verity volume has to
> > > be secure and thus in-kernel validation implemented here will be used
> > > before we trust the root hash and allow the block device to be created.
> > > 
> > > Why we are doing validation in the Kernel?
> > > 
> > > The reason is to still be secure in cases where the attacker is able to
> > > compromise the user mode application in which case the user mode validation
> > > could not have been trusted.
> > > The root hash signature validation in the kernel along with existing
> > > dm-verity implementation gives a higher level of confidence in the
> > > executable code or the protected data. Before allowing the creation of
> > > the device mapper block device the kernel code will check that the detached
> > > pkcs7 signature passed to it validates the roothash and the signature is
> > > trusted by builtin keys set at kernel creation. The kernel should be
> > > secured using Verified boot, UEFI Secure Boot or similar technologies so we
> > > can trust it.
> > > 
> > > What about attacker mounting non dm-verity volumes to run executable
> > > code?
> > > 
> > > This verification can be used to have a security architecture where a LSM
> > > can enforce this verification for all the volumes and by doing this it can
> > > ensure that all executable code runs from signed and trusted dm-verity
> > > volumes.
> > > 
> > > Further patches will be posted that build on this and enforce this
> > > verification based on policy for all the volumes on the system.
> > > 
> > 
> > I don't understand your justification for this feature.
> > 
> > If userspace has already been pwned severely enough for the attacker to be
> > executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
> > ioctls need), what good are restrictions on loading more binaries from disk?
> > 
> > Please explain your security model.
> > 
> > - Eric
> > 
> 
> In a datacenter like environment, this will protect the system from below
> attacks:
> 
> 1.Prevents attacker from deploying scripts that run arbitrary executables on the system.
> 2.Prevents physically present malicious admin to run arbitrary code on the
>   machine.
> 
> Regards,
> Jaskaran

So you are trying to protect against people who already have a root shell?

Can't they just e.g. run /usr/bin/python and type in some Python code?

Or run /usr/bin/curl and upload all your secret data to their server.

- Eric
Jaskaran Singh Khurana June 28, 2019, 11:27 p.m. UTC | #4
Hello Eric,

On Fri, 28 Jun 2019, Eric Biggers wrote:

>> In a datacenter like environment, this will protect the system from below
>> attacks:
>>
>> 1.Prevents attacker from deploying scripts that run arbitrary executables on the system.
>> 2.Prevents physically present malicious admin to run arbitrary code on the
>>   machine.
>>
>> Regards,
>> Jaskaran
>
> So you are trying to protect against people who already have a root shell?
>
> Can't they just e.g. run /usr/bin/python and type in some Python code?
>
> Or run /usr/bin/curl and upload all your secret data to their server.
>
> - Eric
>

You are correct, it would not be feasible for a general purpose distro, 
but for embedded systems and other cases where there is a more tightly 
locked-down system.

Regards,
Jaskaran.
James Morris June 29, 2019, 4:01 a.m. UTC | #5
On Thu, 27 Jun 2019, Eric Biggers wrote:

> I don't understand your justification for this feature.
> 
> If userspace has already been pwned severely enough for the attacker to be
> executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
> ioctls need), what good are restrictions on loading more binaries from disk?
> 
> Please explain your security model.

Let's say the system has a policy where all code must be signed with a 
valid key, and that one mechanism for enforcing this is via signed 
dm-verity volumes. Validating the signature within the kernel provides 
stronger assurance than userspace validation. The kernel validates and 
executes the code, using kernel-resident keys, and does not need to rely 
on validation which has occurred across a trust boundary.

You don't need arbitrary CAP_SYS_ADMIN code execution, you just need a 
flaw in the app (or its dependent libraries, or configuration) which 
allows signature validation to be bypassed.

The attacker now needs a kernel rather than a userspace vulnerability to 
bypass the signed code policy.
Milan Broz July 1, 2019, 9:41 a.m. UTC | #6
On 29/06/2019 06:01, James Morris wrote:
> On Thu, 27 Jun 2019, Eric Biggers wrote:
> 
>> I don't understand your justification for this feature.
>>
>> If userspace has already been pwned severely enough for the attacker to be
>> executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
>> ioctls need), what good are restrictions on loading more binaries from disk?
>>
>> Please explain your security model.
> 
> Let's say the system has a policy where all code must be signed with a 
> valid key, and that one mechanism for enforcing this is via signed 
> dm-verity volumes. Validating the signature within the kernel provides 
> stronger assurance than userspace validation. The kernel validates and 
> executes the code, using kernel-resident keys, and does not need to rely 
> on validation which has occurred across a trust boundary.

Yes, but as it is implemented in this patch, a certificate is provided as
a binary blob by the (super)user that activates the dm-verity device.

Actually, I can put there anything that looks like a correct signature (self-signed
or so), and dm-verity code is happy because the root hash is now signed.

Maybe could this concept be extended to support in-kernel compiled certificates?

I like the idea of signed root hash, but the truth is that if you have access
to device activation, it brings nothing, you can just put any cert in the keyring
and use it.

Milan

> 
> You don't need arbitrary CAP_SYS_ADMIN code execution, you just need a 
> flaw in the app (or its dependent libraries, or configuration) which 
> allows signature validation to be bypassed.
> 
> The attacker now needs a kernel rather than a userspace vulnerability to 
> bypass the signed code policy.
>
Jaskaran Singh Khurana July 1, 2019, 5:33 p.m. UTC | #7
Hello Milan,
On Mon, 1 Jul 2019, Milan Broz wrote:

> On 29/06/2019 06:01, James Morris wrote:
>> On Thu, 27 Jun 2019, Eric Biggers wrote:
>>
>>> I don't understand your justification for this feature.
>>>
>>> If userspace has already been pwned severely enough for the attacker to be
>>> executing arbitrary code with CAP_SYS_ADMIN (which is what the device mapper
>>> ioctls need), what good are restrictions on loading more binaries from disk?
>>>
>>> Please explain your security model.
>>
>> Let's say the system has a policy where all code must be signed with a
>> valid key, and that one mechanism for enforcing this is via signed
>> dm-verity volumes. Validating the signature within the kernel provides
>> stronger assurance than userspace validation. The kernel validates and
>> executes the code, using kernel-resident keys, and does not need to rely
>> on validation which has occurred across a trust boundary.
>
> Yes, but as it is implemented in this patch, a certificate is provided as
> a binary blob by the (super)user that activates the dm-verity device.
>
> Actually, I can put there anything that looks like a correct signature (self-signed
> or so), and dm-verity code is happy because the root hash is now signed.
>
> Maybe could this concept be extended to support in-kernel compiled certificates?
>
> I like the idea of signed root hash, but the truth is that if you have access
> to device activation, it brings nothing, you can just put any cert in the keyring
> and use it.
>
> Milan
>

The signature needs to be trusted by the .builtin_trusted_keys which is
a read-only list of keys that were compiled into the kernel. The 
verify_pkcs7_signature verifies trust against the builtin keyring so I 
think what you are suggesting is covered here.

Regards,
Jaskaran.