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

tpm: vtpm_proxy: Prevent userspace from sending driver command

To prevent userspace from sending the TPM driver command to set
the locality, we need to check every command that is sent from
user space. To distinguish user space commands from internally
sent commands we introduce an additional state flag
STATE_DRIVER_COMMAND that is set while the driver sends this
command. Similar to the TPM 2 space commands we return an error
code when this command is detected.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

authored by

Stefan Berger and committed by
Jarkko Sakkinen
d8b5d945 be4c9acf

+33
+33
drivers/char/tpm/tpm_vtpm_proxy.c
··· 43 43 #define STATE_OPENED_FLAG BIT(0) 44 44 #define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */ 45 45 #define STATE_REGISTERED_FLAG BIT(2) 46 + #define STATE_DRIVER_COMMAND BIT(3) /* sending a driver specific command */ 46 47 47 48 size_t req_len; /* length of queued TPM request */ 48 49 size_t resp_len; /* length of queued TPM response */ ··· 300 299 return len; 301 300 } 302 301 302 + static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, 303 + u8 *buf, size_t count) 304 + { 305 + struct tpm_input_header *hdr = (struct tpm_input_header *)buf; 306 + 307 + if (count < sizeof(struct tpm_input_header)) 308 + return 0; 309 + 310 + if (chip->flags & TPM_CHIP_FLAG_TPM2) { 311 + switch (be32_to_cpu(hdr->ordinal)) { 312 + case TPM2_CC_SET_LOCALITY: 313 + return 1; 314 + } 315 + } else { 316 + switch (be32_to_cpu(hdr->ordinal)) { 317 + case TPM_ORD_SET_LOCALITY: 318 + return 1; 319 + } 320 + } 321 + return 0; 322 + } 323 + 303 324 /* 304 325 * Called when core TPM driver forwards TPM requests to 'server side'. 305 326 * ··· 343 320 count, sizeof(proxy_dev->buffer)); 344 321 return -EIO; 345 322 } 323 + 324 + if (!(proxy_dev->state & STATE_DRIVER_COMMAND) && 325 + vtpm_proxy_is_driver_command(chip, buf, count)) 326 + return -EFAULT; 346 327 347 328 mutex_lock(&proxy_dev->buf_lock); 348 329 ··· 403 376 struct tpm_buf buf; 404 377 int rc; 405 378 const struct tpm_output_header *header; 379 + struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 406 380 407 381 if (chip->flags & TPM_CHIP_FLAG_TPM2) 408 382 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, ··· 415 387 return rc; 416 388 tpm_buf_append_u8(&buf, locality); 417 389 390 + proxy_dev->state |= STATE_DRIVER_COMMAND; 391 + 418 392 rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, 419 393 TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, 420 394 "attempting to set locality"); 395 + 396 + proxy_dev->state &= ~STATE_DRIVER_COMMAND; 397 + 421 398 if (rc < 0) { 422 399 locality = rc; 423 400 goto out;