diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 08:55:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 08:55:50 -0700 |
commit | 96b5b7f4f2d59b37c1fc2fba1ae25999accd6dcd (patch) | |
tree | cda421c6cd7533940b35504660a05a366a3ece0c /drivers/char/tpm/tpm.c | |
parent | f72caf7e496465182eeda842ac66a5e75404ddf1 (diff) | |
parent | 539c99fd7fc28f8db257c713c10fb4aceadf8887 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (61 commits)
KEYS: Return more accurate error codes
LSM: Add __init to fixup function.
TOMOYO: Add pathname grouping support.
ima: remove ACPI dependency
TPM: ACPI/PNP dependency removal
security/selinux/ss: Use kstrdup
TOMOYO: Use stack memory for pending entry.
Revert "ima: remove ACPI dependency"
Revert "TPM: ACPI/PNP dependency removal"
KEYS: Do preallocation for __key_link()
TOMOYO: Use mutex_lock_interruptible.
KEYS: Better handling of errors from construct_alloc_key()
KEYS: keyring_serialise_link_sem is only needed for keyring->keyring links
TOMOYO: Use GFP_NOFS rather than GFP_KERNEL.
ima: remove ACPI dependency
TPM: ACPI/PNP dependency removal
selinux: generalize disabling of execmem for plt-in-heap archs
LSM Audit: rename LSM_AUDIT_NO_AUDIT to LSM_AUDIT_DATA_NONE
CRED: Holding a spinlock does not imply the holding of RCU read lock
SMACK: Don't #include Ext2 headers
...
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 068c816e694..05ad4a17a28 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1068,6 +1068,27 @@ void tpm_remove_hardware(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_remove_hardware); +#define TPM_ORD_SAVESTATE cpu_to_be32(152) +#define SAVESTATE_RESULT_SIZE 10 + +static struct tpm_input_header savestate_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(10), + .ordinal = TPM_ORD_SAVESTATE +}; + +/* Bug workaround - some TPM's don't flush the most + * recently changed pcr on suspend, so force the flush + * with an extend to the selected _unused_ non-volatile pcr. + */ +static int tpm_suspend_pcr; +static int __init tpm_suspend_setup(char *str) +{ + get_option(&str, &tpm_suspend_pcr); + return 1; +} +__setup("tpm_suspend_pcr=", tpm_suspend_setup); + /* * We are about to suspend. Save the TPM state * so that it can be restored. @@ -1075,17 +1096,29 @@ EXPORT_SYMBOL_GPL(tpm_remove_hardware); int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) { struct tpm_chip *chip = dev_get_drvdata(dev); - u8 savestate[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* blob length (in bytes) */ - 0, 0, 0, 152 /* TPM_ORD_SaveState */ - }; + struct tpm_cmd_t cmd; + int rc; + + u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; if (chip == NULL) return -ENODEV; - tpm_transmit(chip, savestate, sizeof(savestate)); - return 0; + /* for buggy tpm, flush pcrs with extend to selected dummy */ + if (tpm_suspend_pcr) { + cmd.header.in = pcrextend_header; + cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); + memcpy(cmd.params.pcrextend_in.hash, dummy_hash, + TPM_DIGEST_SIZE); + rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, + "extending dummy pcr before suspend"); + } + + /* now do the actual savestate */ + cmd.header.in = savestate_header; + rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, + "sending savestate before suspend"); + return rc; } EXPORT_SYMBOL_GPL(tpm_pm_suspend); |