diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 17:50:52 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 17:50:52 +0200 |
commit | 0302e28dee643932ee7b3c112ebccdbb9f8ec32c (patch) | |
tree | 405d4cb3f772ef069ed7f291adc4b74a4e73346e /drivers/char/tpm/tpm-chip.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jik... (diff) | |
parent | tpm: Fix reference count to main device (diff) | |
download | linux-0302e28dee643932ee7b3c112ebccdbb9f8ec32c.tar.xz linux-0302e28dee643932ee7b3c112ebccdbb9f8ec32c.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Highlights:
IMA:
- provide ">" and "<" operators for fowner/uid/euid rules
KEYS:
- add a system blacklist keyring
- add KEYCTL_RESTRICT_KEYRING, exposes keyring link restriction
functionality to userland via keyctl()
LSM:
- harden LSM API with __ro_after_init
- add prlmit security hook, implement for SELinux
- revive security_task_alloc hook
TPM:
- implement contextual TPM command 'spaces'"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (98 commits)
tpm: Fix reference count to main device
tpm_tis: convert to using locality callbacks
tpm: fix handling of the TPM 2.0 event logs
tpm_crb: remove a cruft constant
keys: select CONFIG_CRYPTO when selecting DH / KDF
apparmor: Make path_max parameter readonly
apparmor: fix parameters so that the permission test is bypassed at boot
apparmor: fix invalid reference to index variable of iterator line 836
apparmor: use SHASH_DESC_ON_STACK
security/apparmor/lsm.c: set debug messages
apparmor: fix boolreturn.cocci warnings
Smack: Use GFP_KERNEL for smk_netlbl_mls().
smack: fix double free in smack_parse_opts_str()
KEYS: add SP800-56A KDF support for DH
KEYS: Keyring asymmetric key restrict method with chaining
KEYS: Restrict asymmetric key linkage using a specific keychain
KEYS: Add a lookup_restriction function for the asymmetric key type
KEYS: Add KEYCTL_RESTRICT_KEYRING
KEYS: Consistent ordering for __key_link_begin and restrict check
KEYS: Add an optional lookup_restriction hook to key_type
...
Diffstat (limited to 'drivers/char/tpm/tpm-chip.c')
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index c406343848da..9dec9f551b83 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr); static DEFINE_MUTEX(idr_lock); struct class *tpm_class; +struct class *tpmrm_class; dev_t tpm_devt; /** @@ -128,9 +129,19 @@ static void tpm_dev_release(struct device *dev) mutex_unlock(&idr_lock); kfree(chip->log.bios_event_log); + kfree(chip->work_space.context_buf); + kfree(chip->work_space.session_buf); kfree(chip); } +static void tpm_devs_release(struct device *dev) +{ + struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs); + + /* release the master device reference */ + put_device(&chip->dev); +} + /** * tpm_chip_alloc() - allocate a new struct tpm_chip instance * @pdev: device to which the chip is associated @@ -167,31 +178,65 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, chip->dev_num = rc; device_initialize(&chip->dev); + device_initialize(&chip->devs); chip->dev.class = tpm_class; chip->dev.release = tpm_dev_release; chip->dev.parent = pdev; chip->dev.groups = chip->groups; + chip->devs.parent = pdev; + chip->devs.class = tpmrm_class; + chip->devs.release = tpm_devs_release; + /* get extra reference on main device to hold on + * behalf of devs. This holds the chip structure + * while cdevs is in use. The corresponding put + * is in the tpm_devs_release (TPM2 only) + */ + if (chip->flags & TPM_CHIP_FLAG_TPM2) + get_device(&chip->dev); + if (chip->dev_num == 0) chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); else chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num); + chip->devs.devt = + MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES); + rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num); if (rc) goto out; + rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num); + if (rc) + goto out; if (!pdev) chip->flags |= TPM_CHIP_FLAG_VIRTUAL; cdev_init(&chip->cdev, &tpm_fops); + cdev_init(&chip->cdevs, &tpmrm_fops); chip->cdev.owner = THIS_MODULE; + chip->cdevs.owner = THIS_MODULE; chip->cdev.kobj.parent = &chip->dev.kobj; + chip->cdevs.kobj.parent = &chip->devs.kobj; + + chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!chip->work_space.context_buf) { + rc = -ENOMEM; + goto out; + } + chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!chip->work_space.session_buf) { + rc = -ENOMEM; + goto out; + } + chip->locality = -1; return chip; out: + put_device(&chip->devs); put_device(&chip->dev); return ERR_PTR(rc); } @@ -236,7 +281,6 @@ static int tpm_add_char_device(struct tpm_chip *chip) "unable to cdev_add() %s, major %d, minor %d, err=%d\n", dev_name(&chip->dev), MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); - return rc; } @@ -251,6 +295,27 @@ static int tpm_add_char_device(struct tpm_chip *chip) return rc; } + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = cdev_add(&chip->cdevs, chip->devs.devt, 1); + if (rc) { + dev_err(&chip->dev, + "unable to cdev_add() %s, major %d, minor %d, err=%d\n", + dev_name(&chip->devs), MAJOR(chip->devs.devt), + MINOR(chip->devs.devt), rc); + return rc; + } + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = device_add(&chip->devs); + if (rc) { + dev_err(&chip->dev, + "unable to device_register() %s, major %d, minor %d, err=%d\n", + dev_name(&chip->devs), MAJOR(chip->devs.devt), + MINOR(chip->devs.devt), rc); + cdev_del(&chip->cdevs); + return rc; + } + /* Make the chip available. */ mutex_lock(&idr_lock); idr_replace(&dev_nums_idr, chip, chip->dev_num); @@ -384,6 +449,10 @@ void tpm_chip_unregister(struct tpm_chip *chip) { tpm_del_legacy_sysfs(chip); tpm_bios_log_teardown(chip); + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + cdev_del(&chip->cdevs); + device_del(&chip->devs); + } tpm_del_char_device(chip); } EXPORT_SYMBOL_GPL(tpm_chip_unregister); |