Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55b3a0cb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull general security subsystem updates from James Morris:
 "TPM (from Jarkko):
   - essential clean up for tpm_crb so that ARM64 and x86 versions do
     not distract each other as much as before

   - /dev/tpm0 rejects now too short writes (shorter buffer than
     specified in the command header

   - use DMA-safe buffer in tpm_tis_spi

   - otherwise mostly minor fixes.

  Smack:
   - base support for overlafs

  Capabilities:
   - BPRM_FCAPS fixes, from Richard Guy Briggs:

     The audit subsystem is adding a BPRM_FCAPS record when auditing
     setuid application execution (SYSCALL execve). This is not expected
     as it was supposed to be limited to when the file system actually
     had capabilities in an extended attribute. It lists all
     capabilities making the event really ugly to parse what is
     happening. The PATH record correctly records the setuid bit and
     owner. Suppress the BPRM_FCAPS record on set*id.

  TOMOYO:
   - Y2038 timestamping fixes"

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (28 commits)
  MAINTAINERS: update the IMA, EVM, trusted-keys, encrypted-keys entries
  Smack: Base support for overlayfs
  MAINTAINERS: remove David Safford as maintainer for encrypted+trusted keys
  tomoyo: fix timestamping for y2038
  capabilities: audit log other surprising conditions
  capabilities: fix logic for effective root or real root
  capabilities: invert logic for clarity
  capabilities: remove a layer of conditional logic
  capabilities: move audit log decision to function
  capabilities: use intuitive names for id changes
  capabilities: use root_priveleged inline to clarify logic
  capabilities: rename has_cap to has_fcap
  capabilities: intuitive names for cap gain status
  capabilities: factor out cap_bprm_set_creds privileged root
  tpm, tpm_tis: use ARRAY_SIZE() to define TPM_HID_USR_IDX
  tpm: fix duplicate inline declaration specifier
  tpm: fix type of a local variables in tpm_tis_spi.c
  tpm: fix type of a local variable in tpm2_map_command()
  tpm: fix type of a local variable in tpm2_get_cc_attrs_tbl()
  tpm-dev-common: Reject too short writes
  ...
parents dee02770 34d8751f
Loading
Loading
Loading
Loading
+4 −9
Original line number Diff line number Diff line
@@ -5219,8 +5219,7 @@ F: fs/ext4/

Extended Verification Module (EVM)
M:	Mimi Zohar <zohar@linux.vnet.ibm.com>
L:	linux-ima-devel@lists.sourceforge.net
L:	linux-security-module@vger.kernel.org
L:	linux-integrity@vger.kernel.org
S:	Supported
F:	security/integrity/evm/

@@ -6847,9 +6846,7 @@ L: linux-crypto@vger.kernel.org
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M:	Mimi Zohar <zohar@linux.vnet.ibm.com>
M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
L:	linux-ima-devel@lists.sourceforge.net
L:	linux-ima-user@lists.sourceforge.net
L:	linux-security-module@vger.kernel.org
L:	linux-integrity@vger.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
S:	Supported
F:	security/integrity/ima/
@@ -7632,8 +7629,7 @@ F: kernel/kexec*

KEYS-ENCRYPTED
M:	Mimi Zohar <zohar@linux.vnet.ibm.com>
M:	David Safford <safford@us.ibm.com>
L:	linux-security-module@vger.kernel.org
L:	linux-integrity@vger.kernel.org
L:	keyrings@vger.kernel.org
S:	Supported
F:	Documentation/security/keys/trusted-encrypted.rst
@@ -7641,9 +7637,8 @@ F: include/keys/encrypted-type.h
F:	security/keys/encrypted-keys/

KEYS-TRUSTED
M:	David Safford <safford@us.ibm.com>
M:	Mimi Zohar <zohar@linux.vnet.ibm.com>
L:	linux-security-module@vger.kernel.org
L:	linux-integrity@vger.kernel.org
L:	keyrings@vger.kernel.org
S:	Supported
F:	Documentation/security/keys/trusted-encrypted.rst
+6 −0
Original line number Diff line number Diff line
@@ -110,6 +110,12 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
		return -EFAULT;
	}

	if (in_size < 6 ||
	    in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) {
		mutex_unlock(&priv->buffer_mutex);
		return -EINVAL;
	}

	/* atomic tpm command send and result receive. We only hold the ops
	 * lock during this period so that the tpm can be unregistered even if
	 * the char dev is held open.
+48 −39
Original line number Diff line number Diff line
@@ -20,44 +20,48 @@
#include <linux/device.h>
#include "tpm.h"

#define READ_PUBEK_RESULT_SIZE 314
struct tpm_readpubek_out {
	u8 algorithm[4];
	u8 encscheme[2];
	u8 sigscheme[2];
	__be32 paramsize;
	u8 parameters[12];
	__be32 keysize;
	u8 modulus[256];
	u8 checksum[20];
} __packed;

#define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
#define TPM_ORD_READPUBEK 124
static const struct tpm_input_header tpm_readpubek_header = {
	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
	.length = cpu_to_be32(30),
	.ordinal = cpu_to_be32(TPM_ORD_READPUBEK)
};

static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
			  char *buf)
{
	u8 *data;
	struct tpm_cmd_t tpm_cmd;
	ssize_t err;
	int i, rc;
	struct tpm_buf tpm_buf;
	struct tpm_readpubek_out *out;
	ssize_t rc;
	int i;
	char *str = buf;
	struct tpm_chip *chip = to_tpm_chip(dev);
	char anti_replay[20];

	memset(&tpm_cmd, 0, sizeof(tpm_cmd));
	memset(&anti_replay, 0, sizeof(anti_replay));

	rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK);
	if (rc)
		return rc;

	tpm_cmd.header.in = tpm_readpubek_header;
	err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
	tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay));

	rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE,
			      READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
			      "attempting to read the PUBEK");
	if (err)
		goto out;
	if (rc) {
		tpm_buf_destroy(&tpm_buf);
		return 0;
	}

	/*
	   ignore header 10 bytes
	   algorithm 32 bits (1 == RSA )
	   encscheme 16 bits
	   sigscheme 16 bits
	   parameters (RSA 12->bytes: keybit, #primes, expbit)
	   keylenbytes 32 bits
	   256 byte modulus
	   ignore checksum 20 bytes
	 */
	data = tpm_cmd.params.readpubek_out_buffer;
	out = (struct tpm_readpubek_out *)&tpm_buf.data[10];
	str +=
	    sprintf(str,
		    "Algorithm: %02X %02X %02X %02X\n"
@@ -68,21 +72,26 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
		    "%02X %02X %02X %02X\n"
		    "Modulus length: %d\n"
		    "Modulus:\n",
		    data[0], data[1], data[2], data[3],
		    data[4], data[5],
		    data[6], data[7],
		    data[12], data[13], data[14], data[15],
		    data[16], data[17], data[18], data[19],
		    data[20], data[21], data[22], data[23],
		    be32_to_cpu(*((__be32 *) (data + 24))));
		    out->algorithm[0], out->algorithm[1], out->algorithm[2],
		    out->algorithm[3],
		    out->encscheme[0], out->encscheme[1],
		    out->sigscheme[0], out->sigscheme[1],
		    out->parameters[0], out->parameters[1],
		    out->parameters[2], out->parameters[3],
		    out->parameters[4], out->parameters[5],
		    out->parameters[6], out->parameters[7],
		    out->parameters[8], out->parameters[9],
		    out->parameters[10], out->parameters[11],
		    be32_to_cpu(out->keysize));

	for (i = 0; i < 256; i++) {
		str += sprintf(str, "%02X ", data[i + 28]);
		str += sprintf(str, "%02X ", out->modulus[i]);
		if ((i + 1) % 16 == 0)
			str += sprintf(str, "\n");
	}
