2018-06-25 10:46:37

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 0/5] Have IMA find and use a tpm_chip until system shutdown

This series of patches converts IMA's usage of the tpm_chip to find a TPM
chip initially and use it until the machine is shut down. To do this we need
to introduce a kref for the tpm_chip that IMA and all other users of a
tpm_chip hold onto until they don't need the TPM chip anymore.

Stefan

v3->v4:
- followed Jason's suggestions

v2->v3:
- renaming tpm_chip_find_get() to tpm_get_ops()
- IMA does not lock access to ima_tpm_chip anymore
- IMA does not have a reboot notifier to release the chip anymore

v1->v2:
- use the kref of the device via get_device()/put_device()


Stefan Berger (5):
tpm: rename tpm_chip_find_get() to tpm_find_get_ops()
tpm: Implement tpm_default_chip() to find a TPM chip
tpm: Convert tpm_find_get_ops() to use tpm_default_chip()
ima: Use tpm_default_chip() and call TPM functions with a tpm_chip
ima: Get rid of ima_used_chip and use ima_tpm_chip != NULL instead

drivers/char/tpm/tpm-chip.c | 68 +++++++++++++++++++----------
drivers/char/tpm/tpm-interface.c | 14 +++---
drivers/char/tpm/tpm.h | 2 +-
include/linux/tpm.h | 5 +++
security/integrity/ima/ima.h | 2 +-
security/integrity/ima/ima_crypto.c | 4 +-
security/integrity/ima/ima_init.c | 16 +++----
security/integrity/ima/ima_queue.c | 4 +-
8 files changed, 69 insertions(+), 46 deletions(-)

--
2.17.1



2018-06-25 10:44:31

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 4/5] ima: Use tpm_default_chip() and call TPM functions with a tpm_chip

Rather than accessing the TPM functions by passing a NULL pointer for
the tpm_chip, which causes a lookup for a suitable chip every time, get a
hold of a tpm_chip and access the TPM functions using it.

Signed-off-by: Stefan Berger <[email protected]>
---
security/integrity/ima/ima.h | 1 +
security/integrity/ima/ima_crypto.c | 2 +-
security/integrity/ima/ima_init.c | 11 ++++-------
security/integrity/ima/ima_queue.c | 2 +-
4 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 354bb5716ce3..35409461a3f2 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -56,6 +56,7 @@ extern int ima_policy_flag;
extern int ima_used_chip;
extern int ima_hash_algo;
extern int ima_appraise;
+extern struct tpm_chip *ima_tpm_chip;

/* IMA event related data */
struct ima_event_data {
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 4e085a17124f..88082f35adb2 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -634,7 +634,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
if (!ima_used_chip)
return;

- if (tpm_pcr_read(NULL, idx, pcr) != 0)
+ if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0)
pr_err("Error Communicating to TPM chip\n");
}

diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 29b72cd2502e..1437ed3dbccc 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -27,6 +27,7 @@
/* name for boot aggregate entry */
static const char *boot_aggregate_name = "boot_aggregate";
int ima_used_chip;
+struct tpm_chip *ima_tpm_chip;

/* Add the boot aggregate to the IMA measurement list and extend
* the PCR register.
@@ -106,17 +107,13 @@ void __init ima_load_x509(void)

int __init ima_init(void)
{
- u8 pcr_i[TPM_DIGEST_SIZE];
int rc;

- ima_used_chip = 0;
- rc = tpm_pcr_read(NULL, 0, pcr_i);
- if (rc == 0)
- ima_used_chip = 1;
+ ima_tpm_chip = tpm_default_chip();

+ ima_used_chip = ima_tpm_chip != NULL;
if (!ima_used_chip)
- pr_info("No TPM chip found, activating TPM-bypass! (rc=%d)\n",
- rc);
+ pr_info("No TPM chip found, activating TPM-bypass!\n");

rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
if (rc)
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 418f35e38015..c6303fa19a49 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -145,7 +145,7 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
if (!ima_used_chip)
return result;

- result = tpm_pcr_extend(NULL, pcr, hash);
+ result = tpm_pcr_extend(ima_tpm_chip, pcr, hash);
if (result != 0)
pr_err("Error Communicating to TPM chip, result: %d\n", result);
return result;
--
2.17.1


2018-06-25 10:44:46

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 5/5] ima: Get rid of ima_used_chip and use ima_tpm_chip != NULL instead

Get rid of ima_used_chip and use ima_tpm_chip variable instead for
determining whether to use the TPM chip.

Signed-off-by: Stefan Berger <[email protected]>
---
security/integrity/ima/ima.h | 1 -
security/integrity/ima/ima_crypto.c | 2 +-
security/integrity/ima/ima_init.c | 7 ++-----
security/integrity/ima/ima_queue.c | 2 +-
4 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 35409461a3f2..2ab1affffa36 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -53,7 +53,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
extern int ima_policy_flag;

/* set during initialization */
-extern int ima_used_chip;
extern int ima_hash_algo;
extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 88082f35adb2..7e7e7e7c250a 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -631,7 +631,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,

