diff options
-rw-r--r-- | MAINTAINERS | 13 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-dev-common.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 87 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 15 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 73 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-space.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 59 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.h | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_spi.c | 73 | ||||
-rw-r--r-- | security/commoncap.c | 193 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 79 | ||||
-rw-r--r-- | security/tomoyo/audit.c | 2 | ||||
-rw-r--r-- | security/tomoyo/common.c | 4 | ||||
-rw-r--r-- | security/tomoyo/common.h | 2 | ||||
-rw-r--r-- | security/tomoyo/util.c | 39 |
17 files changed, 385 insertions, 279 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 779fa6dde58b..026644adfd8f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5219,8 +5219,7 @@ F: fs/ext4/ | |||
5219 | 5219 | ||
5220 | Extended Verification Module (EVM) | 5220 | Extended Verification Module (EVM) |
5221 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> | 5221 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> |
5222 | L: linux-ima-devel@lists.sourceforge.net | 5222 | L: linux-integrity@vger.kernel.org |
5223 | L: linux-security-module@vger.kernel.org | ||
5224 | S: Supported | 5223 | S: Supported |
5225 | F: security/integrity/evm/ | 5224 | F: security/integrity/evm/ |
5226 | 5225 | ||
@@ -6847,9 +6846,7 @@ L: linux-crypto@vger.kernel.org | |||
6847 | INTEGRITY MEASUREMENT ARCHITECTURE (IMA) | 6846 | INTEGRITY MEASUREMENT ARCHITECTURE (IMA) |
6848 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> | 6847 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> |
6849 | M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> | 6848 | M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> |
6850 | L: linux-ima-devel@lists.sourceforge.net | 6849 | L: linux-integrity@vger.kernel.org |
6851 | L: linux-ima-user@lists.sourceforge.net | ||
6852 | L: linux-security-module@vger.kernel.org | ||
6853 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git | 6850 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git |
6854 | S: Supported | 6851 | S: Supported |
6855 | F: security/integrity/ima/ | 6852 | F: security/integrity/ima/ |
@@ -7632,8 +7629,7 @@ F: kernel/kexec* | |||
7632 | 7629 | ||
7633 | KEYS-ENCRYPTED | 7630 | KEYS-ENCRYPTED |
7634 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> | 7631 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> |
7635 | M: David Safford <safford@us.ibm.com> | 7632 | L: linux-integrity@vger.kernel.org |
7636 | L: linux-security-module@vger.kernel.org | ||
7637 | L: keyrings@vger.kernel.org | 7633 | L: keyrings@vger.kernel.org |
7638 | S: Supported | 7634 | S: Supported |
7639 | F: Documentation/security/keys/trusted-encrypted.rst | 7635 | F: Documentation/security/keys/trusted-encrypted.rst |
@@ -7641,9 +7637,8 @@ F: include/keys/encrypted-type.h | |||
7641 | F: security/keys/encrypted-keys/ | 7637 | F: security/keys/encrypted-keys/ |
7642 | 7638 | ||
7643 | KEYS-TRUSTED | 7639 | KEYS-TRUSTED |
7644 | M: David Safford <safford@us.ibm.com> | ||
7645 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> | 7640 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> |
7646 | L: linux-security-module@vger.kernel.org | 7641 | L: linux-integrity@vger.kernel.org |
7647 | L: keyrings@vger.kernel.org | 7642 | L: keyrings@vger.kernel.org |
7648 | S: Supported | 7643 | S: Supported |
7649 | F: Documentation/security/keys/trusted-encrypted.rst | 7644 | F: Documentation/security/keys/trusted-encrypted.rst |
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 610638a80383..461bf0b8a094 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c | |||
@@ -110,6 +110,12 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
110 | return -EFAULT; | 110 | return -EFAULT; |
111 | } | 111 | } |
112 | 112 | ||
113 | if (in_size < 6 || | ||
114 | in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) { | ||
115 | mutex_unlock(&priv->buffer_mutex); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
113 | /* atomic tpm command send and result receive. We only hold the ops | 119 | /* atomic tpm command send and result receive. We only hold the ops |
114 | * lock during this period so that the tpm can be unregistered even if | 120 | * lock during this period so that the tpm can be unregistered even if |
115 | * the char dev is held open. | 121 | * the char dev is held open. |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 86f38d239476..83a77a445538 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
@@ -20,44 +20,48 @@ | |||
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include "tpm.h" | 21 | #include "tpm.h" |
22 | 22 | ||
23 | #define READ_PUBEK_RESULT_SIZE 314 | 23 | struct tpm_readpubek_out { |
24 | u8 algorithm[4]; | ||
25 | u8 encscheme[2]; | ||
26 | u8 sigscheme[2]; | ||
27 | __be32 paramsize; | ||
28 | u8 parameters[12]; | ||
29 | __be32 keysize; | ||
30 | u8 modulus[256]; | ||
31 | u8 checksum[20]; | ||
32 | } __packed; | ||
33 | |||
24 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) | 34 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) |
25 | #define TPM_ORD_READPUBEK 124 | 35 | #define TPM_ORD_READPUBEK 124 |
26 | static const struct tpm_input_header tpm_readpubek_header = { | 36 | |
27 | .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), | ||
28 | .length = cpu_to_be32(30), | ||
29 | .ordinal = cpu_to_be32(TPM_ORD_READPUBEK) | ||
30 | }; | ||
31 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | 37 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, |
32 | char *buf) | 38 | char *buf) |
33 | { | 39 | { |
34 | u8 *data; | 40 | struct tpm_buf tpm_buf; |
35 | struct tpm_cmd_t tpm_cmd; | 41 | struct tpm_readpubek_out *out; |
36 | ssize_t err; | 42 | ssize_t rc; |
37 | int i, rc; | 43 | int i; |
38 | char *str = buf; | 44 | char *str = buf; |
39 | struct tpm_chip *chip = to_tpm_chip(dev); | 45 | struct tpm_chip *chip = to_tpm_chip(dev); |
46 | char anti_replay[20]; | ||
40 | 47 | ||
41 | memset(&tpm_cmd, 0, sizeof(tpm_cmd)); | 48 | memset(&anti_replay, 0, sizeof(anti_replay)); |
42 | 49 | ||
43 | tpm_cmd.header.in = tpm_readpubek_header; | 50 | rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); |
44 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 51 | if (rc) |
45 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, | 52 | return rc; |
46 | "attempting to read the PUBEK"); | 53 | |
47 | if (err) | 54 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); |
48 | goto out; | 55 | |
49 | 56 | rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE, | |
50 | /* | 57 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, |
51 | ignore header 10 bytes | 58 | "attempting to read the PUBEK"); |
52 | algorithm 32 bits (1 == RSA ) | 59 | if (rc) { |
53 | encscheme 16 bits | 60 | tpm_buf_destroy(&tpm_buf); |
54 | sigscheme 16 bits | 61 | return 0; |
55 | parameters (RSA 12->bytes: keybit, #primes, expbit) | 62 | } |
56 | keylenbytes 32 bits | 63 | |
57 | 256 byte modulus | 64 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; |
58 | ignore checksum 20 bytes | ||
59 | */ | ||
60 | data = tpm_cmd.params.readpubek_out_buffer; | ||
61 | str += | 65 | str += |
62 | sprintf(str, | 66 | sprintf(str, |
63 | "Algorithm: %02X %02X %02X %02X\n" | 67 | "Algorithm: %02X %02X %02X %02X\n" |
@@ -68,21 +72,26 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
68 | "%02X %02X %02X %02X\n" | 72 | "%02X %02X %02X %02X\n" |
69 | "Modulus length: %d\n" | 73 | "Modulus length: %d\n" |
70 | "Modulus:\n", | 74 | "Modulus:\n", |
71 | data[0], data[1], data[2], data[3], | 75 | out->algorithm[0], out->algorithm[1], out->algorithm[2], |
72 | data[4], data[5], | 76 | out->algorithm[3], |
73 | data[6], data[7], | 77 | out->encscheme[0], out->encscheme[1], |
74 | data[12], data[13], data[14], data[15], | 78 | out->sigscheme[0], out->sigscheme[1], |
75 | data[16], data[17], data[18], data[19], | 79 | out->parameters[0], out->parameters[1], |
76 | data[20], data[21], data[22], data[23], | 80 | out->parameters[2], out->parameters[3], |
77 | be32_to_cpu(*((__be32 *) (data + 24)))); | 81 | out->parameters[4], out->parameters[5], |
82 | out->parameters[6], out->parameters[7], | ||
83 | out->parameters[8], out->parameters[9], | ||
84 | out->parameters[10], out->parameters[11], | ||
85 | be32_to_cpu(out->keysize)); | ||
78 | 86 | ||
79 | for (i = 0; i < 256; i++) { | 87 | for (i = 0; i < 256; i++) { |
80 | str += sprintf(str, "%02X ", data[i + 28]); | 88 | str += sprintf(str, "%02X ", out->modulus[i]); |
81 | if ((i + 1) % 16 == 0) | 89 | if ((i + 1) % 16 == 0) |
82 | str += sprintf(str, "\n"); | 90 | str += sprintf(str, "\n"); |
83 | } | 91 | } |
84 | out: | 92 | |
85 | rc = str - buf; | 93 | rc = str - buf; |
94 | tpm_buf_destroy(&tpm_buf); | ||
86 | return rc; | 95 | return rc; |
87 | } | 96 | } |
88 | static DEVICE_ATTR_RO(pubek); | 97 | static DEVICE_ATTR_RO(pubek); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 2d5466a72e40..528cffbd49d3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -345,17 +345,6 @@ enum tpm_sub_capabilities { | |||
345 | TPM_CAP_PROP_TIS_DURATION = 0x120, | 345 | TPM_CAP_PROP_TIS_DURATION = 0x120, |
346 | }; | 346 | }; |
347 | 347 | ||
348 | struct tpm_readpubek_params_out { | ||
349 | u8 algorithm[4]; | ||
350 | u8 encscheme[2]; | ||
351 | u8 sigscheme[2]; | ||
352 | __be32 paramsize; | ||
353 | u8 parameters[12]; /*assuming RSA*/ | ||
354 | __be32 keysize; | ||
355 | u8 modulus[256]; | ||
356 | u8 checksum[20]; | ||
357 | } __packed; | ||
358 | |||
359 | typedef union { | 348 | typedef union { |
360 | struct tpm_input_header in; | 349 | struct tpm_input_header in; |
361 | struct tpm_output_header out; | 350 | struct tpm_output_header out; |
@@ -385,8 +374,6 @@ struct tpm_getrandom_in { | |||
385 | } __packed; | 374 | } __packed; |
386 | 375 | ||
387 | typedef union { | 376 | typedef union { |
388 | struct tpm_readpubek_params_out readpubek_out; | ||
389 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; | ||
390 | struct tpm_pcrread_in pcrread_in; | 377 | struct tpm_pcrread_in pcrread_in; |
391 | struct tpm_pcrread_out pcrread_out; | 378 | struct tpm_pcrread_out pcrread_out; |
392 | struct tpm_getrandom_in getrandom_in; | 379 | struct tpm_getrandom_in getrandom_in; |
@@ -557,7 +544,7 @@ static inline void tpm_add_ppi(struct tpm_chip *chip) | |||
557 | } | 544 | } |
558 | #endif | 545 | #endif |
559 | 546 | ||
560 | static inline inline u32 tpm2_rc_value(u32 rc) | 547 | static inline u32 tpm2_rc_value(u32 rc) |
561 | { | 548 | { |
562 | return (rc & BIT(7)) ? rc & 0xff : rc; | 549 | return (rc & BIT(7)) ? rc & 0xff : rc; |
563 | } | 550 | } |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index e1a41b788f08..f40d20671a78 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -834,72 +834,43 @@ static const struct tpm_input_header tpm2_selftest_header = { | |||
834 | }; | 834 | }; |
835 | 835 | ||
836 | /** | 836 | /** |
837 | * tpm2_continue_selftest() - start a self test | 837 | * tpm2_do_selftest() - ensure that all self tests have passed |
838 | * | ||
839 | * @chip: TPM chip to use | ||
840 | * @full: test all commands instead of testing only those that were not | ||
841 | * previously tested. | ||
842 | * | ||
843 | * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING. | ||
844 | */ | ||
845 | static int tpm2_start_selftest(struct tpm_chip *chip, bool full) | ||
846 | { | ||
847 | int rc; | ||
848 | struct tpm2_cmd cmd; | ||
849 | |||
850 | cmd.header.in = tpm2_selftest_header; | ||
851 | cmd.params.selftest_in.full_test = full; | ||
852 | |||
853 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, | ||
854 | "continue selftest"); | ||
855 | |||
856 | /* At least some prototype chips seem to give RC_TESTING error | ||
857 | * immediately. This is a workaround for that. | ||
858 | */ | ||
859 | if (rc == TPM2_RC_TESTING) { | ||
860 | dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n"); | ||
861 | rc = 0; | ||
862 | } | ||
863 | |||
864 | return rc; | ||
865 | } | ||
866 | |||
867 | /** | ||
868 | * tpm2_do_selftest() - run a full self test | ||
869 | * | 838 | * |
870 | * @chip: TPM chip to use | 839 | * @chip: TPM chip to use |
871 | * | 840 | * |
872 | * Return: Same as with tpm_transmit_cmd. | 841 | * Return: Same as with tpm_transmit_cmd. |
873 | * | 842 | * |
874 | * During the self test TPM2 commands return with the error code RC_TESTING. | 843 | * The TPM can either run all self tests synchronously and then return |
875 | * Waiting is done by issuing PCR read until it executes successfully. | 844 | * RC_SUCCESS once all tests were successful. Or it can choose to run the tests |
845 | * asynchronously and return RC_TESTING immediately while the self tests still | ||
846 | * execute in the background. This function handles both cases and waits until | ||
847 | * all tests have completed. | ||
876 | */ | 848 | */ |
877 | static int tpm2_do_selftest(struct tpm_chip *chip) | 849 | static int tpm2_do_selftest(struct tpm_chip *chip) |
878 | { | 850 | { |
879 | int rc; | 851 | int rc; |
880 | unsigned int loops; | 852 | unsigned int delay_msec = 20; |
881 | unsigned int delay_msec = 100; | 853 | long duration; |
882 | unsigned long duration; | 854 | struct tpm2_cmd cmd; |
883 | int i; | ||
884 | |||
885 | duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); | ||
886 | 855 | ||
887 | loops = jiffies_to_msecs(duration) / delay_msec; | 856 | duration = jiffies_to_msecs( |
857 | tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); | ||
888 | 858 | ||
889 | rc = tpm2_start_selftest(chip, true); | 859 | while (duration > 0) { |
890 | if (rc) | 860 | cmd.header.in = tpm2_selftest_header; |
891 | return rc; | 861 | cmd.params.selftest_in.full_test = 0; |
892 | 862 | ||
893 | for (i = 0; i < loops; i++) { | 863 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, |
894 | /* Attempt to read a PCR value */ | 864 | 0, 0, "continue selftest"); |
895 | rc = tpm2_pcr_read(chip, 0, NULL); | ||
896 | if (rc < 0) | ||
897 | break; | ||
898 | 865 | ||
899 | if (rc != TPM2_RC_TESTING) | 866 | if (rc != TPM2_RC_TESTING) |
900 | break; | 867 | break; |
901 | 868 | ||
902 | tpm_msleep(delay_msec); | 869 | tpm_msleep(delay_msec); |
870 | duration -= delay_msec; | ||
871 | |||
872 | /* wait longer the next round */ | ||
873 | delay_msec *= 2; | ||
903 | } | 874 | } |
904 | 875 | ||
905 | return rc; | 876 | return rc; |
@@ -1009,7 +980,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | |||
1009 | { | 980 | { |
1010 | struct tpm_buf buf; | 981 | struct tpm_buf buf; |
1011 | u32 nr_commands; | 982 | u32 nr_commands; |
1012 | u32 *attrs; | 983 | __be32 *attrs; |
1013 | u32 cc; | 984 | u32 cc; |
1014 | int i; | 985 | int i; |
1015 | int rc; | 986 | int rc; |
@@ -1049,7 +1020,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | |||
1049 | 1020 | ||
1050 | chip->nr_commands = nr_commands; | 1021 | chip->nr_commands = nr_commands; |
1051 | 1022 | ||
1052 | attrs = (u32 *)&buf.data[TPM_HEADER_SIZE + 9]; | 1023 | attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9]; |
1053 | for (i = 0; i < nr_commands; i++, attrs++) { | 1024 | for (i = 0; i < nr_commands; i++, attrs++) { |
1054 | chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); | 1025 | chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); |
1055 | cc = chip->cc_attrs_tbl[i] & 0xFFFF; | 1026 | cc = chip->cc_attrs_tbl[i] & 0xFFFF; |
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index e2e059d8ffec..4e4014eabdb9 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c | |||
@@ -242,7 +242,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | |||
242 | struct tpm_space *space = &chip->work_space; | 242 | struct tpm_space *space = &chip->work_space; |
243 | unsigned int nr_handles; | 243 | unsigned int nr_handles; |
244 | u32 attrs; | 244 | u32 attrs; |
245 | u32 *handle; | 245 | __be32 *handle; |
246 | int i; | 246 | int i; |
247 | 247 | ||
248 | i = tpm2_find_cc(chip, cc); | 248 | i = tpm2_find_cc(chip, cc); |
@@ -252,7 +252,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | |||
252 | attrs = chip->cc_attrs_tbl[i]; | 252 | attrs = chip->cc_attrs_tbl[i]; |
253 | nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); | 253 | nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); |
254 | 254 | ||
255 | handle = (u32 *)&cmd[TPM_HEADER_SIZE]; | 255 | handle = (__be32 *)&cmd[TPM_HEADER_SIZE]; |
256 | for (i = 0; i < nr_handles; i++, handle++) { | 256 | for (i = 0; i < nr_handles; i++, handle++) { |
257 | if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { | 257 | if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { |
258 | if (!tpm2_map_to_phandle(space, handle)) | 258 | if (!tpm2_map_to_phandle(space, handle)) |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8f0a98dea327..7b3c2a8aa9de 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -92,14 +92,9 @@ enum crb_status { | |||
92 | CRB_DRV_STS_COMPLETE = BIT(0), | 92 | CRB_DRV_STS_COMPLETE = BIT(0), |
93 | }; | 93 | }; |
94 | 94 | ||
95 | enum crb_flags { | ||
96 | CRB_FL_ACPI_START = BIT(0), | ||
97 | CRB_FL_CRB_START = BIT(1), | ||
98 | CRB_FL_CRB_SMC_START = BIT(2), | ||
99 | }; | ||
100 | |||
101 | struct crb_priv { | 95 | struct crb_priv { |
102 | unsigned int flags; | 96 | u32 sm; |
97 | const char *hid; | ||
103 | void __iomem *iobase; | 98 | void __iomem *iobase; |
104 | struct crb_regs_head __iomem *regs_h; | 99 | struct crb_regs_head __iomem *regs_h; |
105 | struct crb_regs_tail __iomem *regs_t; | 100 | struct crb_regs_tail __iomem *regs_t; |
@@ -128,14 +123,16 @@ struct tpm2_crb_smc { | |||
128 | * Anyhow, we do not wait here as a consequent CMD_READY request | 123 | * Anyhow, we do not wait here as a consequent CMD_READY request |
129 | * will be handled correctly even if idle was not completed. | 124 | * will be handled correctly even if idle was not completed. |
130 | * | 125 | * |
131 | * The function does nothing for devices with ACPI-start method. | 126 | * The function does nothing for devices with ACPI-start method |
127 | * or SMC-start method. | ||
132 | * | 128 | * |
133 | * Return: 0 always | 129 | * Return: 0 always |
134 | */ | 130 | */ |
135 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | 131 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) |
136 | { | 132 | { |
137 | if ((priv->flags & CRB_FL_ACPI_START) || | 133 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
138 | (priv->flags & CRB_FL_CRB_SMC_START)) | 134 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
135 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
139 | return 0; | 136 | return 0; |
140 | 137 | ||
141 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); | 138 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); |
@@ -174,14 +171,16 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | |||
174 | * The device should respond within TIMEOUT_C. | 171 | * The device should respond within TIMEOUT_C. |
175 | * | 172 | * |
176 | * The function does nothing for devices with ACPI-start method | 173 | * The function does nothing for devices with ACPI-start method |
174 | * or SMC-start method. | ||
177 | * | 175 | * |
178 | * Return: 0 on success -ETIME on timeout; | 176 | * Return: 0 on success -ETIME on timeout; |
179 | */ | 177 | */ |
180 | static int __maybe_unused crb_cmd_ready(struct device *dev, | 178 | static int __maybe_unused crb_cmd_ready(struct device *dev, |
181 | struct crb_priv *priv) | 179 | struct crb_priv *priv) |
182 | { | 180 | { |
183 | if ((priv->flags & CRB_FL_ACPI_START) || | 181 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
184 | (priv->flags & CRB_FL_CRB_SMC_START)) | 182 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
183 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
185 | return 0; | 184 | return 0; |
186 | 185 | ||
187 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); | 186 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); |
@@ -325,13 +324,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
325 | /* Make sure that cmd is populated before issuing start. */ | 324 | /* Make sure that cmd is populated before issuing start. */ |
326 | wmb(); | 325 | wmb(); |
327 | 326 | ||
328 | if (priv->flags & CRB_FL_CRB_START) | 327 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs |
328 | * report only ACPI start but in practice seems to require both | ||
329 | * CRB start, hence invoking CRB start method if hid == MSFT0101. | ||
330 | */ | ||
331 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || | ||
332 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED) || | ||
333 | (!strcmp(priv->hid, "MSFT0101"))) | ||
329 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 334 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
330 | 335 | ||
331 | if (priv->flags & CRB_FL_ACPI_START) | 336 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
337 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) | ||
332 | rc = crb_do_acpi_start(chip); | 338 | rc = crb_do_acpi_start(chip); |
333 | 339 | ||
334 | if (priv->flags & CRB_FL_CRB_SMC_START) { | 340 | if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
335 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 341 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
336 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); | 342 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); |
337 | } | 343 | } |
@@ -345,7 +351,9 @@ static void crb_cancel(struct tpm_chip *chip) | |||
345 | 351 | ||
346 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); | 352 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); |
347 | 353 | ||
348 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) | 354 | if (((priv->sm == ACPI_TPM2_START_METHOD) || |
355 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) && | ||
356 | crb_do_acpi_start(chip)) | ||
349 | dev_err(&chip->dev, "ACPI Start failed\n"); | 357 | dev_err(&chip->dev, "ACPI Start failed\n"); |
350 | } | 358 | } |
351 | 359 | ||
@@ -458,7 +466,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
458 | * the control area, as one nice sane region except for some older | 466 | * the control area, as one nice sane region except for some older |
459 | * stuff that puts the control area outside the ACPI IO region. | 467 | * stuff that puts the control area outside the ACPI IO region. |
460 | */ | 468 | */ |
461 | if (!(priv->flags & CRB_FL_ACPI_START)) { | 469 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || |
470 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) { | ||
462 | if (buf->control_address == io_res.start + | 471 | if (buf->control_address == io_res.start + |
463 | sizeof(*priv->regs_h)) | 472 | sizeof(*priv->regs_h)) |
464 | priv->regs_h = priv->iobase; | 473 | priv->regs_h = priv->iobase; |
@@ -552,18 +561,6 @@ static int crb_acpi_add(struct acpi_device *device) | |||
552 | if (!priv) | 561 | if (!priv) |
553 | return -ENOMEM; | 562 | return -ENOMEM; |
554 | 563 | ||
555 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs | ||
556 | * report only ACPI start but in practice seems to require both | ||
557 | * ACPI start and CRB start. | ||
558 | */ | ||
559 | if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || | ||
560 | !strcmp(acpi_device_hid(device), "MSFT0101")) | ||
561 | priv->flags |= CRB_FL_CRB_START; | ||
562 | |||
563 | if (sm == ACPI_TPM2_START_METHOD || | ||
564 | sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) | ||
565 | priv->flags |= CRB_FL_ACPI_START; | ||
566 | |||
567 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { | 564 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
568 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { | 565 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { |
569 | dev_err(dev, | 566 | dev_err(dev, |
@@ -574,9 +571,11 @@ static int crb_acpi_add(struct acpi_device *device) | |||
574 | } | 571 | } |
575 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); | 572 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); |
576 | priv->smc_func_id = crb_smc->smc_func_id; | 573 | priv->smc_func_id = crb_smc->smc_func_id; |
577 | priv->flags |= CRB_FL_CRB_SMC_START; | ||
578 | } | 574 | } |
579 | 575 | ||
576 | priv->sm = sm; | ||
577 | priv->hid = acpi_device_hid(device); | ||
578 | |||
580 | rc = crb_map_io(device, priv, buf); | 579 | rc = crb_map_io(device, priv, buf); |
581 | if (rc) | 580 | if (rc) |
582 | return rc; | 581 | return rc; |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 7e55aa9ce680..e2d1055fb814 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
31 | #include <linux/of.h> | 31 | #include <linux/of.h> |
32 | #include <linux/of_device.h> | 32 | #include <linux/of_device.h> |
33 | #include <linux/kernel.h> | ||
33 | #include "tpm.h" | 34 | #include "tpm.h" |
34 | #include "tpm_tis_core.h" | 35 | #include "tpm_tis_core.h" |
35 | 36 | ||
@@ -223,7 +224,7 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | |||
223 | } | 224 | } |
224 | 225 | ||
225 | static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | 226 | static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, |
226 | u8 *value) | 227 | const u8 *value) |
227 | { | 228 | { |
228 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 229 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
229 | 230 | ||
@@ -365,7 +366,7 @@ static struct pnp_driver tis_pnp_driver = { | |||
365 | }, | 366 | }, |
366 | }; | 367 | }; |
367 | 368 | ||
368 | #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 | 369 | #define TIS_HID_USR_IDX (ARRAY_SIZE(tpm_pnp_tbl) - 2) |
369 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | 370 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, |
370 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 371 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
371 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 372 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 63bc6c3b949e..fdde971bc810 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
@@ -252,7 +252,7 @@ out: | |||
252 | * tpm.c can skip polling for the data to be available as the interrupt is | 252 | * tpm.c can skip polling for the data to be available as the interrupt is |
253 | * waited for here | 253 | * waited for here |
254 | */ | 254 | */ |
255 | static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | 255 | static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) |
256 | { | 256 | { |
257 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 257 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
258 | int rc, status, burstcnt; | 258 | int rc, status, burstcnt; |
@@ -343,7 +343,7 @@ static void disable_interrupts(struct tpm_chip *chip) | |||
343 | * tpm.c can skip polling for the data to be available as the interrupt is | 343 | * tpm.c can skip polling for the data to be available as the interrupt is |
344 | * waited for here | 344 | * waited for here |
345 | */ | 345 | */ |
346 | static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | 346 | static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) |
347 | { | 347 | { |
348 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 348 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
349 | int rc; | 349 | int rc; |
@@ -445,7 +445,7 @@ static int probe_itpm(struct tpm_chip *chip) | |||
445 | { | 445 | { |
446 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 446 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
447 | int rc = 0; | 447 | int rc = 0; |
448 | u8 cmd_getticks[] = { | 448 | static const u8 cmd_getticks[] = { |
449 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, | 449 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, |
450 | 0x00, 0x00, 0x00, 0xf1 | 450 | 0x00, 0x00, 0x00, 0xf1 |
451 | }; | 451 | }; |
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index e2212f021a02..6bbac319ff3b 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h | |||
@@ -98,7 +98,7 @@ struct tpm_tis_phy_ops { | |||
98 | int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, | 98 | int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, |
99 | u8 *result); | 99 | u8 *result); |
100 | int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, | 100 | int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, |
101 | u8 *value); | 101 | const u8 *value); |
102 | int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); | 102 | int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); |
103 | int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); | 103 | int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); |
104 | int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); | 104 | int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); |
@@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr, | |||
128 | } | 128 | } |
129 | 129 | ||
130 | static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, | 130 | static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, |
131 | u16 len, u8 *value) | 131 | u16 len, const u8 *value) |
132 | { | 132 | { |
133 | return data->phy_ops->write_bytes(data, addr, len, value); | 133 | return data->phy_ops->write_bytes(data, addr, len, value); |
134 | } | 134 | } |
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 88fe72ae967f..424ff2fde1f2 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c | |||
@@ -46,9 +46,7 @@ | |||
46 | struct tpm_tis_spi_phy { | 46 | struct tpm_tis_spi_phy { |
47 | struct tpm_tis_data priv; | 47 | struct tpm_tis_data priv; |
48 | struct spi_device *spi_device; | 48 | struct spi_device *spi_device; |
49 | 49 | u8 *iobuf; | |
50 | u8 tx_buf[4]; | ||
51 | u8 rx_buf[4]; | ||
52 | }; | 50 | }; |
53 | 51 | ||
54 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) | 52 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) |
@@ -57,7 +55,7 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da | |||
57 | } | 55 | } |
58 | 56 | ||
59 | static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | 57 | static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, |
60 | u8 *buffer, u8 direction) | 58 | u8 *in, const u8 *out) |
61 | { | 59 | { |
62 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); | 60 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); |
63 | int ret = 0; | 61 | int ret = 0; |
@@ -71,14 +69,14 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
71 | while (len) { | 69 | while (len) { |
72 | transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); | 70 | transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); |
73 | 71 | ||
74 | phy->tx_buf[0] = direction | (transfer_len - 1); | 72 | phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); |
75 | phy->tx_buf[1] = 0xd4; | 73 | phy->iobuf[1] = 0xd4; |
76 | phy->tx_buf[2] = addr >> 8; | 74 | phy->iobuf[2] = addr >> 8; |
77 | phy->tx_buf[3] = addr; | 75 | phy->iobuf[3] = addr; |
78 | 76 | ||
79 | memset(&spi_xfer, 0, sizeof(spi_xfer)); | 77 | memset(&spi_xfer, 0, sizeof(spi_xfer)); |
80 | spi_xfer.tx_buf = phy->tx_buf; | 78 | spi_xfer.tx_buf = phy->iobuf; |
81 | spi_xfer.rx_buf = phy->rx_buf; | 79 | spi_xfer.rx_buf = phy->iobuf; |
82 | spi_xfer.len = 4; | 80 | spi_xfer.len = 4; |
83 | spi_xfer.cs_change = 1; | 81 | spi_xfer.cs_change = 1; |
84 | 82 | ||
@@ -88,9 +86,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
88 | if (ret < 0) | 86 | if (ret < 0) |
89 | goto exit; | 87 | goto exit; |
90 | 88 | ||
91 | if ((phy->rx_buf[3] & 0x01) == 0) { | 89 | if ((phy->iobuf[3] & 0x01) == 0) { |
92 | // handle SPI wait states | 90 | // handle SPI wait states |
93 | phy->tx_buf[0] = 0; | 91 | phy->iobuf[0] = 0; |
94 | 92 | ||
95 | for (i = 0; i < TPM_RETRY; i++) { | 93 | for (i = 0; i < TPM_RETRY; i++) { |
96 | spi_xfer.len = 1; | 94 | spi_xfer.len = 1; |
@@ -99,7 +97,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
99 | ret = spi_sync_locked(phy->spi_device, &m); | 97 | ret = spi_sync_locked(phy->spi_device, &m); |
100 | if (ret < 0) | 98 | if (ret < 0) |
101 | goto exit; | 99 | goto exit; |
102 | if (phy->rx_buf[0] & 0x01) | 100 | if (phy->iobuf[0] & 0x01) |
103 | break; | 101 | break; |
104 | } | 102 | } |
105 | 103 | ||
@@ -113,12 +111,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
113 | spi_xfer.len = transfer_len; | 111 | spi_xfer.len = transfer_len; |
114 | spi_xfer.delay_usecs = 5; | 112 | spi_xfer.delay_usecs = 5; |
115 | 113 | ||
116 | if (direction) { | 114 | if (in) { |
117 | spi_xfer.tx_buf = NULL; | 115 | spi_xfer.tx_buf = NULL; |
118 | spi_xfer.rx_buf = buffer; | 116 | } else if (out) { |
119 | } else { | ||
120 | spi_xfer.tx_buf = buffer; | ||
121 | spi_xfer.rx_buf = NULL; | 117 | spi_xfer.rx_buf = NULL; |
118 | memcpy(phy->iobuf, out, transfer_len); | ||
119 | out += transfer_len; | ||
122 | } | 120 | } |
123 | 121 | ||
124 | spi_message_init(&m); | 122 | spi_message_init(&m); |
@@ -127,8 +125,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
127 | if (ret < 0) | 125 | if (ret < 0) |
128 | goto exit; | 126 | goto exit; |
129 | 127 | ||
128 | if (in) { | ||
129 | memcpy(in, phy->iobuf, transfer_len); | ||
130 | in += transfer_len; | ||
131 | } | ||
132 | |||
130 | len -= transfer_len; | 133 | len -= transfer_len; |
131 | buffer += transfer_len; | ||
132 | } | 134 | } |
133 | 135 | ||
134 | exit: | 136 | exit: |
@@ -139,40 +141,51 @@ exit: | |||
139 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, | 141 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, |
140 | u16 len, u8 *result) | 142 | u16 len, u8 *result) |
141 | { | 143 | { |
142 | return tpm_tis_spi_transfer(data, addr, len, result, 0x80); | 144 | return tpm_tis_spi_transfer(data, addr, len, result, NULL); |
143 | } | 145 | } |
144 | 146 | ||
145 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, | 147 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, |
146 | u16 len, u8 *value) | 148 | u16 len, const u8 *value) |
147 | { | 149 | { |
148 | return tpm_tis_spi_transfer(data, addr, len, value, 0); | 150 | return tpm_tis_spi_transfer(data, addr, len, NULL, value); |
149 | } | 151 | } |
150 | 152 | ||
151 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | 153 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) |
152 | { | 154 | { |
155 | __le16 result_le; | ||
153 | int rc; | 156 | int rc; |
154 | 157 | ||
155 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), (u8 *)result); | 158 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), |
159 | (u8 *)&result_le); | ||
156 | if (!rc) | 160 | if (!rc) |
157 | *result = le16_to_cpu(*result); | 161 | *result = le16_to_cpu(result_le); |
162 | |||
158 | return rc; | 163 | return rc; |
159 | } | 164 | } |
160 | 165 | ||
161 | static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) | 166 | static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) |
162 | { | 167 | { |
168 | __le32 result_le; | ||
163 | int rc; | 169 | int rc; |
164 | 170 | ||
165 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), (u8 *)result); | 171 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), |
172 | (u8 *)&result_le); | ||
166 | if (!rc) | 173 | if (!rc) |
167 | *result = le32_to_cpu(*result); | 174 | *result = le32_to_cpu(result_le); |
175 | |||
168 | return rc; | 176 | return rc; |
169 | } | 177 | } |
170 | 178 | ||
171 | static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) | 179 | static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) |
172 | { | 180 | { |
173 | value = cpu_to_le32(value); | 181 | __le32 value_le; |
174 | return data->phy_ops->write_bytes(data, addr, sizeof(u32), | 182 | int rc; |
175 | (u8 *)&value); | 183 | |
184 | value_le = cpu_to_le32(value); | ||
185 | rc = data->phy_ops->write_bytes(data, addr, sizeof(u32), | ||
186 | (u8 *)&value_le); | ||
187 | |||
188 | return rc; | ||
176 | } | 189 | } |
177 | 190 | ||
178 | static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { | 191 | static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { |
@@ -194,6 +207,10 @@ static int tpm_tis_spi_probe(struct spi_device *dev) | |||
194 | 207 | ||
195 | phy->spi_device = dev; | 208 | phy->spi_device = dev; |
196 | 209 | ||
210 | phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); | ||
211 | if (!phy->iobuf) | ||
212 | return -ENOMEM; | ||
213 | |||
197 | return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, | 214 | return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, |
198 | NULL); | 215 | NULL); |
199 | } | 216 | } |
diff --git a/security/commoncap.c b/security/commoncap.c index fc46f5b85251..4f8e09340956 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -536,7 +536,7 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size) | |||
536 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | 536 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, |
537 | struct linux_binprm *bprm, | 537 | struct linux_binprm *bprm, |
538 | bool *effective, | 538 | bool *effective, |
539 | bool *has_cap) | 539 | bool *has_fcap) |
540 | { | 540 | { |
541 | struct cred *new = bprm->cred; | 541 | struct cred *new = bprm->cred; |
542 | unsigned i; | 542 | unsigned i; |
@@ -546,7 +546,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | |||
546 | *effective = true; | 546 | *effective = true; |
547 | 547 | ||
548 | if (caps->magic_etc & VFS_CAP_REVISION_MASK) | 548 | if (caps->magic_etc & VFS_CAP_REVISION_MASK) |
549 | *has_cap = true; | 549 | *has_fcap = true; |
550 | 550 | ||
551 | CAP_FOR_EACH_U32(i) { | 551 | CAP_FOR_EACH_U32(i) { |
552 | __u32 permitted = caps->permitted.cap[i]; | 552 | __u32 permitted = caps->permitted.cap[i]; |
@@ -653,7 +653,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
653 | * its xattrs and, if present, apply them to the proposed credentials being | 653 | * its xattrs and, if present, apply them to the proposed credentials being |
654 | * constructed by execve(). | 654 | * constructed by execve(). |
655 | */ | 655 | */ |
656 | static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap) | 656 | static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_fcap) |
657 | { | 657 | { |
658 | int rc = 0; | 658 | int rc = 0; |
659 | struct cpu_vfs_cap_data vcaps; | 659 | struct cpu_vfs_cap_data vcaps; |
@@ -684,7 +684,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c | |||
684 | goto out; | 684 | goto out; |
685 | } | 685 | } |
686 | 686 | ||
687 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_cap); | 687 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_fcap); |
688 | if (rc == -EINVAL) | 688 | if (rc == -EINVAL) |
689 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", | 689 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", |
690 | __func__, rc, bprm->filename); | 690 | __func__, rc, bprm->filename); |
@@ -696,6 +696,115 @@ out: | |||
696 | return rc; | 696 | return rc; |
697 | } | 697 | } |
698 | 698 | ||
699 | static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); } | ||
700 | |||
701 | static inline bool __is_real(kuid_t uid, struct cred *cred) | ||
702 | { return uid_eq(cred->uid, uid); } | ||
703 | |||
704 | static inline bool __is_eff(kuid_t uid, struct cred *cred) | ||
705 | { return uid_eq(cred->euid, uid); } | ||
706 | |||
707 | static inline bool __is_suid(kuid_t uid, struct cred *cred) | ||
708 | { return !__is_real(uid, cred) && __is_eff(uid, cred); } | ||
709 | |||
710 | /* | ||
711 | * handle_privileged_root - Handle case of privileged root | ||
712 | * @bprm: The execution parameters, including the proposed creds | ||
713 | * @has_fcap: Are any file capabilities set? | ||
714 | * @effective: Do we have effective root privilege? | ||
715 | * @root_uid: This namespace' root UID WRT initial USER namespace | ||
716 | * | ||
717 | * Handle the case where root is privileged and hasn't been neutered by | ||
718 | * SECURE_NOROOT. If file capabilities are set, they won't be combined with | ||
719 | * set UID root and nothing is changed. If we are root, cap_permitted is | ||
720 | * updated. If we have become set UID root, the effective bit is set. | ||
721 | */ | ||
722 | static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap, | ||
723 | bool *effective, kuid_t root_uid) | ||
724 | { | ||
725 | const struct cred *old = current_cred(); | ||
726 | struct cred *new = bprm->cred; | ||
727 | |||
728 | if (!root_privileged()) | ||
729 | return; | ||
730 | /* | ||
731 | * If the legacy file capability is set, then don't set privs | ||
732 | * for a setuid root binary run by a non-root user. Do set it | ||
733 | * for a root user just to cause least surprise to an admin. | ||
734 | */ | ||
735 | if (has_fcap && __is_suid(root_uid, new)) { | ||
736 | warn_setuid_and_fcaps_mixed(bprm->filename); | ||
737 | return; | ||
738 | } | ||
739 | /* | ||
740 | * To support inheritance of root-permissions and suid-root | ||
741 | * executables under compatibility mode, we override the | ||
742 | * capability sets for the file. | ||
743 | */ | ||
744 | if (__is_eff(root_uid, new) || __is_real(root_uid, new)) { | ||
745 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | ||
746 | new->cap_permitted = cap_combine(old->cap_bset, | ||
747 | old->cap_inheritable); | ||
748 | } | ||
749 | /* | ||
750 | * If only the real uid is 0, we do not set the effective bit. | ||
751 | */ | ||
752 | if (__is_eff(root_uid, new)) | ||
753 | *effective = true; | ||
754 | } | ||
755 | |||
756 | #define __cap_gained(field, target, source) \ | ||
757 | !cap_issubset(target->cap_##field, source->cap_##field) | ||
758 | #define __cap_grew(target, source, cred) \ | ||
759 | !cap_issubset(cred->cap_##target, cred->cap_##source) | ||
760 | #define __cap_full(field, cred) \ | ||
761 | cap_issubset(CAP_FULL_SET, cred->cap_##field) | ||
762 | |||
763 | static inline bool __is_setuid(struct cred *new, const struct cred *old) | ||
764 | { return !uid_eq(new->euid, old->uid); } | ||
765 | |||
766 | static inline bool __is_setgid(struct cred *new, const struct cred *old) | ||
767 | { return !gid_eq(new->egid, old->gid); } | ||
768 | |||
769 | /* | ||
770 | * 1) Audit candidate if current->cap_effective is set | ||
771 | * | ||
772 | * We do not bother to audit if 3 things are true: | ||
773 | * 1) cap_effective has all caps | ||
774 | * 2) we became root *OR* are were already root | ||
775 | * 3) root is supposed to have all caps (SECURE_NOROOT) | ||
776 | * Since this is just a normal root execing a process. | ||
777 | * | ||
778 | * Number 1 above might fail if you don't have a full bset, but I think | ||
779 | * that is interesting information to audit. | ||
780 | * | ||
781 | * A number of other conditions require logging: | ||
782 | * 2) something prevented setuid root getting all caps | ||
783 | * 3) non-setuid root gets fcaps | ||
784 | * 4) non-setuid root gets ambient | ||
785 | */ | ||
786 | static inline bool nonroot_raised_pE(struct cred *new, const struct cred *old, | ||
787 | kuid_t root, bool has_fcap) | ||
788 | { | ||
789 | bool ret = false; | ||
790 | |||
791 | if ((__cap_grew(effective, ambient, new) && | ||
792 | !(__cap_full(effective, new) && | ||
793 | (__is_eff(root, new) || __is_real(root, new)) && | ||
794 | root_privileged())) || | ||
795 | (root_privileged() && | ||
796 | __is_suid(root, new) && | ||
797 | !__cap_full(effective, new)) || | ||
798 | (!__is_setuid(new, old) && | ||
799 | ((has_fcap && | ||
800 | __cap_gained(permitted, new, old)) || | ||
801 | __cap_gained(ambient, new, old)))) | ||
802 | |||
803 | ret = true; | ||
804 | |||
805 | return ret; | ||
806 | } | ||
807 | |||
699 | /** | 808 | /** |
700 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). | 809 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). |
701 | * @bprm: The execution parameters, including the proposed creds | 810 | * @bprm: The execution parameters, including the proposed creds |
@@ -708,61 +817,33 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
708 | { | 817 | { |
709 | const struct cred *old = current_cred(); | 818 | const struct cred *old = current_cred(); |
710 | struct cred *new = bprm->cred; | 819 | struct cred *new = bprm->cred; |
711 | bool effective, has_cap = false, is_setid; | 820 | bool effective = false, has_fcap = false, is_setid; |
712 | int ret; | 821 | int ret; |
713 | kuid_t root_uid; | 822 | kuid_t root_uid; |
714 | 823 | ||
715 | if (WARN_ON(!cap_ambient_invariant_ok(old))) | 824 | if (WARN_ON(!cap_ambient_invariant_ok(old))) |
716 | return -EPERM; | 825 | return -EPERM; |
717 | 826 | ||
718 | effective = false; | 827 | ret = get_file_caps(bprm, &effective, &has_fcap); |
719 | ret = get_file_caps(bprm, &effective, &has_cap); | ||
720 | if (ret < 0) | 828 | if (ret < 0) |
721 | return ret; | 829 | return ret; |
722 | 830 | ||
723 | root_uid = make_kuid(new->user_ns, 0); | 831 | root_uid = make_kuid(new->user_ns, 0); |
724 | 832 | ||
725 | if (!issecure(SECURE_NOROOT)) { | 833 | handle_privileged_root(bprm, has_fcap, &effective, root_uid); |
726 | /* | ||
727 | * If the legacy file capability is set, then don't set privs | ||
728 | * for a setuid root binary run by a non-root user. Do set it | ||
729 | * for a root user just to cause least surprise to an admin. | ||
730 | */ | ||
731 | if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { | ||
732 | warn_setuid_and_fcaps_mixed(bprm->filename); | ||
733 | goto skip; | ||
734 | } | ||
735 | /* | ||
736 | * To support inheritance of root-permissions and suid-root | ||
737 | * executables under compatibility mode, we override the | ||
738 | * capability sets for the file. | ||
739 | * | ||
740 | * If only the real uid is 0, we do not set the effective bit. | ||
741 | */ | ||
742 | if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { | ||
743 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | ||
744 | new->cap_permitted = cap_combine(old->cap_bset, | ||
745 | old->cap_inheritable); | ||
746 | } | ||
747 | if (uid_eq(new->euid, root_uid)) | ||
748 | effective = true; | ||
749 | } | ||
750 | skip: | ||
751 | 834 | ||
752 | /* if we have fs caps, clear dangerous personality flags */ | 835 | /* if we have fs caps, clear dangerous personality flags */ |
753 | if (!cap_issubset(new->cap_permitted, old->cap_permitted)) | 836 | if (__cap_gained(permitted, new, old)) |
754 | bprm->per_clear |= PER_CLEAR_ON_SETID; | 837 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
755 | 838 | ||
756 | |||
757 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised | 839 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised |
758 | * credentials unless they have the appropriate permit. | 840 | * credentials unless they have the appropriate permit. |
759 | * | 841 | * |
760 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. | 842 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. |
761 | */ | 843 | */ |
762 | is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid); | 844 | is_setid = __is_setuid(new, old) || __is_setgid(new, old); |
763 | 845 | ||
764 | if ((is_setid || | 846 | if ((is_setid || __cap_gained(permitted, new, old)) && |
765 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && | ||
766 | ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) || | 847 | ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) || |
767 | !ptracer_capable(current, new->user_ns))) { | 848 | !ptracer_capable(current, new->user_ns))) { |
768 | /* downgrade; they get no more than they had, and maybe less */ | 849 | /* downgrade; they get no more than they had, and maybe less */ |
@@ -779,7 +860,7 @@ skip: | |||
779 | new->sgid = new->fsgid = new->egid; | 860 | new->sgid = new->fsgid = new->egid; |
780 | 861 | ||
781 | /* File caps or setid cancels ambient. */ | 862 | /* File caps or setid cancels ambient. */ |
782 | if (has_cap || is_setid) | 863 | if (has_fcap || is_setid) |
783 | cap_clear(new->cap_ambient); | 864 | cap_clear(new->cap_ambient); |
784 | 865 | ||
785 | /* | 866 | /* |
@@ -800,26 +881,10 @@ skip: | |||
800 | if (WARN_ON(!cap_ambient_invariant_ok(new))) | 881 | if (WARN_ON(!cap_ambient_invariant_ok(new))) |
801 | return -EPERM; | 882 | return -EPERM; |
802 | 883 | ||
803 | /* | 884 | if (nonroot_raised_pE(new, old, root_uid, has_fcap)) { |
804 | * Audit candidate if current->cap_effective is set | 885 | ret = audit_log_bprm_fcaps(bprm, new, old); |
805 | * | 886 | if (ret < 0) |
806 | * We do not bother to audit if 3 things are true: | 887 | return ret; |
807 | * 1) cap_effective has all caps | ||
808 | * 2) we are root | ||
809 | * 3) root is supposed to have all caps (SECURE_NOROOT) | ||
810 | * Since this is just a normal root execing a process. | ||
811 | * | ||
812 | * Number 1 above might fail if you don't have a full bset, but I think | ||
813 | * that is interesting information to audit. | ||
814 | */ | ||
815 | if (!cap_issubset(new->cap_effective, new->cap_ambient)) { | ||
816 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || | ||
817 | !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) || | ||
818 | issecure(SECURE_NOROOT)) { | ||
819 | ret = audit_log_bprm_fcaps(bprm, new, old); | ||
820 | if (ret < 0) | ||
821 | return ret; | ||
822 | } | ||
823 | } | 888 | } |
824 | 889 | ||
825 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 890 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
@@ -829,13 +894,11 @@ skip: | |||
829 | 894 | ||
830 | /* Check for privilege-elevated exec. */ | 895 | /* Check for privilege-elevated exec. */ |
831 | bprm->cap_elevated = 0; | 896 | bprm->cap_elevated = 0; |
832 | if (is_setid) { | 897 | if (is_setid || |
898 | (!__is_real(root_uid, new) && | ||
899 | (effective || | ||
900 | __cap_grew(permitted, ambient, new)))) | ||
833 | bprm->cap_elevated = 1; | 901 | bprm->cap_elevated = 1; |
834 | } else if (!uid_eq(new->uid, root_uid)) { | ||
835 | if (effective || | ||
836 | !cap_issubset(new->cap_permitted, new->cap_ambient)) | ||
837 | bprm->cap_elevated = 1; | ||
838 | } | ||
839 | 902 | ||
840 | return 0; | 903 | return 0; |
841 | } | 904 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 286171a16ed2..14cc7940b36d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -4600,6 +4600,82 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | |||
4600 | return 0; | 4600 | return 0; |
4601 | } | 4601 | } |
4602 | 4602 | ||
4603 | static int smack_inode_copy_up(struct dentry *dentry, struct cred **new) | ||
4604 | { | ||
4605 | |||
4606 | struct task_smack *tsp; | ||
4607 | struct smack_known *skp; | ||
4608 | struct inode_smack *isp; | ||
4609 | struct cred *new_creds = *new; | ||
4610 | |||
4611 | if (new_creds == NULL) { | ||
4612 | new_creds = prepare_creds(); | ||
4613 | if (new_creds == NULL) | ||
4614 | return -ENOMEM; | ||
4615 | } | ||
4616 | |||
4617 | tsp = new_creds->security; | ||
4618 | |||
4619 | /* | ||
4620 | * Get label from overlay inode and set it in create_sid | ||
4621 | */ | ||
4622 | isp = d_inode(dentry->d_parent)->i_security; | ||
4623 | skp = isp->smk_inode; | ||
4624 | tsp->smk_task = skp; | ||
4625 | *new = new_creds; | ||
4626 | return 0; | ||
4627 | } | ||
4628 | |||
4629 | static int smack_inode_copy_up_xattr(const char *name) | ||
4630 | { | ||
4631 | /* | ||
4632 | * Return 1 if this is the smack access Smack attribute. | ||
4633 | */ | ||
4634 | if (strcmp(name, XATTR_NAME_SMACK) == 0) | ||
4635 | return 1; | ||
4636 | |||
4637 | return -EOPNOTSUPP; | ||
4638 | } | ||
4639 | |||
4640 | static int smack_dentry_create_files_as(struct dentry *dentry, int mode, | ||
4641 | struct qstr *name, | ||
4642 | const struct cred *old, | ||
4643 | struct cred *new) | ||
4644 | { | ||
4645 | struct task_smack *otsp = old->security; | ||
4646 | struct task_smack *ntsp = new->security; | ||
4647 | struct inode_smack *isp; | ||
4648 | int may; | ||
4649 | |||
4650 | /* | ||
4651 | * Use the process credential unless all of | ||
4652 | * the transmuting criteria are met | ||
4653 | */ | ||
4654 | ntsp->smk_task = otsp->smk_task; | ||
4655 | |||
4656 | /* | ||
4657 | * the attribute of the containing directory | ||
4658 | */ | ||
4659 | isp = d_inode(dentry->d_parent)->i_security; | ||
4660 | |||
4661 | if (isp->smk_flags & SMK_INODE_TRANSMUTE) { | ||
4662 | rcu_read_lock(); | ||
4663 | may = smk_access_entry(otsp->smk_task->smk_known, | ||
4664 | isp->smk_inode->smk_known, | ||
4665 | &otsp->smk_task->smk_rules); | ||
4666 | rcu_read_unlock(); | ||
4667 | |||
4668 | /* | ||
4669 | * If the directory is transmuting and the rule | ||
4670 | * providing access is transmuting use the containing | ||
4671 | * directory label instead of the process label. | ||
4672 | */ | ||
4673 | if (may > 0 && (may & MAY_TRANSMUTE)) | ||
4674 | ntsp->smk_task = isp->smk_inode; | ||
4675 | } | ||
4676 | return 0; | ||
4677 | } | ||
4678 | |||
4603 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | 4679 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { |
4604 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), | 4680 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), |
4605 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), | 4681 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), |
@@ -4735,6 +4811,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | |||
4735 | LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), | 4811 | LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), |
4736 | LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx), | 4812 | LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx), |
4737 | LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx), | 4813 | LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx), |
4814 | LSM_HOOK_INIT(inode_copy_up, smack_inode_copy_up), | ||
4815 | LSM_HOOK_INIT(inode_copy_up_xattr, smack_inode_copy_up_xattr), | ||
4816 | LSM_HOOK_INIT(dentry_create_files_as, smack_dentry_create_files_as), | ||
4738 | }; | 4817 | }; |
4739 | 4818 | ||
4740 | 4819 | ||
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index d330b060dcff..0f73fe30e37a 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c | |||
@@ -157,7 +157,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
157 | if (!buffer) | 157 | if (!buffer) |
158 | return NULL; | 158 | return NULL; |
159 | 159 | ||
160 | tomoyo_convert_time(get_seconds(), &stamp); | 160 | tomoyo_convert_time(ktime_get_real_seconds(), &stamp); |
161 | 161 | ||
162 | pos = snprintf(buffer, tomoyo_buffer_len - 1, | 162 | pos = snprintf(buffer, tomoyo_buffer_len - 1, |
163 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " | 163 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 21691b99e61f..25eed4b0b0e8 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -2257,7 +2257,7 @@ static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = { | |||
2257 | /* Timestamp counter for last updated. */ | 2257 | /* Timestamp counter for last updated. */ |
2258 | static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT]; | 2258 | static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT]; |
2259 | /* Counter for number of updates. */ | 2259 | /* Counter for number of updates. */ |
2260 | static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT]; | 2260 | static time64_t tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT]; |
2261 | 2261 | ||
2262 | /** | 2262 | /** |
2263 | * tomoyo_update_stat - Update statistic counters. | 2263 | * tomoyo_update_stat - Update statistic counters. |
@@ -2272,7 +2272,7 @@ void tomoyo_update_stat(const u8 index) | |||
2272 | * I don't use atomic operations because race condition is not fatal. | 2272 | * I don't use atomic operations because race condition is not fatal. |
2273 | */ | 2273 | */ |
2274 | tomoyo_stat_updated[index]++; | 2274 | tomoyo_stat_updated[index]++; |
2275 | tomoyo_stat_modified[index] = get_seconds(); | 2275 | tomoyo_stat_modified[index] = ktime_get_real_seconds(); |
2276 | } | 2276 | } |
2277 | 2277 | ||
2278 | /** | 2278 | /** |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index e4097d7994b1..7adccdd8e36d 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -1037,7 +1037,7 @@ void tomoyo_check_acl(struct tomoyo_request_info *r, | |||
1037 | bool (*check_entry) (struct tomoyo_request_info *, | 1037 | bool (*check_entry) (struct tomoyo_request_info *, |
1038 | const struct tomoyo_acl_info *)); | 1038 | const struct tomoyo_acl_info *)); |
1039 | void tomoyo_check_profile(void); | 1039 | void tomoyo_check_profile(void); |
1040 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); | 1040 | void tomoyo_convert_time(time64_t time, struct tomoyo_time *stamp); |
1041 | void tomoyo_del_condition(struct list_head *element); | 1041 | void tomoyo_del_condition(struct list_head *element); |
1042 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 1042 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
1043 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj); | 1043 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj); |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 580b318910f1..d3d9d9f1edb0 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -87,38 +87,17 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = { | |||
87 | * @stamp: Pointer to "struct tomoyo_time". | 87 | * @stamp: Pointer to "struct tomoyo_time". |
88 | * | 88 | * |
89 | * Returns nothing. | 89 | * Returns nothing. |
90 | * | ||
91 | * This function does not handle Y2038 problem. | ||
92 | */ | 90 | */ |
93 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) | 91 | void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp) |
94 | { | 92 | { |
95 | static const u16 tomoyo_eom[2][12] = { | 93 | struct tm tm; |
96 | { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | 94 | time64_to_tm(time64, 0, &tm); |
97 | { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | 95 | stamp->sec = tm.tm_sec; |
98 | }; | 96 | stamp->min = tm.tm_min; |
99 | u16 y; | 97 | stamp->hour = tm.tm_hour; |
100 | u8 m; | 98 | stamp->day = tm.tm_mday; |
101 | bool r; | 99 | stamp->month = tm.tm_mon + 1; |
102 | stamp->sec = time % 60; | 100 | stamp->year = tm.tm_year + 1900; |
103 | time /= 60; | ||
104 | stamp->min = time % 60; | ||
105 | time /= 60; | ||
106 | stamp->hour = time % 24; | ||
107 | time /= 24; | ||
108 | for (y = 1970; ; y++) { | ||
109 | const unsigned short days = (y & 3) ? 365 : 366; | ||
110 | if (time < days) | ||
111 | break; | ||
112 | time -= days; | ||
113 | } | ||
114 | r = (y & 3) == 0; | ||
115 | for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) | ||
116 | ; | ||
117 | if (m) | ||
118 | time -= tomoyo_eom[r][m - 1]; | ||
119 | stamp->year = y; | ||
120 | stamp->month = ++m; | ||
121 | stamp->day = ++time; | ||
122 | } | 101 | } |
123 | 102 | ||
124 | /** | 103 | /** |