out:

	rc = str - buf;
	tpm_buf_destroy(&tpm_buf);
	return rc;
}
static DEVICE_ATTR_RO(pubek);
+1 −14
Original line number Diff line number Diff line
@@ -345,17 +345,6 @@ enum tpm_sub_capabilities {
	TPM_CAP_PROP_TIS_DURATION = 0x120,
};

struct	tpm_readpubek_params_out {
	u8	algorithm[4];
	u8	encscheme[2];
	u8	sigscheme[2];
	__be32	paramsize;
	u8	parameters[12]; /*assuming RSA*/
	__be32	keysize;
	u8	modulus[256];
	u8	checksum[20];
} __packed;

typedef union {
	struct	tpm_input_header in;
	struct	tpm_output_header out;
@@ -385,8 +374,6 @@ struct tpm_getrandom_in {
} __packed;

typedef union {
	struct	tpm_readpubek_params_out readpubek_out;
	u8	readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
	struct	tpm_pcrread_in	pcrread_in;
	struct	tpm_pcrread_out	pcrread_out;
	struct	tpm_getrandom_in getrandom_in;
@@ -557,7 +544,7 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
}
#endif

static inline inline u32 tpm2_rc_value(u32 rc)
static inline u32 tpm2_rc_value(u32 rc)
{
	return (rc & BIT(7)) ? rc & 0xff : rc;
}
+22 −51
Original line number Diff line number Diff line
@@ -834,72 +834,43 @@ static const struct tpm_input_header tpm2_selftest_header = {
};

/**
 * tpm2_continue_selftest() - start a self test
 *
 * @chip: TPM chip to use
 * @full: test all commands instead of testing only those that were not
 *        previously tested.
 *
 * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING.
 */
static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
{
	int rc;
	struct tpm2_cmd cmd;

	cmd.header.in = tpm2_selftest_header;
	cmd.params.selftest_in.full_test = full;

	rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
			      "continue selftest");

	/* At least some prototype chips seem to give RC_TESTING error
	 * immediately. This is a workaround for that.
	 */
	if (rc == TPM2_RC_TESTING) {
		dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
		rc = 0;
	}

	return rc;
}