static void __init ima_pcrread(int idx, u8 *pcr)
{
- if (!ima_used_chip)
+ if (!ima_tpm_chip)
return;

if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0)
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 1437ed3dbccc..faac9ecaa0ae 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -26,7 +26,6 @@

/* name for boot aggregate entry */
static const char *boot_aggregate_name = "boot_aggregate";
-int ima_used_chip;
struct tpm_chip *ima_tpm_chip;

/* Add the boot aggregate to the IMA measurement list and extend
@@ -65,7 +64,7 @@ static int __init ima_add_boot_aggregate(void)
iint->ima_hash->algo = HASH_ALGO_SHA1;
iint->ima_hash->length = SHA1_DIGEST_SIZE;

- if (ima_used_chip) {
+ if (ima_tpm_chip) {
result = ima_calc_boot_aggregate(&hash.hdr);
if (result < 0) {
audit_cause = "hashing_error";
@@ -110,9 +109,7 @@ int __init ima_init(void)
int rc;

ima_tpm_chip = tpm_default_chip();
-
- ima_used_chip = ima_tpm_chip != NULL;
- if (!ima_used_chip)
+ if (!ima_tpm_chip)
pr_info("No TPM chip found, activating TPM-bypass!\n");

rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index c6303fa19a49..b186819bd5aa 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -142,7 +142,7 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
{
int result = 0;

- if (!ima_used_chip)
+ if (!ima_tpm_chip)
return result;

result = tpm_pcr_extend(ima_tpm_chip, pcr, hash);
--
2.17.1


2018-06-25 10:45:04

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 3/5] tpm: Convert tpm_find_get_ops() to use tpm_default_chip()

Convert tpm_find_get_ops() to use tpm_default_chip() in case no chip
is passed in.

Signed-off-by: Stefan Berger <[email protected]>
---
drivers/char/tpm/tpm-chip.c | 32 +++++++++++++-------------------
1 file changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index f551061262c9..b01d34983766 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -124,29 +124,23 @@ EXPORT_SYMBOL_GPL(tpm_default_chip);
*/
struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip)
{
- struct tpm_chip *res = NULL;
- int chip_num = 0;
- int chip_prev;
-
- mutex_lock(&idr_lock);
+ int rc;

- if (!chip) {
- do {
- chip_prev = chip_num;
- chip = idr_get_next(&dev_nums_idr, &chip_num);
- if (chip && !tpm_try_get_ops(chip)) {
- res = chip;
- break;
- }
- } while (chip_prev != chip_num);
- } else {
+ if (chip) {
if (!tpm_try_get_ops(chip))
- res = chip;
+ return chip;
+ return NULL;
}

- mutex_unlock(&idr_lock);
-
- return res;
+ chip = tpm_default_chip();
+ if (!chip)
+ return NULL;
+ rc = tpm_try_get_ops(chip);
+ /* release additional reference we got from tpm_default_chip() */
+ put_device(&chip->dev);
+ if (!rc)
+ return NULL;
+ return chip;
}

/**
--
2.17.1


2018-06-25 10:45:14

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 1/5] tpm: rename tpm_chip_find_get() to tpm_find_get_ops()

Rename tpm_chip_find_get() to tpm_find_get_ops() to more closely match
the tpm_put_ops() counter part.

Signed-off-by: Stefan Berger <[email protected]>
---
drivers/char/tpm/tpm-chip.c | 9 ++++++---
drivers/char/tpm/tpm-interface.c | 14 +++++++-------
drivers/char/tpm/tpm.h | 2 +-
3 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 0a62c19937b6..242b716aed5e 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -81,18 +81,21 @@ void tpm_put_ops(struct tpm_chip *chip)
EXPORT_SYMBOL_GPL(tpm_put_ops);

/**
- * tpm_chip_find_get() - find and reserve a TPM chip
+ * tpm_find_get_ops() - find and reserve a TPM chip
* @chip: a &struct tpm_chip instance, %NULL for the default chip
*
* Finds a TPM chip and reserves its class device and operations. The chip must
- * be released with tpm_chip_put_ops() after use.
+ * be released with tpm_put_ops() after use.
+ * This function is for internal use only. It supports existing TPM callers
+ * by accepting NULL, but those callers should be converted to pass in a chip
+ * directly.
*
* Return:
* A reserved &struct tpm_chip instance.
* %NULL if a chip is not found.
* %NULL if the chip is not available.
*/
-struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip)
+struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip)
{
struct tpm_chip *res = NULL;
int chip_num = 0;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index c43a9e28995e..b4bb34216050 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -929,7 +929,7 @@ int tpm_is_tpm2(struct tpm_chip *chip)
{
int rc;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;

@@ -953,7 +953,7 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
int rc;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
@@ -1012,7 +1012,7 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
u32 count = 0;
int i;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;

@@ -1141,7 +1141,7 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
int rc;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;

@@ -1261,7 +1261,7 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
return -EINVAL;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;

@@ -1323,7 +1323,7 @@ int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload,
{
int rc;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
return -ENODEV;

@@ -1351,7 +1351,7 @@ int tpm_unseal_trusted(struct tpm_chip *chip,
{
int rc;

- chip = tpm_chip_find_get(chip);
+ chip = tpm_find_get_ops(chip);
if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
return -ENODEV;

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 7f2d0f489e9c..c38772474091 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -535,7 +535,7 @@ static inline void tpm_msleep(unsigned int delay_msec)
delay_msec * 1000);
};

-struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip);
+struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);

--
2.17.1


2018-06-25 10:45:32

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v4 2/5] tpm: Implement tpm_default_chip() to find a TPM chip

