Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tpm: fix: sanitized code paths in tpm_chip_register()

I started to work with PPI interface so that it would be available
under character device sysfs directory and realized that chip
registeration was still too messy.

In TPM 1.x in some rare scenarios (errors that almost never occur)
wrong order in deinitialization steps was taken in teardown. I
reproduced these scenarios by manually inserting error codes in the
place of the corresponding function calls.

The key problem is that the teardown is messy with two separate code
paths (this was inherited when moving code from tpm-interface.c).

Moved TPM 1.x specific register/unregister functionality to own helper
functions and added single code path for teardown in tpm_chip_register().
Now the code paths have been fixed and it should be easier to review
later on this part of the code.

Cc: <stable@vger.kernel.org>
Fixes: 7a1d7e6dd76a ("tpm: TPM 2.0 baseline support")
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Scot Doyle <lkml14@scotdoyle.com>
Reviewed-by: Peter Huewe <peterhuewe@gmx.de>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>

authored by

Jarkko Sakkinen and committed by
Peter Huewe
34d47b63 d972b052

+42 -24
+42 -24
drivers/char/tpm/tpm-chip.c
··· 170 170 device_unregister(&chip->dev); 171 171 } 172 172 173 + static int tpm1_chip_register(struct tpm_chip *chip) 174 + { 175 + int rc; 176 + 177 + if (chip->flags & TPM_CHIP_FLAG_TPM2) 178 + return 0; 179 + 180 + rc = tpm_sysfs_add_device(chip); 181 + if (rc) 182 + return rc; 183 + 184 + rc = tpm_add_ppi(chip); 185 + if (rc) { 186 + tpm_sysfs_del_device(chip); 187 + return rc; 188 + } 189 + 190 + chip->bios_dir = tpm_bios_log_setup(chip->devname); 191 + 192 + return 0; 193 + } 194 + 195 + static void tpm1_chip_unregister(struct tpm_chip *chip) 196 + { 197 + if (chip->flags & TPM_CHIP_FLAG_TPM2) 198 + return; 199 + 200 + if (chip->bios_dir) 201 + tpm_bios_log_teardown(chip->bios_dir); 202 + 203 + tpm_remove_ppi(chip); 204 + 205 + tpm_sysfs_del_device(chip); 206 + } 207 + 173 208 /* 174 209 * tpm_chip_register() - create a character device for the TPM chip 175 210 * @chip: TPM chip to use. ··· 220 185 { 221 186 int rc; 222 187 223 - /* Populate sysfs for TPM1 devices. */ 224 - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { 225 - rc = tpm_sysfs_add_device(chip); 226 - if (rc) 227 - goto del_misc; 228 - 229 - rc = tpm_add_ppi(chip); 230 - if (rc) 231 - goto del_sysfs; 232 - 233 - chip->bios_dir = tpm_bios_log_setup(chip->devname); 234 - } 188 + rc = tpm1_chip_register(chip); 189 + if (rc) 190 + return rc; 235 191 236 192 rc = tpm_dev_add_device(chip); 237 193 if (rc) 238 - return rc; 194 + goto out_err; 239 195 240 196 /* Make the chip available. */ 241 197 spin_lock(&driver_lock); ··· 236 210 chip->flags |= TPM_CHIP_FLAG_REGISTERED; 237 211 238 212 return 0; 239 - del_sysfs: 240 - tpm_sysfs_del_device(chip); 241 - del_misc: 242 - tpm_dev_del_device(chip); 213 + out_err: 214 + tpm1_chip_unregister(chip); 243 215 return rc; 244 216 } 245 217 EXPORT_SYMBOL_GPL(tpm_chip_register); ··· 262 238 spin_unlock(&driver_lock); 263 239 synchronize_rcu(); 264 240 265 - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { 266 - if (chip->bios_dir) 267 - tpm_bios_log_teardown(chip->bios_dir); 268 - tpm_remove_ppi(chip); 269 - tpm_sysfs_del_device(chip); 270 - } 271 - 241 + tpm1_chip_unregister(chip); 272 242 tpm_dev_del_device(chip); 273 243 } 274 244 EXPORT_SYMBOL_GPL(tpm_chip_unregister);