/**
 * tpm2_do_selftest() - run a full self test
 * tpm2_do_selftest() - ensure that all self tests have passed
 *
 * @chip: TPM chip to use
 *
 * Return: Same as with tpm_transmit_cmd.
 *
 * During the self test TPM2 commands return with the error code RC_TESTING.
 * Waiting is done by issuing PCR read until it executes successfully.
 * The TPM can either run all self tests synchronously and then return
 * RC_SUCCESS once all tests were successful. Or it can choose to run the tests
 * asynchronously and return RC_TESTING immediately while the self tests still
 * execute in the background. This function handles both cases and waits until
 * all tests have completed.
 */
static int tpm2_do_selftest(struct tpm_chip *chip)
{
	int rc;
	unsigned int loops;
	unsigned int delay_msec = 100;
	unsigned long duration;
	int i;

	duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
	unsigned int delay_msec = 20;
	long duration;
	struct tpm2_cmd cmd;

	loops = jiffies_to_msecs(duration) / delay_msec;
	duration = jiffies_to_msecs(
		tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST));

	rc = tpm2_start_selftest(chip, true);
	if (rc)
		return rc;
	while (duration > 0) {
		cmd.header.in = tpm2_selftest_header;
		cmd.params.selftest_in.full_test = 0;

	for (i = 0; i < loops; i++) {
		/* Attempt to read a PCR value */
		rc = tpm2_pcr_read(chip, 0, NULL);
		if (rc < 0)
			break;
		rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
				      0, 0, "continue selftest");

		if (rc != TPM2_RC_TESTING)
			break;

		tpm_msleep(delay_msec);
		duration -= delay_msec;

		/* wait longer the next round */
		delay_msec *= 2;
	}

	return rc;
@@ -1009,7 +980,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
{
	struct tpm_buf buf;
	u32 nr_commands;
	u32 *attrs;
	__be32 *attrs;
	u32 cc;
	int i;
	int rc;
@@ -1049,7 +1020,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)

	chip->nr_commands = nr_commands;

	attrs = (u32 *)&buf.data[TPM_HEADER_SIZE + 9];
	attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9];
	for (i = 0; i < nr_commands; i++, attrs++) {
		chip->cc_attrs_tbl[i] = be32_to_cpup(attrs);
		cc = chip->cc_attrs_tbl[i] & 0xFFFF;
Loading