Implement tpm_default_chip() to find a TPM chip and get a reference to it.
This function is also suitable for other subsystems to call and hold onto
the chip.

Signed-off-by: Stefan Berger <[email protected]>
---
drivers/char/tpm/tpm-chip.c | 27 +++++++++++++++++++++++++++
include/linux/tpm.h | 5 +++++
2 files changed, 32 insertions(+)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 242b716aed5e..f551061262c9 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -80,6 +80,33 @@ void tpm_put_ops(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_put_ops);

+/**
+ * tpm_default_chip() - find a TPM chip and get a reference to it
+ */
+struct tpm_chip *tpm_default_chip(void)
+{
+ struct tpm_chip *chip, *res = NULL;
+ int chip_num = 0;
+ int chip_prev;
+
+ mutex_lock(&idr_lock);
+
+ do {
+ chip_prev = chip_num;
+ chip = idr_get_next(&dev_nums_idr, &chip_num);
+ if (chip) {
+ get_device(&chip->dev);
+ res = chip;
+ break;
+ }
+ } while (chip_prev != chip_num);
+
+ mutex_unlock(&idr_lock);
+
+ return res;
+}
+EXPORT_SYMBOL_GPL(tpm_default_chip);
+
/**
* tpm_find_get_ops() - find and reserve a TPM chip
* @chip: a &struct tpm_chip instance, %NULL for the default chip
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 06639fb6ab85..e0e51c49a0e6 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -61,6 +61,7 @@ extern int tpm_seal_trusted(struct tpm_chip *chip,
extern int tpm_unseal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
struct trusted_key_options *options);
+extern struct tpm_chip *tpm_default_chip(void);
#else
static inline int tpm_is_tpm2(struct tpm_chip *chip)
{
@@ -96,5 +97,9 @@ static inline int tpm_unseal_trusted(struct tpm_chip *chip,
{
return -ENODEV;
}
+static inline struct tpm_chip *tpm_default_chip(void)
+{
+ return NULL;
+}
#endif
#endif
--
2.17.1


2018-06-26 08:21:36

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 0/5] Have IMA find and use a tpm_chip until system shutdown

On Mon, 2018-06-25 at 06:43 -0400, Stefan Berger wrote:
> This series of patches converts IMA's usage of the tpm_chip to find a TPM
> chip initially and use it until the machine is shut down. To do this we need
> to introduce a kref for the tpm_chip that IMA and all other users of a
> tpm_chip hold onto until they don't need the TPM chip anymore.
>
> Stefan
>
> v3->v4:
> - followed Jason's suggestions

"Jason's suggestions" means nothing.

/Jarkko

2018-06-26 08:22:02

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 0/5] Have IMA find and use a tpm_chip until system shutdown

On Tue, 2018-06-26 at 11:19 +0300, Jarkko Sakkinen wrote:
> On Mon, 2018-06-25 at 06:43 -0400, Stefan Berger wrote:
> > This series of patches converts IMA's usage of the tpm_chip to find a TPM
> > chip initially and use it until the machine is shut down. To do this we need
> > to introduce a kref for the tpm_chip that IMA and all other users of a
> > tpm_chip hold onto until they don't need the TPM chip anymore.
> >
> > Stefan
> >
> > v3->v4:
> > - followed Jason's suggestions
>
> "Jason's suggestions" means nothing.

Please fix the change log for the next version.

/Jarkko

2018-06-26 08:23:09

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 0/5] Have IMA find and use a tpm_chip until system shutdown

On Tue, 2018-06-26 at 11:20 +0300, Jarkko Sakkinen wrote:
> On Tue, 2018-06-26 at 11:19 +0300, Jarkko Sakkinen wrote:
> > On Mon, 2018-06-25 at 06:43 -0400, Stefan Berger wrote:
> > > This series of patches converts IMA's usage of the tpm_chip to find a TPM
> > > chip initially and use it until the machine is shut down. To do this we
> > > need
> > > to introduce a kref for the tpm_chip that IMA and all other users of a
> > > tpm_chip hold onto until they don't need the TPM chip anymore.
> > >
> > > Stefan
> > >
> > > v3->v4:
> > > - followed Jason's suggestions
> >
> > "Jason's suggestions" means nothing.
>
> Please fix the change log for the next version.

You should probably resend this version as also linu-security-module
is missing. NAK because of that.

/Jarkko