diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 11:50:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 11:50:52 -0400 |
| commit | 0302e28dee643932ee7b3c112ebccdbb9f8ec32c (patch) | |
| tree | 405d4cb3f772ef069ed7f291adc4b74a4e73346e | |
| parent | 89c9fea3c8034cdb2fd745f551cde0b507fd6893 (diff) | |
| parent | 8979b02aaf1d6de8d52cc143aa4da961ed32e5a2 (diff) | |
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
...
95 files changed, 3240 insertions, 1120 deletions
diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt index 2b7816dea370..5ad6480e3fb9 100644 --- a/Documentation/crypto/asymmetric-keys.txt +++ b/Documentation/crypto/asymmetric-keys.txt | |||
| @@ -311,3 +311,54 @@ Functions are provided to register and unregister parsers: | |||
| 311 | 311 | ||
| 312 | Parsers may not have the same name. The names are otherwise only used for | 312 | Parsers may not have the same name. The names are otherwise only used for |
| 313 | displaying in debugging messages. | 313 | displaying in debugging messages. |
| 314 | |||
| 315 | |||
| 316 | ========================= | ||
| 317 | KEYRING LINK RESTRICTIONS | ||
| 318 | ========================= | ||
| 319 | |||
| 320 | Keyrings created from userspace using add_key can be configured to check the | ||
| 321 | signature of the key being linked. | ||
| 322 | |||
| 323 | Several restriction methods are available: | ||
| 324 | |||
| 325 | (1) Restrict using the kernel builtin trusted keyring | ||
| 326 | |||
| 327 | - Option string used with KEYCTL_RESTRICT_KEYRING: | ||
| 328 | - "builtin_trusted" | ||
| 329 | |||
| 330 | The kernel builtin trusted keyring will be searched for the signing | ||
| 331 | key. The ca_keys kernel parameter also affects which keys are used for | ||
| 332 | signature verification. | ||
| 333 | |||
| 334 | (2) Restrict using the kernel builtin and secondary trusted keyrings | ||
| 335 | |||
| 336 | - Option string used with KEYCTL_RESTRICT_KEYRING: | ||
| 337 | - "builtin_and_secondary_trusted" | ||
| 338 | |||
| 339 | The kernel builtin and secondary trusted keyrings will be searched for the | ||
| 340 | signing key. The ca_keys kernel parameter also affects which keys are used | ||
| 341 | for signature verification. | ||
| 342 | |||
| 343 | (3) Restrict using a separate key or keyring | ||
| 344 | |||
| 345 | - Option string used with KEYCTL_RESTRICT_KEYRING: | ||
| 346 | - "key_or_keyring:<key or keyring serial number>[:chain]" | ||
| 347 | |||
| 348 | Whenever a key link is requested, the link will only succeed if the key | ||
| 349 | being linked is signed by one of the designated keys. This key may be | ||
| 350 | specified directly by providing a serial number for one asymmetric key, or | ||
| 351 | a group of keys may be searched for the signing key by providing the | ||
| 352 | serial number for a keyring. | ||
| 353 | |||
| 354 | When the "chain" option is provided at the end of the string, the keys | ||
| 355 | within the destination keyring will also be searched for signing keys. | ||
| 356 | This allows for verification of certificate chains by adding each | ||
| 357 | cert in order (starting closest to the root) to one keyring. | ||
| 358 | |||
| 359 | In all of these cases, if the signing key is found the signature of the key to | ||
| 360 | be linked will be verified using the signing key. The requested key is added | ||
| 361 | to the keyring only if the signature is successfully verified. -ENOKEY is | ||
| 362 | returned if the parent certificate could not be found, or -EKEYREJECTED is | ||
| 363 | returned if the signature check fails or the key is blacklisted. Other errors | ||
| 364 | may be returned if the signature check could not be performed. | ||
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 0e03baf271bd..cd5019934d7f 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
| @@ -827,7 +827,7 @@ The keyctl syscall functions are: | |||
| 827 | 827 | ||
| 828 | long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params, | 828 | long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params, |
| 829 | char *buffer, size_t buflen, | 829 | char *buffer, size_t buflen, |
| 830 | void *reserved); | 830 | struct keyctl_kdf_params *kdf); |
| 831 | 831 | ||
| 832 | The params struct contains serial numbers for three keys: | 832 | The params struct contains serial numbers for three keys: |
| 833 | 833 | ||
| @@ -844,18 +844,61 @@ The keyctl syscall functions are: | |||
| 844 | public key. If the base is the remote public key, the result is | 844 | public key. If the base is the remote public key, the result is |
| 845 | the shared secret. | 845 | the shared secret. |
| 846 | 846 | ||
| 847 | The reserved argument must be set to NULL. | 847 | If the parameter kdf is NULL, the following applies: |
| 848 | 848 | ||
| 849 | The buffer length must be at least the length of the prime, or zero. | 849 | - The buffer length must be at least the length of the prime, or zero. |
| 850 | 850 | ||
| 851 | If the buffer length is nonzero, the length of the result is | 851 | - If the buffer length is nonzero, the length of the result is |
| 852 | returned when it is successfully calculated and copied in to the | 852 | returned when it is successfully calculated and copied in to the |
| 853 | buffer. When the buffer length is zero, the minimum required | 853 | buffer. When the buffer length is zero, the minimum required |
| 854 | buffer length is returned. | 854 | buffer length is returned. |
| 855 | |||
| 856 | The kdf parameter allows the caller to apply a key derivation function | ||
| 857 | (KDF) on the Diffie-Hellman computation where only the result | ||
| 858 | of the KDF is returned to the caller. The KDF is characterized with | ||
| 859 | struct keyctl_kdf_params as follows: | ||
| 860 | |||
| 861 | - char *hashname specifies the NUL terminated string identifying | ||
| 862 | the hash used from the kernel crypto API and applied for the KDF | ||
| 863 | operation. The KDF implemenation complies with SP800-56A as well | ||
| 864 | as with SP800-108 (the counter KDF). | ||
| 865 | |||
| 866 | - char *otherinfo specifies the OtherInfo data as documented in | ||
| 867 | SP800-56A section 5.8.1.2. The length of the buffer is given with | ||
| 868 | otherinfolen. The format of OtherInfo is defined by the caller. | ||
| 869 | The otherinfo pointer may be NULL if no OtherInfo shall be used. | ||
| 855 | 870 | ||
| 856 | This function will return error EOPNOTSUPP if the key type is not | 871 | This function will return error EOPNOTSUPP if the key type is not |
| 857 | supported, error ENOKEY if the key could not be found, or error | 872 | supported, error ENOKEY if the key could not be found, or error |
| 858 | EACCES if the key is not readable by the caller. | 873 | EACCES if the key is not readable by the caller. In addition, the |
| 874 | function will return EMSGSIZE when the parameter kdf is non-NULL | ||
| 875 | and either the buffer length or the OtherInfo length exceeds the | ||
| 876 | allowed length. | ||
| 877 | |||
| 878 | (*) Restrict keyring linkage | ||
| 879 | |||
| 880 | long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring, | ||
| 881 | const char *type, const char *restriction); | ||
| 882 | |||
| 883 | An existing keyring can restrict linkage of additional keys by evaluating | ||
| 884 | the contents of the key according to a restriction scheme. | ||
| 885 | |||
| 886 | "keyring" is the key ID for an existing keyring to apply a restriction | ||
| 887 | to. It may be empty or may already have keys linked. Existing linked keys | ||
| 888 | will remain in the keyring even if the new restriction would reject them. | ||
| 889 | |||
| 890 | "type" is a registered key type. | ||
| 891 | |||
| 892 | "restriction" is a string describing how key linkage is to be restricted. | ||
| 893 | The format varies depending on the key type, and the string is passed to | ||
| 894 | the lookup_restriction() function for the requested type. It may specify | ||
| 895 | a method and relevant data for the restriction such as signature | ||
| 896 | verification or constraints on key payload. If the requested key type is | ||
| 897 | later unregistered, no keys may be added to the keyring after the key type | ||
| 898 | is removed. | ||
| 899 | |||
| 900 | To apply a keyring restriction the process must have Set Attribute | ||
| 901 | permission and the keyring must not be previously restricted. | ||
| 859 | 902 | ||
| 860 | =============== | 903 | =============== |
| 861 | KERNEL SERVICES | 904 | KERNEL SERVICES |
| @@ -1032,10 +1075,7 @@ payload contents" for more information. | |||
| 1032 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 1075 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
| 1033 | const struct cred *cred, | 1076 | const struct cred *cred, |
| 1034 | key_perm_t perm, | 1077 | key_perm_t perm, |
| 1035 | int (*restrict_link)(struct key *, | 1078 | struct key_restriction *restrict_link, |
| 1036 | const struct key_type *, | ||
| 1037 | unsigned long, | ||
| 1038 | const union key_payload *), | ||
| 1039 | unsigned long flags, | 1079 | unsigned long flags, |
| 1040 | struct key *dest); | 1080 | struct key *dest); |
| 1041 | 1081 | ||
| @@ -1047,20 +1087,23 @@ payload contents" for more information. | |||
| 1047 | KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted | 1087 | KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted |
| 1048 | towards the user's quota). Error ENOMEM can also be returned. | 1088 | towards the user's quota). Error ENOMEM can also be returned. |
| 1049 | 1089 | ||
| 1050 | If restrict_link not NULL, it should point to a function that will be | 1090 | If restrict_link is not NULL, it should point to a structure that contains |
| 1051 | called each time an attempt is made to link a key into the new keyring. | 1091 | the function that will be called each time an attempt is made to link a |
| 1052 | This function is called to check whether a key may be added into the keying | 1092 | key into the new keyring. The structure may also contain a key pointer |
| 1053 | or not. Callers of key_create_or_update() within the kernel can pass | 1093 | and an associated key type. The function is called to check whether a key |
| 1054 | KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using | 1094 | may be added into the keyring or not. The key type is used by the garbage |
| 1055 | this is to manage rings of cryptographic keys that are set up when the | 1095 | collector to clean up function or data pointers in this structure if the |
| 1056 | kernel boots where userspace is also permitted to add keys - provided they | 1096 | given key type is unregistered. Callers of key_create_or_update() within |
| 1057 | can be verified by a key the kernel already has. | 1097 | the kernel can pass KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. |
| 1098 | An example of using this is to manage rings of cryptographic keys that are | ||
| 1099 | set up when the kernel boots where userspace is also permitted to add keys | ||
| 1100 | - provided they can be verified by a key the kernel already has. | ||
| 1058 | 1101 | ||
| 1059 | When called, the restriction function will be passed the keyring being | 1102 | When called, the restriction function will be passed the keyring being |
| 1060 | added to, the key flags value and the type and payload of the key being | 1103 | added to, the key type, the payload of the key being added, and data to be |
| 1061 | added. Note that when a new key is being created, this is called between | 1104 | used in the restriction check. Note that when a new key is being created, |
| 1062 | payload preparsing and actual key creation. The function should return 0 | 1105 | this is called between payload preparsing and actual key creation. The |
| 1063 | to allow the link or an error to reject it. | 1106 | function should return 0 to allow the link or an error to reject it. |
| 1064 | 1107 | ||
| 1065 | A convenience function, restrict_link_reject, exists to always return | 1108 | A convenience function, restrict_link_reject, exists to always return |
| 1066 | -EPERM to in this case. | 1109 | -EPERM to in this case. |
| @@ -1445,6 +1488,15 @@ The structure has a number of fields, some of which are mandatory: | |||
| 1445 | The authorisation key. | 1488 | The authorisation key. |
| 1446 | 1489 | ||
| 1447 | 1490 | ||
| 1491 | (*) struct key_restriction *(*lookup_restriction)(const char *params); | ||
| 1492 | |||
| 1493 | This optional method is used to enable userspace configuration of keyring | ||
| 1494 | restrictions. The restriction parameter string (not including the key type | ||
| 1495 | name) is passed in, and this method returns a pointer to a key_restriction | ||
| 1496 | structure containing the relevant functions and data to evaluate each | ||
| 1497 | attempted key link operation. If there is no match, -EINVAL is returned. | ||
| 1498 | |||
| 1499 | |||
| 1448 | ============================ | 1500 | ============================ |
| 1449 | REQUEST-KEY CALLBACK SERVICE | 1501 | REQUEST-KEY CALLBACK SERVICE |
| 1450 | ============================ | 1502 | ============================ |
diff --git a/certs/Kconfig b/certs/Kconfig index fc5955f5fc8a..6ce51ede9e9b 100644 --- a/certs/Kconfig +++ b/certs/Kconfig | |||
| @@ -64,4 +64,22 @@ config SECONDARY_TRUSTED_KEYRING | |||
| 64 | those keys are not blacklisted and are vouched for by a key built | 64 | those keys are not blacklisted and are vouched for by a key built |
| 65 | into the kernel or already in the secondary trusted keyring. | 65 | into the kernel or already in the secondary trusted keyring. |
| 66 | 66 | ||
| 67 | config SYSTEM_BLACKLIST_KEYRING | ||
| 68 | bool "Provide system-wide ring of blacklisted keys" | ||
| 69 | depends on KEYS | ||
| 70 | help | ||
| 71 | Provide a system keyring to which blacklisted keys can be added. | ||
| 72 | Keys in the keyring are considered entirely untrusted. Keys in this | ||
| 73 | keyring are used by the module signature checking to reject loading | ||
| 74 | of modules signed with a blacklisted key. | ||
| 75 | |||
| 76 | config SYSTEM_BLACKLIST_HASH_LIST | ||
| 77 | string "Hashes to be preloaded into the system blacklist keyring" | ||
| 78 | depends on SYSTEM_BLACKLIST_KEYRING | ||
| 79 | help | ||
| 80 | If set, this option should be the filename of a list of hashes in the | ||
| 81 | form "<hash>", "<hash>", ... . This will be included into a C | ||
| 82 | wrapper to incorporate the list into the kernel. Each <hash> should | ||
| 83 | be a string of hex digits. | ||
| 84 | |||
| 67 | endmenu | 85 | endmenu |
diff --git a/certs/Makefile b/certs/Makefile index 2773c4afa24c..4119bb376ea1 100644 --- a/certs/Makefile +++ b/certs/Makefile | |||
| @@ -3,6 +3,12 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o | 5 | obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o |
| 6 | obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o | ||
| 7 | ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"") | ||
| 8 | obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o | ||
| 9 | else | ||
| 10 | obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o | ||
| 11 | endif | ||
| 6 | 12 | ||
| 7 | ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) | 13 | ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) |
| 8 | 14 | ||
diff --git a/certs/blacklist.c b/certs/blacklist.c new file mode 100644 index 000000000000..3eddce0e307a --- /dev/null +++ b/certs/blacklist.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | /* System hash blacklist. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define pr_fmt(fmt) "blacklist: "fmt | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/key.h> | ||
| 16 | #include <linux/key-type.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/ctype.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/seq_file.h> | ||
| 21 | #include <keys/system_keyring.h> | ||
| 22 | #include "blacklist.h" | ||
| 23 | |||
| 24 | static struct key *blacklist_keyring; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * The description must be a type prefix, a colon and then an even number of | ||
| 28 | * hex digits. The hash is kept in the description. | ||
| 29 | */ | ||
| 30 | static int blacklist_vet_description(const char *desc) | ||
| 31 | { | ||
| 32 | int n = 0; | ||
| 33 | |||
| 34 | if (*desc == ':') | ||
| 35 | return -EINVAL; | ||
| 36 | for (; *desc; desc++) | ||
| 37 | if (*desc == ':') | ||
| 38 | goto found_colon; | ||
| 39 | return -EINVAL; | ||
| 40 | |||
| 41 | found_colon: | ||
| 42 | desc++; | ||
| 43 | for (; *desc; desc++) { | ||
| 44 | if (!isxdigit(*desc)) | ||
| 45 | return -EINVAL; | ||
| 46 | n++; | ||
| 47 | } | ||
| 48 | |||
| 49 | if (n == 0 || n & 1) | ||
| 50 | return -EINVAL; | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 55 | * The hash to be blacklisted is expected to be in the description. There will | ||
| 56 | * be no payload. | ||
| 57 | */ | ||
| 58 | static int blacklist_preparse(struct key_preparsed_payload *prep) | ||
| 59 | { | ||
| 60 | if (prep->datalen > 0) | ||
| 61 | return -EINVAL; | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static void blacklist_free_preparse(struct key_preparsed_payload *prep) | ||
| 66 | { | ||
| 67 | } | ||
| 68 | |||
| 69 | static void blacklist_describe(const struct key *key, struct seq_file *m) | ||
| 70 | { | ||
| 71 | seq_puts(m, key->description); | ||
| 72 | } | ||
| 73 | |||
| 74 | static struct key_type key_type_blacklist = { | ||
| 75 | .name = "blacklist", | ||
| 76 | .vet_description = blacklist_vet_description, | ||
| 77 | .preparse = blacklist_preparse, | ||
| 78 | .free_preparse = blacklist_free_preparse, | ||
| 79 | .instantiate = generic_key_instantiate, | ||
| 80 | .describe = blacklist_describe, | ||
| 81 | }; | ||
| 82 | |||
| 83 | /** | ||
| 84 | * mark_hash_blacklisted - Add a hash to the system blacklist | ||
| 85 | * @hash - The hash as a hex string with a type prefix (eg. "tbs:23aa429783") | ||
| 86 | */ | ||
| 87 | int mark_hash_blacklisted(const char *hash) | ||
| 88 | { | ||
| 89 | key_ref_t key; | ||
| 90 | |||
| 91 | key = key_create_or_update(make_key_ref(blacklist_keyring, true), | ||
| 92 | "blacklist", | ||
| 93 | hash, | ||
| 94 | NULL, | ||
| 95 | 0, | ||
| 96 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
| 97 | KEY_USR_VIEW), | ||
| 98 | KEY_ALLOC_NOT_IN_QUOTA | | ||
| 99 | KEY_ALLOC_BUILT_IN); | ||
| 100 | if (IS_ERR(key)) { | ||
| 101 | pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key)); | ||
| 102 | return PTR_ERR(key); | ||
| 103 | } | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | /** | ||
| 108 | * is_hash_blacklisted - Determine if a hash is blacklisted | ||
| 109 | * @hash: The hash to be checked as a binary blob | ||
| 110 | * @hash_len: The length of the binary hash | ||
| 111 | * @type: Type of hash | ||
| 112 | */ | ||
| 113 | int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type) | ||
| 114 | { | ||
| 115 | key_ref_t kref; | ||
| 116 | size_t type_len = strlen(type); | ||
| 117 | char *buffer, *p; | ||
| 118 | int ret = 0; | ||
| 119 | |||
| 120 | buffer = kmalloc(type_len + 1 + hash_len * 2 + 1, GFP_KERNEL); | ||
| 121 | if (!buffer) | ||
| 122 | return -ENOMEM; | ||
| 123 | p = memcpy(buffer, type, type_len); | ||
| 124 | p += type_len; | ||
| 125 | *p++ = ':'; | ||
| 126 | bin2hex(p, hash, hash_len); | ||
| 127 | p += hash_len * 2; | ||
| 128 | *p = 0; | ||
| 129 | |||
| 130 | kref = keyring_search(make_key_ref(blacklist_keyring, true), | ||
| 131 | &key_type_blacklist, buffer); | ||
| 132 | if (!IS_ERR(kref)) { | ||
| 133 | key_ref_put(kref); | ||
| 134 | ret = -EKEYREJECTED; | ||
| 135 | } | ||
| 136 | |||
| 137 | kfree(buffer); | ||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | EXPORT_SYMBOL_GPL(is_hash_blacklisted); | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Intialise the blacklist | ||
| 144 | */ | ||
| 145 | static int __init blacklist_init(void) | ||
| 146 | { | ||
| 147 | const char *const *bl; | ||
| 148 | |||
| 149 | if (register_key_type(&key_type_blacklist) < 0) | ||
| 150 | panic("Can't allocate system blacklist key type\n"); | ||
| 151 | |||
| 152 | blacklist_keyring = | ||
| 153 | keyring_alloc(".blacklist", | ||
| 154 | KUIDT_INIT(0), KGIDT_INIT(0), | ||
| 155 | current_cred(), | ||
| 156 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
| 157 | KEY_USR_VIEW | KEY_USR_READ | | ||
| 158 | KEY_USR_SEARCH, | ||
| 159 | KEY_ALLOC_NOT_IN_QUOTA | | ||
| 160 | KEY_FLAG_KEEP, | ||
| 161 | NULL, NULL); | ||
| 162 | if (IS_ERR(blacklist_keyring)) | ||
| 163 | panic("Can't allocate system blacklist keyring\n"); | ||
| 164 | |||
| 165 | for (bl = blacklist_hashes; *bl; bl++) | ||
| 166 | if (mark_hash_blacklisted(*bl) < 0) | ||
| 167 | pr_err("- blacklisting failed\n"); | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Must be initialised before we try and load the keys into the keyring. | ||
| 173 | */ | ||
| 174 | device_initcall(blacklist_init); | ||
diff --git a/certs/blacklist.h b/certs/blacklist.h new file mode 100644 index 000000000000..150d82da8e99 --- /dev/null +++ b/certs/blacklist.h | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | #include <linux/kernel.h> | ||
| 2 | |||
| 3 | extern const char __initdata *const blacklist_hashes[]; | ||
diff --git a/certs/blacklist_hashes.c b/certs/blacklist_hashes.c new file mode 100644 index 000000000000..5bd449f7db17 --- /dev/null +++ b/certs/blacklist_hashes.c | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #include "blacklist.h" | ||
| 2 | |||
| 3 | const char __initdata *const blacklist_hashes[] = { | ||
| 4 | #include CONFIG_SYSTEM_BLACKLIST_HASH_LIST | ||
| 5 | , NULL | ||
| 6 | }; | ||
diff --git a/certs/blacklist_nohashes.c b/certs/blacklist_nohashes.c new file mode 100644 index 000000000000..851de10706a5 --- /dev/null +++ b/certs/blacklist_nohashes.c | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | #include "blacklist.h" | ||
| 2 | |||
| 3 | const char __initdata *const blacklist_hashes[] = { | ||
| 4 | NULL | ||
| 5 | }; | ||
diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 50979d6dcecd..6251d1b27f0c 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 15 | #include <linux/cred.h> | 15 | #include <linux/cred.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | #include <keys/asymmetric-type.h> | 18 | #include <keys/asymmetric-type.h> |
| 18 | #include <keys/system_keyring.h> | 19 | #include <keys/system_keyring.h> |
| 19 | #include <crypto/pkcs7.h> | 20 | #include <crypto/pkcs7.h> |
| @@ -32,11 +33,13 @@ extern __initconst const unsigned long system_certificate_list_size; | |||
| 32 | * Restrict the addition of keys into a keyring based on the key-to-be-added | 33 | * Restrict the addition of keys into a keyring based on the key-to-be-added |
| 33 | * being vouched for by a key in the built in system keyring. | 34 | * being vouched for by a key in the built in system keyring. |
| 34 | */ | 35 | */ |
| 35 | int restrict_link_by_builtin_trusted(struct key *keyring, | 36 | int restrict_link_by_builtin_trusted(struct key *dest_keyring, |
| 36 | const struct key_type *type, | 37 | const struct key_type *type, |
| 37 | const union key_payload *payload) | 38 | const union key_payload *payload, |
| 39 | struct key *restriction_key) | ||
| 38 | { | 40 | { |
| 39 | return restrict_link_by_signature(builtin_trusted_keys, type, payload); | 41 | return restrict_link_by_signature(dest_keyring, type, payload, |
| 42 | builtin_trusted_keys); | ||
| 40 | } | 43 | } |
| 41 | 44 | ||
| 42 | #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING | 45 | #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING |
| @@ -49,20 +52,40 @@ int restrict_link_by_builtin_trusted(struct key *keyring, | |||
| 49 | * keyrings. | 52 | * keyrings. |
| 50 | */ | 53 | */ |
| 51 | int restrict_link_by_builtin_and_secondary_trusted( | 54 | int restrict_link_by_builtin_and_secondary_trusted( |
| 52 | struct key *keyring, | 55 | struct key *dest_keyring, |
| 53 | const struct key_type *type, | 56 | const struct key_type *type, |
| 54 | const union key_payload *payload) | 57 | const union key_payload *payload, |
| 58 | struct key *restrict_key) | ||
| 55 | { | 59 | { |
| 56 | /* If we have a secondary trusted keyring, then that contains a link | 60 | /* If we have a secondary trusted keyring, then that contains a link |
| 57 | * through to the builtin keyring and the search will follow that link. | 61 | * through to the builtin keyring and the search will follow that link. |
| 58 | */ | 62 | */ |
| 59 | if (type == &key_type_keyring && | 63 | if (type == &key_type_keyring && |
| 60 | keyring == secondary_trusted_keys && | 64 | dest_keyring == secondary_trusted_keys && |
| 61 | payload == &builtin_trusted_keys->payload) | 65 | payload == &builtin_trusted_keys->payload) |
| 62 | /* Allow the builtin keyring to be added to the secondary */ | 66 | /* Allow the builtin keyring to be added to the secondary */ |
| 63 | return 0; | 67 | return 0; |
| 64 | 68 | ||
| 65 | return restrict_link_by_signature(secondary_trusted_keys, type, payload); | 69 | return restrict_link_by_signature(dest_keyring, type, payload, |
| 70 | secondary_trusted_keys); | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Allocate a struct key_restriction for the "builtin and secondary trust" | ||
| 75 | * keyring. Only for use in system_trusted_keyring_init(). | ||
| 76 | */ | ||
| 77 | static __init struct key_restriction *get_builtin_and_secondary_restriction(void) | ||
| 78 | { | ||
| 79 | struct key_restriction *restriction; | ||
| 80 | |||
| 81 | restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | ||
| 82 | |||
| 83 | if (!restriction) | ||
| 84 | panic("Can't allocate secondary trusted keyring restriction\n"); | ||
| 85 | |||
| 86 | restriction->check = restrict_link_by_builtin_and_secondary_trusted; | ||
| 87 | |||
| 88 | return restriction; | ||
| 66 | } | 89 | } |
| 67 | #endif | 90 | #endif |
| 68 | 91 | ||
| @@ -91,7 +114,7 @@ static __init int system_trusted_keyring_init(void) | |||
| 91 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | | 114 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | |
| 92 | KEY_USR_WRITE), | 115 | KEY_USR_WRITE), |
| 93 | KEY_ALLOC_NOT_IN_QUOTA, | 116 | KEY_ALLOC_NOT_IN_QUOTA, |
| 94 | restrict_link_by_builtin_and_secondary_trusted, | 117 | get_builtin_and_secondary_restriction(), |
| 95 | NULL); | 118 | NULL); |
| 96 | if (IS_ERR(secondary_trusted_keys)) | 119 | if (IS_ERR(secondary_trusted_keys)) |
| 97 | panic("Can't allocate secondary trusted keyring\n"); | 120 | panic("Can't allocate secondary trusted keyring\n"); |
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 6600181d5d01..e4b0ed386bc8 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/ctype.h> | 19 | #include <linux/ctype.h> |
| 20 | #include <keys/system_keyring.h> | ||
| 20 | #include "asymmetric_keys.h" | 21 | #include "asymmetric_keys.h" |
| 21 | 22 | ||
| 22 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
| @@ -451,15 +452,100 @@ static void asymmetric_key_destroy(struct key *key) | |||
| 451 | asymmetric_key_free_kids(kids); | 452 | asymmetric_key_free_kids(kids); |
| 452 | } | 453 | } |
| 453 | 454 | ||
| 455 | static struct key_restriction *asymmetric_restriction_alloc( | ||
| 456 | key_restrict_link_func_t check, | ||
| 457 | struct key *key) | ||
| 458 | { | ||
| 459 | struct key_restriction *keyres = | ||
| 460 | kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | ||
| 461 | |||
| 462 | if (!keyres) | ||
| 463 | return ERR_PTR(-ENOMEM); | ||
| 464 | |||
| 465 | keyres->check = check; | ||
| 466 | keyres->key = key; | ||
| 467 | keyres->keytype = &key_type_asymmetric; | ||
| 468 | |||
| 469 | return keyres; | ||
| 470 | } | ||
| 471 | |||
| 472 | /* | ||
| 473 | * look up keyring restrict functions for asymmetric keys | ||
| 474 | */ | ||
| 475 | static struct key_restriction *asymmetric_lookup_restriction( | ||
| 476 | const char *restriction) | ||
| 477 | { | ||
| 478 | char *restrict_method; | ||
| 479 | char *parse_buf; | ||
| 480 | char *next; | ||
| 481 | struct key_restriction *ret = ERR_PTR(-EINVAL); | ||
| 482 | |||
| 483 | if (strcmp("builtin_trusted", restriction) == 0) | ||
| 484 | return asymmetric_restriction_alloc( | ||
| 485 | restrict_link_by_builtin_trusted, NULL); | ||
| 486 | |||
| 487 | if (strcmp("builtin_and_secondary_trusted", restriction) == 0) | ||
| 488 | return asymmetric_restriction_alloc( | ||
| 489 | restrict_link_by_builtin_and_secondary_trusted, NULL); | ||
| 490 | |||
| 491 | parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL); | ||
| 492 | if (!parse_buf) | ||
| 493 | return ERR_PTR(-ENOMEM); | ||
| 494 | |||
| 495 | next = parse_buf; | ||
| 496 | restrict_method = strsep(&next, ":"); | ||
| 497 | |||
| 498 | if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) { | ||
| 499 | char *key_text; | ||
| 500 | key_serial_t serial; | ||
| 501 | struct key *key; | ||
| 502 | key_restrict_link_func_t link_fn = | ||
| 503 | restrict_link_by_key_or_keyring; | ||
| 504 | bool allow_null_key = false; | ||
| 505 | |||
| 506 | key_text = strsep(&next, ":"); | ||
| 507 | |||
| 508 | if (next) { | ||
| 509 | if (strcmp(next, "chain") != 0) | ||
| 510 | goto out; | ||
| 511 | |||
| 512 | link_fn = restrict_link_by_key_or_keyring_chain; | ||
| 513 | allow_null_key = true; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (kstrtos32(key_text, 0, &serial) < 0) | ||
| 517 | goto out; | ||
| 518 | |||
| 519 | if ((serial == 0) && allow_null_key) { | ||
| 520 | key = NULL; | ||
| 521 | } else { | ||
| 522 | key = key_lookup(serial); | ||
| 523 | if (IS_ERR(key)) { | ||
| 524 | ret = ERR_CAST(key); | ||
| 525 | goto out; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | ret = asymmetric_restriction_alloc(link_fn, key); | ||
| 530 | if (IS_ERR(ret)) | ||
| 531 | key_put(key); | ||
| 532 | } | ||
| 533 | |||
| 534 | out: | ||
| 535 | kfree(parse_buf); | ||
| 536 | return ret; | ||
| 537 | } | ||
| 538 | |||
| 454 | struct key_type key_type_asymmetric = { | 539 | struct key_type key_type_asymmetric = { |
| 455 | .name = "asymmetric", | 540 | .name = "asymmetric", |
| 456 | .preparse = asymmetric_key_preparse, | 541 | .preparse = asymmetric_key_preparse, |
| 457 | .free_preparse = asymmetric_key_free_preparse, | 542 | .free_preparse = asymmetric_key_free_preparse, |
| 458 | .instantiate = generic_key_instantiate, | 543 | .instantiate = generic_key_instantiate, |
| 459 | .match_preparse = asymmetric_key_match_preparse, | 544 | .match_preparse = asymmetric_key_match_preparse, |
| 460 | .match_free = asymmetric_key_match_free, | 545 | .match_free = asymmetric_key_match_free, |
| 461 | .destroy = asymmetric_key_destroy, | 546 | .destroy = asymmetric_key_destroy, |
| 462 | .describe = asymmetric_key_describe, | 547 | .describe = asymmetric_key_describe, |
| 548 | .lookup_restriction = asymmetric_lookup_restriction, | ||
| 463 | }; | 549 | }; |
| 464 | EXPORT_SYMBOL_GPL(key_type_asymmetric); | 550 | EXPORT_SYMBOL_GPL(key_type_asymmetric); |
| 465 | 551 | ||
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index f4e81074f5e0..ac341e19e530 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h | |||
| @@ -23,6 +23,7 @@ struct pkcs7_signed_info { | |||
| 23 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ | 23 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ |
| 24 | unsigned index; | 24 | unsigned index; |
| 25 | bool unsupported_crypto; /* T if not usable due to missing crypto */ | 25 | bool unsupported_crypto; /* T if not usable due to missing crypto */ |
| 26 | bool blacklisted; | ||
| 26 | 27 | ||
| 27 | /* Message digest - the digest of the Content Data (or NULL) */ | 28 | /* Message digest - the digest of the Content Data (or NULL) */ |
| 28 | const void *msgdigest; | 29 | const void *msgdigest; |
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 2ffd69769466..2d93d9eccb4d 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c | |||
| @@ -190,6 +190,18 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
| 190 | x509->subject, | 190 | x509->subject, |
| 191 | x509->raw_serial_size, x509->raw_serial); | 191 | x509->raw_serial_size, x509->raw_serial); |
| 192 | x509->seen = true; | 192 | x509->seen = true; |
| 193 | |||
| 194 | if (x509->blacklisted) { | ||
| 195 | /* If this cert is blacklisted, then mark everything | ||
| 196 | * that depends on this as blacklisted too. | ||
| 197 | */ | ||
| 198 | sinfo->blacklisted = true; | ||
| 199 | for (p = sinfo->signer; p != x509; p = p->signer) | ||
| 200 | p->blacklisted = true; | ||
| 201 | pr_debug("- blacklisted\n"); | ||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 193 | if (x509->unsupported_key) | 205 | if (x509->unsupported_key) |
| 194 | goto unsupported_crypto_in_x509; | 206 | goto unsupported_crypto_in_x509; |
| 195 | 207 | ||
| @@ -357,17 +369,19 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | |||
| 357 | * | 369 | * |
| 358 | * (*) -EBADMSG if some part of the message was invalid, or: | 370 | * (*) -EBADMSG if some part of the message was invalid, or: |
| 359 | * | 371 | * |
| 360 | * (*) -ENOPKG if none of the signature chains are verifiable because suitable | 372 | * (*) 0 if no signature chains were found to be blacklisted or to contain |
| 361 | * crypto modules couldn't be found, or: | 373 | * unsupported crypto, or: |
| 362 | * | 374 | * |
| 363 | * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified | 375 | * (*) -EKEYREJECTED if a blacklisted key was encountered, or: |
| 364 | * (note that a signature chain may be of zero length), or: | 376 | * |
| 377 | * (*) -ENOPKG if none of the signature chains are verifiable because suitable | ||
| 378 | * crypto modules couldn't be found. | ||
| 365 | */ | 379 | */ |
| 366 | int pkcs7_verify(struct pkcs7_message *pkcs7, | 380 | int pkcs7_verify(struct pkcs7_message *pkcs7, |
| 367 | enum key_being_used_for usage) | 381 | enum key_being_used_for usage) |
| 368 | { | 382 | { |
| 369 | struct pkcs7_signed_info *sinfo; | 383 | struct pkcs7_signed_info *sinfo; |
| 370 | int enopkg = -ENOPKG; | 384 | int actual_ret = -ENOPKG; |
| 371 | int ret; | 385 | int ret; |
| 372 | 386 | ||
| 373 | kenter(""); | 387 | kenter(""); |
| @@ -412,6 +426,8 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, | |||
| 412 | 426 | ||
| 413 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { | 427 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { |
| 414 | ret = pkcs7_verify_one(pkcs7, sinfo); | 428 | ret = pkcs7_verify_one(pkcs7, sinfo); |
| 429 | if (sinfo->blacklisted && actual_ret == -ENOPKG) | ||
| 430 | actual_ret = -EKEYREJECTED; | ||
| 415 | if (ret < 0) { | 431 | if (ret < 0) { |
| 416 | if (ret == -ENOPKG) { | 432 | if (ret == -ENOPKG) { |
| 417 | sinfo->unsupported_crypto = true; | 433 | sinfo->unsupported_crypto = true; |
| @@ -420,11 +436,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, | |||
| 420 | kleave(" = %d", ret); | 436 | kleave(" = %d", ret); |
| 421 | return ret; | 437 | return ret; |
| 422 | } | 438 | } |
| 423 | enopkg = 0; | 439 | actual_ret = 0; |
| 424 | } | 440 | } |
| 425 | 441 | ||
| 426 | kleave(" = %d", enopkg); | 442 | kleave(" = %d", actual_ret); |
| 427 | return enopkg; | 443 | return actual_ret; |
| 428 | } | 444 | } |
| 429 | EXPORT_SYMBOL_GPL(pkcs7_verify); | 445 | EXPORT_SYMBOL_GPL(pkcs7_verify); |
| 430 | 446 | ||
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index 19d1afb9890f..86fb68508952 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c | |||
| @@ -56,9 +56,10 @@ __setup("ca_keys=", ca_keys_setup); | |||
| 56 | 56 | ||
| 57 | /** | 57 | /** |
| 58 | * restrict_link_by_signature - Restrict additions to a ring of public keys | 58 | * restrict_link_by_signature - Restrict additions to a ring of public keys |
| 59 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. | 59 | * @dest_keyring: Keyring being linked to. |
| 60 | * @type: The type of key being added. | 60 | * @type: The type of key being added. |
| 61 | * @payload: The payload of the new key. | 61 | * @payload: The payload of the new key. |
| 62 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. | ||
| 62 | * | 63 | * |
| 63 | * Check the new certificate against the ones in the trust keyring. If one of | 64 | * Check the new certificate against the ones in the trust keyring. If one of |
| 64 | * those is the signing key and validates the new certificate, then mark the | 65 | * those is the signing key and validates the new certificate, then mark the |
| @@ -69,9 +70,10 @@ __setup("ca_keys=", ca_keys_setup); | |||
| 69 | * signature check fails or the key is blacklisted and some other error if | 70 | * signature check fails or the key is blacklisted and some other error if |
| 70 | * there is a matching certificate but the signature check cannot be performed. | 71 | * there is a matching certificate but the signature check cannot be performed. |
| 71 | */ | 72 | */ |
| 72 | int restrict_link_by_signature(struct key *trust_keyring, | 73 | int restrict_link_by_signature(struct key *dest_keyring, |
| 73 | const struct key_type *type, | 74 | const struct key_type *type, |
| 74 | const union key_payload *payload) | 75 | const union key_payload *payload, |
| 76 | struct key *trust_keyring) | ||
| 75 | { | 77 | { |
| 76 | const struct public_key_signature *sig; | 78 | const struct public_key_signature *sig; |
| 77 | struct key *key; | 79 | struct key *key; |
| @@ -106,3 +108,156 @@ int restrict_link_by_signature(struct key *trust_keyring, | |||
| 106 | key_put(key); | 108 | key_put(key); |
| 107 | return ret; | 109 | return ret; |
| 108 | } | 110 | } |
| 111 | |||
| 112 | static bool match_either_id(const struct asymmetric_key_ids *pair, | ||
| 113 | const struct asymmetric_key_id *single) | ||
| 114 | { | ||
| 115 | return (asymmetric_key_id_same(pair->id[0], single) || | ||
| 116 | asymmetric_key_id_same(pair->id[1], single)); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int key_or_keyring_common(struct key *dest_keyring, | ||
| 120 | const struct key_type *type, | ||
| 121 | const union key_payload *payload, | ||
| 122 | struct key *trusted, bool check_dest) | ||
| 123 | { | ||
| 124 | const struct public_key_signature *sig; | ||
| 125 | struct key *key = NULL; | ||
| 126 | int ret; | ||
| 127 | |||
| 128 | pr_devel("==>%s()\n", __func__); | ||
| 129 | |||
| 130 | if (!dest_keyring) | ||
| 131 | return -ENOKEY; | ||
| 132 | else if (dest_keyring->type != &key_type_keyring) | ||
| 133 | return -EOPNOTSUPP; | ||
| 134 | |||
| 135 | if (!trusted && !check_dest) | ||
| 136 | return -ENOKEY; | ||
| 137 | |||
| 138 | if (type != &key_type_asymmetric) | ||
| 139 | return -EOPNOTSUPP; | ||
| 140 | |||
| 141 | sig = payload->data[asym_auth]; | ||
| 142 | if (!sig->auth_ids[0] && !sig->auth_ids[1]) | ||
| 143 | return -ENOKEY; | ||
| 144 | |||
| 145 | if (trusted) { | ||
| 146 | if (trusted->type == &key_type_keyring) { | ||
| 147 | /* See if we have a key that signed this one. */ | ||
| 148 | key = find_asymmetric_key(trusted, sig->auth_ids[0], | ||
| 149 | sig->auth_ids[1], false); | ||
| 150 | if (IS_ERR(key)) | ||
| 151 | key = NULL; | ||
| 152 | } else if (trusted->type == &key_type_asymmetric) { | ||
| 153 | const struct asymmetric_key_ids *signer_ids; | ||
| 154 | |||
| 155 | signer_ids = asymmetric_key_ids(trusted); | ||
| 156 | |||
| 157 | /* | ||
| 158 | * The auth_ids come from the candidate key (the | ||
| 159 | * one that is being considered for addition to | ||
| 160 | * dest_keyring) and identify the key that was | ||
| 161 | * used to sign. | ||
| 162 | * | ||
| 163 | * The signer_ids are identifiers for the | ||
| 164 | * signing key specified for dest_keyring. | ||
| 165 | * | ||
| 166 | * The first auth_id is the preferred id, and | ||
| 167 | * the second is the fallback. If only one | ||
| 168 | * auth_id is present, it may match against | ||
| 169 | * either signer_id. If two auth_ids are | ||
| 170 | * present, the first auth_id must match one | ||
| 171 | * signer_id and the second auth_id must match | ||
| 172 | * the second signer_id. | ||
| 173 | */ | ||
| 174 | if (!sig->auth_ids[0] || !sig->auth_ids[1]) { | ||
| 175 | const struct asymmetric_key_id *auth_id; | ||
| 176 | |||
| 177 | auth_id = sig->auth_ids[0] ?: sig->auth_ids[1]; | ||
| 178 | if (match_either_id(signer_ids, auth_id)) | ||
| 179 | key = __key_get(trusted); | ||
| 180 | |||
| 181 | } else if (asymmetric_key_id_same(signer_ids->id[1], | ||
| 182 | sig->auth_ids[1]) && | ||
| 183 | match_either_id(signer_ids, | ||
| 184 | sig->auth_ids[0])) { | ||
| 185 | key = __key_get(trusted); | ||
| 186 | } | ||
| 187 | } else { | ||
| 188 | return -EOPNOTSUPP; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | if (check_dest && !key) { | ||
| 193 | /* See if the destination has a key that signed this one. */ | ||
| 194 | key = find_asymmetric_key(dest_keyring, sig->auth_ids[0], | ||
| 195 | sig->auth_ids[1], false); | ||
| 196 | if (IS_ERR(key)) | ||
| 197 | key = NULL; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (!key) | ||
| 201 | return -ENOKEY; | ||
| 202 | |||
| 203 | ret = key_validate(key); | ||
| 204 | if (ret == 0) | ||
| 205 | ret = verify_signature(key, sig); | ||
| 206 | |||
| 207 | key_put(key); | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | |||
| 211 | /** | ||
| 212 | * restrict_link_by_key_or_keyring - Restrict additions to a ring of public | ||
| 213 | * keys using the restrict_key information stored in the ring. | ||
| 214 | * @dest_keyring: Keyring being linked to. | ||
| 215 | * @type: The type of key being added. | ||
| 216 | * @payload: The payload of the new key. | ||
| 217 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. | ||
| 218 | * | ||
| 219 | * Check the new certificate only against the key or keys passed in the data | ||
| 220 | * parameter. If one of those is the signing key and validates the new | ||
| 221 | * certificate, then mark the new certificate as being ok to link. | ||
| 222 | * | ||
| 223 | * Returns 0 if the new certificate was accepted, -ENOKEY if we | ||
| 224 | * couldn't find a matching parent certificate in the trusted list, | ||
| 225 | * -EKEYREJECTED if the signature check fails, and some other error if | ||
| 226 | * there is a matching certificate but the signature check cannot be | ||
| 227 | * performed. | ||
| 228 | */ | ||
| 229 | int restrict_link_by_key_or_keyring(struct key *dest_keyring, | ||
| 230 | const struct key_type *type, | ||
| 231 | const union key_payload *payload, | ||
| 232 | struct key *trusted) | ||
| 233 | { | ||
| 234 | return key_or_keyring_common(dest_keyring, type, payload, trusted, | ||
| 235 | false); | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | ||
| 239 | * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of | ||
| 240 | * public keys using the restrict_key information stored in the ring. | ||
| 241 | * @dest_keyring: Keyring being linked to. | ||
| 242 | * @type: The type of key being added. | ||
| 243 | * @payload: The payload of the new key. | ||
| 244 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. | ||
| 245 | * | ||
| 246 | * Check the new certificate only against the key or keys passed in the data | ||
| 247 | * parameter. If one of those is the signing key and validates the new | ||
| 248 | * certificate, then mark the new certificate as being ok to link. | ||
| 249 | * | ||
| 250 | * Returns 0 if the new certificate was accepted, -ENOKEY if we | ||
| 251 | * couldn't find a matching parent certificate in the trusted list, | ||
| 252 | * -EKEYREJECTED if the signature check fails, and some other error if | ||
| 253 | * there is a matching certificate but the signature check cannot be | ||
| 254 | * performed. | ||
| 255 | */ | ||
| 256 | int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, | ||
| 257 | const struct key_type *type, | ||
| 258 | const union key_payload *payload, | ||
| 259 | struct key *trusted) | ||
| 260 | { | ||
| 261 | return key_or_keyring_common(dest_keyring, type, payload, trusted, | ||
| 262 | true); | ||
| 263 | } | ||
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 05eef1c68881..e373e7483812 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h | |||
| @@ -42,6 +42,7 @@ struct x509_certificate { | |||
| 42 | bool self_signed; /* T if self-signed (check unsupported_sig too) */ | 42 | bool self_signed; /* T if self-signed (check unsupported_sig too) */ |
| 43 | bool unsupported_key; /* T if key uses unsupported crypto */ | 43 | bool unsupported_key; /* T if key uses unsupported crypto */ |
| 44 | bool unsupported_sig; /* T if signature uses unsupported crypto */ | 44 | bool unsupported_sig; /* T if signature uses unsupported crypto */ |
| 45 | bool blacklisted; | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | /* | 48 | /* |
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index fb732296cd36..eea71dc9686c 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
| @@ -84,6 +84,16 @@ int x509_get_sig_params(struct x509_certificate *cert) | |||
| 84 | goto error_2; | 84 | goto error_2; |
| 85 | might_sleep(); | 85 | might_sleep(); |
| 86 | ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); | 86 | ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); |
| 87 | if (ret < 0) | ||
| 88 | goto error_2; | ||
| 89 | |||
| 90 | ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs"); | ||
| 91 | if (ret == -EKEYREJECTED) { | ||
| 92 | pr_err("Cert %*phN is blacklisted\n", | ||
| 93 | sig->digest_size, sig->digest); | ||
| 94 | cert->blacklisted = true; | ||
| 95 | ret = 0; | ||
| 96 | } | ||
| 87 | 97 | ||
| 88 | error_2: | 98 | error_2: |
| 89 | kfree(desc); | 99 | kfree(desc); |
| @@ -186,6 +196,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
| 186 | cert->sig->pkey_algo, cert->sig->hash_algo); | 196 | cert->sig->pkey_algo, cert->sig->hash_algo); |
| 187 | } | 197 | } |
| 188 | 198 | ||
| 199 | /* Don't permit addition of blacklisted keys */ | ||
| 200 | ret = -EKEYREJECTED; | ||
| 201 | if (cert->blacklisted) | ||
| 202 | goto error_free_cert; | ||
| 203 | |||
| 189 | /* Propose a description */ | 204 | /* Propose a description */ |
| 190 | sulen = strlen(cert->subject); | 205 | sulen = strlen(cert->subject); |
| 191 | if (cert->raw_skid) { | 206 | if (cert->raw_skid) { |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index af985cca413c..a30352202f1f 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
| @@ -6,6 +6,7 @@ menuconfig TCG_TPM | |||
| 6 | tristate "TPM Hardware Support" | 6 | tristate "TPM Hardware Support" |
| 7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
| 8 | select SECURITYFS | 8 | select SECURITYFS |
| 9 | select CRYPTO | ||
| 9 | select CRYPTO_HASH_INFO | 10 | select CRYPTO_HASH_INFO |
| 10 | ---help--- | 11 | ---help--- |
| 11 | If you have a TPM security chip in your system, which | 12 | If you have a TPM security chip in your system, which |
| @@ -135,7 +136,7 @@ config TCG_XEN | |||
| 135 | 136 | ||
| 136 | config TCG_CRB | 137 | config TCG_CRB |
| 137 | tristate "TPM 2.0 CRB Interface" | 138 | tristate "TPM 2.0 CRB Interface" |
| 138 | depends on X86 && ACPI | 139 | depends on ACPI |
| 139 | ---help--- | 140 | ---help--- |
| 140 | If you have a TPM security chip that is compliant with the | 141 | If you have a TPM security chip that is compliant with the |
| 141 | TCG CRB 2.0 TPM specification say Yes and it will be accessible | 142 | TCG CRB 2.0 TPM specification say Yes and it will be accessible |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 3d386a8c579f..23681f01f95a 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | # | 3 | # |
| 4 | obj-$(CONFIG_TCG_TPM) += tpm.o | 4 | obj-$(CONFIG_TCG_TPM) += tpm.o |
| 5 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ | 5 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ |
| 6 | tpm1_eventlog.o tpm2_eventlog.o | 6 | tpm-dev-common.o tpmrm-dev.o tpm1_eventlog.o tpm2_eventlog.o \ |
| 7 | tpm2-space.o | ||
| 7 | tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o | 8 | tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o |
| 8 | tpm-$(CONFIG_OF) += tpm_of.o | 9 | tpm-$(CONFIG_OF) += tpm_of.o |
| 9 | obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o | 10 | obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o |
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 028a9cd76b63..1b10e38f214e 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c | |||
| @@ -111,6 +111,13 @@ static const struct st33zp24_phy_ops i2c_phy_ops = { | |||
| 111 | .recv = st33zp24_i2c_recv, | 111 | .recv = st33zp24_i2c_recv, |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false }; | ||
| 115 | |||
| 116 | static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = { | ||
| 117 | { "lpcpd-gpios", &lpcpd_gpios, 1 }, | ||
| 118 | {}, | ||
| 119 | }; | ||
| 120 | |||
| 114 | static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client) | 121 | static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client) |
| 115 | { | 122 | { |
| 116 | struct tpm_chip *chip = i2c_get_clientdata(client); | 123 | struct tpm_chip *chip = i2c_get_clientdata(client); |
| @@ -118,10 +125,14 @@ static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client) | |||
| 118 | struct st33zp24_i2c_phy *phy = tpm_dev->phy_id; | 125 | struct st33zp24_i2c_phy *phy = tpm_dev->phy_id; |
| 119 | struct gpio_desc *gpiod_lpcpd; | 126 | struct gpio_desc *gpiod_lpcpd; |
| 120 | struct device *dev = &client->dev; | 127 | struct device *dev = &client->dev; |
| 128 | int ret; | ||
| 129 | |||
| 130 | ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios); | ||
| 131 | if (ret) | ||
| 132 | return ret; | ||
| 121 | 133 | ||
| 122 | /* Get LPCPD GPIO from ACPI */ | 134 | /* Get LPCPD GPIO from ACPI */ |
| 123 | gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1, | 135 | gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH); |
| 124 | GPIOD_OUT_HIGH); | ||
| 125 | if (IS_ERR(gpiod_lpcpd)) { | 136 | if (IS_ERR(gpiod_lpcpd)) { |
| 126 | dev_err(&client->dev, | 137 | dev_err(&client->dev, |
| 127 | "Failed to retrieve lpcpd-gpios from acpi.\n"); | 138 | "Failed to retrieve lpcpd-gpios from acpi.\n"); |
| @@ -268,8 +279,14 @@ static int st33zp24_i2c_probe(struct i2c_client *client, | |||
| 268 | static int st33zp24_i2c_remove(struct i2c_client *client) | 279 | static int st33zp24_i2c_remove(struct i2c_client *client) |
| 269 | { | 280 | { |
| 270 | struct tpm_chip *chip = i2c_get_clientdata(client); | 281 | struct tpm_chip *chip = i2c_get_clientdata(client); |
| 282 | int ret; | ||
| 271 | 283 | ||
| 272 | return st33zp24_remove(chip); | 284 | ret = st33zp24_remove(chip); |
| 285 | if (ret) | ||
| 286 | return ret; | ||
| 287 | |||
| 288 | acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev)); | ||
| 289 | return 0; | ||
| 273 | } | 290 | } |
| 274 | 291 | ||
| 275 | static const struct i2c_device_id st33zp24_i2c_id[] = { | 292 | static const struct i2c_device_id st33zp24_i2c_id[] = { |
diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index 9f5a0117098c..c69d15198f84 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c | |||
| @@ -230,6 +230,13 @@ static const struct st33zp24_phy_ops spi_phy_ops = { | |||
| 230 | .recv = st33zp24_spi_recv, | 230 | .recv = st33zp24_spi_recv, |
| 231 | }; | 231 | }; |
| 232 | 232 | ||
| 233 | static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false }; | ||
| 234 | |||
| 235 | static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = { | ||
| 236 | { "lpcpd-gpios", &lpcpd_gpios, 1 }, | ||
| 237 | {}, | ||
| 238 | }; | ||
| 239 | |||
| 233 | static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) | 240 | static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) |
| 234 | { | 241 | { |
| 235 | struct tpm_chip *chip = spi_get_drvdata(spi_dev); | 242 | struct tpm_chip *chip = spi_get_drvdata(spi_dev); |
| @@ -237,10 +244,14 @@ static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) | |||
| 237 | struct st33zp24_spi_phy *phy = tpm_dev->phy_id; | 244 | struct st33zp24_spi_phy *phy = tpm_dev->phy_id; |
| 238 | struct gpio_desc *gpiod_lpcpd; | 245 | struct gpio_desc *gpiod_lpcpd; |
| 239 | struct device *dev = &spi_dev->dev; | 246 | struct device *dev = &spi_dev->dev; |
| 247 | int ret; | ||
| 248 | |||
| 249 | ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios); | ||
| 250 | if (ret) | ||
| 251 | return ret; | ||
| 240 | 252 | ||
| 241 | /* Get LPCPD GPIO from ACPI */ | 253 | /* Get LPCPD GPIO from ACPI */ |
| 242 | gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1, | 254 | gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH); |
| 243 | GPIOD_OUT_HIGH); | ||
| 244 | if (IS_ERR(gpiod_lpcpd)) { | 255 | if (IS_ERR(gpiod_lpcpd)) { |
| 245 | dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n"); | 256 | dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n"); |
| 246 | phy->io_lpcpd = -1; | 257 | phy->io_lpcpd = -1; |
| @@ -385,8 +396,14 @@ static int st33zp24_spi_probe(struct spi_device *dev) | |||
| 385 | static int st33zp24_spi_remove(struct spi_device *dev) | 396 | static int st33zp24_spi_remove(struct spi_device *dev) |
| 386 | { | 397 | { |
| 387 | struct tpm_chip *chip = spi_get_drvdata(dev); | 398 | struct tpm_chip *chip = spi_get_drvdata(dev); |
| 399 | int ret; | ||
| 388 | 400 | ||
| 389 | return st33zp24_remove(chip); | 401 | ret = st33zp24_remove(chip); |
| 402 | if (ret) | ||
| 403 | return ret; | ||
| 404 | |||
| 405 | acpi_dev_remove_driver_gpios(ACPI_COMPANION(&dev->dev)); | ||
| 406 | return 0; | ||
| 390 | } | 407 | } |
| 391 | 408 | ||
| 392 | static const struct spi_device_id st33zp24_spi_id[] = { | 409 | static const struct spi_device_id st33zp24_spi_id[] = { |
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index e8e0f7c02686..4d1dc8b46877 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c | |||
| @@ -117,9 +117,9 @@ static u8 st33zp24_status(struct tpm_chip *chip) | |||
| 117 | /* | 117 | /* |
| 118 | * check_locality if the locality is active | 118 | * check_locality if the locality is active |
| 119 | * @param: chip, the tpm chip description | 119 | * @param: chip, the tpm chip description |
| 120 | * @return: the active locality or -EACCESS. | 120 | * @return: true if LOCALITY0 is active, otherwise false |
| 121 | */ | 121 | */ |
| 122 | static int check_locality(struct tpm_chip *chip) | 122 | static bool check_locality(struct tpm_chip *chip) |
| 123 | { | 123 | { |
| 124 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); | 124 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); |
| 125 | u8 data; | 125 | u8 data; |
| @@ -129,9 +129,9 @@ static int check_locality(struct tpm_chip *chip) | |||
| 129 | if (status && (data & | 129 | if (status && (data & |
| 130 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | 130 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == |
| 131 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | 131 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) |
| 132 | return tpm_dev->locality; | 132 | return true; |
| 133 | 133 | ||
| 134 | return -EACCES; | 134 | return false; |
| 135 | } /* check_locality() */ | 135 | } /* check_locality() */ |
| 136 | 136 | ||
| 137 | /* | 137 | /* |
| @@ -146,7 +146,7 @@ static int request_locality(struct tpm_chip *chip) | |||
| 146 | long ret; | 146 | long ret; |
| 147 | u8 data; | 147 | u8 data; |
| 148 | 148 | ||
| 149 | if (check_locality(chip) == tpm_dev->locality) | 149 | if (check_locality(chip)) |
| 150 | return tpm_dev->locality; | 150 | return tpm_dev->locality; |
| 151 | 151 | ||
| 152 | data = TPM_ACCESS_REQUEST_USE; | 152 | data = TPM_ACCESS_REQUEST_USE; |
| @@ -158,7 +158,7 @@ static int request_locality(struct tpm_chip *chip) | |||
| 158 | 158 | ||
| 159 | /* Request locality is usually effective after the request */ | 159 | /* Request locality is usually effective after the request */ |
| 160 | do { | 160 | do { |
| 161 | if (check_locality(chip) >= 0) | 161 | if (check_locality(chip)) |
| 162 | return tpm_dev->locality; | 162 | return tpm_dev->locality; |
| 163 | msleep(TPM_TIMEOUT); | 163 | msleep(TPM_TIMEOUT); |
| 164 | } while (time_before(jiffies, stop)); | 164 | } while (time_before(jiffies, stop)); |
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); | |||
| 33 | static DEFINE_MUTEX(idr_lock); | 33 | static DEFINE_MUTEX(idr_lock); |
| 34 | 34 | ||
| 35 | struct class *tpm_class; | 35 | struct class *tpm_class; |
| 36 | struct class *tpmrm_class; | ||
| 36 | dev_t tpm_devt; | 37 | dev_t tpm_devt; |
| 37 | 38 | ||
| 38 | /** | 39 | /** |
| @@ -128,9 +129,19 @@ static void tpm_dev_release(struct device *dev) | |||
| 128 | mutex_unlock(&idr_lock); | 129 | mutex_unlock(&idr_lock); |
| 129 | 130 | ||
| 130 | kfree(chip->log.bios_event_log); | 131 | kfree(chip->log.bios_event_log); |
| 132 | kfree(chip->work_space.context_buf); | ||
| 133 | kfree(chip->work_space.session_buf); | ||
| 131 | kfree(chip); | 134 | kfree(chip); |
| 132 | } | 135 | } |
| 133 | 136 | ||
| 137 | static void tpm_devs_release(struct device *dev) | ||
| 138 | { | ||
| 139 | struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs); | ||
| 140 | |||
| 141 | /* release the master device reference */ | ||
| 142 | put_device(&chip->dev); | ||
| 143 | } | ||
| 144 | |||
| 134 | /** | 145 | /** |
| 135 | * tpm_chip_alloc() - allocate a new struct tpm_chip instance | 146 | * tpm_chip_alloc() - allocate a new struct tpm_chip instance |
| 136 | * @pdev: device to which the chip is associated | 147 | * @pdev: device to which the chip is associated |
| @@ -167,31 +178,65 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, | |||
| 167 | chip->dev_num = rc; | 178 | chip->dev_num = rc; |
| 168 | 179 | ||
| 169 | device_initialize(&chip->dev); | 180 | device_initialize(&chip->dev); |
| 181 | device_initialize(&chip->devs); | ||
| 170 | 182 | ||
| 171 | chip->dev.class = tpm_class; | 183 | chip->dev.class = tpm_class; |
| 172 | chip->dev.release = tpm_dev_release; | 184 | chip->dev.release = tpm_dev_release; |
| 173 | chip->dev.parent = pdev; | 185 | chip->dev.parent = pdev; |
| 174 | chip->dev.groups = chip->groups; | 186 | chip->dev.groups = chip->groups; |
| 175 | 187 | ||
| 188 | chip->devs.parent = pdev; | ||
| 189 | chip->devs.class = tpmrm_class; | ||
| 190 | chip->devs.release = tpm_devs_release; | ||
| 191 | /* get extra reference on main device to hold on | ||
| 192 | * behalf of devs. This holds the chip structure | ||
| 193 | * while cdevs is in use. The corresponding put | ||
| 194 | * is in the tpm_devs_release (TPM2 only) | ||
| 195 | */ | ||
| 196 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 197 | get_device(&chip->dev); | ||
| 198 | |||
| 176 | if (chip->dev_num == 0) | 199 | if (chip->dev_num == 0) |
| 177 | chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); | 200 | chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); |
| 178 | else | 201 | else |
| 179 | chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num); | 202 | chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num); |
| 180 | 203 | ||
| 204 | chip->devs.devt = | ||
| 205 | MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES); | ||
| 206 | |||
| 181 | rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num); | 207 | rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num); |
| 182 | if (rc) | 208 | if (rc) |
| 183 | goto out; | 209 | goto out; |
| 210 | rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num); | ||
| 211 | if (rc) | ||
| 212 | goto out; | ||
| 184 | 213 | ||
| 185 | if (!pdev) | 214 | if (!pdev) |
| 186 | chip->flags |= TPM_CHIP_FLAG_VIRTUAL; | 215 | chip->flags |= TPM_CHIP_FLAG_VIRTUAL; |
| 187 | 216 | ||
| 188 | cdev_init(&chip->cdev, &tpm_fops); | 217 | cdev_init(&chip->cdev, &tpm_fops); |
| 218 | cdev_init(&chip->cdevs, &tpmrm_fops); | ||
| 189 | chip->cdev.owner = THIS_MODULE; | 219 | chip->cdev.owner = THIS_MODULE; |
| 220 | chip->cdevs.owner = THIS_MODULE; | ||
| 190 | chip->cdev.kobj.parent = &chip->dev.kobj; | 221 | chip->cdev.kobj.parent = &chip->dev.kobj; |
| 222 | chip->cdevs.kobj.parent = &chip->devs.kobj; | ||
| 223 | |||
| 224 | chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 225 | if (!chip->work_space.context_buf) { | ||
| 226 | rc = -ENOMEM; | ||
| 227 | goto out; | ||
| 228 | } | ||
| 229 | chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 230 | if (!chip->work_space.session_buf) { | ||
| 231 | rc = -ENOMEM; | ||
| 232 | goto out; | ||
| 233 | } | ||
| 191 | 234 | ||
| 235 | chip->locality = -1; | ||
| 192 | return chip; | 236 | return chip; |
| 193 | 237 | ||
| 194 | out: | 238 | out: |
| 239 | put_device(&chip->devs); | ||
| 195 | put_device(&chip->dev); | 240 | put_device(&chip->dev); |
| 196 | return ERR_PTR(rc); | 241 | return ERR_PTR(rc); |
| 197 | } | 242 | } |
| @@ -236,7 +281,6 @@ static int tpm_add_char_device(struct tpm_chip *chip) | |||
| 236 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", | 281 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", |
| 237 | dev_name(&chip->dev), MAJOR(chip->dev.devt), | 282 | dev_name(&chip->dev), MAJOR(chip->dev.devt), |
| 238 | MINOR(chip->dev.devt), rc); | 283 | MINOR(chip->dev.devt), rc); |
| 239 | |||
| 240 | return rc; | 284 | return rc; |
| 241 | } | 285 | } |
| 242 | 286 | ||
| @@ -251,6 +295,27 @@ static int tpm_add_char_device(struct tpm_chip *chip) | |||
| 251 | return rc; | 295 | return rc; |
| 252 | } | 296 | } |
| 253 | 297 | ||
| 298 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 299 | rc = cdev_add(&chip->cdevs, chip->devs.devt, 1); | ||
| 300 | if (rc) { | ||
| 301 | dev_err(&chip->dev, | ||
| 302 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", | ||
| 303 | dev_name(&chip->devs), MAJOR(chip->devs.devt), | ||
| 304 | MINOR(chip->devs.devt), rc); | ||
| 305 | return rc; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 309 | rc = device_add(&chip->devs); | ||
| 310 | if (rc) { | ||
| 311 | dev_err(&chip->dev, | ||
| 312 | "unable to device_register() %s, major %d, minor %d, err=%d\n", | ||
| 313 | dev_name(&chip->devs), MAJOR(chip->devs.devt), | ||
| 314 | MINOR(chip->devs.devt), rc); | ||
| 315 | cdev_del(&chip->cdevs); | ||
| 316 | return rc; | ||
| 317 | } | ||
| 318 | |||
| 254 | /* Make the chip available. */ | 319 | /* Make the chip available. */ |
| 255 | mutex_lock(&idr_lock); | 320 | mutex_lock(&idr_lock); |
| 256 | idr_replace(&dev_nums_idr, chip, chip->dev_num); | 321 | idr_replace(&dev_nums_idr, chip, chip->dev_num); |
| @@ -384,6 +449,10 @@ void tpm_chip_unregister(struct tpm_chip *chip) | |||
| 384 | { | 449 | { |
| 385 | tpm_del_legacy_sysfs(chip); | 450 | tpm_del_legacy_sysfs(chip); |
| 386 | tpm_bios_log_teardown(chip); | 451 | tpm_bios_log_teardown(chip); |
| 452 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | ||
| 453 | cdev_del(&chip->cdevs); | ||
| 454 | device_del(&chip->devs); | ||
| 455 | } | ||
| 387 | tpm_del_char_device(chip); | 456 | tpm_del_char_device(chip); |
| 388 | } | 457 | } |
| 389 | EXPORT_SYMBOL_GPL(tpm_chip_unregister); | 458 | EXPORT_SYMBOL_GPL(tpm_chip_unregister); |
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c new file mode 100644 index 000000000000..610638a80383 --- /dev/null +++ b/drivers/char/tpm/tpm-dev-common.c | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2004 IBM Corporation | ||
| 3 | * Authors: | ||
| 4 | * Leendert van Doorn <leendert@watson.ibm.com> | ||
| 5 | * Dave Safford <safford@watson.ibm.com> | ||
| 6 | * Reiner Sailer <sailer@watson.ibm.com> | ||
| 7 | * Kylene Hall <kjhall@us.ibm.com> | ||
| 8 | * | ||
| 9 | * Copyright (C) 2013 Obsidian Research Corp | ||
| 10 | * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> | ||
| 11 | * | ||
| 12 | * Device file system interface to the TPM | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or | ||
| 15 | * modify it under the terms of the GNU General Public License as | ||
| 16 | * published by the Free Software Foundation, version 2 of the | ||
| 17 | * License. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/uaccess.h> | ||
| 22 | #include "tpm.h" | ||
| 23 | #include "tpm-dev.h" | ||
| 24 | |||
| 25 | static void user_reader_timeout(unsigned long ptr) | ||
| 26 | { | ||
| 27 | struct file_priv *priv = (struct file_priv *)ptr; | ||
| 28 | |||
| 29 | pr_warn("TPM user space timeout is deprecated (pid=%d)\n", | ||
| 30 | task_tgid_nr(current)); | ||
| 31 | |||
| 32 | schedule_work(&priv->work); | ||
| 33 | } | ||
| 34 | |||
| 35 | static void timeout_work(struct work_struct *work) | ||
| 36 | { | ||
| 37 | struct file_priv *priv = container_of(work, struct file_priv, work); | ||
| 38 | |||
| 39 | mutex_lock(&priv->buffer_mutex); | ||
| 40 | atomic_set(&priv->data_pending, 0); | ||
| 41 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); | ||
| 42 | mutex_unlock(&priv->buffer_mutex); | ||
| 43 | } | ||
| 44 | |||
| 45 | void tpm_common_open(struct file *file, struct tpm_chip *chip, | ||
| 46 | struct file_priv *priv) | ||
| 47 | { | ||
| 48 | priv->chip = chip; | ||
| 49 | atomic_set(&priv->data_pending, 0); | ||
| 50 | mutex_init(&priv->buffer_mutex); | ||
| 51 | setup_timer(&priv->user_read_timer, user_reader_timeout, | ||
| 52 | (unsigned long)priv); | ||
| 53 | INIT_WORK(&priv->work, timeout_work); | ||
| 54 | |||
| 55 | file->private_data = priv; | ||
| 56 | } | ||
| 57 | |||
| 58 | ssize_t tpm_common_read(struct file *file, char __user *buf, | ||
| 59 | size_t size, loff_t *off) | ||
| 60 | { | ||
| 61 | struct file_priv *priv = file->private_data; | ||
| 62 | ssize_t ret_size; | ||
| 63 | ssize_t orig_ret_size; | ||
| 64 | int rc; | ||
| 65 | |||
| 66 | del_singleshot_timer_sync(&priv->user_read_timer); | ||
| 67 | flush_work(&priv->work); | ||
| 68 | ret_size = atomic_read(&priv->data_pending); | ||
| 69 | if (ret_size > 0) { /* relay data */ | ||
| 70 | orig_ret_size = ret_size; | ||
| 71 | if (size < ret_size) | ||
| 72 | ret_size = size; | ||
| 73 | |||
| 74 | mutex_lock(&priv->buffer_mutex); | ||
| 75 | rc = copy_to_user(buf, priv->data_buffer, ret_size); | ||
| 76 | memset(priv->data_buffer, 0, orig_ret_size); | ||
| 77 | if (rc) | ||
| 78 | ret_size = -EFAULT; | ||
| 79 | |||
| 80 | mutex_unlock(&priv->buffer_mutex); | ||
| 81 | } | ||
| 82 | |||
| 83 | atomic_set(&priv->data_pending, 0); | ||
| 84 | |||
| 85 | return ret_size; | ||
| 86 | } | ||
| 87 | |||
| 88 | ssize_t tpm_common_write(struct file *file, const char __user *buf, | ||
| 89 | size_t size, loff_t *off, struct tpm_space *space) | ||
| 90 | { | ||
| 91 | struct file_priv *priv = file->private_data; | ||
| 92 | size_t in_size = size; | ||
| 93 | ssize_t out_size; | ||
| 94 | |||
| 95 | /* Cannot perform a write until the read has cleared either via | ||
| 96 | * tpm_read or a user_read_timer timeout. This also prevents split | ||
| 97 | * buffered writes from blocking here. | ||
| 98 | */ | ||
| 99 | if (atomic_read(&priv->data_pending) != 0) | ||
| 100 | return -EBUSY; | ||
| 101 | |||
| 102 | if (in_size > TPM_BUFSIZE) | ||
| 103 | return -E2BIG; | ||
| 104 | |||
| 105 | mutex_lock(&priv->buffer_mutex); | ||
| 106 | |||
| 107 | if (copy_from_user | ||
| 108 | (priv->data_buffer, (void __user *) buf, in_size)) { | ||
| 109 | mutex_unlock(&priv->buffer_mutex); | ||
| 110 | return -EFAULT; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* 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 | ||
| 115 | * the char dev is held open. | ||
| 116 | */ | ||
| 117 | if (tpm_try_get_ops(priv->chip)) { | ||
| 118 | mutex_unlock(&priv->buffer_mutex); | ||
| 119 | return -EPIPE; | ||
| 120 | } | ||
| 121 | out_size = tpm_transmit(priv->chip, space, priv->data_buffer, | ||
| 122 | sizeof(priv->data_buffer), 0); | ||
| 123 | |||
| 124 | tpm_put_ops(priv->chip); | ||
| 125 | if (out_size < 0) { | ||
| 126 | mutex_unlock(&priv->buffer_mutex); | ||
| 127 | return out_size; | ||
| 128 | } | ||
| 129 | |||
| 130 | atomic_set(&priv->data_pending, out_size); | ||
| 131 | mutex_unlock(&priv->buffer_mutex); | ||
| 132 | |||
| 133 | /* Set a timeout by which the reader must come claim the result */ | ||
| 134 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); | ||
| 135 | |||
| 136 | return in_size; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Called on file close | ||
| 141 | */ | ||
| 142 | void tpm_common_release(struct file *file, struct file_priv *priv) | ||
| 143 | { | ||
| 144 | del_singleshot_timer_sync(&priv->user_read_timer); | ||
| 145 | flush_work(&priv->work); | ||
| 146 | file->private_data = NULL; | ||
| 147 | atomic_set(&priv->data_pending, 0); | ||
| 148 | } | ||
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index 02a8850d3a69..ebd74ab5abef 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c | |||
| @@ -18,48 +18,15 @@ | |||
| 18 | * | 18 | * |
| 19 | */ | 19 | */ |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/uaccess.h> | 21 | #include "tpm-dev.h" |
| 22 | #include "tpm.h" | ||
| 23 | |||
| 24 | struct file_priv { | ||
| 25 | struct tpm_chip *chip; | ||
| 26 | |||
| 27 | /* Data passed to and from the tpm via the read/write calls */ | ||
| 28 | atomic_t data_pending; | ||
| 29 | struct mutex buffer_mutex; | ||
| 30 | |||
| 31 | struct timer_list user_read_timer; /* user needs to claim result */ | ||
| 32 | struct work_struct work; | ||
| 33 | |||
| 34 | u8 data_buffer[TPM_BUFSIZE]; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static void user_reader_timeout(unsigned long ptr) | ||
| 38 | { | ||
| 39 | struct file_priv *priv = (struct file_priv *)ptr; | ||
| 40 | |||
| 41 | pr_warn("TPM user space timeout is deprecated (pid=%d)\n", | ||
| 42 | task_tgid_nr(current)); | ||
| 43 | |||
| 44 | schedule_work(&priv->work); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void timeout_work(struct work_struct *work) | ||
| 48 | { | ||
| 49 | struct file_priv *priv = container_of(work, struct file_priv, work); | ||
| 50 | |||
| 51 | mutex_lock(&priv->buffer_mutex); | ||
| 52 | atomic_set(&priv->data_pending, 0); | ||
| 53 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); | ||
| 54 | mutex_unlock(&priv->buffer_mutex); | ||
| 55 | } | ||
| 56 | 22 | ||
| 57 | static int tpm_open(struct inode *inode, struct file *file) | 23 | static int tpm_open(struct inode *inode, struct file *file) |
| 58 | { | 24 | { |
| 59 | struct tpm_chip *chip = | 25 | struct tpm_chip *chip; |
| 60 | container_of(inode->i_cdev, struct tpm_chip, cdev); | ||
| 61 | struct file_priv *priv; | 26 | struct file_priv *priv; |
| 62 | 27 | ||
| 28 | chip = container_of(inode->i_cdev, struct tpm_chip, cdev); | ||
| 29 | |||
| 63 | /* It's assured that the chip will be opened just once, | 30 | /* It's assured that the chip will be opened just once, |
| 64 | * by the check of is_open variable, which is protected | 31 | * by the check of is_open variable, which is protected |
| 65 | * by driver_lock. */ | 32 | * by driver_lock. */ |
| @@ -69,100 +36,22 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
| 69 | } | 36 | } |
| 70 | 37 | ||
| 71 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 38 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 72 | if (priv == NULL) { | 39 | if (priv == NULL) |
| 73 | clear_bit(0, &chip->is_open); | 40 | goto out; |
| 74 | return -ENOMEM; | ||
| 75 | } | ||
| 76 | 41 | ||
| 77 | priv->chip = chip; | 42 | tpm_common_open(file, chip, priv); |
| 78 | atomic_set(&priv->data_pending, 0); | ||
| 79 | mutex_init(&priv->buffer_mutex); | ||
| 80 | setup_timer(&priv->user_read_timer, user_reader_timeout, | ||
| 81 | (unsigned long)priv); | ||
| 82 | INIT_WORK(&priv->work, timeout_work); | ||
| 83 | 43 | ||
| 84 | file->private_data = priv; | ||
| 85 | return 0; | 44 | return 0; |
| 86 | } | ||
| 87 | |||
| 88 | static ssize_t tpm_read(struct file *file, char __user *buf, | ||
| 89 | size_t size, loff_t *off) | ||
| 90 | { | ||
| 91 | struct file_priv *priv = file->private_data; | ||
| 92 | ssize_t ret_size; | ||
| 93 | int rc; | ||
| 94 | 45 | ||
| 95 | del_singleshot_timer_sync(&priv->user_read_timer); | 46 | out: |
| 96 | flush_work(&priv->work); | 47 | clear_bit(0, &chip->is_open); |
| 97 | ret_size = atomic_read(&priv->data_pending); | 48 | return -ENOMEM; |
| 98 | if (ret_size > 0) { /* relay data */ | ||
| 99 | ssize_t orig_ret_size = ret_size; | ||
| 100 | if (size < ret_size) | ||
| 101 | ret_size = size; | ||
| 102 | |||
| 103 | mutex_lock(&priv->buffer_mutex); | ||
| 104 | rc = copy_to_user(buf, priv->data_buffer, ret_size); | ||
| 105 | memset(priv->data_buffer, 0, orig_ret_size); | ||
| 106 | if (rc) | ||
| 107 | ret_size = -EFAULT; | ||
| 108 | |||
| 109 | mutex_unlock(&priv->buffer_mutex); | ||
| 110 | } | ||
| 111 | |||
| 112 | atomic_set(&priv->data_pending, 0); | ||
| 113 | |||
| 114 | return ret_size; | ||
| 115 | } | 49 | } |
| 116 | 50 | ||
| 117 | static ssize_t tpm_write(struct file *file, const char __user *buf, | 51 | static ssize_t tpm_write(struct file *file, const char __user *buf, |
| 118 | size_t size, loff_t *off) | 52 | size_t size, loff_t *off) |
| 119 | { | 53 | { |
| 120 | struct file_priv *priv = file->private_data; | 54 | return tpm_common_write(file, buf, size, off, NULL); |
| 121 | size_t in_size = size; | ||
| 122 | ssize_t out_size; | ||
| 123 | |||
| 124 | /* cannot perform a write until the read has cleared | ||
| 125 | either via tpm_read or a user_read_timer timeout. | ||
| 126 | This also prevents splitted buffered writes from blocking here. | ||
| 127 | */ | ||
| 128 | if (atomic_read(&priv->data_pending) != 0) | ||
| 129 | return -EBUSY; | ||
| 130 | |||
| 131 | if (in_size > TPM_BUFSIZE) | ||
| 132 | return -E2BIG; | ||
| 133 | |||
| 134 | mutex_lock(&priv->buffer_mutex); | ||
| 135 | |||
| 136 | if (copy_from_user | ||
| 137 | (priv->data_buffer, (void __user *) buf, in_size)) { | ||
| 138 | mutex_unlock(&priv->buffer_mutex); | ||
| 139 | return -EFAULT; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* atomic tpm command send and result receive. We only hold the ops | ||
| 143 | * lock during this period so that the tpm can be unregistered even if | ||
| 144 | * the char dev is held open. | ||
| 145 | */ | ||
| 146 | if (tpm_try_get_ops(priv->chip)) { | ||
| 147 | mutex_unlock(&priv->buffer_mutex); | ||
| 148 | return -EPIPE; | ||
| 149 | } | ||
| 150 | out_size = tpm_transmit(priv->chip, priv->data_buffer, | ||
| 151 | sizeof(priv->data_buffer), 0); | ||
| 152 | |||
| 153 | tpm_put_ops(priv->chip); | ||
| 154 | if (out_size < 0) { | ||
| 155 | mutex_unlock(&priv->buffer_mutex); | ||
| 156 | return out_size; | ||
| 157 | } | ||
| 158 | |||
| 159 | atomic_set(&priv->data_pending, out_size); | ||
| 160 | mutex_unlock(&priv->buffer_mutex); | ||
| 161 | |||
| 162 | /* Set a timeout by which the reader must come claim the result */ | ||
| 163 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); | ||
| 164 | |||
| 165 | return in_size; | ||
| 166 | } | 55 | } |
| 167 | 56 | ||
| 168 | /* | 57 | /* |
| @@ -172,12 +61,10 @@ static int tpm_release(struct inode *inode, struct file *file) | |||
| 172 | { | 61 | { |
| 173 | struct file_priv *priv = file->private_data; | 62 | struct file_priv *priv = file->private_data; |
| 174 | 63 | ||
| 175 | del_singleshot_timer_sync(&priv->user_read_timer); | 64 | tpm_common_release(file, priv); |
| 176 | flush_work(&priv->work); | ||
| 177 | file->private_data = NULL; | ||
| 178 | atomic_set(&priv->data_pending, 0); | ||
| 179 | clear_bit(0, &priv->chip->is_open); | 65 | clear_bit(0, &priv->chip->is_open); |
| 180 | kfree(priv); | 66 | kfree(priv); |
| 67 | |||
| 181 | return 0; | 68 | return 0; |
| 182 | } | 69 | } |
| 183 | 70 | ||
| @@ -185,9 +72,7 @@ const struct file_operations tpm_fops = { | |||
| 185 | .owner = THIS_MODULE, | 72 | .owner = THIS_MODULE, |
| 186 | .llseek = no_llseek, | 73 | .llseek = no_llseek, |
| 187 | .open = tpm_open, | 74 | .open = tpm_open, |
| 188 | .read = tpm_read, | 75 | .read = tpm_common_read, |
| 189 | .write = tpm_write, | 76 | .write = tpm_write, |
| 190 | .release = tpm_release, | 77 | .release = tpm_release, |
| 191 | }; | 78 | }; |
| 192 | |||
| 193 | |||
diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h new file mode 100644 index 000000000000..ff15cf719bad --- /dev/null +++ b/drivers/char/tpm/tpm-dev.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef _TPM_DEV_H | ||
| 2 | #define _TPM_DEV_H | ||
| 3 | |||
| 4 | #include "tpm.h" | ||
| 5 | |||
| 6 | struct file_priv { | ||
| 7 | struct tpm_chip *chip; | ||
| 8 | |||
| 9 | /* Data passed to and from the tpm via the read/write calls */ | ||
| 10 | atomic_t data_pending; | ||
| 11 | struct mutex buffer_mutex; | ||
| 12 | |||
| 13 | struct timer_list user_read_timer; /* user needs to claim result */ | ||
| 14 | struct work_struct work; | ||
| 15 | |||
| 16 | u8 data_buffer[TPM_BUFSIZE]; | ||
| 17 | }; | ||
| 18 | |||
| 19 | void tpm_common_open(struct file *file, struct tpm_chip *chip, | ||
| 20 | struct file_priv *priv); | ||
| 21 | ssize_t tpm_common_read(struct file *file, char __user *buf, | ||
| 22 | size_t size, loff_t *off); | ||
| 23 | ssize_t tpm_common_write(struct file *file, const char __user *buf, | ||
| 24 | size_t size, loff_t *off, struct tpm_space *space); | ||
| 25 | void tpm_common_release(struct file *file, struct file_priv *priv); | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index bd2128e0b56c..158c1db83f05 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
| @@ -328,6 +328,47 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, | |||
| 328 | } | 328 | } |
| 329 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | 329 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); |
| 330 | 330 | ||
| 331 | static bool tpm_validate_command(struct tpm_chip *chip, | ||
| 332 | struct tpm_space *space, | ||
| 333 | const u8 *cmd, | ||
| 334 | size_t len) | ||
| 335 | { | ||
| 336 | const struct tpm_input_header *header = (const void *)cmd; | ||
| 337 | int i; | ||
| 338 | u32 cc; | ||
| 339 | u32 attrs; | ||
| 340 | unsigned int nr_handles; | ||
| 341 | |||
| 342 | if (len < TPM_HEADER_SIZE) | ||
| 343 | return false; | ||
| 344 | |||
| 345 | if (!space) | ||
| 346 | return true; | ||
| 347 | |||
| 348 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) { | ||
| 349 | cc = be32_to_cpu(header->ordinal); | ||
| 350 | |||
| 351 | i = tpm2_find_cc(chip, cc); | ||
| 352 | if (i < 0) { | ||
| 353 | dev_dbg(&chip->dev, "0x%04X is an invalid command\n", | ||
| 354 | cc); | ||
| 355 | return false; | ||
| 356 | } | ||
| 357 | |||
| 358 | attrs = chip->cc_attrs_tbl[i]; | ||
| 359 | nr_handles = | ||
| 360 | 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0)); | ||
| 361 | if (len < TPM_HEADER_SIZE + 4 * nr_handles) | ||
| 362 | goto err_len; | ||
| 363 | } | ||
| 364 | |||
| 365 | return true; | ||
| 366 | err_len: | ||
| 367 | dev_dbg(&chip->dev, | ||
| 368 | "%s: insufficient command length %zu", __func__, len); | ||
| 369 | return false; | ||
| 370 | } | ||
| 371 | |||
| 331 | /** | 372 | /** |
| 332 | * tmp_transmit - Internal kernel interface to transmit TPM commands. | 373 | * tmp_transmit - Internal kernel interface to transmit TPM commands. |
| 333 | * | 374 | * |
| @@ -340,14 +381,17 @@ EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | |||
| 340 | * 0 when the operation is successful. | 381 | * 0 when the operation is successful. |
| 341 | * A negative number for system errors (errno). | 382 | * A negative number for system errors (errno). |
| 342 | */ | 383 | */ |
| 343 | ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | 384 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, |
| 344 | unsigned int flags) | 385 | u8 *buf, size_t bufsiz, unsigned int flags) |
| 345 | { | 386 | { |
| 346 | ssize_t rc; | 387 | struct tpm_output_header *header = (void *)buf; |
| 388 | int rc; | ||
| 389 | ssize_t len = 0; | ||
| 347 | u32 count, ordinal; | 390 | u32 count, ordinal; |
| 348 | unsigned long stop; | 391 | unsigned long stop; |
| 392 | bool need_locality; | ||
| 349 | 393 | ||
| 350 | if (bufsiz < TPM_HEADER_SIZE) | 394 | if (!tpm_validate_command(chip, space, buf, bufsiz)) |
| 351 | return -EINVAL; | 395 | return -EINVAL; |
| 352 | 396 | ||
| 353 | if (bufsiz > TPM_BUFSIZE) | 397 | if (bufsiz > TPM_BUFSIZE) |
| @@ -369,10 +413,24 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | |||
| 369 | if (chip->dev.parent) | 413 | if (chip->dev.parent) |
| 370 | pm_runtime_get_sync(chip->dev.parent); | 414 | pm_runtime_get_sync(chip->dev.parent); |
| 371 | 415 | ||
| 416 | /* Store the decision as chip->locality will be changed. */ | ||
| 417 | need_locality = chip->locality == -1; | ||
| 418 | |||
| 419 | if (need_locality && chip->ops->request_locality) { | ||
| 420 | rc = chip->ops->request_locality(chip, 0); | ||
| 421 | if (rc < 0) | ||
| 422 | goto out_no_locality; | ||
| 423 | chip->locality = rc; | ||
| 424 | } | ||
| 425 | |||
| 426 | rc = tpm2_prepare_space(chip, space, ordinal, buf); | ||
| 427 | if (rc) | ||
| 428 | goto out; | ||
| 429 | |||
| 372 | rc = chip->ops->send(chip, (u8 *) buf, count); | 430 | rc = chip->ops->send(chip, (u8 *) buf, count); |
| 373 | if (rc < 0) { | 431 | if (rc < 0) { |
| 374 | dev_err(&chip->dev, | 432 | dev_err(&chip->dev, |
| 375 | "tpm_transmit: tpm_send: error %zd\n", rc); | 433 | "tpm_transmit: tpm_send: error %d\n", rc); |
| 376 | goto out; | 434 | goto out; |
| 377 | } | 435 | } |
| 378 | 436 | ||
| @@ -405,17 +463,36 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | |||
| 405 | goto out; | 463 | goto out; |
| 406 | 464 | ||
| 407 | out_recv: | 465 | out_recv: |
| 408 | rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); | 466 | len = chip->ops->recv(chip, (u8 *) buf, bufsiz); |
| 409 | if (rc < 0) | 467 | if (len < 0) { |
| 468 | rc = len; | ||
| 410 | dev_err(&chip->dev, | 469 | dev_err(&chip->dev, |
| 411 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 470 | "tpm_transmit: tpm_recv: error %d\n", rc); |
| 471 | goto out; | ||
| 472 | } else if (len < TPM_HEADER_SIZE) { | ||
| 473 | rc = -EFAULT; | ||
| 474 | goto out; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (len != be32_to_cpu(header->length)) { | ||
| 478 | rc = -EFAULT; | ||
| 479 | goto out; | ||
| 480 | } | ||
| 481 | |||
| 482 | rc = tpm2_commit_space(chip, space, ordinal, buf, &len); | ||
| 483 | |||
| 412 | out: | 484 | out: |
| 485 | if (need_locality && chip->ops->relinquish_locality) { | ||
| 486 | chip->ops->relinquish_locality(chip, chip->locality); | ||
| 487 | chip->locality = -1; | ||
| 488 | } | ||
| 489 | out_no_locality: | ||
| 413 | if (chip->dev.parent) | 490 | if (chip->dev.parent) |
| 414 | pm_runtime_put_sync(chip->dev.parent); | 491 | pm_runtime_put_sync(chip->dev.parent); |
| 415 | 492 | ||
| 416 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) | 493 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
| 417 | mutex_unlock(&chip->tpm_mutex); | 494 | mutex_unlock(&chip->tpm_mutex); |
| 418 | return rc; | 495 | return rc ? rc : len; |
| 419 | } | 496 | } |
| 420 | 497 | ||
| 421 | /** | 498 | /** |
| @@ -434,23 +511,18 @@ out: | |||
| 434 | * A negative number for system errors (errno). | 511 | * A negative number for system errors (errno). |
| 435 | * A positive number for a TPM error. | 512 | * A positive number for a TPM error. |
| 436 | */ | 513 | */ |
| 437 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, | 514 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, |
| 438 | size_t bufsiz, size_t min_rsp_body_length, | 515 | const void *buf, size_t bufsiz, |
| 439 | unsigned int flags, const char *desc) | 516 | size_t min_rsp_body_length, unsigned int flags, |
| 517 | const char *desc) | ||
| 440 | { | 518 | { |
| 441 | const struct tpm_output_header *header; | 519 | const struct tpm_output_header *header = buf; |
| 442 | int err; | 520 | int err; |
| 443 | ssize_t len; | 521 | ssize_t len; |
| 444 | 522 | ||
| 445 | len = tpm_transmit(chip, (const u8 *)buf, bufsiz, flags); | 523 | len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); |
| 446 | if (len < 0) | 524 | if (len < 0) |
| 447 | return len; | 525 | return len; |
| 448 | else if (len < TPM_HEADER_SIZE) | ||
| 449 | return -EFAULT; | ||
| 450 | |||
| 451 | header = buf; | ||
| 452 | if (len != be32_to_cpu(header->length)) | ||
| 453 | return -EFAULT; | ||
| 454 | 526 | ||
| 455 | err = be32_to_cpu(header->return_code); | 527 | err = be32_to_cpu(header->return_code); |
| 456 | if (err != 0 && desc) | 528 | if (err != 0 && desc) |
| @@ -501,7 +573,7 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, | |||
| 501 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 573 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
| 502 | tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id); | 574 | tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id); |
| 503 | } | 575 | } |
| 504 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 576 | rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
| 505 | min_cap_length, 0, desc); | 577 | min_cap_length, 0, desc); |
| 506 | if (!rc) | 578 | if (!rc) |
| 507 | *cap = tpm_cmd.params.getcap_out.cap; | 579 | *cap = tpm_cmd.params.getcap_out.cap; |
| @@ -525,7 +597,8 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) | |||
| 525 | start_cmd.header.in = tpm_startup_header; | 597 | start_cmd.header.in = tpm_startup_header; |
| 526 | 598 | ||
| 527 | start_cmd.params.startup_in.startup_type = startup_type; | 599 | start_cmd.params.startup_in.startup_type = startup_type; |
| 528 | return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0, | 600 | return tpm_transmit_cmd(chip, NULL, &start_cmd, |
| 601 | TPM_INTERNAL_RESULT_SIZE, 0, | ||
| 529 | 0, "attempting to start the TPM"); | 602 | 0, "attempting to start the TPM"); |
| 530 | } | 603 | } |
| 531 | 604 | ||
| @@ -682,8 +755,8 @@ static int tpm_continue_selftest(struct tpm_chip *chip) | |||
| 682 | struct tpm_cmd_t cmd; | 755 | struct tpm_cmd_t cmd; |
| 683 | 756 | ||
| 684 | cmd.header.in = continue_selftest_header; | 757 | cmd.header.in = continue_selftest_header; |
| 685 | rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, 0, | 758 | rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, |
| 686 | "continue selftest"); | 759 | 0, 0, "continue selftest"); |
| 687 | return rc; | 760 | return rc; |
| 688 | } | 761 | } |
| 689 | 762 | ||
| @@ -703,7 +776,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
| 703 | 776 | ||
| 704 | cmd.header.in = pcrread_header; | 777 | cmd.header.in = pcrread_header; |
| 705 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); | 778 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); |
| 706 | rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, | 779 | rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE, |
| 707 | READ_PCR_RESULT_BODY_SIZE, 0, | 780 | READ_PCR_RESULT_BODY_SIZE, 0, |
| 708 | "attempting to read a pcr value"); | 781 | "attempting to read a pcr value"); |
| 709 | 782 | ||
| @@ -815,7 +888,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
| 815 | cmd.header.in = pcrextend_header; | 888 | cmd.header.in = pcrextend_header; |
| 816 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | 889 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); |
| 817 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | 890 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); |
| 818 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 891 | rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE, |
| 819 | EXTEND_PCR_RESULT_BODY_SIZE, 0, | 892 | EXTEND_PCR_RESULT_BODY_SIZE, 0, |
| 820 | "attempting extend a PCR value"); | 893 | "attempting extend a PCR value"); |
| 821 | 894 | ||
| @@ -920,8 +993,8 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) | |||
| 920 | if (chip == NULL) | 993 | if (chip == NULL) |
| 921 | return -ENODEV; | 994 | return -ENODEV; |
| 922 | 995 | ||
| 923 | rc = tpm_transmit_cmd(chip, cmd, buflen, 0, 0, "attempting tpm_cmd"); | 996 | rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0, |
| 924 | 997 | "attempting tpm_cmd"); | |
| 925 | tpm_put_ops(chip); | 998 | tpm_put_ops(chip); |
| 926 | return rc; | 999 | return rc; |
| 927 | } | 1000 | } |
| @@ -1022,16 +1095,16 @@ int tpm_pm_suspend(struct device *dev) | |||
| 1022 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | 1095 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); |
| 1023 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | 1096 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, |
| 1024 | TPM_DIGEST_SIZE); | 1097 | TPM_DIGEST_SIZE); |
| 1025 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 1098 | rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE, |
| 1026 | EXTEND_PCR_RESULT_BODY_SIZE, 0, | 1099 | EXTEND_PCR_RESULT_BODY_SIZE, 0, |
| 1027 | "extending dummy pcr before suspend"); | 1100 | "extending dummy pcr before suspend"); |
| 1028 | } | 1101 | } |
| 1029 | 1102 | ||
| 1030 | /* now do the actual savestate */ | 1103 | /* now do the actual savestate */ |
| 1031 | for (try = 0; try < TPM_RETRY; try++) { | 1104 | for (try = 0; try < TPM_RETRY; try++) { |
| 1032 | cmd.header.in = savestate_header; | 1105 | cmd.header.in = savestate_header; |
| 1033 | rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0, | 1106 | rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE, |
| 1034 | 0, NULL); | 1107 | 0, 0, NULL); |
| 1035 | 1108 | ||
| 1036 | /* | 1109 | /* |
| 1037 | * If the TPM indicates that it is too busy to respond to | 1110 | * If the TPM indicates that it is too busy to respond to |
| @@ -1114,7 +1187,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
| 1114 | tpm_cmd.header.in = tpm_getrandom_header; | 1187 | tpm_cmd.header.in = tpm_getrandom_header; |
| 1115 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | 1188 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); |
| 1116 | 1189 | ||
| 1117 | err = tpm_transmit_cmd(chip, &tpm_cmd, | 1190 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, |
| 1118 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | 1191 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, |
| 1119 | offsetof(struct tpm_getrandom_out, | 1192 | offsetof(struct tpm_getrandom_out, |
| 1120 | rng_data), | 1193 | rng_data), |
| @@ -1205,9 +1278,17 @@ static int __init tpm_init(void) | |||
| 1205 | return PTR_ERR(tpm_class); | 1278 | return PTR_ERR(tpm_class); |
| 1206 | } | 1279 | } |
| 1207 | 1280 | ||
| 1208 | rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm"); | 1281 | tpmrm_class = class_create(THIS_MODULE, "tpmrm"); |
| 1282 | if (IS_ERR(tpmrm_class)) { | ||
| 1283 | pr_err("couldn't create tpmrm class\n"); | ||
| 1284 | class_destroy(tpm_class); | ||
| 1285 | return PTR_ERR(tpmrm_class); | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm"); | ||
| 1209 | if (rc < 0) { | 1289 | if (rc < 0) { |
| 1210 | pr_err("tpm: failed to allocate char dev region\n"); | 1290 | pr_err("tpm: failed to allocate char dev region\n"); |
| 1291 | class_destroy(tpmrm_class); | ||
| 1211 | class_destroy(tpm_class); | 1292 | class_destroy(tpm_class); |
| 1212 | return rc; | 1293 | return rc; |
| 1213 | } | 1294 | } |
| @@ -1219,7 +1300,8 @@ static void __exit tpm_exit(void) | |||
| 1219 | { | 1300 | { |
| 1220 | idr_destroy(&dev_nums_idr); | 1301 | idr_destroy(&dev_nums_idr); |
| 1221 | class_destroy(tpm_class); | 1302 | class_destroy(tpm_class); |
| 1222 | unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); | 1303 | class_destroy(tpmrm_class); |
| 1304 | unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); | ||
| 1223 | } | 1305 | } |
| 1224 | 1306 | ||
| 1225 | subsys_initcall(tpm_init); | 1307 | subsys_initcall(tpm_init); |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 2f596d74f80c..55405dbe43fa 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
| @@ -40,7 +40,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
| 40 | struct tpm_chip *chip = to_tpm_chip(dev); | 40 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 41 | 41 | ||
| 42 | tpm_cmd.header.in = tpm_readpubek_header; | 42 | tpm_cmd.header.in = tpm_readpubek_header; |
| 43 | err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 43 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, |
| 44 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, | 44 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, |
| 45 | "attempting to read the PUBEK"); | 45 | "attempting to read the PUBEK"); |
| 46 | if (err) | 46 | if (err) |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4937b56a275c..4b4c8dee3096 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -89,10 +89,13 @@ enum tpm2_structures { | |||
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | enum tpm2_return_codes { | 91 | enum tpm2_return_codes { |
| 92 | TPM2_RC_SUCCESS = 0x0000, | ||
| 92 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ | 93 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ |
| 94 | TPM2_RC_HANDLE = 0x008B, | ||
| 93 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ | 95 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ |
| 94 | TPM2_RC_DISABLED = 0x0120, | 96 | TPM2_RC_DISABLED = 0x0120, |
| 95 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ | 97 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ |
| 98 | TPM2_RC_REFERENCE_H0 = 0x0910, | ||
| 96 | }; | 99 | }; |
| 97 | 100 | ||
| 98 | enum tpm2_algorithms { | 101 | enum tpm2_algorithms { |
| @@ -114,6 +117,8 @@ enum tpm2_command_codes { | |||
| 114 | TPM2_CC_CREATE = 0x0153, | 117 | TPM2_CC_CREATE = 0x0153, |
| 115 | TPM2_CC_LOAD = 0x0157, | 118 | TPM2_CC_LOAD = 0x0157, |
| 116 | TPM2_CC_UNSEAL = 0x015E, | 119 | TPM2_CC_UNSEAL = 0x015E, |
| 120 | TPM2_CC_CONTEXT_LOAD = 0x0161, | ||
| 121 | TPM2_CC_CONTEXT_SAVE = 0x0162, | ||
| 117 | TPM2_CC_FLUSH_CONTEXT = 0x0165, | 122 | TPM2_CC_FLUSH_CONTEXT = 0x0165, |
| 118 | TPM2_CC_GET_CAPABILITY = 0x017A, | 123 | TPM2_CC_GET_CAPABILITY = 0x017A, |
| 119 | TPM2_CC_GET_RANDOM = 0x017B, | 124 | TPM2_CC_GET_RANDOM = 0x017B, |
| @@ -127,21 +132,39 @@ enum tpm2_permanent_handles { | |||
| 127 | }; | 132 | }; |
| 128 | 133 | ||
| 129 | enum tpm2_capabilities { | 134 | enum tpm2_capabilities { |
| 135 | TPM2_CAP_HANDLES = 1, | ||
| 136 | TPM2_CAP_COMMANDS = 2, | ||
| 130 | TPM2_CAP_PCRS = 5, | 137 | TPM2_CAP_PCRS = 5, |
| 131 | TPM2_CAP_TPM_PROPERTIES = 6, | 138 | TPM2_CAP_TPM_PROPERTIES = 6, |
| 132 | }; | 139 | }; |
| 133 | 140 | ||
| 141 | enum tpm2_properties { | ||
| 142 | TPM_PT_TOTAL_COMMANDS = 0x0129, | ||
| 143 | }; | ||
| 144 | |||
| 134 | enum tpm2_startup_types { | 145 | enum tpm2_startup_types { |
| 135 | TPM2_SU_CLEAR = 0x0000, | 146 | TPM2_SU_CLEAR = 0x0000, |
| 136 | TPM2_SU_STATE = 0x0001, | 147 | TPM2_SU_STATE = 0x0001, |
| 137 | }; | 148 | }; |
| 138 | 149 | ||
| 150 | enum tpm2_cc_attrs { | ||
| 151 | TPM2_CC_ATTR_CHANDLES = 25, | ||
| 152 | TPM2_CC_ATTR_RHANDLE = 28, | ||
| 153 | }; | ||
| 154 | |||
| 139 | #define TPM_VID_INTEL 0x8086 | 155 | #define TPM_VID_INTEL 0x8086 |
| 140 | #define TPM_VID_WINBOND 0x1050 | 156 | #define TPM_VID_WINBOND 0x1050 |
| 141 | #define TPM_VID_STM 0x104A | 157 | #define TPM_VID_STM 0x104A |
| 142 | 158 | ||
| 143 | #define TPM_PPI_VERSION_LEN 3 | 159 | #define TPM_PPI_VERSION_LEN 3 |
| 144 | 160 | ||
| 161 | struct tpm_space { | ||
| 162 | u32 context_tbl[3]; | ||
| 163 | u8 *context_buf; | ||
| 164 | u32 session_tbl[3]; | ||
| 165 | u8 *session_buf; | ||
| 166 | }; | ||
| 167 | |||
| 145 | enum tpm_chip_flags { | 168 | enum tpm_chip_flags { |
| 146 | TPM_CHIP_FLAG_TPM2 = BIT(1), | 169 | TPM_CHIP_FLAG_TPM2 = BIT(1), |
| 147 | TPM_CHIP_FLAG_IRQ = BIT(2), | 170 | TPM_CHIP_FLAG_IRQ = BIT(2), |
| @@ -161,7 +184,9 @@ struct tpm_chip_seqops { | |||
| 161 | 184 | ||
| 162 | struct tpm_chip { | 185 | struct tpm_chip { |
| 163 | struct device dev; | 186 | struct device dev; |
| 187 | struct device devs; | ||
| 164 | struct cdev cdev; | 188 | struct cdev cdev; |
| 189 | struct cdev cdevs; | ||
| 165 | 190 | ||
| 166 | /* A driver callback under ops cannot be run unless ops_sem is held | 191 | /* A driver callback under ops cannot be run unless ops_sem is held |
| 167 | * (sometimes implicitly, eg for the sysfs code). ops becomes null | 192 | * (sometimes implicitly, eg for the sysfs code). ops becomes null |
| @@ -199,6 +224,13 @@ struct tpm_chip { | |||
| 199 | acpi_handle acpi_dev_handle; | 224 | acpi_handle acpi_dev_handle; |
| 200 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; | 225 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; |
| 201 | #endif /* CONFIG_ACPI */ | 226 | #endif /* CONFIG_ACPI */ |
| 227 | |||
| 228 | struct tpm_space work_space; | ||
| 229 | u32 nr_commands; | ||
| 230 | u32 *cc_attrs_tbl; | ||
| 231 | |||
| 232 | /* active locality */ | ||
| 233 | int locality; | ||
| 202 | }; | 234 | }; |
| 203 | 235 | ||
| 204 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) | 236 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) |
| @@ -485,18 +517,21 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) | |||
| 485 | } | 517 | } |
| 486 | 518 | ||
| 487 | extern struct class *tpm_class; | 519 | extern struct class *tpm_class; |
| 520 | extern struct class *tpmrm_class; | ||
| 488 | extern dev_t tpm_devt; | 521 | extern dev_t tpm_devt; |
| 489 | extern const struct file_operations tpm_fops; | 522 | extern const struct file_operations tpm_fops; |
| 523 | extern const struct file_operations tpmrm_fops; | ||
| 490 | extern struct idr dev_nums_idr; | 524 | extern struct idr dev_nums_idr; |
| 491 | 525 | ||
| 492 | enum tpm_transmit_flags { | 526 | enum tpm_transmit_flags { |
| 493 | TPM_TRANSMIT_UNLOCKED = BIT(0), | 527 | TPM_TRANSMIT_UNLOCKED = BIT(0), |
| 494 | }; | 528 | }; |
| 495 | 529 | ||
| 496 | ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | 530 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, |
| 497 | unsigned int flags); | 531 | u8 *buf, size_t bufsiz, unsigned int flags); |
| 498 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, size_t bufsiz, | 532 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, |
| 499 | size_t min_rsp_body_len, unsigned int flags, | 533 | const void *buf, size_t bufsiz, |
| 534 | size_t min_rsp_body_length, unsigned int flags, | ||
| 500 | const char *desc); | 535 | const char *desc); |
| 501 | ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, | 536 | ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, |
| 502 | const char *desc, size_t min_cap_length); | 537 | const char *desc, size_t min_cap_length); |
| @@ -541,6 +576,8 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); | |||
| 541 | int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, | 576 | int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, |
| 542 | struct tpm2_digest *digests); | 577 | struct tpm2_digest *digests); |
| 543 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); | 578 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); |
| 579 | void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | ||
| 580 | unsigned int flags); | ||
| 544 | int tpm2_seal_trusted(struct tpm_chip *chip, | 581 | int tpm2_seal_trusted(struct tpm_chip *chip, |
| 545 | struct trusted_key_payload *payload, | 582 | struct trusted_key_payload *payload, |
| 546 | struct trusted_key_options *options); | 583 | struct trusted_key_options *options); |
| @@ -554,4 +591,11 @@ int tpm2_auto_startup(struct tpm_chip *chip); | |||
| 554 | void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); | 591 | void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); |
| 555 | unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); | 592 | unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); |
| 556 | int tpm2_probe(struct tpm_chip *chip); | 593 | int tpm2_probe(struct tpm_chip *chip); |
| 594 | int tpm2_find_cc(struct tpm_chip *chip, u32 cc); | ||
| 595 | int tpm2_init_space(struct tpm_space *space); | ||
| 596 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space); | ||
| 597 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | ||
| 598 | u8 *cmd); | ||
| 599 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | ||
| 600 | u32 cc, u8 *buf, size_t *bufsiz); | ||
| 557 | #endif | 601 | #endif |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 881aea9732bf..3ee6883f26c1 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
| @@ -266,7 +266,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
| 266 | sizeof(cmd.params.pcrread_in.pcr_select)); | 266 | sizeof(cmd.params.pcrread_in.pcr_select)); |
| 267 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | 267 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); |
| 268 | 268 | ||
| 269 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 269 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), |
| 270 | TPM2_PCR_READ_RESP_BODY_SIZE, | 270 | TPM2_PCR_READ_RESP_BODY_SIZE, |
| 271 | 0, "attempting to read a pcr value"); | 271 | 0, "attempting to read a pcr value"); |
| 272 | if (rc == 0) { | 272 | if (rc == 0) { |
| @@ -333,7 +333,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, | |||
| 333 | } | 333 | } |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, 0, | 336 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, |
| 337 | "attempting extend a PCR value"); | 337 | "attempting extend a PCR value"); |
| 338 | 338 | ||
| 339 | tpm_buf_destroy(&buf); | 339 | tpm_buf_destroy(&buf); |
| @@ -382,7 +382,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) | |||
| 382 | cmd.header.in = tpm2_getrandom_header; | 382 | cmd.header.in = tpm2_getrandom_header; |
| 383 | cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); | 383 | cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); |
| 384 | 384 | ||
| 385 | err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 385 | err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), |
| 386 | offsetof(struct tpm2_get_random_out, | 386 | offsetof(struct tpm2_get_random_out, |
| 387 | buffer), | 387 | buffer), |
| 388 | 0, "attempting get random"); | 388 | 0, "attempting get random"); |
| @@ -419,6 +419,35 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = { | |||
| 419 | }; | 419 | }; |
| 420 | 420 | ||
| 421 | /** | 421 | /** |
| 422 | * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command | ||
| 423 | * @chip: TPM chip to use | ||
| 424 | * @payload: the key data in clear and encrypted form | ||
| 425 | * @options: authentication values and other options | ||
| 426 | * | ||
| 427 | * Return: same as with tpm_transmit_cmd | ||
| 428 | */ | ||
| 429 | void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | ||
| 430 | unsigned int flags) | ||
| 431 | { | ||
| 432 | struct tpm_buf buf; | ||
| 433 | int rc; | ||
| 434 | |||
| 435 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); | ||
| 436 | if (rc) { | ||
| 437 | dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n", | ||
| 438 | handle); | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | |||
| 442 | tpm_buf_append_u32(&buf, handle); | ||
| 443 | |||
| 444 | (void) tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, flags, | ||
| 445 | "flushing context"); | ||
| 446 | |||
| 447 | tpm_buf_destroy(&buf); | ||
| 448 | } | ||
| 449 | |||
| 450 | /** | ||
| 422 | * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. | 451 | * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. |
| 423 | * | 452 | * |
| 424 | * @buf: an allocated tpm_buf instance | 453 | * @buf: an allocated tpm_buf instance |
| @@ -528,7 +557,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, | |||
| 528 | goto out; | 557 | goto out; |
| 529 | } | 558 | } |
| 530 | 559 | ||
| 531 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, 0, | 560 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, 0, |
| 532 | "sealing data"); | 561 | "sealing data"); |
| 533 | if (rc) | 562 | if (rc) |
| 534 | goto out; | 563 | goto out; |
| @@ -612,7 +641,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, | |||
| 612 | goto out; | 641 | goto out; |
| 613 | } | 642 | } |
| 614 | 643 | ||
| 615 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, flags, | 644 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, flags, |
| 616 | "loading blob"); | 645 | "loading blob"); |
| 617 | if (!rc) | 646 | if (!rc) |
| 618 | *blob_handle = be32_to_cpup( | 647 | *blob_handle = be32_to_cpup( |
| @@ -628,39 +657,6 @@ out: | |||
| 628 | } | 657 | } |
| 629 | 658 | ||
| 630 | /** | 659 | /** |
| 631 | * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command | ||
| 632 | * | ||
| 633 | * @chip: TPM chip to use | ||
| 634 | * @handle: the key data in clear and encrypted form | ||
| 635 | * @flags: tpm transmit flags | ||
| 636 | * | ||
| 637 | * Return: Same as with tpm_transmit_cmd. | ||
| 638 | */ | ||
| 639 | static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | ||
| 640 | unsigned int flags) | ||
| 641 | { | ||
| 642 | struct tpm_buf buf; | ||
| 643 | int rc; | ||
| 644 | |||
| 645 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); | ||
| 646 | if (rc) { | ||
| 647 | dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n", | ||
| 648 | handle); | ||
| 649 | return; | ||
| 650 | } | ||
| 651 | |||
| 652 | tpm_buf_append_u32(&buf, handle); | ||
| 653 | |||
| 654 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, flags, | ||
| 655 | "flushing context"); | ||
| 656 | if (rc) | ||
| 657 | dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle, | ||
| 658 | rc); | ||
| 659 | |||
| 660 | tpm_buf_destroy(&buf); | ||
| 661 | } | ||
| 662 | |||
| 663 | /** | ||
| 664 | * tpm2_unseal_cmd() - execute a TPM2_Unload command | 660 | * tpm2_unseal_cmd() - execute a TPM2_Unload command |
| 665 | * | 661 | * |
| 666 | * @chip: TPM chip to use | 662 | * @chip: TPM chip to use |
| @@ -697,7 +693,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, | |||
| 697 | options->blobauth /* hmac */, | 693 | options->blobauth /* hmac */, |
| 698 | TPM_DIGEST_SIZE); | 694 | TPM_DIGEST_SIZE); |
| 699 | 695 | ||
| 700 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 6, flags, | 696 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 6, flags, |
| 701 | "unsealing"); | 697 | "unsealing"); |
| 702 | if (rc > 0) | 698 | if (rc > 0) |
| 703 | rc = -EPERM; | 699 | rc = -EPERM; |
| @@ -774,7 +770,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, | |||
| 774 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); | 770 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); |
| 775 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | 771 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); |
| 776 | 772 | ||
| 777 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 773 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), |
| 778 | TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc); | 774 | TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc); |
| 779 | if (!rc) | 775 | if (!rc) |
| 780 | *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); | 776 | *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); |
| @@ -809,7 +805,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type) | |||
| 809 | cmd.header.in = tpm2_startup_header; | 805 | cmd.header.in = tpm2_startup_header; |
| 810 | 806 | ||
| 811 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); | 807 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); |
| 812 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, | 808 | return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, |
| 813 | "attempting to start the TPM"); | 809 | "attempting to start the TPM"); |
| 814 | } | 810 | } |
| 815 | 811 | ||
| @@ -838,7 +834,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | |||
| 838 | cmd.header.in = tpm2_shutdown_header; | 834 | cmd.header.in = tpm2_shutdown_header; |
| 839 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); | 835 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); |
| 840 | 836 | ||
| 841 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, | 837 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, |
| 842 | "stopping the TPM"); | 838 | "stopping the TPM"); |
| 843 | 839 | ||
| 844 | /* In places where shutdown command is sent there's no much we can do | 840 | /* In places where shutdown command is sent there's no much we can do |
| @@ -902,7 +898,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) | |||
| 902 | cmd.header.in = tpm2_selftest_header; | 898 | cmd.header.in = tpm2_selftest_header; |
| 903 | cmd.params.selftest_in.full_test = full; | 899 | cmd.params.selftest_in.full_test = full; |
| 904 | 900 | ||
| 905 | rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, | 901 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, |
| 906 | "continue selftest"); | 902 | "continue selftest"); |
| 907 | 903 | ||
| 908 | /* At least some prototype chips seem to give RC_TESTING error | 904 | /* At least some prototype chips seem to give RC_TESTING error |
| @@ -953,7 +949,8 @@ static int tpm2_do_selftest(struct tpm_chip *chip) | |||
| 953 | cmd.params.pcrread_in.pcr_select[1] = 0x00; | 949 | cmd.params.pcrread_in.pcr_select[1] = 0x00; |
| 954 | cmd.params.pcrread_in.pcr_select[2] = 0x00; | 950 | cmd.params.pcrread_in.pcr_select[2] = 0x00; |
| 955 | 951 | ||
| 956 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL); | 952 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, |
| 953 | NULL); | ||
| 957 | if (rc < 0) | 954 | if (rc < 0) |
| 958 | break; | 955 | break; |
| 959 | 956 | ||
| @@ -986,7 +983,7 @@ int tpm2_probe(struct tpm_chip *chip) | |||
| 986 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); | 983 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); |
| 987 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | 984 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); |
| 988 | 985 | ||
| 989 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL); | 986 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, NULL); |
| 990 | if (rc < 0) | 987 | if (rc < 0) |
| 991 | return rc; | 988 | return rc; |
| 992 | 989 | ||
| @@ -1024,7 +1021,7 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) | |||
| 1024 | tpm_buf_append_u32(&buf, 0); | 1021 | tpm_buf_append_u32(&buf, 0); |
| 1025 | tpm_buf_append_u32(&buf, 1); | 1022 | tpm_buf_append_u32(&buf, 1); |
| 1026 | 1023 | ||
| 1027 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9, 0, | 1024 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 9, 0, |
| 1028 | "get tpm pcr allocation"); | 1025 | "get tpm pcr allocation"); |
| 1029 | if (rc) | 1026 | if (rc) |
| 1030 | goto out; | 1027 | goto out; |
| @@ -1067,15 +1064,76 @@ out: | |||
| 1067 | return rc; | 1064 | return rc; |
| 1068 | } | 1065 | } |
| 1069 | 1066 | ||
| 1067 | static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | ||
| 1068 | { | ||
| 1069 | struct tpm_buf buf; | ||
| 1070 | u32 nr_commands; | ||
| 1071 | u32 *attrs; | ||
| 1072 | u32 cc; | ||
| 1073 | int i; | ||
| 1074 | int rc; | ||
| 1075 | |||
| 1076 | rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL); | ||
| 1077 | if (rc) | ||
| 1078 | goto out; | ||
| 1079 | |||
| 1080 | if (nr_commands > 0xFFFFF) { | ||
| 1081 | rc = -EFAULT; | ||
| 1082 | goto out; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | chip->cc_attrs_tbl = devm_kzalloc(&chip->dev, 4 * nr_commands, | ||
| 1086 | GFP_KERNEL); | ||
| 1087 | |||
| 1088 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); | ||
| 1089 | if (rc) | ||
| 1090 | goto out; | ||
| 1091 | |||
| 1092 | tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS); | ||
| 1093 | tpm_buf_append_u32(&buf, TPM2_CC_FIRST); | ||
| 1094 | tpm_buf_append_u32(&buf, nr_commands); | ||
| 1095 | |||
| 1096 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | ||
| 1097 | 9 + 4 * nr_commands, 0, NULL); | ||
| 1098 | if (rc) { | ||
| 1099 | tpm_buf_destroy(&buf); | ||
| 1100 | goto out; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | if (nr_commands != | ||
| 1104 | be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) { | ||
| 1105 | tpm_buf_destroy(&buf); | ||
| 1106 | goto out; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | chip->nr_commands = nr_commands; | ||
| 1110 | |||
| 1111 | attrs = (u32 *)&buf.data[TPM_HEADER_SIZE + 9]; | ||
| 1112 | for (i = 0; i < nr_commands; i++, attrs++) { | ||
| 1113 | chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); | ||
| 1114 | cc = chip->cc_attrs_tbl[i] & 0xFFFF; | ||
| 1115 | |||
| 1116 | if (cc == TPM2_CC_CONTEXT_SAVE || cc == TPM2_CC_FLUSH_CONTEXT) { | ||
| 1117 | chip->cc_attrs_tbl[i] &= | ||
| 1118 | ~(GENMASK(2, 0) << TPM2_CC_ATTR_CHANDLES); | ||
| 1119 | chip->cc_attrs_tbl[i] |= 1 << TPM2_CC_ATTR_CHANDLES; | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | tpm_buf_destroy(&buf); | ||
| 1124 | |||
| 1125 | out: | ||
| 1126 | if (rc > 0) | ||
| 1127 | rc = -ENODEV; | ||
| 1128 | return rc; | ||
| 1129 | } | ||
| 1130 | |||
| 1070 | /** | 1131 | /** |
| 1071 | * tpm2_auto_startup - Perform the standard automatic TPM initialization | 1132 | * tpm2_auto_startup - Perform the standard automatic TPM initialization |
| 1072 | * sequence | 1133 | * sequence |
| 1073 | * @chip: TPM chip to use | 1134 | * @chip: TPM chip to use |
| 1074 | * | 1135 | * |
| 1075 | * Initializes timeout values for operation and command durations, conducts | 1136 | * Returns 0 on success, < 0 in case of fatal error. |
| 1076 | * a self-test and reads the list of active PCR banks. | ||
| 1077 | * | ||
| 1078 | * Return: 0 on success. Otherwise, a system error code is returned. | ||
| 1079 | */ | 1137 | */ |
| 1080 | int tpm2_auto_startup(struct tpm_chip *chip) | 1138 | int tpm2_auto_startup(struct tpm_chip *chip) |
| 1081 | { | 1139 | { |
| @@ -1104,9 +1162,24 @@ int tpm2_auto_startup(struct tpm_chip *chip) | |||
| 1104 | } | 1162 | } |
| 1105 | 1163 | ||
| 1106 | rc = tpm2_get_pcr_allocation(chip); | 1164 | rc = tpm2_get_pcr_allocation(chip); |
| 1165 | if (rc) | ||
| 1166 | goto out; | ||
| 1167 | |||
| 1168 | rc = tpm2_get_cc_attrs_tbl(chip); | ||
| 1107 | 1169 | ||
| 1108 | out: | 1170 | out: |
| 1109 | if (rc > 0) | 1171 | if (rc > 0) |
| 1110 | rc = -ENODEV; | 1172 | rc = -ENODEV; |
| 1111 | return rc; | 1173 | return rc; |
| 1112 | } | 1174 | } |
| 1175 | |||
| 1176 | int tpm2_find_cc(struct tpm_chip *chip, u32 cc) | ||
| 1177 | { | ||
| 1178 | int i; | ||
| 1179 | |||
| 1180 | for (i = 0; i < chip->nr_commands; i++) | ||
| 1181 | if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0))) | ||
| 1182 | return i; | ||
| 1183 | |||
| 1184 | return -1; | ||
| 1185 | } | ||
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c new file mode 100644 index 000000000000..e2e059d8ffec --- /dev/null +++ b/drivers/char/tpm/tpm2-space.c | |||
| @@ -0,0 +1,528 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2016 Intel Corporation | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | ||
| 6 | * | ||
| 7 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 8 | * | ||
| 9 | * This file contains TPM2 protocol implementations of the commands | ||
| 10 | * used by the kernel internally. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * as published by the Free Software Foundation; version 2 | ||
| 15 | * of the License. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/gfp.h> | ||
| 19 | #include <asm/unaligned.h> | ||
| 20 | #include "tpm.h" | ||
| 21 | |||
| 22 | enum tpm2_handle_types { | ||
| 23 | TPM2_HT_HMAC_SESSION = 0x02000000, | ||
| 24 | TPM2_HT_POLICY_SESSION = 0x03000000, | ||
| 25 | TPM2_HT_TRANSIENT = 0x80000000, | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct tpm2_context { | ||
| 29 | __be64 sequence; | ||
| 30 | __be32 saved_handle; | ||
| 31 | __be32 hierarchy; | ||
| 32 | __be16 blob_size; | ||
| 33 | } __packed; | ||
| 34 | |||
| 35 | static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) | ||
| 36 | { | ||
| 37 | int i; | ||
| 38 | |||
| 39 | for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { | ||
| 40 | if (space->session_tbl[i]) | ||
| 41 | tpm2_flush_context_cmd(chip, space->session_tbl[i], | ||
| 42 | TPM_TRANSMIT_UNLOCKED); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | int tpm2_init_space(struct tpm_space *space) | ||
| 47 | { | ||
| 48 | space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 49 | if (!space->context_buf) | ||
| 50 | return -ENOMEM; | ||
| 51 | |||
| 52 | space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 53 | if (space->session_buf == NULL) { | ||
| 54 | kfree(space->context_buf); | ||
| 55 | return -ENOMEM; | ||
| 56 | } | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) | ||
| 62 | { | ||
| 63 | mutex_lock(&chip->tpm_mutex); | ||
| 64 | tpm2_flush_sessions(chip, space); | ||
| 65 | mutex_unlock(&chip->tpm_mutex); | ||
| 66 | kfree(space->context_buf); | ||
| 67 | kfree(space->session_buf); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, | ||
| 71 | unsigned int *offset, u32 *handle) | ||
| 72 | { | ||
| 73 | struct tpm_buf tbuf; | ||
| 74 | struct tpm2_context *ctx; | ||
| 75 | unsigned int body_size; | ||
| 76 | int rc; | ||
| 77 | |||
| 78 | rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); | ||
| 79 | if (rc) | ||
| 80 | return rc; | ||
| 81 | |||
| 82 | ctx = (struct tpm2_context *)&buf[*offset]; | ||
| 83 | body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size); | ||
| 84 | tpm_buf_append(&tbuf, &buf[*offset], body_size); | ||
| 85 | |||
| 86 | rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4, | ||
| 87 | TPM_TRANSMIT_UNLOCKED, NULL); | ||
| 88 | if (rc < 0) { | ||
| 89 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", | ||
| 90 | __func__, rc); | ||
| 91 | tpm_buf_destroy(&tbuf); | ||
| 92 | return -EFAULT; | ||
| 93 | } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE || | ||
| 94 | rc == TPM2_RC_REFERENCE_H0) { | ||
| 95 | /* | ||
| 96 | * TPM_RC_HANDLE means that the session context can't | ||
| 97 | * be loaded because of an internal counter mismatch | ||
| 98 | * that makes the TPM think there might have been a | ||
| 99 | * replay. This might happen if the context was saved | ||
| 100 | * and loaded outside the space. | ||
| 101 | * | ||
| 102 | * TPM_RC_REFERENCE_H0 means the session has been | ||
| 103 | * flushed outside the space | ||
| 104 | */ | ||
| 105 | rc = -ENOENT; | ||
| 106 | tpm_buf_destroy(&tbuf); | ||
| 107 | } else if (rc > 0) { | ||
| 108 | dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", | ||
| 109 | __func__, rc); | ||
| 110 | tpm_buf_destroy(&tbuf); | ||
| 111 | return -EFAULT; | ||
| 112 | } | ||
| 113 | |||
| 114 | *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]); | ||
| 115 | *offset += body_size; | ||
| 116 | |||
| 117 | tpm_buf_destroy(&tbuf); | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, | ||
| 122 | unsigned int buf_size, unsigned int *offset) | ||
| 123 | { | ||
| 124 | struct tpm_buf tbuf; | ||
| 125 | unsigned int body_size; | ||
| 126 | int rc; | ||
| 127 | |||
| 128 | rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); | ||
| 129 | if (rc) | ||
| 130 | return rc; | ||
| 131 | |||
| 132 | tpm_buf_append_u32(&tbuf, handle); | ||
| 133 | |||
| 134 | rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0, | ||
| 135 | TPM_TRANSMIT_UNLOCKED, NULL); | ||
| 136 | if (rc < 0) { | ||
| 137 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", | ||
| 138 | __func__, rc); | ||
| 139 | tpm_buf_destroy(&tbuf); | ||
| 140 | return -EFAULT; | ||
| 141 | } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) { | ||
| 142 | tpm_buf_destroy(&tbuf); | ||
| 143 | return -ENOENT; | ||
| 144 | } else if (rc) { | ||
| 145 | dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", | ||
| 146 | __func__, rc); | ||
| 147 | tpm_buf_destroy(&tbuf); | ||
| 148 | return -EFAULT; | ||
| 149 | } | ||
| 150 | |||
| 151 | body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE; | ||
| 152 | if ((*offset + body_size) > buf_size) { | ||
| 153 | dev_warn(&chip->dev, "%s: out of backing storage\n", __func__); | ||
| 154 | tpm_buf_destroy(&tbuf); | ||
| 155 | return -ENOMEM; | ||
| 156 | } | ||
| 157 | |||
| 158 | memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size); | ||
| 159 | *offset += body_size; | ||
| 160 | tpm_buf_destroy(&tbuf); | ||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void tpm2_flush_space(struct tpm_chip *chip) | ||
| 165 | { | ||
| 166 | struct tpm_space *space = &chip->work_space; | ||
| 167 | int i; | ||
| 168 | |||
| 169 | for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) | ||
| 170 | if (space->context_tbl[i] && ~space->context_tbl[i]) | ||
| 171 | tpm2_flush_context_cmd(chip, space->context_tbl[i], | ||
| 172 | TPM_TRANSMIT_UNLOCKED); | ||
| 173 | |||
| 174 | tpm2_flush_sessions(chip, space); | ||
| 175 | } | ||
| 176 | |||
| 177 | static int tpm2_load_space(struct tpm_chip *chip) | ||
| 178 | { | ||
| 179 | struct tpm_space *space = &chip->work_space; | ||
| 180 | unsigned int offset; | ||
| 181 | int i; | ||
| 182 | int rc; | ||
| 183 | |||
| 184 | for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) { | ||
| 185 | if (!space->context_tbl[i]) | ||
| 186 | continue; | ||
| 187 | |||
| 188 | /* sanity check, should never happen */ | ||
| 189 | if (~space->context_tbl[i]) { | ||
| 190 | dev_err(&chip->dev, "context table is inconsistent"); | ||
| 191 | return -EFAULT; | ||
| 192 | } | ||
| 193 | |||
| 194 | rc = tpm2_load_context(chip, space->context_buf, &offset, | ||
| 195 | &space->context_tbl[i]); | ||
| 196 | if (rc) | ||
| 197 | return rc; | ||
| 198 | } | ||
| 199 | |||
| 200 | for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) { | ||
| 201 | u32 handle; | ||
| 202 | |||
| 203 | if (!space->session_tbl[i]) | ||
| 204 | continue; | ||
| 205 | |||
| 206 | rc = tpm2_load_context(chip, space->session_buf, | ||
| 207 | &offset, &handle); | ||
| 208 | if (rc == -ENOENT) { | ||
| 209 | /* load failed, just forget session */ | ||
| 210 | space->session_tbl[i] = 0; | ||
| 211 | } else if (rc) { | ||
| 212 | tpm2_flush_space(chip); | ||
| 213 | return rc; | ||
| 214 | } | ||
| 215 | if (handle != space->session_tbl[i]) { | ||
| 216 | dev_warn(&chip->dev, "session restored to wrong handle\n"); | ||
| 217 | tpm2_flush_space(chip); | ||
| 218 | return -EFAULT; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static bool tpm2_map_to_phandle(struct tpm_space *space, void *handle) | ||
| 226 | { | ||
| 227 | u32 vhandle = be32_to_cpup((__be32 *)handle); | ||
| 228 | u32 phandle; | ||
| 229 | int i; | ||
| 230 | |||
| 231 | i = 0xFFFFFF - (vhandle & 0xFFFFFF); | ||
| 232 | if (i >= ARRAY_SIZE(space->context_tbl) || !space->context_tbl[i]) | ||
| 233 | return false; | ||
| 234 | |||
| 235 | phandle = space->context_tbl[i]; | ||
| 236 | *((__be32 *)handle) = cpu_to_be32(phandle); | ||
| 237 | return true; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | ||
| 241 | { | ||
| 242 | struct tpm_space *space = &chip->work_space; | ||
| 243 | unsigned int nr_handles; | ||
| 244 | u32 attrs; | ||
| 245 | u32 *handle; | ||
| 246 | int i; | ||
| 247 | |||
| 248 | i = tpm2_find_cc(chip, cc); | ||
| 249 | if (i < 0) | ||
| 250 | return -EINVAL; | ||
| 251 | |||
| 252 | attrs = chip->cc_attrs_tbl[i]; | ||
| 253 | nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); | ||
| 254 | |||
| 255 | handle = (u32 *)&cmd[TPM_HEADER_SIZE]; | ||
| 256 | for (i = 0; i < nr_handles; i++, handle++) { | ||
| 257 | if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { | ||
| 258 | if (!tpm2_map_to_phandle(space, handle)) | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | ||
| 267 | u8 *cmd) | ||
| 268 | { | ||
| 269 | int rc; | ||
| 270 | |||
| 271 | if (!space) | ||
| 272 | return 0; | ||
| 273 | |||
| 274 | memcpy(&chip->work_space.context_tbl, &space->context_tbl, | ||
| 275 | sizeof(space->context_tbl)); | ||
| 276 | memcpy(&chip->work_space.session_tbl, &space->session_tbl, | ||
| 277 | sizeof(space->session_tbl)); | ||
| 278 | memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE); | ||
| 279 | memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE); | ||
| 280 | |||
| 281 | rc = tpm2_load_space(chip); | ||
| 282 | if (rc) { | ||
| 283 | tpm2_flush_space(chip); | ||
| 284 | return rc; | ||
| 285 | } | ||
| 286 | |||
| 287 | rc = tpm2_map_command(chip, cc, cmd); | ||
| 288 | if (rc) { | ||
| 289 | tpm2_flush_space(chip); | ||
| 290 | return rc; | ||
| 291 | } | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static bool tpm2_add_session(struct tpm_chip *chip, u32 handle) | ||
| 297 | { | ||
| 298 | struct tpm_space *space = &chip->work_space; | ||
| 299 | int i; | ||
| 300 | |||
| 301 | for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) | ||
| 302 | if (space->session_tbl[i] == 0) | ||
| 303 | break; | ||
| 304 | |||
| 305 | if (i == ARRAY_SIZE(space->session_tbl)) | ||
| 306 | return false; | ||
| 307 | |||
| 308 | space->session_tbl[i] = handle; | ||
| 309 | return true; | ||
| 310 | } | ||
| 311 | |||
| 312 | static u32 tpm2_map_to_vhandle(struct tpm_space *space, u32 phandle, bool alloc) | ||
| 313 | { | ||
| 314 | int i; | ||
| 315 | |||
| 316 | for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) { | ||
| 317 | if (alloc) { | ||
| 318 | if (!space->context_tbl[i]) { | ||
| 319 | space->context_tbl[i] = phandle; | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | } else if (space->context_tbl[i] == phandle) | ||
| 323 | break; | ||
| 324 | } | ||
| 325 | |||
| 326 | if (i == ARRAY_SIZE(space->context_tbl)) | ||
| 327 | return 0; | ||
| 328 | |||
| 329 | return TPM2_HT_TRANSIENT | (0xFFFFFF - i); | ||
| 330 | } | ||
| 331 | |||
| 332 | static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, | ||
| 333 | size_t len) | ||
| 334 | { | ||
| 335 | struct tpm_space *space = &chip->work_space; | ||
| 336 | struct tpm_output_header *header = (void *)rsp; | ||
| 337 | u32 phandle; | ||
| 338 | u32 phandle_type; | ||
| 339 | u32 vhandle; | ||
| 340 | u32 attrs; | ||
| 341 | int i; | ||
| 342 | |||
| 343 | if (be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) | ||
| 344 | return 0; | ||
| 345 | |||
| 346 | i = tpm2_find_cc(chip, cc); | ||
| 347 | /* sanity check, should never happen */ | ||
| 348 | if (i < 0) | ||
| 349 | return -EFAULT; | ||
| 350 | |||
| 351 | attrs = chip->cc_attrs_tbl[i]; | ||
| 352 | if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1)) | ||
| 353 | return 0; | ||
| 354 | |||
| 355 | phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]); | ||
| 356 | phandle_type = phandle & 0xFF000000; | ||
| 357 | |||
| 358 | switch (phandle_type) { | ||
| 359 | case TPM2_HT_TRANSIENT: | ||
| 360 | vhandle = tpm2_map_to_vhandle(space, phandle, true); | ||
| 361 | if (!vhandle) | ||
| 362 | goto out_no_slots; | ||
| 363 | |||
| 364 | *(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle); | ||
| 365 | break; | ||
| 366 | case TPM2_HT_HMAC_SESSION: | ||
| 367 | case TPM2_HT_POLICY_SESSION: | ||
| 368 | if (!tpm2_add_session(chip, phandle)) | ||
| 369 | goto out_no_slots; | ||
| 370 | break; | ||
| 371 | default: | ||
| 372 | dev_err(&chip->dev, "%s: unknown handle 0x%08X\n", | ||
| 373 | __func__, phandle); | ||
| 374 | break; | ||
| 375 | }; | ||
| 376 | |||
| 377 | return 0; | ||
| 378 | out_no_slots: | ||
| 379 | tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED); | ||
| 380 | dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, | ||
| 381 | phandle); | ||
| 382 | return -ENOMEM; | ||
| 383 | } | ||
| 384 | |||
| 385 | struct tpm2_cap_handles { | ||
| 386 | u8 more_data; | ||
| 387 | __be32 capability; | ||
| 388 | __be32 count; | ||
| 389 | __be32 handles[]; | ||
| 390 | } __packed; | ||
| 391 | |||
| 392 | static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp, | ||
| 393 | size_t len) | ||
| 394 | { | ||
| 395 | struct tpm_space *space = &chip->work_space; | ||
| 396 | struct tpm_output_header *header = (void *)rsp; | ||
| 397 | struct tpm2_cap_handles *data; | ||
| 398 | u32 phandle; | ||
| 399 | u32 phandle_type; | ||
| 400 | u32 vhandle; | ||
| 401 | int i; | ||
| 402 | int j; | ||
| 403 | |||
| 404 | if (cc != TPM2_CC_GET_CAPABILITY || | ||
| 405 | be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) { | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (len < TPM_HEADER_SIZE + 9) | ||
| 410 | return -EFAULT; | ||
| 411 | |||
| 412 | data = (void *)&rsp[TPM_HEADER_SIZE]; | ||
| 413 | if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES) | ||
| 414 | return 0; | ||
| 415 | |||
| 416 | if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count)) | ||
| 417 | return -EFAULT; | ||
| 418 | |||
| 419 | for (i = 0, j = 0; i < be32_to_cpu(data->count); i++) { | ||
| 420 | phandle = be32_to_cpup((__be32 *)&data->handles[i]); | ||
| 421 | phandle_type = phandle & 0xFF000000; | ||
| 422 | |||
| 423 | switch (phandle_type) { | ||
| 424 | case TPM2_HT_TRANSIENT: | ||
| 425 | vhandle = tpm2_map_to_vhandle(space, phandle, false); | ||
| 426 | if (!vhandle) | ||
| 427 | break; | ||
| 428 | |||
| 429 | data->handles[j] = cpu_to_be32(vhandle); | ||
| 430 | j++; | ||
| 431 | break; | ||
| 432 | |||
| 433 | default: | ||
| 434 | data->handles[j] = cpu_to_be32(phandle); | ||
| 435 | j++; | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | |||
| 439 | } | ||
| 440 | |||
| 441 | header->length = cpu_to_be32(TPM_HEADER_SIZE + 9 + 4 * j); | ||
| 442 | data->count = cpu_to_be32(j); | ||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static int tpm2_save_space(struct tpm_chip *chip) | ||
| 447 | { | ||
| 448 | struct tpm_space *space = &chip->work_space; | ||
| 449 | unsigned int offset; | ||
| 450 | int i; | ||
| 451 | int rc; | ||
| 452 | |||
| 453 | for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) { | ||
| 454 | if (!(space->context_tbl[i] && ~space->context_tbl[i])) | ||
| 455 | continue; | ||
| 456 | |||
| 457 | rc = tpm2_save_context(chip, space->context_tbl[i], | ||
| 458 | space->context_buf, PAGE_SIZE, | ||
| 459 | &offset); | ||
| 460 | if (rc == -ENOENT) { | ||
| 461 | space->context_tbl[i] = 0; | ||
| 462 | continue; | ||
| 463 | } else if (rc) | ||
| 464 | return rc; | ||
| 465 | |||
| 466 | tpm2_flush_context_cmd(chip, space->context_tbl[i], | ||
| 467 | TPM_TRANSMIT_UNLOCKED); | ||
| 468 | space->context_tbl[i] = ~0; | ||
| 469 | } | ||
| 470 | |||
| 471 | for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) { | ||
| 472 | if (!space->session_tbl[i]) | ||
| 473 | continue; | ||
| 474 | |||
| 475 | rc = tpm2_save_context(chip, space->session_tbl[i], | ||
| 476 | space->session_buf, PAGE_SIZE, | ||
| 477 | &offset); | ||
| 478 | |||
| 479 | if (rc == -ENOENT) { | ||
| 480 | /* handle error saving session, just forget it */ | ||
| 481 | space->session_tbl[i] = 0; | ||
| 482 | } else if (rc < 0) { | ||
| 483 | tpm2_flush_space(chip); | ||
| 484 | return rc; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | return 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | ||
| 492 | u32 cc, u8 *buf, size_t *bufsiz) | ||
| 493 | { | ||
| 494 | struct tpm_output_header *header = (void *)buf; | ||
| 495 | int rc; | ||
| 496 | |||
| 497 | if (!space) | ||
| 498 | return 0; | ||
| 499 | |||
| 500 | rc = tpm2_map_response_header(chip, cc, buf, *bufsiz); | ||
| 501 | if (rc) { | ||
| 502 | tpm2_flush_space(chip); | ||
| 503 | return rc; | ||
| 504 | } | ||
| 505 | |||
| 506 | rc = tpm2_map_response_body(chip, cc, buf, *bufsiz); | ||
| 507 | if (rc) { | ||
| 508 | tpm2_flush_space(chip); | ||
| 509 | return rc; | ||
| 510 | } | ||
| 511 | |||
| 512 | rc = tpm2_save_space(chip); | ||
| 513 | if (rc) { | ||
| 514 | tpm2_flush_space(chip); | ||
| 515 | return rc; | ||
| 516 | } | ||
| 517 | |||
| 518 | *bufsiz = be32_to_cpu(header->length); | ||
| 519 | |||
| 520 | memcpy(&space->context_tbl, &chip->work_space.context_tbl, | ||
| 521 | sizeof(space->context_tbl)); | ||
| 522 | memcpy(&space->session_tbl, &chip->work_space.session_tbl, | ||
| 523 | sizeof(space->session_tbl)); | ||
| 524 | memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE); | ||
| 525 | memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE); | ||
| 526 | |||
| 527 | return 0; | ||
| 528 | } | ||
diff --git a/drivers/char/tpm/tpm2_eventlog.c b/drivers/char/tpm/tpm2_eventlog.c index 513897cf9c4b..34a8afa69138 100644 --- a/drivers/char/tpm/tpm2_eventlog.c +++ b/drivers/char/tpm/tpm2_eventlog.c | |||
| @@ -56,18 +56,24 @@ static int calc_tpm2_event_size(struct tcg_pcr_event2 *event, | |||
| 56 | 56 | ||
| 57 | efispecid = (struct tcg_efi_specid_event *)event_header->event; | 57 | efispecid = (struct tcg_efi_specid_event *)event_header->event; |
| 58 | 58 | ||
| 59 | for (i = 0; (i < event->count) && (i < TPM2_ACTIVE_PCR_BANKS); | 59 | /* Check if event is malformed. */ |
| 60 | i++) { | 60 | if (event->count > efispecid->num_algs) |
| 61 | return 0; | ||
| 62 | |||
| 63 | for (i = 0; i < event->count; i++) { | ||
| 61 | halg_size = sizeof(event->digests[i].alg_id); | 64 | halg_size = sizeof(event->digests[i].alg_id); |
| 62 | memcpy(&halg, marker, halg_size); | 65 | memcpy(&halg, marker, halg_size); |
| 63 | marker = marker + halg_size; | 66 | marker = marker + halg_size; |
| 64 | for (j = 0; (j < efispecid->num_algs); j++) { | 67 | for (j = 0; j < efispecid->num_algs; j++) { |
| 65 | if (halg == efispecid->digest_sizes[j].alg_id) { | 68 | if (halg == efispecid->digest_sizes[j].alg_id) { |
| 66 | marker = marker + | 69 | marker += |
| 67 | efispecid->digest_sizes[j].digest_size; | 70 | efispecid->digest_sizes[j].digest_size; |
| 68 | break; | 71 | break; |
| 69 | } | 72 | } |
| 70 | } | 73 | } |
| 74 | /* Algorithm without known length. Such event is unparseable. */ | ||
| 75 | if (j == efispecid->num_algs) | ||
| 76 | return 0; | ||
| 71 | } | 77 | } |
| 72 | 78 | ||
| 73 | event_field = (struct tcg_event_field *)marker; | 79 | event_field = (struct tcg_event_field *)marker; |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 86f355b6df1d..b917b9d5f710 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | #include <linux/rculist.h> | 20 | #include <linux/rculist.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
| 23 | #ifdef CONFIG_ARM64 | ||
| 24 | #include <linux/arm-smccc.h> | ||
| 25 | #endif | ||
| 23 | #include "tpm.h" | 26 | #include "tpm.h" |
| 24 | 27 | ||
| 25 | #define ACPI_SIG_TPM2 "TPM2" | 28 | #define ACPI_SIG_TPM2 "TPM2" |
| @@ -34,6 +37,16 @@ enum crb_defaults { | |||
| 34 | CRB_ACPI_START_INDEX = 1, | 37 | CRB_ACPI_START_INDEX = 1, |
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| 40 | enum crb_loc_ctrl { | ||
| 41 | CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0), | ||
| 42 | CRB_LOC_CTRL_RELINQUISH = BIT(1), | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum crb_loc_state { | ||
| 46 | CRB_LOC_STATE_LOC_ASSIGNED = BIT(1), | ||
| 47 | CRB_LOC_STATE_TPM_REG_VALID_STS = BIT(7), | ||
| 48 | }; | ||
| 49 | |||
| 37 | enum crb_ctrl_req { | 50 | enum crb_ctrl_req { |
| 38 | CRB_CTRL_REQ_CMD_READY = BIT(0), | 51 | CRB_CTRL_REQ_CMD_READY = BIT(0), |
| 39 | CRB_CTRL_REQ_GO_IDLE = BIT(1), | 52 | CRB_CTRL_REQ_GO_IDLE = BIT(1), |
| @@ -52,18 +65,28 @@ enum crb_cancel { | |||
| 52 | CRB_CANCEL_INVOKE = BIT(0), | 65 | CRB_CANCEL_INVOKE = BIT(0), |
| 53 | }; | 66 | }; |
| 54 | 67 | ||
| 55 | struct crb_control_area { | 68 | struct crb_regs_head { |
| 56 | u32 req; | 69 | u32 loc_state; |
| 57 | u32 sts; | 70 | u32 reserved1; |
| 58 | u32 cancel; | 71 | u32 loc_ctrl; |
| 59 | u32 start; | 72 | u32 loc_sts; |
| 60 | u32 int_enable; | 73 | u8 reserved2[32]; |
| 61 | u32 int_sts; | 74 | u64 intf_id; |
| 62 | u32 cmd_size; | 75 | u64 ctrl_ext; |
| 63 | u32 cmd_pa_low; | 76 | } __packed; |
| 64 | u32 cmd_pa_high; | 77 | |
| 65 | u32 rsp_size; | 78 | struct crb_regs_tail { |
| 66 | u64 rsp_pa; | 79 | u32 ctrl_req; |
| 80 | u32 ctrl_sts; | ||
| 81 | u32 ctrl_cancel; | ||
| 82 | u32 ctrl_start; | ||
| 83 | u32 ctrl_int_enable; | ||
| 84 | u32 ctrl_int_sts; | ||
| 85 | u32 ctrl_cmd_size; | ||
| 86 | u32 ctrl_cmd_pa_low; | ||
| 87 | u32 ctrl_cmd_pa_high; | ||
| 88 | u32 ctrl_rsp_size; | ||
| 89 | u64 ctrl_rsp_pa; | ||
| 67 | } __packed; | 90 | } __packed; |
| 68 | 91 | ||
| 69 | enum crb_status { | 92 | enum crb_status { |
| @@ -73,15 +96,26 @@ enum crb_status { | |||
| 73 | enum crb_flags { | 96 | enum crb_flags { |
| 74 | CRB_FL_ACPI_START = BIT(0), | 97 | CRB_FL_ACPI_START = BIT(0), |
| 75 | CRB_FL_CRB_START = BIT(1), | 98 | CRB_FL_CRB_START = BIT(1), |
| 99 | CRB_FL_CRB_SMC_START = BIT(2), | ||
| 76 | }; | 100 | }; |
| 77 | 101 | ||
| 78 | struct crb_priv { | 102 | struct crb_priv { |
| 79 | unsigned int flags; | 103 | unsigned int flags; |
| 80 | void __iomem *iobase; | 104 | void __iomem *iobase; |
| 81 | struct crb_control_area __iomem *cca; | 105 | struct crb_regs_head __iomem *regs_h; |
| 106 | struct crb_regs_tail __iomem *regs_t; | ||
| 82 | u8 __iomem *cmd; | 107 | u8 __iomem *cmd; |
| 83 | u8 __iomem *rsp; | 108 | u8 __iomem *rsp; |
| 84 | u32 cmd_size; | 109 | u32 cmd_size; |
| 110 | u32 smc_func_id; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct tpm2_crb_smc { | ||
| 114 | u32 interrupt; | ||
| 115 | u8 interrupt_flags; | ||
| 116 | u8 op_flags; | ||
| 117 | u16 reserved2; | ||
| 118 | u32 smc_func_id; | ||
| 85 | }; | 119 | }; |
| 86 | 120 | ||
| 87 | /** | 121 | /** |
| @@ -101,15 +135,35 @@ struct crb_priv { | |||
| 101 | */ | 135 | */ |
| 102 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | 136 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) |
| 103 | { | 137 | { |
| 104 | if (priv->flags & CRB_FL_ACPI_START) | 138 | if ((priv->flags & CRB_FL_ACPI_START) || |
| 139 | (priv->flags & CRB_FL_CRB_SMC_START)) | ||
| 105 | return 0; | 140 | return 0; |
| 106 | 141 | ||
| 107 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req); | 142 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); |
| 108 | /* we don't really care when this settles */ | 143 | /* we don't really care when this settles */ |
| 109 | 144 | ||
| 110 | return 0; | 145 | return 0; |
| 111 | } | 146 | } |
| 112 | 147 | ||
| 148 | static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | ||
| 149 | unsigned long timeout) | ||
| 150 | { | ||
| 151 | ktime_t start; | ||
| 152 | ktime_t stop; | ||
| 153 | |||
| 154 | start = ktime_get(); | ||
| 155 | stop = ktime_add(start, ms_to_ktime(timeout)); | ||
| 156 | |||
| 157 | do { | ||
| 158 | if ((ioread32(reg) & mask) == value) | ||
| 159 | return true; | ||
| 160 | |||
| 161 | usleep_range(50, 100); | ||
| 162 | } while (ktime_before(ktime_get(), stop)); | ||
| 163 | |||
| 164 | return false; | ||
| 165 | } | ||
| 166 | |||
| 113 | /** | 167 | /** |
| 114 | * crb_cmd_ready - request tpm crb device to enter ready state | 168 | * crb_cmd_ready - request tpm crb device to enter ready state |
| 115 | * | 169 | * |
| @@ -127,35 +181,57 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | |||
| 127 | static int __maybe_unused crb_cmd_ready(struct device *dev, | 181 | static int __maybe_unused crb_cmd_ready(struct device *dev, |
| 128 | struct crb_priv *priv) | 182 | struct crb_priv *priv) |
| 129 | { | 183 | { |
| 130 | ktime_t stop, start; | 184 | if ((priv->flags & CRB_FL_ACPI_START) || |
| 131 | 185 | (priv->flags & CRB_FL_CRB_SMC_START)) | |
| 132 | if (priv->flags & CRB_FL_ACPI_START) | ||
| 133 | return 0; | 186 | return 0; |
| 134 | 187 | ||
| 135 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req); | 188 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); |
| 189 | if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, | ||
| 190 | CRB_CTRL_REQ_CMD_READY /* mask */, | ||
| 191 | 0, /* value */ | ||
| 192 | TPM2_TIMEOUT_C)) { | ||
| 193 | dev_warn(dev, "cmdReady timed out\n"); | ||
| 194 | return -ETIME; | ||
| 195 | } | ||
| 136 | 196 | ||
| 137 | start = ktime_get(); | 197 | return 0; |
| 138 | stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C)); | 198 | } |
| 139 | do { | ||
| 140 | if (!(ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY)) | ||
| 141 | return 0; | ||
| 142 | usleep_range(50, 100); | ||
| 143 | } while (ktime_before(ktime_get(), stop)); | ||
| 144 | 199 | ||
| 145 | if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) { | 200 | static int crb_request_locality(struct tpm_chip *chip, int loc) |
| 146 | dev_warn(dev, "cmdReady timed out\n"); | 201 | { |
| 202 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
| 203 | u32 value = CRB_LOC_STATE_LOC_ASSIGNED | | ||
| 204 | CRB_LOC_STATE_TPM_REG_VALID_STS; | ||
| 205 | |||
| 206 | if (!priv->regs_h) | ||
| 207 | return 0; | ||
| 208 | |||
| 209 | iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); | ||
| 210 | if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, | ||
| 211 | TPM2_TIMEOUT_C)) { | ||
| 212 | dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); | ||
| 147 | return -ETIME; | 213 | return -ETIME; |
| 148 | } | 214 | } |
| 149 | 215 | ||
| 150 | return 0; | 216 | return 0; |
| 151 | } | 217 | } |
| 152 | 218 | ||
| 219 | static void crb_relinquish_locality(struct tpm_chip *chip, int loc) | ||
| 220 | { | ||
| 221 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
| 222 | |||
| 223 | if (!priv->regs_h) | ||
| 224 | return; | ||
| 225 | |||
| 226 | iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); | ||
| 227 | } | ||
| 228 | |||
| 153 | static u8 crb_status(struct tpm_chip *chip) | 229 | static u8 crb_status(struct tpm_chip *chip) |
| 154 | { | 230 | { |
| 155 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 231 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| 156 | u8 sts = 0; | 232 | u8 sts = 0; |
| 157 | 233 | ||
| 158 | if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) != | 234 | if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) != |
| 159 | CRB_START_INVOKE) | 235 | CRB_START_INVOKE) |
| 160 | sts |= CRB_DRV_STS_COMPLETE; | 236 | sts |= CRB_DRV_STS_COMPLETE; |
| 161 | 237 | ||
| @@ -171,13 +247,12 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 171 | if (count < 6) | 247 | if (count < 6) |
| 172 | return -EIO; | 248 | return -EIO; |
| 173 | 249 | ||
| 174 | if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR) | 250 | if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR) |
| 175 | return -EIO; | 251 | return -EIO; |
| 176 | 252 | ||
| 177 | memcpy_fromio(buf, priv->rsp, 6); | 253 | memcpy_fromio(buf, priv->rsp, 6); |
| 178 | expected = be32_to_cpup((__be32 *) &buf[2]); | 254 | expected = be32_to_cpup((__be32 *) &buf[2]); |
| 179 | 255 | if (expected > count || expected < 6) | |
| 180 | if (expected > count) | ||
| 181 | return -EIO; | 256 | return -EIO; |
| 182 | 257 | ||
| 183 | memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); | 258 | memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); |
| @@ -202,6 +277,34 @@ static int crb_do_acpi_start(struct tpm_chip *chip) | |||
| 202 | return rc; | 277 | return rc; |
| 203 | } | 278 | } |
| 204 | 279 | ||
| 280 | #ifdef CONFIG_ARM64 | ||
| 281 | /* | ||
| 282 | * This is a TPM Command Response Buffer start method that invokes a | ||
| 283 | * Secure Monitor Call to requrest the firmware to execute or cancel | ||
| 284 | * a TPM 2.0 command. | ||
| 285 | */ | ||
| 286 | static int tpm_crb_smc_start(struct device *dev, unsigned long func_id) | ||
| 287 | { | ||
| 288 | struct arm_smccc_res res; | ||
| 289 | |||
| 290 | arm_smccc_smc(func_id, 0, 0, 0, 0, 0, 0, 0, &res); | ||
| 291 | if (res.a0 != 0) { | ||
| 292 | dev_err(dev, | ||
| 293 | FW_BUG "tpm_crb_smc_start() returns res.a0 = 0x%lx\n", | ||
| 294 | res.a0); | ||
| 295 | return -EIO; | ||
| 296 | } | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | #else | ||
| 301 | static int tpm_crb_smc_start(struct device *dev, unsigned long func_id) | ||
| 302 | { | ||
| 303 | dev_err(dev, FW_BUG "tpm_crb: incorrect start method\n"); | ||
| 304 | return -EINVAL; | ||
| 305 | } | ||
| 306 | #endif | ||
| 307 | |||
| 205 | static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | 308 | static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) |
| 206 | { | 309 | { |
| 207 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 310 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| @@ -210,7 +313,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 210 | /* Zero the cancel register so that the next command will not get | 313 | /* Zero the cancel register so that the next command will not get |
| 211 | * canceled. | 314 | * canceled. |
| 212 | */ | 315 | */ |
| 213 | iowrite32(0, &priv->cca->cancel); | 316 | iowrite32(0, &priv->regs_t->ctrl_cancel); |
| 214 | 317 | ||
| 215 | if (len > priv->cmd_size) { | 318 | if (len > priv->cmd_size) { |
| 216 | dev_err(&chip->dev, "invalid command count value %zd %d\n", | 319 | dev_err(&chip->dev, "invalid command count value %zd %d\n", |
| @@ -224,11 +327,16 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 224 | wmb(); | 327 | wmb(); |
| 225 | 328 | ||
| 226 | if (priv->flags & CRB_FL_CRB_START) | 329 | if (priv->flags & CRB_FL_CRB_START) |
| 227 | iowrite32(CRB_START_INVOKE, &priv->cca->start); | 330 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
| 228 | 331 | ||
| 229 | if (priv->flags & CRB_FL_ACPI_START) | 332 | if (priv->flags & CRB_FL_ACPI_START) |
| 230 | rc = crb_do_acpi_start(chip); | 333 | rc = crb_do_acpi_start(chip); |
| 231 | 334 | ||
| 335 | if (priv->flags & CRB_FL_CRB_SMC_START) { | ||
| 336 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | ||
| 337 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); | ||
| 338 | } | ||
| 339 | |||
| 232 | return rc; | 340 | return rc; |
| 233 | } | 341 | } |
| 234 | 342 | ||
| @@ -236,7 +344,7 @@ static void crb_cancel(struct tpm_chip *chip) | |||
| 236 | { | 344 | { |
| 237 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 345 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| 238 | 346 | ||
| 239 | iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel); | 347 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); |
| 240 | 348 | ||
| 241 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) | 349 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) |
| 242 | dev_err(&chip->dev, "ACPI Start failed\n"); | 350 | dev_err(&chip->dev, "ACPI Start failed\n"); |
| @@ -245,7 +353,7 @@ static void crb_cancel(struct tpm_chip *chip) | |||
| 245 | static bool crb_req_canceled(struct tpm_chip *chip, u8 status) | 353 | static bool crb_req_canceled(struct tpm_chip *chip, u8 status) |
| 246 | { | 354 | { |
| 247 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 355 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| 248 | u32 cancel = ioread32(&priv->cca->cancel); | 356 | u32 cancel = ioread32(&priv->regs_t->ctrl_cancel); |
| 249 | 357 | ||
| 250 | return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; | 358 | return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; |
| 251 | } | 359 | } |
| @@ -257,6 +365,8 @@ static const struct tpm_class_ops tpm_crb = { | |||
| 257 | .send = crb_send, | 365 | .send = crb_send, |
| 258 | .cancel = crb_cancel, | 366 | .cancel = crb_cancel, |
| 259 | .req_canceled = crb_req_canceled, | 367 | .req_canceled = crb_req_canceled, |
| 368 | .request_locality = crb_request_locality, | ||
| 369 | .relinquish_locality = crb_relinquish_locality, | ||
| 260 | .req_complete_mask = CRB_DRV_STS_COMPLETE, | 370 | .req_complete_mask = CRB_DRV_STS_COMPLETE, |
| 261 | .req_complete_val = CRB_DRV_STS_COMPLETE, | 371 | .req_complete_val = CRB_DRV_STS_COMPLETE, |
| 262 | }; | 372 | }; |
| @@ -295,6 +405,27 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, | |||
| 295 | return priv->iobase + (new_res.start - io_res->start); | 405 | return priv->iobase + (new_res.start - io_res->start); |
| 296 | } | 406 | } |
| 297 | 407 | ||
| 408 | /* | ||
| 409 | * Work around broken BIOSs that return inconsistent values from the ACPI | ||
| 410 | * region vs the registers. Trust the ACPI region. Such broken systems | ||
| 411 | * probably cannot send large TPM commands since the buffer will be truncated. | ||
| 412 | */ | ||
| 413 | static u64 crb_fixup_cmd_size(struct device *dev, struct resource *io_res, | ||
| 414 | u64 start, u64 size) | ||
| 415 | { | ||
| 416 | if (io_res->start > start || io_res->end < start) | ||
| 417 | return size; | ||
| 418 | |||
| 419 | if (start + size - 1 <= io_res->end) | ||
| 420 | return size; | ||
| 421 | |||
| 422 | dev_err(dev, | ||
| 423 | FW_BUG "ACPI region does not cover the entire command/response buffer. %pr vs %llx %llx\n", | ||
| 424 | io_res, start, size); | ||
| 425 | |||
| 426 | return io_res->end - start + 1; | ||
| 427 | } | ||
| 428 | |||
| 298 | static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | 429 | static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, |
| 299 | struct acpi_table_tpm2 *buf) | 430 | struct acpi_table_tpm2 *buf) |
| 300 | { | 431 | { |
| @@ -324,10 +455,22 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
| 324 | if (IS_ERR(priv->iobase)) | 455 | if (IS_ERR(priv->iobase)) |
| 325 | return PTR_ERR(priv->iobase); | 456 | return PTR_ERR(priv->iobase); |
| 326 | 457 | ||
| 327 | priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address, | 458 | /* The ACPI IO region starts at the head area and continues to include |
| 328 | sizeof(struct crb_control_area)); | 459 | * the control area, as one nice sane region except for some older |
| 329 | if (IS_ERR(priv->cca)) | 460 | * stuff that puts the control area outside the ACPI IO region. |
| 330 | return PTR_ERR(priv->cca); | 461 | */ |
| 462 | if (!(priv->flags & CRB_FL_ACPI_START)) { | ||
| 463 | if (buf->control_address == io_res.start + | ||
| 464 | sizeof(*priv->regs_h)) | ||
| 465 | priv->regs_h = priv->iobase; | ||
| 466 | else | ||
| 467 | dev_warn(dev, FW_BUG "Bad ACPI memory layout"); | ||
| 468 | } | ||
| 469 | |||
| 470 | priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, | ||
| 471 | sizeof(struct crb_regs_tail)); | ||
| 472 | if (IS_ERR(priv->regs_t)) | ||
| 473 | return PTR_ERR(priv->regs_t); | ||
| 331 | 474 | ||
| 332 | /* | 475 | /* |
| 333 | * PTT HW bug w/a: wake up the device to access | 476 | * PTT HW bug w/a: wake up the device to access |
| @@ -337,10 +480,11 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
| 337 | if (ret) | 480 | if (ret) |
| 338 | return ret; | 481 | return ret; |
| 339 | 482 | ||
| 340 | pa_high = ioread32(&priv->cca->cmd_pa_high); | 483 | pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high); |
| 341 | pa_low = ioread32(&priv->cca->cmd_pa_low); | 484 | pa_low = ioread32(&priv->regs_t->ctrl_cmd_pa_low); |
| 342 | cmd_pa = ((u64)pa_high << 32) | pa_low; | 485 | cmd_pa = ((u64)pa_high << 32) | pa_low; |
| 343 | cmd_size = ioread32(&priv->cca->cmd_size); | 486 | cmd_size = crb_fixup_cmd_size(dev, &io_res, cmd_pa, |
| 487 | ioread32(&priv->regs_t->ctrl_cmd_size)); | ||
| 344 | 488 | ||
| 345 | dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n", | 489 | dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n", |
| 346 | pa_high, pa_low, cmd_size); | 490 | pa_high, pa_low, cmd_size); |
| @@ -351,9 +495,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
| 351 | goto out; | 495 | goto out; |
| 352 | } | 496 | } |
| 353 | 497 | ||
| 354 | memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8); | 498 | memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); |
| 355 | rsp_pa = le64_to_cpu(rsp_pa); | 499 | rsp_pa = le64_to_cpu(rsp_pa); |
| 356 | rsp_size = ioread32(&priv->cca->rsp_size); | 500 | rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa, |
| 501 | ioread32(&priv->regs_t->ctrl_rsp_size)); | ||
| 357 | 502 | ||
| 358 | if (cmd_pa != rsp_pa) { | 503 | if (cmd_pa != rsp_pa) { |
| 359 | priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size); | 504 | priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size); |
| @@ -386,6 +531,7 @@ static int crb_acpi_add(struct acpi_device *device) | |||
| 386 | struct crb_priv *priv; | 531 | struct crb_priv *priv; |
| 387 | struct tpm_chip *chip; | 532 | struct tpm_chip *chip; |
| 388 | struct device *dev = &device->dev; | 533 | struct device *dev = &device->dev; |
| 534 | struct tpm2_crb_smc *crb_smc; | ||
| 389 | acpi_status status; | 535 | acpi_status status; |
| 390 | u32 sm; | 536 | u32 sm; |
| 391 | int rc; | 537 | int rc; |
| @@ -418,6 +564,19 @@ static int crb_acpi_add(struct acpi_device *device) | |||
| 418 | sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) | 564 | sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) |
| 419 | priv->flags |= CRB_FL_ACPI_START; | 565 | priv->flags |= CRB_FL_ACPI_START; |
| 420 | 566 | ||
| 567 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_SMC) { | ||
| 568 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { | ||
| 569 | dev_err(dev, | ||
| 570 | FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n", | ||
| 571 | buf->header.length, | ||
| 572 | ACPI_TPM2_COMMAND_BUFFER_WITH_SMC); | ||
| 573 | return -EINVAL; | ||
| 574 | } | ||
| 575 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); | ||
| 576 | priv->smc_func_id = crb_smc->smc_func_id; | ||
| 577 | priv->flags |= CRB_FL_CRB_SMC_START; | ||
| 578 | } | ||
| 579 | |||
| 421 | rc = crb_map_io(device, priv, buf); | 580 | rc = crb_map_io(device, priv, buf); |
| 422 | if (rc) | 581 | if (rc) |
| 423 | return rc; | 582 | return rc; |
| @@ -463,8 +622,7 @@ static int crb_acpi_remove(struct acpi_device *device) | |||
| 463 | return 0; | 622 | return 0; |
| 464 | } | 623 | } |
| 465 | 624 | ||
| 466 | #ifdef CONFIG_PM | 625 | static int __maybe_unused crb_pm_runtime_suspend(struct device *dev) |
| 467 | static int crb_pm_runtime_suspend(struct device *dev) | ||
| 468 | { | 626 | { |
| 469 | struct tpm_chip *chip = dev_get_drvdata(dev); | 627 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 470 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 628 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| @@ -472,17 +630,38 @@ static int crb_pm_runtime_suspend(struct device *dev) | |||
| 472 | return crb_go_idle(dev, priv); | 630 | return crb_go_idle(dev, priv); |
| 473 | } | 631 | } |
| 474 | 632 | ||
| 475 | static int crb_pm_runtime_resume(struct device *dev) | 633 | static int __maybe_unused crb_pm_runtime_resume(struct device *dev) |
| 476 | { | 634 | { |
| 477 | struct tpm_chip *chip = dev_get_drvdata(dev); | 635 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 478 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 636 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
| 479 | 637 | ||
| 480 | return crb_cmd_ready(dev, priv); | 638 | return crb_cmd_ready(dev, priv); |
| 481 | } | 639 | } |
| 482 | #endif /* CONFIG_PM */ | 640 | |
| 641 | static int __maybe_unused crb_pm_suspend(struct device *dev) | ||
| 642 | { | ||
| 643 | int ret; | ||
| 644 | |||
| 645 | ret = tpm_pm_suspend(dev); | ||
| 646 | if (ret) | ||
| 647 | return ret; | ||
| 648 | |||
| 649 | return crb_pm_runtime_suspend(dev); | ||
| 650 | } | ||
| 651 | |||
| 652 | static int __maybe_unused crb_pm_resume(struct device *dev) | ||
| 653 | { | ||
| 654 | int ret; | ||
| 655 | |||
| 656 | ret = crb_pm_runtime_resume(dev); | ||
| 657 | if (ret) | ||
| 658 | return ret; | ||
| 659 | |||
| 660 | return tpm_pm_resume(dev); | ||
| 661 | } | ||
| 483 | 662 | ||
| 484 | static const struct dev_pm_ops crb_pm = { | 663 | static const struct dev_pm_ops crb_pm = { |
| 485 | SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume) | 664 | SET_SYSTEM_SLEEP_PM_OPS(crb_pm_suspend, crb_pm_resume) |
| 486 | SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL) | 665 | SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL) |
| 487 | }; | 666 | }; |
| 488 | 667 | ||
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 62ee44e57ddc..dc47fa222a26 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
| @@ -278,22 +278,22 @@ enum tis_defaults { | |||
| 278 | #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) | 278 | #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) |
| 279 | #define TPM_DID_VID(l) (0x0006 | ((l) << 4)) | 279 | #define TPM_DID_VID(l) (0x0006 | ((l) << 4)) |
| 280 | 280 | ||
| 281 | static int check_locality(struct tpm_chip *chip, int loc) | 281 | static bool check_locality(struct tpm_chip *chip, int loc) |
| 282 | { | 282 | { |
| 283 | u8 buf; | 283 | u8 buf; |
| 284 | int rc; | 284 | int rc; |
| 285 | 285 | ||
| 286 | rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); | 286 | rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); |
| 287 | if (rc < 0) | 287 | if (rc < 0) |
| 288 | return rc; | 288 | return false; |
| 289 | 289 | ||
| 290 | if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | 290 | if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == |
| 291 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { | 291 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { |
| 292 | tpm_dev.locality = loc; | 292 | tpm_dev.locality = loc; |
| 293 | return loc; | 293 | return true; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | return -EIO; | 296 | return false; |
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | /* implementation similar to tpm_tis */ | 299 | /* implementation similar to tpm_tis */ |
| @@ -315,7 +315,7 @@ static int request_locality(struct tpm_chip *chip, int loc) | |||
| 315 | unsigned long stop; | 315 | unsigned long stop; |
| 316 | u8 buf = TPM_ACCESS_REQUEST_USE; | 316 | u8 buf = TPM_ACCESS_REQUEST_USE; |
| 317 | 317 | ||
| 318 | if (check_locality(chip, loc) >= 0) | 318 | if (check_locality(chip, loc)) |
| 319 | return loc; | 319 | return loc; |
| 320 | 320 | ||
| 321 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); | 321 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); |
| @@ -323,7 +323,7 @@ static int request_locality(struct tpm_chip *chip, int loc) | |||
| 323 | /* wait for burstcount */ | 323 | /* wait for burstcount */ |
| 324 | stop = jiffies + chip->timeout_a; | 324 | stop = jiffies + chip->timeout_a; |
| 325 | do { | 325 | do { |
| 326 | if (check_locality(chip, loc) >= 0) | 326 | if (check_locality(chip, loc)) |
| 327 | return loc; | 327 | return loc; |
| 328 | usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); | 328 | usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); |
| 329 | } while (time_before(jiffies, stop)); | 329 | } while (time_before(jiffies, stop)); |
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index e3a9155ee671..c6428771841f 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c | |||
| @@ -49,9 +49,10 @@ | |||
| 49 | */ | 49 | */ |
| 50 | #define TPM_I2C_MAX_BUF_SIZE 32 | 50 | #define TPM_I2C_MAX_BUF_SIZE 32 |
| 51 | #define TPM_I2C_RETRY_COUNT 32 | 51 | #define TPM_I2C_RETRY_COUNT 32 |
| 52 | #define TPM_I2C_BUS_DELAY 1 /* msec */ | 52 | #define TPM_I2C_BUS_DELAY 1000 /* usec */ |
| 53 | #define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */ | 53 | #define TPM_I2C_RETRY_DELAY_SHORT (2 * 1000) /* usec */ |
| 54 | #define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */ | 54 | #define TPM_I2C_RETRY_DELAY_LONG (10 * 1000) /* usec */ |
| 55 | #define TPM_I2C_DELAY_RANGE 300 /* usec */ | ||
| 55 | 56 | ||
| 56 | #define OF_IS_TPM2 ((void *)1) | 57 | #define OF_IS_TPM2 ((void *)1) |
| 57 | #define I2C_IS_TPM2 1 | 58 | #define I2C_IS_TPM2 1 |
| @@ -123,7 +124,9 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) | |||
| 123 | /* this causes the current command to be aborted */ | 124 | /* this causes the current command to be aborted */ |
| 124 | for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) { | 125 | for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) { |
| 125 | status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data); | 126 | status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data); |
| 126 | msleep(TPM_I2C_BUS_DELAY); | 127 | if (status < 0) |
| 128 | usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY | ||
| 129 | + TPM_I2C_DELAY_RANGE); | ||
| 127 | } | 130 | } |
| 128 | return status; | 131 | return status; |
| 129 | } | 132 | } |
| @@ -160,7 +163,8 @@ static int i2c_nuvoton_get_burstcount(struct i2c_client *client, | |||
| 160 | burst_count = min_t(u8, TPM_I2C_MAX_BUF_SIZE, data); | 163 | burst_count = min_t(u8, TPM_I2C_MAX_BUF_SIZE, data); |
| 161 | break; | 164 | break; |
| 162 | } | 165 | } |
| 163 | msleep(TPM_I2C_BUS_DELAY); | 166 | usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY |
| 167 | + TPM_I2C_DELAY_RANGE); | ||
| 164 | } while (time_before(jiffies, stop)); | 168 | } while (time_before(jiffies, stop)); |
| 165 | 169 | ||
| 166 | return burst_count; | 170 | return burst_count; |
| @@ -203,13 +207,17 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, | |||
| 203 | return 0; | 207 | return 0; |
| 204 | 208 | ||
| 205 | /* use polling to wait for the event */ | 209 | /* use polling to wait for the event */ |
| 206 | ten_msec = jiffies + msecs_to_jiffies(TPM_I2C_RETRY_DELAY_LONG); | 210 | ten_msec = jiffies + usecs_to_jiffies(TPM_I2C_RETRY_DELAY_LONG); |
| 207 | stop = jiffies + timeout; | 211 | stop = jiffies + timeout; |
| 208 | do { | 212 | do { |
| 209 | if (time_before(jiffies, ten_msec)) | 213 | if (time_before(jiffies, ten_msec)) |
| 210 | msleep(TPM_I2C_RETRY_DELAY_SHORT); | 214 | usleep_range(TPM_I2C_RETRY_DELAY_SHORT, |
| 215 | TPM_I2C_RETRY_DELAY_SHORT | ||
| 216 | + TPM_I2C_DELAY_RANGE); | ||
| 211 | else | 217 | else |
| 212 | msleep(TPM_I2C_RETRY_DELAY_LONG); | 218 | usleep_range(TPM_I2C_RETRY_DELAY_LONG, |
| 219 | TPM_I2C_RETRY_DELAY_LONG | ||
| 220 | + TPM_I2C_DELAY_RANGE); | ||
| 213 | status_valid = i2c_nuvoton_check_status(chip, mask, | 221 | status_valid = i2c_nuvoton_check_status(chip, mask, |
| 214 | value); | 222 | value); |
| 215 | if (status_valid) | 223 | if (status_valid) |
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 1b9d61ffe991..f01d083eced2 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
| @@ -299,6 +299,8 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | |||
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | kfree(ibmvtpm); | 301 | kfree(ibmvtpm); |
| 302 | /* For tpm_ibmvtpm_get_desired_dma */ | ||
| 303 | dev_set_drvdata(&vdev->dev, NULL); | ||
| 302 | 304 | ||
| 303 | return 0; | 305 | return 0; |
| 304 | } | 306 | } |
| @@ -313,14 +315,16 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | |||
| 313 | static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) | 315 | static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) |
| 314 | { | 316 | { |
| 315 | struct tpm_chip *chip = dev_get_drvdata(&vdev->dev); | 317 | struct tpm_chip *chip = dev_get_drvdata(&vdev->dev); |
| 316 | struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev); | 318 | struct ibmvtpm_dev *ibmvtpm; |
| 317 | 319 | ||
| 318 | /* | 320 | /* |
| 319 | * ibmvtpm initializes at probe time, so the data we are | 321 | * ibmvtpm initializes at probe time, so the data we are |
| 320 | * asking for may not be set yet. Estimate that 4K required | 322 | * asking for may not be set yet. Estimate that 4K required |
| 321 | * for TCE-mapped buffer in addition to CRQ. | 323 | * for TCE-mapped buffer in addition to CRQ. |
| 322 | */ | 324 | */ |
| 323 | if (!ibmvtpm) | 325 | if (chip) |
| 326 | ibmvtpm = dev_get_drvdata(&chip->dev); | ||
| 327 | else | ||
| 324 | return CRQ_RES_BUF_SIZE + PAGE_SIZE; | 328 | return CRQ_RES_BUF_SIZE + PAGE_SIZE; |
| 325 | 329 | ||
| 326 | return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; | 330 | return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index c0f296b5d413..b617b2eeb080 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
| @@ -56,7 +56,7 @@ static int wait_startup(struct tpm_chip *chip, int l) | |||
| 56 | return -1; | 56 | return -1; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static int check_locality(struct tpm_chip *chip, int l) | 59 | static bool check_locality(struct tpm_chip *chip, int l) |
| 60 | { | 60 | { |
| 61 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 61 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
| 62 | int rc; | 62 | int rc; |
| @@ -64,30 +64,22 @@ static int check_locality(struct tpm_chip *chip, int l) | |||
| 64 | 64 | ||
| 65 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | 65 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); |
| 66 | if (rc < 0) | 66 | if (rc < 0) |
| 67 | return rc; | 67 | return false; |
| 68 | 68 | ||
| 69 | if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | 69 | if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == |
| 70 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | 70 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { |
| 71 | return priv->locality = l; | 71 | priv->locality = l; |
| 72 | return true; | ||
| 73 | } | ||
| 72 | 74 | ||
| 73 | return -1; | 75 | return false; |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | static void release_locality(struct tpm_chip *chip, int l, int force) | 78 | static void release_locality(struct tpm_chip *chip, int l) |
| 77 | { | 79 | { |
| 78 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 80 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
| 79 | int rc; | ||
| 80 | u8 access; | ||
| 81 | |||
| 82 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | ||
| 83 | if (rc < 0) | ||
| 84 | return; | ||
| 85 | |||
| 86 | if (force || (access & | ||
| 87 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == | ||
| 88 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) | ||
| 89 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); | ||
| 90 | 81 | ||
| 82 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); | ||
| 91 | } | 83 | } |
| 92 | 84 | ||
| 93 | static int request_locality(struct tpm_chip *chip, int l) | 85 | static int request_locality(struct tpm_chip *chip, int l) |
| @@ -96,7 +88,7 @@ static int request_locality(struct tpm_chip *chip, int l) | |||
| 96 | unsigned long stop, timeout; | 88 | unsigned long stop, timeout; |
| 97 | long rc; | 89 | long rc; |
| 98 | 90 | ||
| 99 | if (check_locality(chip, l) >= 0) | 91 | if (check_locality(chip, l)) |
| 100 | return l; | 92 | return l; |
| 101 | 93 | ||
| 102 | rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE); | 94 | rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE); |
| @@ -112,7 +104,7 @@ again: | |||
| 112 | return -1; | 104 | return -1; |
| 113 | rc = wait_event_interruptible_timeout(priv->int_queue, | 105 | rc = wait_event_interruptible_timeout(priv->int_queue, |
| 114 | (check_locality | 106 | (check_locality |
| 115 | (chip, l) >= 0), | 107 | (chip, l)), |
| 116 | timeout); | 108 | timeout); |
| 117 | if (rc > 0) | 109 | if (rc > 0) |
| 118 | return l; | 110 | return l; |
| @@ -123,7 +115,7 @@ again: | |||
| 123 | } else { | 115 | } else { |
| 124 | /* wait for burstcount */ | 116 | /* wait for burstcount */ |
| 125 | do { | 117 | do { |
| 126 | if (check_locality(chip, l) >= 0) | 118 | if (check_locality(chip, l)) |
| 127 | return l; | 119 | return l; |
| 128 | msleep(TPM_TIMEOUT); | 120 | msleep(TPM_TIMEOUT); |
| 129 | } while (time_before(jiffies, stop)); | 121 | } while (time_before(jiffies, stop)); |
| @@ -160,8 +152,10 @@ static int get_burstcount(struct tpm_chip *chip) | |||
| 160 | u32 value; | 152 | u32 value; |
| 161 | 153 | ||
| 162 | /* wait for burstcount */ | 154 | /* wait for burstcount */ |
| 163 | /* which timeout value, spec has 2 answers (c & d) */ | 155 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
| 164 | stop = jiffies + chip->timeout_d; | 156 | stop = jiffies + chip->timeout_a; |
| 157 | else | ||
| 158 | stop = jiffies + chip->timeout_d; | ||
| 165 | do { | 159 | do { |
| 166 | rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); | 160 | rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); |
| 167 | if (rc < 0) | 161 | if (rc < 0) |
| @@ -250,7 +244,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 250 | 244 | ||
| 251 | out: | 245 | out: |
| 252 | tpm_tis_ready(chip); | 246 | tpm_tis_ready(chip); |
| 253 | release_locality(chip, priv->locality, 0); | ||
| 254 | return size; | 247 | return size; |
| 255 | } | 248 | } |
| 256 | 249 | ||
| @@ -266,9 +259,6 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 266 | size_t count = 0; | 259 | size_t count = 0; |
| 267 | bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; | 260 | bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; |
| 268 | 261 | ||
| 269 | if (request_locality(chip, 0) < 0) | ||
| 270 | return -EBUSY; | ||
| 271 | |||
| 272 | status = tpm_tis_status(chip); | 262 | status = tpm_tis_status(chip); |
| 273 | if ((status & TPM_STS_COMMAND_READY) == 0) { | 263 | if ((status & TPM_STS_COMMAND_READY) == 0) { |
| 274 | tpm_tis_ready(chip); | 264 | tpm_tis_ready(chip); |
| @@ -327,7 +317,6 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 327 | 317 | ||
| 328 | out_err: | 318 | out_err: |
| 329 | tpm_tis_ready(chip); | 319 | tpm_tis_ready(chip); |
| 330 | release_locality(chip, priv->locality, 0); | ||
| 331 | return rc; | 320 | return rc; |
| 332 | } | 321 | } |
| 333 | 322 | ||
| @@ -388,7 +377,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 388 | return len; | 377 | return len; |
| 389 | out_err: | 378 | out_err: |
| 390 | tpm_tis_ready(chip); | 379 | tpm_tis_ready(chip); |
| 391 | release_locality(chip, priv->locality, 0); | ||
| 392 | return rc; | 380 | return rc; |
| 393 | } | 381 | } |
| 394 | 382 | ||
| @@ -475,12 +463,14 @@ static int probe_itpm(struct tpm_chip *chip) | |||
| 475 | if (vendor != TPM_VID_INTEL) | 463 | if (vendor != TPM_VID_INTEL) |
| 476 | return 0; | 464 | return 0; |
| 477 | 465 | ||
| 466 | if (request_locality(chip, 0) != 0) | ||
| 467 | return -EBUSY; | ||
| 468 | |||
| 478 | rc = tpm_tis_send_data(chip, cmd_getticks, len); | 469 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
| 479 | if (rc == 0) | 470 | if (rc == 0) |
| 480 | goto out; | 471 | goto out; |
| 481 | 472 | ||
| 482 | tpm_tis_ready(chip); | 473 | tpm_tis_ready(chip); |
| 483 | release_locality(chip, priv->locality, 0); | ||
| 484 | 474 | ||
| 485 | priv->flags |= TPM_TIS_ITPM_WORKAROUND; | 475 | priv->flags |= TPM_TIS_ITPM_WORKAROUND; |
| 486 | 476 | ||
| @@ -494,7 +484,7 @@ static int probe_itpm(struct tpm_chip *chip) | |||
| 494 | 484 | ||
| 495 | out: | 485 | out: |
| 496 | tpm_tis_ready(chip); | 486 | tpm_tis_ready(chip); |
| 497 | release_locality(chip, priv->locality, 0); | 487 | release_locality(chip, priv->locality); |
| 498 | 488 | ||
| 499 | return rc; | 489 | return rc; |
| 500 | } | 490 | } |
| @@ -533,7 +523,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |||
| 533 | wake_up_interruptible(&priv->read_queue); | 523 | wake_up_interruptible(&priv->read_queue); |
| 534 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | 524 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) |
| 535 | for (i = 0; i < 5; i++) | 525 | for (i = 0; i < 5; i++) |
| 536 | if (check_locality(chip, i) >= 0) | 526 | if (check_locality(chip, i)) |
| 537 | break; | 527 | break; |
| 538 | if (interrupt & | 528 | if (interrupt & |
| 539 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | | 529 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | |
| @@ -668,7 +658,6 @@ void tpm_tis_remove(struct tpm_chip *chip) | |||
| 668 | interrupt = 0; | 658 | interrupt = 0; |
| 669 | 659 | ||
| 670 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); | 660 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); |
| 671 | release_locality(chip, priv->locality, 1); | ||
| 672 | } | 661 | } |
| 673 | EXPORT_SYMBOL_GPL(tpm_tis_remove); | 662 | EXPORT_SYMBOL_GPL(tpm_tis_remove); |
| 674 | 663 | ||
| @@ -682,6 +671,8 @@ static const struct tpm_class_ops tpm_tis = { | |||
| 682 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 671 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
| 683 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 672 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
| 684 | .req_canceled = tpm_tis_req_canceled, | 673 | .req_canceled = tpm_tis_req_canceled, |
| 674 | .request_locality = request_locality, | ||
| 675 | .relinquish_locality = release_locality, | ||
| 685 | }; | 676 | }; |
| 686 | 677 | ||
| 687 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | 678 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, |
| @@ -724,11 +715,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |||
| 724 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | 715 | intmask &= ~TPM_GLOBAL_INT_ENABLE; |
| 725 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | 716 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); |
| 726 | 717 | ||
| 727 | if (request_locality(chip, 0) != 0) { | ||
| 728 | rc = -ENODEV; | ||
| 729 | goto out_err; | ||
| 730 | } | ||
| 731 | |||
| 732 | rc = tpm2_probe(chip); | 718 | rc = tpm2_probe(chip); |
| 733 | if (rc) | 719 | if (rc) |
| 734 | goto out_err; | 720 | goto out_err; |
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 5292e5768a7e..88fe72ae967f 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c | |||
| @@ -47,8 +47,8 @@ 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 | ||
| 50 | u8 tx_buf[MAX_SPI_FRAMESIZE + 4]; | 50 | u8 tx_buf[4]; |
| 51 | u8 rx_buf[MAX_SPI_FRAMESIZE + 4]; | 51 | u8 rx_buf[4]; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) | 54 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) |
| @@ -56,122 +56,98 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da | |||
| 56 | return container_of(data, struct tpm_tis_spi_phy, priv); | 56 | return container_of(data, struct tpm_tis_spi_phy, priv); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, | 59 | static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, |
| 60 | u16 len, u8 *result) | 60 | u8 *buffer, u8 direction) |
| 61 | { | 61 | { |
| 62 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); | 62 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); |
| 63 | int ret, i; | 63 | int ret = 0; |
| 64 | int i; | ||
| 64 | struct spi_message m; | 65 | struct spi_message m; |
| 65 | struct spi_transfer spi_xfer = { | 66 | struct spi_transfer spi_xfer; |
| 66 | .tx_buf = phy->tx_buf, | 67 | u8 transfer_len; |
| 67 | .rx_buf = phy->rx_buf, | ||
| 68 | .len = 4, | ||
| 69 | }; | ||
| 70 | 68 | ||
| 71 | if (len > MAX_SPI_FRAMESIZE) | 69 | spi_bus_lock(phy->spi_device->master); |
| 72 | return -ENOMEM; | ||
| 73 | 70 | ||
| 74 | phy->tx_buf[0] = 0x80 | (len - 1); | 71 | while (len) { |
| 75 | phy->tx_buf[1] = 0xd4; | 72 | transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); |
| 76 | phy->tx_buf[2] = (addr >> 8) & 0xFF; | ||
| 77 | phy->tx_buf[3] = addr & 0xFF; | ||
| 78 | 73 | ||
| 79 | spi_xfer.cs_change = 1; | 74 | phy->tx_buf[0] = direction | (transfer_len - 1); |
| 80 | spi_message_init(&m); | 75 | phy->tx_buf[1] = 0xd4; |
| 81 | spi_message_add_tail(&spi_xfer, &m); | 76 | phy->tx_buf[2] = addr >> 8; |
| 77 | phy->tx_buf[3] = addr; | ||
| 78 | |||
| 79 | memset(&spi_xfer, 0, sizeof(spi_xfer)); | ||
| 80 | spi_xfer.tx_buf = phy->tx_buf; | ||
| 81 | spi_xfer.rx_buf = phy->rx_buf; | ||
| 82 | spi_xfer.len = 4; | ||
| 83 | spi_xfer.cs_change = 1; | ||
| 82 | 84 | ||
| 83 | spi_bus_lock(phy->spi_device->master); | ||
| 84 | ret = spi_sync_locked(phy->spi_device, &m); | ||
| 85 | if (ret < 0) | ||
| 86 | goto exit; | ||
| 87 | |||
| 88 | memset(phy->tx_buf, 0, len); | ||
| 89 | |||
| 90 | /* According to TCG PTP specification, if there is no TPM present at | ||
| 91 | * all, then the design has a weak pull-up on MISO. If a TPM is not | ||
| 92 | * present, a pull-up on MISO means that the SB controller sees a 1, | ||
| 93 | * and will latch in 0xFF on the read. | ||
| 94 | */ | ||
| 95 | for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) { | ||
| 96 | spi_xfer.len = 1; | ||
| 97 | spi_message_init(&m); | 85 | spi_message_init(&m); |
| 98 | spi_message_add_tail(&spi_xfer, &m); | 86 | spi_message_add_tail(&spi_xfer, &m); |
| 99 | ret = spi_sync_locked(phy->spi_device, &m); | 87 | ret = spi_sync_locked(phy->spi_device, &m); |
| 100 | if (ret < 0) | 88 | if (ret < 0) |
| 101 | goto exit; | 89 | goto exit; |
| 102 | } | ||
| 103 | |||
| 104 | spi_xfer.cs_change = 0; | ||
| 105 | spi_xfer.len = len; | ||
| 106 | spi_xfer.rx_buf = result; | ||
| 107 | |||
| 108 | spi_message_init(&m); | ||
| 109 | spi_message_add_tail(&spi_xfer, &m); | ||
| 110 | ret = spi_sync_locked(phy->spi_device, &m); | ||
| 111 | |||
| 112 | exit: | ||
| 113 | spi_bus_unlock(phy->spi_device->master); | ||
| 114 | return ret; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, | ||
| 118 | u16 len, u8 *value) | ||
| 119 | { | ||
| 120 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); | ||
| 121 | int ret, i; | ||
| 122 | struct spi_message m; | ||
| 123 | struct spi_transfer spi_xfer = { | ||
| 124 | .tx_buf = phy->tx_buf, | ||
| 125 | .rx_buf = phy->rx_buf, | ||
| 126 | .len = 4, | ||
| 127 | }; | ||
| 128 | |||
| 129 | if (len > MAX_SPI_FRAMESIZE) | ||
| 130 | return -ENOMEM; | ||
| 131 | |||
| 132 | phy->tx_buf[0] = len - 1; | ||
| 133 | phy->tx_buf[1] = 0xd4; | ||
| 134 | phy->tx_buf[2] = (addr >> 8) & 0xFF; | ||
| 135 | phy->tx_buf[3] = addr & 0xFF; | ||
| 136 | 90 | ||
| 137 | spi_xfer.cs_change = 1; | 91 | if ((phy->rx_buf[3] & 0x01) == 0) { |
| 138 | spi_message_init(&m); | 92 | // handle SPI wait states |
| 139 | spi_message_add_tail(&spi_xfer, &m); | 93 | phy->tx_buf[0] = 0; |
| 94 | |||
| 95 | for (i = 0; i < TPM_RETRY; i++) { | ||
| 96 | spi_xfer.len = 1; | ||
| 97 | spi_message_init(&m); | ||
| 98 | spi_message_add_tail(&spi_xfer, &m); | ||
| 99 | ret = spi_sync_locked(phy->spi_device, &m); | ||
| 100 | if (ret < 0) | ||
| 101 | goto exit; | ||
| 102 | if (phy->rx_buf[0] & 0x01) | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | |||
| 106 | if (i == TPM_RETRY) { | ||
| 107 | ret = -ETIMEDOUT; | ||
| 108 | goto exit; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | spi_xfer.cs_change = 0; | ||
| 113 | spi_xfer.len = transfer_len; | ||
| 114 | spi_xfer.delay_usecs = 5; | ||
| 115 | |||
| 116 | if (direction) { | ||
| 117 | spi_xfer.tx_buf = NULL; | ||
| 118 | spi_xfer.rx_buf = buffer; | ||
| 119 | } else { | ||
| 120 | spi_xfer.tx_buf = buffer; | ||
| 121 | spi_xfer.rx_buf = NULL; | ||
| 122 | } | ||
| 140 | 123 | ||
| 141 | spi_bus_lock(phy->spi_device->master); | ||
| 142 | ret = spi_sync_locked(phy->spi_device, &m); | ||
| 143 | if (ret < 0) | ||
| 144 | goto exit; | ||
| 145 | |||
| 146 | memset(phy->tx_buf, 0, len); | ||
| 147 | |||
| 148 | /* According to TCG PTP specification, if there is no TPM present at | ||
| 149 | * all, then the design has a weak pull-up on MISO. If a TPM is not | ||
| 150 | * present, a pull-up on MISO means that the SB controller sees a 1, | ||
| 151 | * and will latch in 0xFF on the read. | ||
| 152 | */ | ||
| 153 | for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) { | ||
| 154 | spi_xfer.len = 1; | ||
| 155 | spi_message_init(&m); | 124 | spi_message_init(&m); |
| 156 | spi_message_add_tail(&spi_xfer, &m); | 125 | spi_message_add_tail(&spi_xfer, &m); |
| 157 | ret = spi_sync_locked(phy->spi_device, &m); | 126 | ret = spi_sync_locked(phy->spi_device, &m); |
| 158 | if (ret < 0) | 127 | if (ret < 0) |
| 159 | goto exit; | 128 | goto exit; |
| 160 | } | ||
| 161 | 129 | ||
| 162 | spi_xfer.len = len; | 130 | len -= transfer_len; |
| 163 | spi_xfer.tx_buf = value; | 131 | buffer += transfer_len; |
| 164 | spi_xfer.cs_change = 0; | 132 | } |
| 165 | spi_xfer.tx_buf = value; | ||
| 166 | spi_message_init(&m); | ||
| 167 | spi_message_add_tail(&spi_xfer, &m); | ||
| 168 | ret = spi_sync_locked(phy->spi_device, &m); | ||
| 169 | 133 | ||
| 170 | exit: | 134 | exit: |
| 171 | spi_bus_unlock(phy->spi_device->master); | 135 | spi_bus_unlock(phy->spi_device->master); |
| 172 | return ret; | 136 | return ret; |
| 173 | } | 137 | } |
| 174 | 138 | ||
| 139 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, | ||
| 140 | u16 len, u8 *result) | ||
| 141 | { | ||
| 142 | return tpm_tis_spi_transfer(data, addr, len, result, 0x80); | ||
| 143 | } | ||
| 144 | |||
| 145 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, | ||
| 146 | u16 len, u8 *value) | ||
| 147 | { | ||
| 148 | return tpm_tis_spi_transfer(data, addr, len, value, 0); | ||
| 149 | } | ||
| 150 | |||
| 175 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | 151 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) |
| 176 | { | 152 | { |
| 177 | int rc; | 153 | int rc; |
diff --git a/drivers/char/tpm/tpmrm-dev.c b/drivers/char/tpm/tpmrm-dev.c new file mode 100644 index 000000000000..c636e7fdd1f5 --- /dev/null +++ b/drivers/char/tpm/tpmrm-dev.c | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 James.Bottomley@HansenPartnership.com | ||
| 3 | * | ||
| 4 | * GPLv2 | ||
| 5 | */ | ||
| 6 | #include <linux/slab.h> | ||
| 7 | #include "tpm-dev.h" | ||
| 8 | |||
| 9 | struct tpmrm_priv { | ||
| 10 | struct file_priv priv; | ||
| 11 | struct tpm_space space; | ||
| 12 | }; | ||
| 13 | |||
| 14 | static int tpmrm_open(struct inode *inode, struct file *file) | ||
| 15 | { | ||
| 16 | struct tpm_chip *chip; | ||
| 17 | struct tpmrm_priv *priv; | ||
| 18 | int rc; | ||
| 19 | |||
| 20 | chip = container_of(inode->i_cdev, struct tpm_chip, cdevs); | ||
| 21 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 22 | if (priv == NULL) | ||
| 23 | return -ENOMEM; | ||
| 24 | |||
| 25 | rc = tpm2_init_space(&priv->space); | ||
| 26 | if (rc) { | ||
| 27 | kfree(priv); | ||
| 28 | return -ENOMEM; | ||
| 29 | } | ||
| 30 | |||
| 31 | tpm_common_open(file, chip, &priv->priv); | ||
| 32 | |||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | static int tpmrm_release(struct inode *inode, struct file *file) | ||
| 37 | { | ||
| 38 | struct file_priv *fpriv = file->private_data; | ||
| 39 | struct tpmrm_priv *priv = container_of(fpriv, struct tpmrm_priv, priv); | ||
| 40 | |||
| 41 | tpm_common_release(file, fpriv); | ||
| 42 | tpm2_del_space(fpriv->chip, &priv->space); | ||
| 43 | kfree(priv); | ||
| 44 | |||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | ssize_t tpmrm_write(struct file *file, const char __user *buf, | ||
| 49 | size_t size, loff_t *off) | ||
| 50 | { | ||
| 51 | struct file_priv *fpriv = file->private_data; | ||
| 52 | struct tpmrm_priv *priv = container_of(fpriv, struct tpmrm_priv, priv); | ||
| 53 | |||
| 54 | return tpm_common_write(file, buf, size, off, &priv->space); | ||
| 55 | } | ||
| 56 | |||
| 57 | const struct file_operations tpmrm_fops = { | ||
| 58 | .owner = THIS_MODULE, | ||
| 59 | .llseek = no_llseek, | ||
| 60 | .open = tpmrm_open, | ||
| 61 | .read = tpm_common_read, | ||
| 62 | .write = tpmrm_write, | ||
| 63 | .release = tpmrm_release, | ||
| 64 | }; | ||
| 65 | |||
diff --git a/fs/namei.c b/fs/namei.c index 19dcf62133cc..9a7f8bd748d8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -340,22 +340,14 @@ int generic_permission(struct inode *inode, int mask) | |||
| 340 | 340 | ||
| 341 | if (S_ISDIR(inode->i_mode)) { | 341 | if (S_ISDIR(inode->i_mode)) { |
| 342 | /* DACs are overridable for directories */ | 342 | /* DACs are overridable for directories */ |
| 343 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) | ||
| 344 | return 0; | ||
| 345 | if (!(mask & MAY_WRITE)) | 343 | if (!(mask & MAY_WRITE)) |
| 346 | if (capable_wrt_inode_uidgid(inode, | 344 | if (capable_wrt_inode_uidgid(inode, |
| 347 | CAP_DAC_READ_SEARCH)) | 345 | CAP_DAC_READ_SEARCH)) |
| 348 | return 0; | 346 | return 0; |
| 349 | return -EACCES; | ||
| 350 | } | ||
| 351 | /* | ||
| 352 | * Read/write DACs are always overridable. | ||
| 353 | * Executable DACs are overridable when there is | ||
| 354 | * at least one exec bit set. | ||
| 355 | */ | ||
| 356 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) | ||
| 357 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) | 347 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) |
| 358 | return 0; | 348 | return 0; |
| 349 | return -EACCES; | ||
| 350 | } | ||
| 359 | 351 | ||
| 360 | /* | 352 | /* |
| 361 | * Searching includes executable on directories, else just read. | 353 | * Searching includes executable on directories, else just read. |
| @@ -364,6 +356,14 @@ int generic_permission(struct inode *inode, int mask) | |||
| 364 | if (mask == MAY_READ) | 356 | if (mask == MAY_READ) |
| 365 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH)) | 357 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH)) |
| 366 | return 0; | 358 | return 0; |
| 359 | /* | ||
| 360 | * Read/write DACs are always overridable. | ||
| 361 | * Executable DACs are overridable when there is | ||
| 362 | * at least one exec bit set. | ||
| 363 | */ | ||
| 364 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) | ||
| 365 | if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) | ||
| 366 | return 0; | ||
| 367 | 367 | ||
| 368 | return -EACCES; | 368 | return -EACCES; |
| 369 | } | 369 | } |
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 7aee9fb3bd1f..0ff3c64ce924 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h | |||
| @@ -1294,6 +1294,7 @@ struct acpi_table_tpm2 { | |||
| 1294 | #define ACPI_TPM2_MEMORY_MAPPED 6 | 1294 | #define ACPI_TPM2_MEMORY_MAPPED 6 |
| 1295 | #define ACPI_TPM2_COMMAND_BUFFER 7 | 1295 | #define ACPI_TPM2_COMMAND_BUFFER 7 |
| 1296 | #define ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD 8 | 1296 | #define ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD 8 |
| 1297 | #define ACPI_TPM2_COMMAND_BUFFER_WITH_SMC 11 | ||
| 1297 | 1298 | ||
| 1298 | /******************************************************************************* | 1299 | /******************************************************************************* |
| 1299 | * | 1300 | * |
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 882ca0e1e7a5..e0b681a717ba 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h | |||
| @@ -50,9 +50,20 @@ struct key; | |||
| 50 | struct key_type; | 50 | struct key_type; |
| 51 | union key_payload; | 51 | union key_payload; |
| 52 | 52 | ||
| 53 | extern int restrict_link_by_signature(struct key *trust_keyring, | 53 | extern int restrict_link_by_signature(struct key *dest_keyring, |
| 54 | const struct key_type *type, | 54 | const struct key_type *type, |
| 55 | const union key_payload *payload); | 55 | const union key_payload *payload, |
| 56 | struct key *trust_keyring); | ||
| 57 | |||
| 58 | extern int restrict_link_by_key_or_keyring(struct key *dest_keyring, | ||
| 59 | const struct key_type *type, | ||
| 60 | const union key_payload *payload, | ||
| 61 | struct key *trusted); | ||
| 62 | |||
| 63 | extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring, | ||
| 64 | const struct key_type *type, | ||
| 65 | const union key_payload *payload, | ||
| 66 | struct key *trusted); | ||
| 56 | 67 | ||
| 57 | extern int verify_signature(const struct key *key, | 68 | extern int verify_signature(const struct key *key, |
| 58 | const struct public_key_signature *sig); | 69 | const struct public_key_signature *sig); |
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index fbd4647767e9..359c2f936004 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h | |||
| @@ -18,7 +18,8 @@ | |||
| 18 | 18 | ||
| 19 | extern int restrict_link_by_builtin_trusted(struct key *keyring, | 19 | extern int restrict_link_by_builtin_trusted(struct key *keyring, |
| 20 | const struct key_type *type, | 20 | const struct key_type *type, |
| 21 | const union key_payload *payload); | 21 | const union key_payload *payload, |
| 22 | struct key *restriction_key); | ||
| 22 | 23 | ||
| 23 | #else | 24 | #else |
| 24 | #define restrict_link_by_builtin_trusted restrict_link_reject | 25 | #define restrict_link_by_builtin_trusted restrict_link_reject |
| @@ -28,11 +29,24 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring, | |||
| 28 | extern int restrict_link_by_builtin_and_secondary_trusted( | 29 | extern int restrict_link_by_builtin_and_secondary_trusted( |
| 29 | struct key *keyring, | 30 | struct key *keyring, |
| 30 | const struct key_type *type, | 31 | const struct key_type *type, |
| 31 | const union key_payload *payload); | 32 | const union key_payload *payload, |
| 33 | struct key *restriction_key); | ||
| 32 | #else | 34 | #else |
| 33 | #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted | 35 | #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted |
| 34 | #endif | 36 | #endif |
| 35 | 37 | ||
| 38 | #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING | ||
| 39 | extern int mark_hash_blacklisted(const char *hash); | ||
| 40 | extern int is_hash_blacklisted(const u8 *hash, size_t hash_len, | ||
| 41 | const char *type); | ||
| 42 | #else | ||
| 43 | static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len, | ||
| 44 | const char *type) | ||
| 45 | { | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | #endif | ||
| 49 | |||
| 36 | #ifdef CONFIG_IMA_BLACKLIST_KEYRING | 50 | #ifdef CONFIG_IMA_BLACKLIST_KEYRING |
| 37 | extern struct key *ima_blacklist_keyring; | 51 | extern struct key *ima_blacklist_keyring; |
| 38 | 52 | ||
diff --git a/include/linux/compat.h b/include/linux/compat.h index 8172b03685f9..1c5f3152cbb5 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -295,6 +295,13 @@ struct compat_old_sigaction { | |||
| 295 | }; | 295 | }; |
| 296 | #endif | 296 | #endif |
| 297 | 297 | ||
| 298 | struct compat_keyctl_kdf_params { | ||
| 299 | compat_uptr_t hashname; | ||
| 300 | compat_uptr_t otherinfo; | ||
| 301 | __u32 otherinfolen; | ||
| 302 | __u32 __spare[8]; | ||
| 303 | }; | ||
| 304 | |||
| 298 | struct compat_statfs; | 305 | struct compat_statfs; |
| 299 | struct compat_statfs64; | 306 | struct compat_statfs64; |
| 300 | struct compat_old_linux_dirent; | 307 | struct compat_old_linux_dirent; |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 82be96564266..e049526bc188 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -219,6 +219,12 @@ extern struct cred init_cred; | |||
| 219 | # define INIT_TASK_TI(tsk) | 219 | # define INIT_TASK_TI(tsk) |
| 220 | #endif | 220 | #endif |
| 221 | 221 | ||
| 222 | #ifdef CONFIG_SECURITY | ||
| 223 | #define INIT_TASK_SECURITY .security = NULL, | ||
| 224 | #else | ||
| 225 | #define INIT_TASK_SECURITY | ||
| 226 | #endif | ||
| 227 | |||
| 222 | /* | 228 | /* |
| 223 | * INIT_TASK is used to set up the first task table, touch at | 229 | * INIT_TASK is used to set up the first task table, touch at |
| 224 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 230 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
| @@ -298,6 +304,7 @@ extern struct cred init_cred; | |||
| 298 | INIT_NUMA_BALANCING(tsk) \ | 304 | INIT_NUMA_BALANCING(tsk) \ |
| 299 | INIT_KASAN(tsk) \ | 305 | INIT_KASAN(tsk) \ |
| 300 | INIT_LIVEPATCH(tsk) \ | 306 | INIT_LIVEPATCH(tsk) \ |
| 307 | INIT_TASK_SECURITY \ | ||
| 301 | } | 308 | } |
| 302 | 309 | ||
| 303 | 310 | ||
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index eaee981c5558..8496cf64575c 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h | |||
| @@ -147,6 +147,14 @@ struct key_type { | |||
| 147 | */ | 147 | */ |
| 148 | request_key_actor_t request_key; | 148 | request_key_actor_t request_key; |
| 149 | 149 | ||
| 150 | /* Look up a keyring access restriction (optional) | ||
| 151 | * | ||
| 152 | * - NULL is a valid return value (meaning the requested restriction | ||
| 153 | * is known but will never block addition of a key) | ||
| 154 | * - should return -EINVAL if the restriction is unknown | ||
| 155 | */ | ||
| 156 | struct key_restriction *(*lookup_restriction)(const char *params); | ||
| 157 | |||
| 150 | /* internal fields */ | 158 | /* internal fields */ |
| 151 | struct list_head link; /* link in types list */ | 159 | struct list_head link; /* link in types list */ |
| 152 | struct lock_class_key lock_class; /* key->sem lock class */ | 160 | struct lock_class_key lock_class; /* key->sem lock class */ |
diff --git a/include/linux/key.h b/include/linux/key.h index e45212f2777e..0c9b93b0d1f7 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/rwsem.h> | 23 | #include <linux/rwsem.h> |
| 24 | #include <linux/atomic.h> | 24 | #include <linux/atomic.h> |
| 25 | #include <linux/assoc_array.h> | 25 | #include <linux/assoc_array.h> |
| 26 | #include <linux/refcount.h> | ||
| 26 | 27 | ||
| 27 | #ifdef __KERNEL__ | 28 | #ifdef __KERNEL__ |
| 28 | #include <linux/uidgid.h> | 29 | #include <linux/uidgid.h> |
| @@ -126,6 +127,17 @@ static inline bool is_key_possessed(const key_ref_t key_ref) | |||
| 126 | return (unsigned long) key_ref & 1UL; | 127 | return (unsigned long) key_ref & 1UL; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 130 | typedef int (*key_restrict_link_func_t)(struct key *dest_keyring, | ||
| 131 | const struct key_type *type, | ||
| 132 | const union key_payload *payload, | ||
| 133 | struct key *restriction_key); | ||
| 134 | |||
| 135 | struct key_restriction { | ||
| 136 | key_restrict_link_func_t check; | ||
| 137 | struct key *key; | ||
| 138 | struct key_type *keytype; | ||
| 139 | }; | ||
| 140 | |||
| 129 | /*****************************************************************************/ | 141 | /*****************************************************************************/ |
| 130 | /* | 142 | /* |
| 131 | * authentication token / access credential / keyring | 143 | * authentication token / access credential / keyring |
| @@ -135,7 +147,7 @@ static inline bool is_key_possessed(const key_ref_t key_ref) | |||
| 135 | * - Kerberos TGTs and tickets | 147 | * - Kerberos TGTs and tickets |
| 136 | */ | 148 | */ |
| 137 | struct key { | 149 | struct key { |
| 138 | atomic_t usage; /* number of references */ | 150 | refcount_t usage; /* number of references */ |
| 139 | key_serial_t serial; /* key serial number */ | 151 | key_serial_t serial; /* key serial number */ |
| 140 | union { | 152 | union { |
| 141 | struct list_head graveyard_link; | 153 | struct list_head graveyard_link; |
| @@ -205,18 +217,17 @@ struct key { | |||
| 205 | }; | 217 | }; |
| 206 | 218 | ||
| 207 | /* This is set on a keyring to restrict the addition of a link to a key | 219 | /* This is set on a keyring to restrict the addition of a link to a key |
| 208 | * to it. If this method isn't provided then it is assumed that the | 220 | * to it. If this structure isn't provided then it is assumed that the |
| 209 | * keyring is open to any addition. It is ignored for non-keyring | 221 | * keyring is open to any addition. It is ignored for non-keyring |
| 210 | * keys. | 222 | * keys. Only set this value using keyring_restrict(), keyring_alloc(), |
| 223 | * or key_alloc(). | ||
| 211 | * | 224 | * |
| 212 | * This is intended for use with rings of trusted keys whereby addition | 225 | * This is intended for use with rings of trusted keys whereby addition |
| 213 | * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION | 226 | * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION |
| 214 | * overrides this, allowing the kernel to add extra keys without | 227 | * overrides this, allowing the kernel to add extra keys without |
| 215 | * restriction. | 228 | * restriction. |
| 216 | */ | 229 | */ |
| 217 | int (*restrict_link)(struct key *keyring, | 230 | struct key_restriction *restrict_link; |
| 218 | const struct key_type *type, | ||
| 219 | const union key_payload *payload); | ||
| 220 | }; | 231 | }; |
| 221 | 232 | ||
| 222 | extern struct key *key_alloc(struct key_type *type, | 233 | extern struct key *key_alloc(struct key_type *type, |
| @@ -225,9 +236,7 @@ extern struct key *key_alloc(struct key_type *type, | |||
| 225 | const struct cred *cred, | 236 | const struct cred *cred, |
| 226 | key_perm_t perm, | 237 | key_perm_t perm, |
| 227 | unsigned long flags, | 238 | unsigned long flags, |
| 228 | int (*restrict_link)(struct key *, | 239 | struct key_restriction *restrict_link); |
| 229 | const struct key_type *, | ||
| 230 | const union key_payload *)); | ||
| 231 | 240 | ||
| 232 | 241 | ||
| 233 | #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ | 242 | #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ |
| @@ -242,7 +251,7 @@ extern void key_put(struct key *key); | |||
| 242 | 251 | ||
| 243 | static inline struct key *__key_get(struct key *key) | 252 | static inline struct key *__key_get(struct key *key) |
| 244 | { | 253 | { |
| 245 | atomic_inc(&key->usage); | 254 | refcount_inc(&key->usage); |
| 246 | return key; | 255 | return key; |
| 247 | } | 256 | } |
| 248 | 257 | ||
| @@ -303,14 +312,13 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid | |||
| 303 | const struct cred *cred, | 312 | const struct cred *cred, |
| 304 | key_perm_t perm, | 313 | key_perm_t perm, |
| 305 | unsigned long flags, | 314 | unsigned long flags, |
| 306 | int (*restrict_link)(struct key *, | 315 | struct key_restriction *restrict_link, |
| 307 | const struct key_type *, | ||
| 308 | const union key_payload *), | ||
| 309 | struct key *dest); | 316 | struct key *dest); |
| 310 | 317 | ||
| 311 | extern int restrict_link_reject(struct key *keyring, | 318 | extern int restrict_link_reject(struct key *keyring, |
| 312 | const struct key_type *type, | 319 | const struct key_type *type, |
| 313 | const union key_payload *payload); | 320 | const union key_payload *payload, |
| 321 | struct key *restriction_key); | ||
| 314 | 322 | ||
| 315 | extern int keyring_clear(struct key *keyring); | 323 | extern int keyring_clear(struct key *keyring); |
| 316 | 324 | ||
| @@ -321,6 +329,9 @@ extern key_ref_t keyring_search(key_ref_t keyring, | |||
| 321 | extern int keyring_add_key(struct key *keyring, | 329 | extern int keyring_add_key(struct key *keyring, |
| 322 | struct key *key); | 330 | struct key *key); |
| 323 | 331 | ||
| 332 | extern int keyring_restrict(key_ref_t keyring, const char *type, | ||
| 333 | const char *restriction); | ||
| 334 | |||
| 324 | extern struct key *key_lookup(key_serial_t id); | 335 | extern struct key *key_lookup(key_serial_t id); |
| 325 | 336 | ||
| 326 | static inline key_serial_t key_serial(const struct key *key) | 337 | static inline key_serial_t key_serial(const struct key *key) |
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e29d4c62a3c8..080f34e66017 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
| @@ -533,8 +533,13 @@ | |||
| 533 | * manual page for definitions of the @clone_flags. | 533 | * manual page for definitions of the @clone_flags. |
| 534 | * @clone_flags contains the flags indicating what should be shared. | 534 | * @clone_flags contains the flags indicating what should be shared. |
| 535 | * Return 0 if permission is granted. | 535 | * Return 0 if permission is granted. |
| 536 | * @task_alloc: | ||
| 537 | * @task task being allocated. | ||
| 538 | * @clone_flags contains the flags indicating what should be shared. | ||
| 539 | * Handle allocation of task-related resources. | ||
| 540 | * Returns a zero on success, negative values on failure. | ||
| 536 | * @task_free: | 541 | * @task_free: |
| 537 | * @task task being freed | 542 | * @task task about to be freed. |
| 538 | * Handle release of task-related resources. (Note that this can be called | 543 | * Handle release of task-related resources. (Note that this can be called |
| 539 | * from interrupt context.) | 544 | * from interrupt context.) |
| 540 | * @cred_alloc_blank: | 545 | * @cred_alloc_blank: |
| @@ -630,10 +635,19 @@ | |||
| 630 | * Check permission before getting the ioprio value of @p. | 635 | * Check permission before getting the ioprio value of @p. |
| 631 | * @p contains the task_struct of process. | 636 | * @p contains the task_struct of process. |
| 632 | * Return 0 if permission is granted. | 637 | * Return 0 if permission is granted. |
| 638 | * @task_prlimit: | ||
| 639 | * Check permission before getting and/or setting the resource limits of | ||
| 640 | * another task. | ||
| 641 | * @cred points to the cred structure for the current task. | ||
| 642 | * @tcred points to the cred structure for the target task. | ||
| 643 | * @flags contains the LSM_PRLIMIT_* flag bits indicating whether the | ||
| 644 | * resource limits are being read, modified, or both. | ||
| 645 | * Return 0 if permission is granted. | ||
| 633 | * @task_setrlimit: | 646 | * @task_setrlimit: |
| 634 | * Check permission before setting the resource limits of the current | 647 | * Check permission before setting the resource limits of process @p |
| 635 | * process for @resource to @new_rlim. The old resource limit values can | 648 | * for @resource to @new_rlim. The old resource limit values can |
| 636 | * be examined by dereferencing (current->signal->rlim + resource). | 649 | * be examined by dereferencing (p->signal->rlim + resource). |
| 650 | * @p points to the task_struct for the target task's group leader. | ||
| 637 | * @resource contains the resource whose limit is being set. | 651 | * @resource contains the resource whose limit is being set. |
| 638 | * @new_rlim contains the new limits for @resource. | 652 | * @new_rlim contains the new limits for @resource. |
| 639 | * Return 0 if permission is granted. | 653 | * Return 0 if permission is granted. |
| @@ -1473,6 +1487,7 @@ union security_list_options { | |||
| 1473 | int (*file_open)(struct file *file, const struct cred *cred); | 1487 | int (*file_open)(struct file *file, const struct cred *cred); |
| 1474 | 1488 | ||
| 1475 | int (*task_create)(unsigned long clone_flags); | 1489 | int (*task_create)(unsigned long clone_flags); |
| 1490 | int (*task_alloc)(struct task_struct *task, unsigned long clone_flags); | ||
| 1476 | void (*task_free)(struct task_struct *task); | 1491 | void (*task_free)(struct task_struct *task); |
| 1477 | int (*cred_alloc_blank)(struct cred *cred, gfp_t gfp); | 1492 | int (*cred_alloc_blank)(struct cred *cred, gfp_t gfp); |
| 1478 | void (*cred_free)(struct cred *cred); | 1493 | void (*cred_free)(struct cred *cred); |
| @@ -1494,6 +1509,8 @@ union security_list_options { | |||
| 1494 | int (*task_setnice)(struct task_struct *p, int nice); | 1509 | int (*task_setnice)(struct task_struct *p, int nice); |
| 1495 | int (*task_setioprio)(struct task_struct *p, int ioprio); | 1510 | int (*task_setioprio)(struct task_struct *p, int ioprio); |
| 1496 | int (*task_getioprio)(struct task_struct *p); | 1511 | int (*task_getioprio)(struct task_struct *p); |
| 1512 | int (*task_prlimit)(const struct cred *cred, const struct cred *tcred, | ||
| 1513 | unsigned int flags); | ||
| 1497 | int (*task_setrlimit)(struct task_struct *p, unsigned int resource, | 1514 | int (*task_setrlimit)(struct task_struct *p, unsigned int resource, |
| 1498 | struct rlimit *new_rlim); | 1515 | struct rlimit *new_rlim); |
| 1499 | int (*task_setscheduler)(struct task_struct *p); | 1516 | int (*task_setscheduler)(struct task_struct *p); |
| @@ -1737,6 +1754,7 @@ struct security_hook_heads { | |||
| 1737 | struct list_head file_receive; | 1754 | struct list_head file_receive; |
| 1738 | struct list_head file_open; | 1755 | struct list_head file_open; |
| 1739 | struct list_head task_create; | 1756 | struct list_head task_create; |
| 1757 | struct list_head task_alloc; | ||
| 1740 | struct list_head task_free; | 1758 | struct list_head task_free; |
| 1741 | struct list_head cred_alloc_blank; | 1759 | struct list_head cred_alloc_blank; |
| 1742 | struct list_head cred_free; | 1760 | struct list_head cred_free; |
| @@ -1755,6 +1773,7 @@ struct security_hook_heads { | |||
| 1755 | struct list_head task_setnice; | 1773 | struct list_head task_setnice; |
| 1756 | struct list_head task_setioprio; | 1774 | struct list_head task_setioprio; |
| 1757 | struct list_head task_getioprio; | 1775 | struct list_head task_getioprio; |
| 1776 | struct list_head task_prlimit; | ||
| 1758 | struct list_head task_setrlimit; | 1777 | struct list_head task_setrlimit; |
| 1759 | struct list_head task_setscheduler; | 1778 | struct list_head task_setscheduler; |
| 1760 | struct list_head task_getscheduler; | 1779 | struct list_head task_getscheduler; |
| @@ -1908,6 +1927,13 @@ static inline void security_delete_hooks(struct security_hook_list *hooks, | |||
| 1908 | } | 1927 | } |
| 1909 | #endif /* CONFIG_SECURITY_SELINUX_DISABLE */ | 1928 | #endif /* CONFIG_SECURITY_SELINUX_DISABLE */ |
| 1910 | 1929 | ||
| 1930 | /* Currently required to handle SELinux runtime hook disable. */ | ||
| 1931 | #ifdef CONFIG_SECURITY_WRITABLE_HOOKS | ||
| 1932 | #define __lsm_ro_after_init | ||
| 1933 | #else | ||
| 1934 | #define __lsm_ro_after_init __ro_after_init | ||
| 1935 | #endif /* CONFIG_SECURITY_WRITABLE_HOOKS */ | ||
| 1936 | |||
| 1911 | extern int __init security_module_enable(const char *module); | 1937 | extern int __init security_module_enable(const char *module); |
| 1912 | extern void __init capability_add_hooks(void); | 1938 | extern void __init capability_add_hooks(void); |
| 1913 | #ifdef CONFIG_SECURITY_YAMA | 1939 | #ifdef CONFIG_SECURITY_YAMA |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 1e590c3bd581..3d4fa448223f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1047,6 +1047,10 @@ struct task_struct { | |||
| 1047 | #ifdef CONFIG_LIVEPATCH | 1047 | #ifdef CONFIG_LIVEPATCH |
| 1048 | int patch_state; | 1048 | int patch_state; |
| 1049 | #endif | 1049 | #endif |
| 1050 | #ifdef CONFIG_SECURITY | ||
| 1051 | /* Used by LSM modules for access restriction: */ | ||
| 1052 | void *security; | ||
| 1053 | #endif | ||
| 1050 | /* CPU-specific state of this task: */ | 1054 | /* CPU-specific state of this task: */ |
| 1051 | struct thread_struct thread; | 1055 | struct thread_struct thread; |
| 1052 | 1056 | ||
diff --git a/include/linux/security.h b/include/linux/security.h index 96899fad7016..af675b576645 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -133,6 +133,10 @@ extern unsigned long dac_mmap_min_addr; | |||
| 133 | /* setfsuid or setfsgid, id0 == fsuid or fsgid */ | 133 | /* setfsuid or setfsgid, id0 == fsuid or fsgid */ |
| 134 | #define LSM_SETID_FS 8 | 134 | #define LSM_SETID_FS 8 |
| 135 | 135 | ||
| 136 | /* Flags for security_task_prlimit(). */ | ||
| 137 | #define LSM_PRLIMIT_READ 1 | ||
| 138 | #define LSM_PRLIMIT_WRITE 2 | ||
| 139 | |||
| 136 | /* forward declares to avoid warnings */ | 140 | /* forward declares to avoid warnings */ |
| 137 | struct sched_param; | 141 | struct sched_param; |
| 138 | struct request_sock; | 142 | struct request_sock; |
| @@ -304,6 +308,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, | |||
| 304 | int security_file_receive(struct file *file); | 308 | int security_file_receive(struct file *file); |
| 305 | int security_file_open(struct file *file, const struct cred *cred); | 309 | int security_file_open(struct file *file, const struct cred *cred); |
| 306 | int security_task_create(unsigned long clone_flags); | 310 | int security_task_create(unsigned long clone_flags); |
| 311 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags); | ||
| 307 | void security_task_free(struct task_struct *task); | 312 | void security_task_free(struct task_struct *task); |
| 308 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); | 313 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); |
| 309 | void security_cred_free(struct cred *cred); | 314 | void security_cred_free(struct cred *cred); |
| @@ -324,6 +329,8 @@ void security_task_getsecid(struct task_struct *p, u32 *secid); | |||
| 324 | int security_task_setnice(struct task_struct *p, int nice); | 329 | int security_task_setnice(struct task_struct *p, int nice); |
| 325 | int security_task_setioprio(struct task_struct *p, int ioprio); | 330 | int security_task_setioprio(struct task_struct *p, int ioprio); |
| 326 | int security_task_getioprio(struct task_struct *p); | 331 | int security_task_getioprio(struct task_struct *p); |
| 332 | int security_task_prlimit(const struct cred *cred, const struct cred *tcred, | ||
| 333 | unsigned int flags); | ||
| 327 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, | 334 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, |
| 328 | struct rlimit *new_rlim); | 335 | struct rlimit *new_rlim); |
| 329 | int security_task_setscheduler(struct task_struct *p); | 336 | int security_task_setscheduler(struct task_struct *p); |
| @@ -855,6 +862,12 @@ static inline int security_task_create(unsigned long clone_flags) | |||
| 855 | return 0; | 862 | return 0; |
| 856 | } | 863 | } |
| 857 | 864 | ||
| 865 | static inline int security_task_alloc(struct task_struct *task, | ||
| 866 | unsigned long clone_flags) | ||
| 867 | { | ||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 858 | static inline void security_task_free(struct task_struct *task) | 871 | static inline void security_task_free(struct task_struct *task) |
| 859 | { } | 872 | { } |
| 860 | 873 | ||
| @@ -949,6 +962,13 @@ static inline int security_task_getioprio(struct task_struct *p) | |||
| 949 | return 0; | 962 | return 0; |
| 950 | } | 963 | } |
| 951 | 964 | ||
| 965 | static inline int security_task_prlimit(const struct cred *cred, | ||
| 966 | const struct cred *tcred, | ||
| 967 | unsigned int flags) | ||
| 968 | { | ||
| 969 | return 0; | ||
| 970 | } | ||
| 971 | |||
| 952 | static inline int security_task_setrlimit(struct task_struct *p, | 972 | static inline int security_task_setrlimit(struct task_struct *p, |
| 953 | unsigned int resource, | 973 | unsigned int resource, |
| 954 | struct rlimit *new_rlim) | 974 | struct rlimit *new_rlim) |
diff --git a/include/linux/tpm.h b/include/linux/tpm.h index da158f06e0b2..5a090f5ab335 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h | |||
| @@ -48,7 +48,8 @@ struct tpm_class_ops { | |||
| 48 | u8 (*status) (struct tpm_chip *chip); | 48 | u8 (*status) (struct tpm_chip *chip); |
| 49 | bool (*update_timeouts)(struct tpm_chip *chip, | 49 | bool (*update_timeouts)(struct tpm_chip *chip, |
| 50 | unsigned long *timeout_cap); | 50 | unsigned long *timeout_cap); |
| 51 | 51 | int (*request_locality)(struct tpm_chip *chip, int loc); | |
| 52 | void (*relinquish_locality)(struct tpm_chip *chip, int loc); | ||
| 52 | }; | 53 | }; |
| 53 | 54 | ||
| 54 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) | 55 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) |
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index 86eddd6241f3..201c6644b237 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | #define KEYCTL_INVALIDATE 21 /* invalidate a key */ | 60 | #define KEYCTL_INVALIDATE 21 /* invalidate a key */ |
| 61 | #define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ | 61 | #define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ |
| 62 | #define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */ | 62 | #define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */ |
| 63 | #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ | ||
| 63 | 64 | ||
| 64 | /* keyctl structures */ | 65 | /* keyctl structures */ |
| 65 | struct keyctl_dh_params { | 66 | struct keyctl_dh_params { |
| @@ -68,4 +69,11 @@ struct keyctl_dh_params { | |||
| 68 | __s32 base; | 69 | __s32 base; |
| 69 | }; | 70 | }; |
| 70 | 71 | ||
| 72 | struct keyctl_kdf_params { | ||
| 73 | char *hashname; | ||
| 74 | char *otherinfo; | ||
| 75 | __u32 otherinfolen; | ||
| 76 | __u32 __spare[8]; | ||
| 77 | }; | ||
| 78 | |||
| 71 | #endif /* _LINUX_KEYCTL_H */ | 79 | #endif /* _LINUX_KEYCTL_H */ |
diff --git a/kernel/fork.c b/kernel/fork.c index 56d85fd81411..dd5a371c392a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1681,9 +1681,12 @@ static __latent_entropy struct task_struct *copy_process( | |||
| 1681 | goto bad_fork_cleanup_perf; | 1681 | goto bad_fork_cleanup_perf; |
| 1682 | /* copy all the process information */ | 1682 | /* copy all the process information */ |
| 1683 | shm_init_task(p); | 1683 | shm_init_task(p); |
| 1684 | retval = copy_semundo(clone_flags, p); | 1684 | retval = security_task_alloc(p, clone_flags); |
| 1685 | if (retval) | 1685 | if (retval) |
| 1686 | goto bad_fork_cleanup_audit; | 1686 | goto bad_fork_cleanup_audit; |
| 1687 | retval = copy_semundo(clone_flags, p); | ||
| 1688 | if (retval) | ||
| 1689 | goto bad_fork_cleanup_security; | ||
| 1687 | retval = copy_files(clone_flags, p); | 1690 | retval = copy_files(clone_flags, p); |
| 1688 | if (retval) | 1691 | if (retval) |
| 1689 | goto bad_fork_cleanup_semundo; | 1692 | goto bad_fork_cleanup_semundo; |
| @@ -1907,6 +1910,8 @@ bad_fork_cleanup_files: | |||
| 1907 | exit_files(p); /* blocking */ | 1910 | exit_files(p); /* blocking */ |
| 1908 | bad_fork_cleanup_semundo: | 1911 | bad_fork_cleanup_semundo: |
| 1909 | exit_sem(p); | 1912 | exit_sem(p); |
| 1913 | bad_fork_cleanup_security: | ||
| 1914 | security_task_free(p); | ||
| 1910 | bad_fork_cleanup_audit: | 1915 | bad_fork_cleanup_audit: |
| 1911 | audit_free(p); | 1916 | audit_free(p); |
| 1912 | bad_fork_cleanup_perf: | 1917 | bad_fork_cleanup_perf: |
diff --git a/kernel/sys.c b/kernel/sys.c index 7ff6d1b10cec..196c7134bee6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -1432,25 +1432,26 @@ out: | |||
| 1432 | } | 1432 | } |
| 1433 | 1433 | ||
| 1434 | /* rcu lock must be held */ | 1434 | /* rcu lock must be held */ |
| 1435 | static int check_prlimit_permission(struct task_struct *task) | 1435 | static int check_prlimit_permission(struct task_struct *task, |
| 1436 | unsigned int flags) | ||
| 1436 | { | 1437 | { |
| 1437 | const struct cred *cred = current_cred(), *tcred; | 1438 | const struct cred *cred = current_cred(), *tcred; |
| 1439 | bool id_match; | ||
| 1438 | 1440 | ||
| 1439 | if (current == task) | 1441 | if (current == task) |
| 1440 | return 0; | 1442 | return 0; |
| 1441 | 1443 | ||
| 1442 | tcred = __task_cred(task); | 1444 | tcred = __task_cred(task); |
| 1443 | if (uid_eq(cred->uid, tcred->euid) && | 1445 | id_match = (uid_eq(cred->uid, tcred->euid) && |
| 1444 | uid_eq(cred->uid, tcred->suid) && | 1446 | uid_eq(cred->uid, tcred->suid) && |
| 1445 | uid_eq(cred->uid, tcred->uid) && | 1447 | uid_eq(cred->uid, tcred->uid) && |
| 1446 | gid_eq(cred->gid, tcred->egid) && | 1448 | gid_eq(cred->gid, tcred->egid) && |
| 1447 | gid_eq(cred->gid, tcred->sgid) && | 1449 | gid_eq(cred->gid, tcred->sgid) && |
| 1448 | gid_eq(cred->gid, tcred->gid)) | 1450 | gid_eq(cred->gid, tcred->gid)); |
| 1449 | return 0; | 1451 | if (!id_match && !ns_capable(tcred->user_ns, CAP_SYS_RESOURCE)) |
| 1450 | if (ns_capable(tcred->user_ns, CAP_SYS_RESOURCE)) | 1452 | return -EPERM; |
| 1451 | return 0; | ||
| 1452 | 1453 | ||
| 1453 | return -EPERM; | 1454 | return security_task_prlimit(cred, tcred, flags); |
| 1454 | } | 1455 | } |
| 1455 | 1456 | ||
| 1456 | SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource, | 1457 | SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource, |
| @@ -1460,12 +1461,17 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource, | |||
| 1460 | struct rlimit64 old64, new64; | 1461 | struct rlimit64 old64, new64; |
| 1461 | struct rlimit old, new; | 1462 | struct rlimit old, new; |
| 1462 | struct task_struct *tsk; | 1463 | struct task_struct *tsk; |
| 1464 | unsigned int checkflags = 0; | ||
| 1463 | int ret; | 1465 | int ret; |
| 1464 | 1466 | ||
| 1467 | if (old_rlim) | ||
| 1468 | checkflags |= LSM_PRLIMIT_READ; | ||
| 1469 | |||
| 1465 | if (new_rlim) { | 1470 | if (new_rlim) { |
| 1466 | if (copy_from_user(&new64, new_rlim, sizeof(new64))) | 1471 | if (copy_from_user(&new64, new_rlim, sizeof(new64))) |
| 1467 | return -EFAULT; | 1472 | return -EFAULT; |
| 1468 | rlim64_to_rlim(&new64, &new); | 1473 | rlim64_to_rlim(&new64, &new); |
| 1474 | checkflags |= LSM_PRLIMIT_WRITE; | ||
| 1469 | } | 1475 | } |
| 1470 | 1476 | ||
| 1471 | rcu_read_lock(); | 1477 | rcu_read_lock(); |
| @@ -1474,7 +1480,7 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource, | |||
| 1474 | rcu_read_unlock(); | 1480 | rcu_read_unlock(); |
| 1475 | return -ESRCH; | 1481 | return -ESRCH; |
| 1476 | } | 1482 | } |
| 1477 | ret = check_prlimit_permission(tsk); | 1483 | ret = check_prlimit_permission(tsk, checkflags); |
| 1478 | if (ret) { | 1484 | if (ret) { |
| 1479 | rcu_read_unlock(); | 1485 | rcu_read_unlock(); |
| 1480 | return ret; | 1486 | return ret; |
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index f4dd41f900d5..6a24569c3578 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <errno.h> | 9 | #include <errno.h> |
| 10 | #include <ctype.h> | 10 | #include <ctype.h> |
| 11 | #include <sys/socket.h> | ||
| 11 | 12 | ||
| 12 | struct security_class_mapping { | 13 | struct security_class_mapping { |
| 13 | const char *name; | 14 | const char *name; |
diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index c29fa4a6228d..ffe8179f5d41 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <stdlib.h> | 32 | #include <stdlib.h> |
| 33 | #include <unistd.h> | 33 | #include <unistd.h> |
| 34 | #include <string.h> | 34 | #include <string.h> |
| 35 | #include <sys/socket.h> | ||
| 35 | 36 | ||
| 36 | static void usage(char *name) | 37 | static void usage(char *name) |
| 37 | { | 38 | { |
diff --git a/security/Kconfig b/security/Kconfig index 213df4d4f2c1..93027fdf47d1 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
| @@ -31,6 +31,11 @@ config SECURITY | |||
| 31 | 31 | ||
| 32 | If you are unsure how to answer this question, answer N. | 32 | If you are unsure how to answer this question, answer N. |
| 33 | 33 | ||
| 34 | config SECURITY_WRITABLE_HOOKS | ||
| 35 | depends on SECURITY | ||
| 36 | bool | ||
| 37 | default n | ||
| 38 | |||
| 34 | config SECURITYFS | 39 | config SECURITYFS |
| 35 | bool "Enable the securityfs filesystem" | 40 | bool "Enable the securityfs filesystem" |
| 36 | help | 41 | help |
diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c index de8dc78b6144..136f2a047836 100644 --- a/security/apparmor/crypto.c +++ b/security/apparmor/crypto.c | |||
| @@ -31,10 +31,7 @@ unsigned int aa_hash_size(void) | |||
| 31 | 31 | ||
| 32 | char *aa_calc_hash(void *data, size_t len) | 32 | char *aa_calc_hash(void *data, size_t len) |
| 33 | { | 33 | { |
| 34 | struct { | 34 | SHASH_DESC_ON_STACK(desc, apparmor_tfm); |
| 35 | struct shash_desc shash; | ||
| 36 | char ctx[crypto_shash_descsize(apparmor_tfm)]; | ||
| 37 | } desc; | ||
| 38 | char *hash = NULL; | 35 | char *hash = NULL; |
| 39 | int error = -ENOMEM; | 36 | int error = -ENOMEM; |
| 40 | 37 | ||
| @@ -45,16 +42,16 @@ char *aa_calc_hash(void *data, size_t len) | |||
| 45 | if (!hash) | 42 | if (!hash) |
| 46 | goto fail; | 43 | goto fail; |
| 47 | 44 | ||
| 48 | desc.shash.tfm = apparmor_tfm; | 45 | desc->tfm = apparmor_tfm; |
| 49 | desc.shash.flags = 0; | 46 | desc->flags = 0; |
| 50 | 47 | ||
| 51 | error = crypto_shash_init(&desc.shash); | 48 | error = crypto_shash_init(desc); |
| 52 | if (error) | 49 | if (error) |
| 53 | goto fail; | 50 | goto fail; |
| 54 | error = crypto_shash_update(&desc.shash, (u8 *) data, len); | 51 | error = crypto_shash_update(desc, (u8 *) data, len); |
| 55 | if (error) | 52 | if (error) |
| 56 | goto fail; | 53 | goto fail; |
| 57 | error = crypto_shash_final(&desc.shash, hash); | 54 | error = crypto_shash_final(desc, hash); |
| 58 | if (error) | 55 | if (error) |
| 59 | goto fail; | 56 | goto fail; |
| 60 | 57 | ||
| @@ -69,10 +66,7 @@ fail: | |||
| 69 | int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, | 66 | int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, |
| 70 | size_t len) | 67 | size_t len) |
| 71 | { | 68 | { |
| 72 | struct { | 69 | SHASH_DESC_ON_STACK(desc, apparmor_tfm); |
| 73 | struct shash_desc shash; | ||
| 74 | char ctx[crypto_shash_descsize(apparmor_tfm)]; | ||
| 75 | } desc; | ||
| 76 | int error = -ENOMEM; | 70 | int error = -ENOMEM; |
| 77 | __le32 le32_version = cpu_to_le32(version); | 71 | __le32 le32_version = cpu_to_le32(version); |
| 78 | 72 | ||
| @@ -86,19 +80,19 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, | |||
| 86 | if (!profile->hash) | 80 | if (!profile->hash) |
| 87 | goto fail; | 81 | goto fail; |
| 88 | 82 | ||
| 89 | desc.shash.tfm = apparmor_tfm; | 83 | desc->tfm = apparmor_tfm; |
| 90 | desc.shash.flags = 0; | 84 | desc->flags = 0; |
| 91 | 85 | ||
| 92 | error = crypto_shash_init(&desc.shash); | 86 | error = crypto_shash_init(desc); |
| 93 | if (error) | 87 | if (error) |
| 94 | goto fail; | 88 | goto fail; |
| 95 | error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4); | 89 | error = crypto_shash_update(desc, (u8 *) &le32_version, 4); |
| 96 | if (error) | 90 | if (error) |
| 97 | goto fail; | 91 | goto fail; |
| 98 | error = crypto_shash_update(&desc.shash, (u8 *) start, len); | 92 | error = crypto_shash_update(desc, (u8 *) start, len); |
| 99 | if (error) | 93 | if (error) |
| 100 | goto fail; | 94 | goto fail; |
| 101 | error = crypto_shash_final(&desc.shash, profile->hash); | 95 | error = crypto_shash_final(desc, profile->hash); |
| 102 | if (error) | 96 | if (error) |
| 103 | goto fail; | 97 | goto fail; |
| 104 | 98 | ||
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 65ff492a9807..0291ff3902f9 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | pr_err_ratelimited("AppArmor: " fmt, ##args) | 57 | pr_err_ratelimited("AppArmor: " fmt, ##args) |
| 58 | 58 | ||
| 59 | /* Flag indicating whether initialization completed */ | 59 | /* Flag indicating whether initialization completed */ |
| 60 | extern int apparmor_initialized __initdata; | 60 | extern int apparmor_initialized; |
| 61 | 61 | ||
| 62 | /* fn's in lib */ | 62 | /* fn's in lib */ |
| 63 | char *aa_split_fqname(char *args, char **ns_name); | 63 | char *aa_split_fqname(char *args, char **ns_name); |
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 66475bda6f72..32cafc12593e 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
| @@ -180,13 +180,13 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix, | |||
| 180 | } else | 180 | } else |
| 181 | policy->hname = kstrdup(name, gfp); | 181 | policy->hname = kstrdup(name, gfp); |
| 182 | if (!policy->hname) | 182 | if (!policy->hname) |
| 183 | return 0; | 183 | return false; |
| 184 | /* base.name is a substring of fqname */ | 184 | /* base.name is a substring of fqname */ |
| 185 | policy->name = basename(policy->hname); | 185 | policy->name = basename(policy->hname); |
| 186 | INIT_LIST_HEAD(&policy->list); | 186 | INIT_LIST_HEAD(&policy->list); |
| 187 | INIT_LIST_HEAD(&policy->profiles); | 187 | INIT_LIST_HEAD(&policy->profiles); |
| 188 | 188 | ||
| 189 | return 1; | 189 | return true; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | /** | 192 | /** |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 709eacd23909..8f3c0f7aca5a 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #include "include/procattr.h" | 39 | #include "include/procattr.h" |
| 40 | 40 | ||
| 41 | /* Flag indicating whether initialization completed */ | 41 | /* Flag indicating whether initialization completed */ |
| 42 | int apparmor_initialized __initdata; | 42 | int apparmor_initialized; |
| 43 | 43 | ||
| 44 | DEFINE_PER_CPU(struct aa_buffers, aa_buffers); | 44 | DEFINE_PER_CPU(struct aa_buffers, aa_buffers); |
| 45 | 45 | ||
| @@ -587,7 +587,7 @@ static int apparmor_task_setrlimit(struct task_struct *task, | |||
| 587 | return error; | 587 | return error; |
| 588 | } | 588 | } |
| 589 | 589 | ||
| 590 | static struct security_hook_list apparmor_hooks[] = { | 590 | static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { |
| 591 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), | 591 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), |
| 592 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), | 592 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), |
| 593 | LSM_HOOK_INIT(capget, apparmor_capget), | 593 | LSM_HOOK_INIT(capget, apparmor_capget), |
| @@ -681,7 +681,7 @@ module_param_named(hash_policy, aa_g_hash_policy, aabool, S_IRUSR | S_IWUSR); | |||
| 681 | #endif | 681 | #endif |
| 682 | 682 | ||
| 683 | /* Debug mode */ | 683 | /* Debug mode */ |
| 684 | bool aa_g_debug = IS_ENABLED(CONFIG_SECURITY_DEBUG_MESSAGES); | 684 | bool aa_g_debug = IS_ENABLED(CONFIG_SECURITY_APPARMOR_DEBUG_MESSAGES); |
| 685 | module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); | 685 | module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); |
| 686 | 686 | ||
| 687 | /* Audit mode */ | 687 | /* Audit mode */ |
| @@ -710,7 +710,7 @@ module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR); | |||
| 710 | 710 | ||
| 711 | /* Maximum pathname length before accesses will start getting rejected */ | 711 | /* Maximum pathname length before accesses will start getting rejected */ |
| 712 | unsigned int aa_g_path_max = 2 * PATH_MAX; | 712 | unsigned int aa_g_path_max = 2 * PATH_MAX; |
| 713 | module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR); | 713 | module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR); |
| 714 | 714 | ||
| 715 | /* Determines how paranoid loading of policy is and how much verification | 715 | /* Determines how paranoid loading of policy is and how much verification |
| 716 | * on the loaded policy is done. | 716 | * on the loaded policy is done. |
| @@ -738,78 +738,77 @@ __setup("apparmor=", apparmor_enabled_setup); | |||
| 738 | /* set global flag turning off the ability to load policy */ | 738 | /* set global flag turning off the ability to load policy */ |
| 739 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) | 739 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) |
| 740 | { | 740 | { |
| 741 | if (!policy_admin_capable(NULL)) | 741 | if (!apparmor_enabled) |
| 742 | return -EINVAL; | ||
| 743 | if (apparmor_initialized && !policy_admin_capable(NULL)) | ||
| 742 | return -EPERM; | 744 | return -EPERM; |
| 743 | return param_set_bool(val, kp); | 745 | return param_set_bool(val, kp); |
| 744 | } | 746 | } |
| 745 | 747 | ||
| 746 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) | 748 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) |
| 747 | { | 749 | { |
| 748 | if (!policy_view_capable(NULL)) | ||
| 749 | return -EPERM; | ||
| 750 | if (!apparmor_enabled) | 750 | if (!apparmor_enabled) |
| 751 | return -EINVAL; | 751 | return -EINVAL; |
| 752 | if (apparmor_initialized && !policy_view_capable(NULL)) | ||
| 753 | return -EPERM; | ||
| 752 | return param_get_bool(buffer, kp); | 754 | return param_get_bool(buffer, kp); |
| 753 | } | 755 | } |
| 754 | 756 | ||
| 755 | static int param_set_aabool(const char *val, const struct kernel_param *kp) | 757 | static int param_set_aabool(const char *val, const struct kernel_param *kp) |
| 756 | { | 758 | { |
| 757 | if (!policy_admin_capable(NULL)) | ||
| 758 | return -EPERM; | ||
| 759 | if (!apparmor_enabled) | 759 | if (!apparmor_enabled) |
| 760 | return -EINVAL; | 760 | return -EINVAL; |
| 761 | if (apparmor_initialized && !policy_admin_capable(NULL)) | ||
| 762 | return -EPERM; | ||
| 761 | return param_set_bool(val, kp); | 763 | return param_set_bool(val, kp); |
| 762 | } | 764 | } |
| 763 | 765 | ||
| 764 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) | 766 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) |
| 765 | { | 767 | { |
| 766 | if (!policy_view_capable(NULL)) | ||
| 767 | return -EPERM; | ||
| 768 | if (!apparmor_enabled) | 768 | if (!apparmor_enabled) |
| 769 | return -EINVAL; | 769 | return -EINVAL; |
| 770 | if (apparmor_initialized && !policy_view_capable(NULL)) | ||
| 771 | return -EPERM; | ||
| 770 | return param_get_bool(buffer, kp); | 772 | return param_get_bool(buffer, kp); |
| 771 | } | 773 | } |
| 772 | 774 | ||
| 773 | static int param_set_aauint(const char *val, const struct kernel_param *kp) | 775 | static int param_set_aauint(const char *val, const struct kernel_param *kp) |
| 774 | { | 776 | { |
| 775 | if (!policy_admin_capable(NULL)) | ||
| 776 | return -EPERM; | ||
| 777 | if (!apparmor_enabled) | 777 | if (!apparmor_enabled) |
| 778 | return -EINVAL; | 778 | return -EINVAL; |
| 779 | if (apparmor_initialized && !policy_admin_capable(NULL)) | ||
| 780 | return -EPERM; | ||
| 779 | return param_set_uint(val, kp); | 781 | return param_set_uint(val, kp); |
| 780 | } | 782 | } |
| 781 | 783 | ||
| 782 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) | 784 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) |
| 783 | { | 785 | { |
| 784 | if (!policy_view_capable(NULL)) | ||
| 785 | return -EPERM; | ||
| 786 | if (!apparmor_enabled) | 786 | if (!apparmor_enabled) |
| 787 | return -EINVAL; | 787 | return -EINVAL; |
| 788 | if (apparmor_initialized && !policy_view_capable(NULL)) | ||
| 789 | return -EPERM; | ||
| 788 | return param_get_uint(buffer, kp); | 790 | return param_get_uint(buffer, kp); |
| 789 | } | 791 | } |
| 790 | 792 | ||
| 791 | static int param_get_audit(char *buffer, struct kernel_param *kp) | 793 | static int param_get_audit(char *buffer, struct kernel_param *kp) |
| 792 | { | 794 | { |
| 793 | if (!policy_view_capable(NULL)) | ||
| 794 | return -EPERM; | ||
| 795 | |||
| 796 | if (!apparmor_enabled) | 795 | if (!apparmor_enabled) |
| 797 | return -EINVAL; | 796 | return -EINVAL; |
| 798 | 797 | if (apparmor_initialized && !policy_view_capable(NULL)) | |
| 798 | return -EPERM; | ||
| 799 | return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); | 799 | return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); |
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | static int param_set_audit(const char *val, struct kernel_param *kp) | 802 | static int param_set_audit(const char *val, struct kernel_param *kp) |
| 803 | { | 803 | { |
| 804 | int i; | 804 | int i; |
| 805 | if (!policy_admin_capable(NULL)) | ||
| 806 | return -EPERM; | ||
| 807 | 805 | ||
| 808 | if (!apparmor_enabled) | 806 | if (!apparmor_enabled) |
| 809 | return -EINVAL; | 807 | return -EINVAL; |
| 810 | |||
| 811 | if (!val) | 808 | if (!val) |
| 812 | return -EINVAL; | 809 | return -EINVAL; |
| 810 | if (apparmor_initialized && !policy_admin_capable(NULL)) | ||
| 811 | return -EPERM; | ||
| 813 | 812 | ||
| 814 | for (i = 0; i < AUDIT_MAX_INDEX; i++) { | 813 | for (i = 0; i < AUDIT_MAX_INDEX; i++) { |
| 815 | if (strcmp(val, audit_mode_names[i]) == 0) { | 814 | if (strcmp(val, audit_mode_names[i]) == 0) { |
| @@ -823,11 +822,10 @@ static int param_set_audit(const char *val, struct kernel_param *kp) | |||
| 823 | 822 | ||
| 824 | static int param_get_mode(char *buffer, struct kernel_param *kp) | 823 | static int param_get_mode(char *buffer, struct kernel_param *kp) |
| 825 | { | 824 | { |
| 826 | if (!policy_view_capable(NULL)) | ||
| 827 | return -EPERM; | ||
| 828 | |||
| 829 | if (!apparmor_enabled) | 825 | if (!apparmor_enabled) |
| 830 | return -EINVAL; | 826 | return -EINVAL; |
| 827 | if (apparmor_initialized && !policy_view_capable(NULL)) | ||
| 828 | return -EPERM; | ||
| 831 | 829 | ||
| 832 | return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]); | 830 | return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]); |
| 833 | } | 831 | } |
| @@ -835,14 +833,13 @@ static int param_get_mode(char *buffer, struct kernel_param *kp) | |||
| 835 | static int param_set_mode(const char *val, struct kernel_param *kp) | 833 | static int param_set_mode(const char *val, struct kernel_param *kp) |
| 836 | { | 834 | { |
| 837 | int i; | 835 | int i; |
| 838 | if (!policy_admin_capable(NULL)) | ||
| 839 | return -EPERM; | ||
| 840 | 836 | ||
| 841 | if (!apparmor_enabled) | 837 | if (!apparmor_enabled) |
| 842 | return -EINVAL; | 838 | return -EINVAL; |
| 843 | |||
| 844 | if (!val) | 839 | if (!val) |
| 845 | return -EINVAL; | 840 | return -EINVAL; |
| 841 | if (apparmor_initialized && !policy_admin_capable(NULL)) | ||
| 842 | return -EPERM; | ||
| 846 | 843 | ||
| 847 | for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) { | 844 | for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) { |
| 848 | if (strcmp(val, aa_profile_mode_names[i]) == 0) { | 845 | if (strcmp(val, aa_profile_mode_names[i]) == 0) { |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index def1fbd6bdfd..cf9d670dca94 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
| @@ -876,9 +876,11 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, | |||
| 876 | if (ns_name) { | 876 | if (ns_name) { |
| 877 | ns = aa_prepare_ns(view, ns_name); | 877 | ns = aa_prepare_ns(view, ns_name); |
| 878 | if (IS_ERR(ns)) { | 878 | if (IS_ERR(ns)) { |
| 879 | op = OP_PROF_LOAD; | ||
| 879 | info = "failed to prepare namespace"; | 880 | info = "failed to prepare namespace"; |
| 880 | error = PTR_ERR(ns); | 881 | error = PTR_ERR(ns); |
| 881 | ns = NULL; | 882 | ns = NULL; |
| 883 | ent = NULL; | ||
| 882 | goto fail; | 884 | goto fail; |
| 883 | } | 885 | } |
| 884 | } else | 886 | } else |
| @@ -1013,7 +1015,7 @@ fail_lock: | |||
| 1013 | /* audit cause of failure */ | 1015 | /* audit cause of failure */ |
| 1014 | op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; | 1016 | op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; |
| 1015 | fail: | 1017 | fail: |
| 1016 | audit_policy(profile, op, ns_name, ent->new->base.hname, | 1018 | audit_policy(profile, op, ns_name, ent ? ent->new->base.hname : NULL, |
| 1017 | info, error); | 1019 | info, error); |
| 1018 | /* audit status that rest of profiles in the atomic set failed too */ | 1020 | /* audit status that rest of profiles in the atomic set failed too */ |
| 1019 | info = "valid profile in failed atomic policy load"; | 1021 | info = "valid profile in failed atomic policy load"; |
| @@ -1023,7 +1025,7 @@ fail: | |||
| 1023 | /* skip entry that caused failure */ | 1025 | /* skip entry that caused failure */ |
| 1024 | continue; | 1026 | continue; |
| 1025 | } | 1027 | } |
| 1026 | op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; | 1028 | op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL; |
| 1027 | audit_policy(profile, op, ns_name, | 1029 | audit_policy(profile, op, ns_name, |
| 1028 | tmp->new->base.hname, info, error); | 1030 | tmp->new->base.hname, info, error); |
| 1029 | } | 1031 | } |
diff --git a/security/commoncap.c b/security/commoncap.c index 78b37838a2d3..7abebd782d5e 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -1071,7 +1071,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, | |||
| 1071 | 1071 | ||
| 1072 | #ifdef CONFIG_SECURITY | 1072 | #ifdef CONFIG_SECURITY |
| 1073 | 1073 | ||
| 1074 | struct security_hook_list capability_hooks[] = { | 1074 | struct security_hook_list capability_hooks[] __lsm_ro_after_init = { |
| 1075 | LSM_HOOK_INIT(capable, cap_capable), | 1075 | LSM_HOOK_INIT(capable, cap_capable), |
| 1076 | LSM_HOOK_INIT(settime, cap_settime), | 1076 | LSM_HOOK_INIT(settime, cap_settime), |
| 1077 | LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check), | 1077 | LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check), |
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 106e855e2d9d..06554c448dce 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
| @@ -81,18 +81,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | |||
| 81 | int __init integrity_init_keyring(const unsigned int id) | 81 | int __init integrity_init_keyring(const unsigned int id) |
| 82 | { | 82 | { |
| 83 | const struct cred *cred = current_cred(); | 83 | const struct cred *cred = current_cred(); |
| 84 | struct key_restriction *restriction; | ||
| 84 | int err = 0; | 85 | int err = 0; |
| 85 | 86 | ||
| 86 | if (!init_keyring) | 87 | if (!init_keyring) |
| 87 | return 0; | 88 | return 0; |
| 88 | 89 | ||
| 90 | restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | ||
| 91 | if (!restriction) | ||
| 92 | return -ENOMEM; | ||
| 93 | |||
| 94 | restriction->check = restrict_link_to_ima; | ||
| 95 | |||
| 89 | keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), | 96 | keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), |
| 90 | KGIDT_INIT(0), cred, | 97 | KGIDT_INIT(0), cred, |
| 91 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 98 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
| 92 | KEY_USR_VIEW | KEY_USR_READ | | 99 | KEY_USR_VIEW | KEY_USR_READ | |
| 93 | KEY_USR_WRITE | KEY_USR_SEARCH), | 100 | KEY_USR_WRITE | KEY_USR_SEARCH), |
| 94 | KEY_ALLOC_NOT_IN_QUOTA, | 101 | KEY_ALLOC_NOT_IN_QUOTA, |
| 95 | restrict_link_to_ima, NULL); | 102 | restriction, NULL); |
| 96 | if (IS_ERR(keyring[id])) { | 103 | if (IS_ERR(keyring[id])) { |
| 97 | err = PTR_ERR(keyring[id]); | 104 | err = PTR_ERR(keyring[id]); |
| 98 | pr_info("Can't allocate %s keyring (%d)\n", | 105 | pr_info("Can't allocate %s keyring (%d)\n", |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 1fd9539a969d..5d0785cfe063 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
| @@ -207,10 +207,11 @@ int ima_appraise_measurement(enum ima_hooks func, | |||
| 207 | 207 | ||
| 208 | cause = "missing-hash"; | 208 | cause = "missing-hash"; |
| 209 | status = INTEGRITY_NOLABEL; | 209 | status = INTEGRITY_NOLABEL; |
| 210 | if (opened & FILE_CREATED) { | 210 | if (opened & FILE_CREATED) |
| 211 | iint->flags |= IMA_NEW_FILE; | 211 | iint->flags |= IMA_NEW_FILE; |
| 212 | if ((iint->flags & IMA_NEW_FILE) && | ||
| 213 | !(iint->flags & IMA_DIGSIG_REQUIRED)) | ||
| 212 | status = INTEGRITY_PASS; | 214 | status = INTEGRITY_PASS; |
| 213 | } | ||
| 214 | goto out; | 215 | goto out; |
| 215 | } | 216 | } |
| 216 | 217 | ||
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 74a279957464..073ddc9bce5b 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/cred.h> | 17 | #include <linux/cred.h> |
| 18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <keys/system_keyring.h> | 21 | #include <keys/system_keyring.h> |
| 21 | 22 | ||
| 22 | 23 | ||
| @@ -27,15 +28,23 @@ struct key *ima_blacklist_keyring; | |||
| 27 | */ | 28 | */ |
| 28 | __init int ima_mok_init(void) | 29 | __init int ima_mok_init(void) |
| 29 | { | 30 | { |
| 31 | struct key_restriction *restriction; | ||
| 32 | |||
| 30 | pr_notice("Allocating IMA blacklist keyring.\n"); | 33 | pr_notice("Allocating IMA blacklist keyring.\n"); |
| 31 | 34 | ||
| 35 | restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | ||
| 36 | if (!restriction) | ||
| 37 | panic("Can't allocate IMA blacklist restriction."); | ||
| 38 | |||
| 39 | restriction->check = restrict_link_by_builtin_trusted; | ||
| 40 | |||
| 32 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", | 41 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", |
| 33 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), | 42 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), |
| 34 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 43 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
| 35 | KEY_USR_VIEW | KEY_USR_READ | | 44 | KEY_USR_VIEW | KEY_USR_READ | |
| 36 | KEY_USR_WRITE | KEY_USR_SEARCH, | 45 | KEY_USR_WRITE | KEY_USR_SEARCH, |
| 37 | KEY_ALLOC_NOT_IN_QUOTA, | 46 | KEY_ALLOC_NOT_IN_QUOTA, |
| 38 | restrict_link_by_builtin_trusted, NULL); | 47 | restriction, NULL); |
| 39 | 48 | ||
| 40 | if (IS_ERR(ima_blacklist_keyring)) | 49 | if (IS_ERR(ima_blacklist_keyring)) |
| 41 | panic("Can't allocate IMA blacklist keyring."); | 50 | panic("Can't allocate IMA blacklist keyring."); |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index aed47b777a57..3ab1067db624 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -64,6 +64,8 @@ struct ima_rule_entry { | |||
| 64 | u8 fsuuid[16]; | 64 | u8 fsuuid[16]; |
| 65 | kuid_t uid; | 65 | kuid_t uid; |
| 66 | kuid_t fowner; | 66 | kuid_t fowner; |
| 67 | bool (*uid_op)(kuid_t, kuid_t); /* Handlers for operators */ | ||
| 68 | bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */ | ||
| 67 | int pcr; | 69 | int pcr; |
| 68 | struct { | 70 | struct { |
| 69 | void *rule; /* LSM file metadata specific */ | 71 | void *rule; /* LSM file metadata specific */ |
| @@ -83,7 +85,7 @@ struct ima_rule_entry { | |||
| 83 | * normal users can easily run the machine out of memory simply building | 85 | * normal users can easily run the machine out of memory simply building |
| 84 | * and running executables. | 86 | * and running executables. |
| 85 | */ | 87 | */ |
| 86 | static struct ima_rule_entry dont_measure_rules[] = { | 88 | static struct ima_rule_entry dont_measure_rules[] __ro_after_init = { |
| 87 | {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, | 89 | {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, |
| 88 | {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, | 90 | {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, |
| 89 | {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, | 91 | {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, |
| @@ -97,32 +99,35 @@ static struct ima_rule_entry dont_measure_rules[] = { | |||
| 97 | {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC} | 99 | {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC} |
| 98 | }; | 100 | }; |
| 99 | 101 | ||
| 100 | static struct ima_rule_entry original_measurement_rules[] = { | 102 | static struct ima_rule_entry original_measurement_rules[] __ro_after_init = { |
| 101 | {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, | 103 | {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, |
| 102 | .flags = IMA_FUNC | IMA_MASK}, | 104 | .flags = IMA_FUNC | IMA_MASK}, |
| 103 | {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, | 105 | {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, |
| 104 | .flags = IMA_FUNC | IMA_MASK}, | 106 | .flags = IMA_FUNC | IMA_MASK}, |
| 105 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, | 107 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, |
| 106 | .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 108 | .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, |
| 109 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | ||
| 107 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, | 110 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, |
| 108 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, | 111 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, |
| 109 | }; | 112 | }; |
| 110 | 113 | ||
| 111 | static struct ima_rule_entry default_measurement_rules[] = { | 114 | static struct ima_rule_entry default_measurement_rules[] __ro_after_init = { |
| 112 | {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, | 115 | {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, |
| 113 | .flags = IMA_FUNC | IMA_MASK}, | 116 | .flags = IMA_FUNC | IMA_MASK}, |
| 114 | {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, | 117 | {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, |
| 115 | .flags = IMA_FUNC | IMA_MASK}, | 118 | .flags = IMA_FUNC | IMA_MASK}, |
| 116 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, | 119 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, |
| 117 | .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID}, | 120 | .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, |
| 121 | .flags = IMA_FUNC | IMA_INMASK | IMA_EUID}, | ||
| 118 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, | 122 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, |
| 119 | .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID}, | 123 | .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, |
| 124 | .flags = IMA_FUNC | IMA_INMASK | IMA_UID}, | ||
| 120 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, | 125 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, |
| 121 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, | 126 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, |
| 122 | {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC}, | 127 | {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC}, |
| 123 | }; | 128 | }; |
| 124 | 129 | ||
| 125 | static struct ima_rule_entry default_appraise_rules[] = { | 130 | static struct ima_rule_entry default_appraise_rules[] __ro_after_init = { |
| 126 | {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, | 131 | {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, |
| 127 | {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, | 132 | {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, |
| 128 | {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, | 133 | {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, |
| @@ -139,10 +144,11 @@ static struct ima_rule_entry default_appraise_rules[] = { | |||
| 139 | .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, | 144 | .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, |
| 140 | #endif | 145 | #endif |
| 141 | #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT | 146 | #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT |
| 142 | {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER}, | 147 | {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, |
| 148 | .flags = IMA_FOWNER}, | ||
| 143 | #else | 149 | #else |
| 144 | /* force signature */ | 150 | /* force signature */ |
| 145 | {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, | 151 | {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, |
| 146 | .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED}, | 152 | .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED}, |
| 147 | #endif | 153 | #endif |
| 148 | }; | 154 | }; |
| @@ -240,19 +246,20 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, | |||
| 240 | if ((rule->flags & IMA_FSUUID) && | 246 | if ((rule->flags & IMA_FSUUID) && |
| 241 | memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid))) | 247 | memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid))) |
| 242 | return false; | 248 | return false; |
| 243 | if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) | 249 | if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid)) |
| 244 | return false; | 250 | return false; |
| 245 | if (rule->flags & IMA_EUID) { | 251 | if (rule->flags & IMA_EUID) { |
| 246 | if (has_capability_noaudit(current, CAP_SETUID)) { | 252 | if (has_capability_noaudit(current, CAP_SETUID)) { |
| 247 | if (!uid_eq(rule->uid, cred->euid) | 253 | if (!rule->uid_op(cred->euid, rule->uid) |
| 248 | && !uid_eq(rule->uid, cred->suid) | 254 | && !rule->uid_op(cred->suid, rule->uid) |
| 249 | && !uid_eq(rule->uid, cred->uid)) | 255 | && !rule->uid_op(cred->uid, rule->uid)) |
| 250 | return false; | 256 | return false; |
| 251 | } else if (!uid_eq(rule->uid, cred->euid)) | 257 | } else if (!rule->uid_op(cred->euid, rule->uid)) |
| 252 | return false; | 258 | return false; |
| 253 | } | 259 | } |
| 254 | 260 | ||
| 255 | if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) | 261 | if ((rule->flags & IMA_FOWNER) && |
| 262 | !rule->fowner_op(inode->i_uid, rule->fowner)) | ||
| 256 | return false; | 263 | return false; |
| 257 | for (i = 0; i < MAX_LSM_RULES; i++) { | 264 | for (i = 0; i < MAX_LSM_RULES; i++) { |
| 258 | int rc = 0; | 265 | int rc = 0; |
| @@ -486,7 +493,9 @@ enum { | |||
| 486 | Opt_obj_user, Opt_obj_role, Opt_obj_type, | 493 | Opt_obj_user, Opt_obj_role, Opt_obj_type, |
| 487 | Opt_subj_user, Opt_subj_role, Opt_subj_type, | 494 | Opt_subj_user, Opt_subj_role, Opt_subj_type, |
| 488 | Opt_func, Opt_mask, Opt_fsmagic, | 495 | Opt_func, Opt_mask, Opt_fsmagic, |
| 489 | Opt_fsuuid, Opt_uid, Opt_euid, Opt_fowner, | 496 | Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq, |
| 497 | Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, | ||
| 498 | Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, | ||
| 490 | Opt_appraise_type, Opt_permit_directio, | 499 | Opt_appraise_type, Opt_permit_directio, |
| 491 | Opt_pcr | 500 | Opt_pcr |
| 492 | }; | 501 | }; |
| @@ -507,9 +516,15 @@ static match_table_t policy_tokens = { | |||
| 507 | {Opt_mask, "mask=%s"}, | 516 | {Opt_mask, "mask=%s"}, |
| 508 | {Opt_fsmagic, "fsmagic=%s"}, | 517 | {Opt_fsmagic, "fsmagic=%s"}, |
| 509 | {Opt_fsuuid, "fsuuid=%s"}, | 518 | {Opt_fsuuid, "fsuuid=%s"}, |
| 510 | {Opt_uid, "uid=%s"}, | 519 | {Opt_uid_eq, "uid=%s"}, |
| 511 | {Opt_euid, "euid=%s"}, | 520 | {Opt_euid_eq, "euid=%s"}, |
| 512 | {Opt_fowner, "fowner=%s"}, | 521 | {Opt_fowner_eq, "fowner=%s"}, |
| 522 | {Opt_uid_gt, "uid>%s"}, | ||
| 523 | {Opt_euid_gt, "euid>%s"}, | ||
| 524 | {Opt_fowner_gt, "fowner>%s"}, | ||
| 525 | {Opt_uid_lt, "uid<%s"}, | ||
| 526 | {Opt_euid_lt, "euid<%s"}, | ||
| 527 | {Opt_fowner_lt, "fowner<%s"}, | ||
| 513 | {Opt_appraise_type, "appraise_type=%s"}, | 528 | {Opt_appraise_type, "appraise_type=%s"}, |
| 514 | {Opt_permit_directio, "permit_directio"}, | 529 | {Opt_permit_directio, "permit_directio"}, |
| 515 | {Opt_pcr, "pcr=%s"}, | 530 | {Opt_pcr, "pcr=%s"}, |
| @@ -541,24 +556,37 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, | |||
| 541 | return result; | 556 | return result; |
| 542 | } | 557 | } |
| 543 | 558 | ||
| 544 | static void ima_log_string(struct audit_buffer *ab, char *key, char *value) | 559 | static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value, |
| 560 | bool (*rule_operator)(kuid_t, kuid_t)) | ||
| 545 | { | 561 | { |
| 546 | audit_log_format(ab, "%s=", key); | 562 | if (rule_operator == &uid_gt) |
| 563 | audit_log_format(ab, "%s>", key); | ||
| 564 | else if (rule_operator == &uid_lt) | ||
| 565 | audit_log_format(ab, "%s<", key); | ||
| 566 | else | ||
| 567 | audit_log_format(ab, "%s=", key); | ||
| 547 | audit_log_untrustedstring(ab, value); | 568 | audit_log_untrustedstring(ab, value); |
| 548 | audit_log_format(ab, " "); | 569 | audit_log_format(ab, " "); |
| 549 | } | 570 | } |
| 571 | static void ima_log_string(struct audit_buffer *ab, char *key, char *value) | ||
| 572 | { | ||
| 573 | ima_log_string_op(ab, key, value, NULL); | ||
| 574 | } | ||
| 550 | 575 | ||
| 551 | static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | 576 | static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) |
| 552 | { | 577 | { |
| 553 | struct audit_buffer *ab; | 578 | struct audit_buffer *ab; |
| 554 | char *from; | 579 | char *from; |
| 555 | char *p; | 580 | char *p; |
| 581 | bool uid_token; | ||
| 556 | int result = 0; | 582 | int result = 0; |
| 557 | 583 | ||
| 558 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); | 584 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); |
| 559 | 585 | ||
| 560 | entry->uid = INVALID_UID; | 586 | entry->uid = INVALID_UID; |
| 561 | entry->fowner = INVALID_UID; | 587 | entry->fowner = INVALID_UID; |
| 588 | entry->uid_op = &uid_eq; | ||
| 589 | entry->fowner_op = &uid_eq; | ||
| 562 | entry->action = UNKNOWN; | 590 | entry->action = UNKNOWN; |
| 563 | while ((p = strsep(&rule, " \t")) != NULL) { | 591 | while ((p = strsep(&rule, " \t")) != NULL) { |
| 564 | substring_t args[MAX_OPT_ARGS]; | 592 | substring_t args[MAX_OPT_ARGS]; |
| @@ -694,11 +722,21 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 694 | if (!result) | 722 | if (!result) |
| 695 | entry->flags |= IMA_FSUUID; | 723 | entry->flags |= IMA_FSUUID; |
| 696 | break; | 724 | break; |
| 697 | case Opt_uid: | 725 | case Opt_uid_gt: |
| 698 | ima_log_string(ab, "uid", args[0].from); | 726 | case Opt_euid_gt: |
| 699 | case Opt_euid: | 727 | entry->uid_op = &uid_gt; |
| 700 | if (token == Opt_euid) | 728 | case Opt_uid_lt: |
| 701 | ima_log_string(ab, "euid", args[0].from); | 729 | case Opt_euid_lt: |
| 730 | if ((token == Opt_uid_lt) || (token == Opt_euid_lt)) | ||
| 731 | entry->uid_op = &uid_lt; | ||
| 732 | case Opt_uid_eq: | ||
| 733 | case Opt_euid_eq: | ||
| 734 | uid_token = (token == Opt_uid_eq) || | ||
| 735 | (token == Opt_uid_gt) || | ||
| 736 | (token == Opt_uid_lt); | ||
| 737 | |||
| 738 | ima_log_string_op(ab, uid_token ? "uid" : "euid", | ||
| 739 | args[0].from, entry->uid_op); | ||
| 702 | 740 | ||
| 703 | if (uid_valid(entry->uid)) { | 741 | if (uid_valid(entry->uid)) { |
| 704 | result = -EINVAL; | 742 | result = -EINVAL; |
| @@ -713,12 +751,18 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 713 | (uid_t)lnum != lnum) | 751 | (uid_t)lnum != lnum) |
| 714 | result = -EINVAL; | 752 | result = -EINVAL; |
| 715 | else | 753 | else |
| 716 | entry->flags |= (token == Opt_uid) | 754 | entry->flags |= uid_token |
| 717 | ? IMA_UID : IMA_EUID; | 755 | ? IMA_UID : IMA_EUID; |
| 718 | } | 756 | } |
| 719 | break; | 757 | break; |
| 720 | case Opt_fowner: | 758 | case Opt_fowner_gt: |
| 721 | ima_log_string(ab, "fowner", args[0].from); | 759 | entry->fowner_op = &uid_gt; |
| 760 | case Opt_fowner_lt: | ||
| 761 | if (token == Opt_fowner_lt) | ||
| 762 | entry->fowner_op = &uid_lt; | ||
| 763 | case Opt_fowner_eq: | ||
| 764 | ima_log_string_op(ab, "fowner", args[0].from, | ||
| 765 | entry->fowner_op); | ||
| 722 | 766 | ||
| 723 | if (uid_valid(entry->fowner)) { | 767 | if (uid_valid(entry->fowner)) { |
| 724 | result = -EINVAL; | 768 | result = -EINVAL; |
| @@ -1049,19 +1093,34 @@ int ima_policy_show(struct seq_file *m, void *v) | |||
| 1049 | 1093 | ||
| 1050 | if (entry->flags & IMA_UID) { | 1094 | if (entry->flags & IMA_UID) { |
| 1051 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); | 1095 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); |
| 1052 | seq_printf(m, pt(Opt_uid), tbuf); | 1096 | if (entry->uid_op == &uid_gt) |
| 1097 | seq_printf(m, pt(Opt_uid_gt), tbuf); | ||
| 1098 | else if (entry->uid_op == &uid_lt) | ||
| 1099 | seq_printf(m, pt(Opt_uid_lt), tbuf); | ||
| 1100 | else | ||
| 1101 | seq_printf(m, pt(Opt_uid_eq), tbuf); | ||
| 1053 | seq_puts(m, " "); | 1102 | seq_puts(m, " "); |
| 1054 | } | 1103 | } |
| 1055 | 1104 | ||
| 1056 | if (entry->flags & IMA_EUID) { | 1105 | if (entry->flags & IMA_EUID) { |
| 1057 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); | 1106 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); |
| 1058 | seq_printf(m, pt(Opt_euid), tbuf); | 1107 | if (entry->uid_op == &uid_gt) |
| 1108 | seq_printf(m, pt(Opt_euid_gt), tbuf); | ||
| 1109 | else if (entry->uid_op == &uid_lt) | ||
| 1110 | seq_printf(m, pt(Opt_euid_lt), tbuf); | ||
| 1111 | else | ||
| 1112 | seq_printf(m, pt(Opt_euid_eq), tbuf); | ||
| 1059 | seq_puts(m, " "); | 1113 | seq_puts(m, " "); |
| 1060 | } | 1114 | } |
| 1061 | 1115 | ||
| 1062 | if (entry->flags & IMA_FOWNER) { | 1116 | if (entry->flags & IMA_FOWNER) { |
| 1063 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner)); | 1117 | snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner)); |
| 1064 | seq_printf(m, pt(Opt_fowner), tbuf); | 1118 | if (entry->fowner_op == &uid_gt) |
| 1119 | seq_printf(m, pt(Opt_fowner_gt), tbuf); | ||
| 1120 | else if (entry->fowner_op == &uid_lt) | ||
| 1121 | seq_printf(m, pt(Opt_fowner_lt), tbuf); | ||
| 1122 | else | ||
| 1123 | seq_printf(m, pt(Opt_fowner_eq), tbuf); | ||
| 1065 | seq_puts(m, " "); | 1124 | seq_puts(m, " "); |
| 1066 | } | 1125 | } |
| 1067 | 1126 | ||
diff --git a/security/keys/Kconfig b/security/keys/Kconfig index d942c7c2bc0a..6fd95f76bfae 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig | |||
| @@ -90,6 +90,8 @@ config KEY_DH_OPERATIONS | |||
| 90 | bool "Diffie-Hellman operations on retained keys" | 90 | bool "Diffie-Hellman operations on retained keys" |
| 91 | depends on KEYS | 91 | depends on KEYS |
| 92 | select MPILIB | 92 | select MPILIB |
| 93 | select CRYPTO | ||
| 94 | select CRYPTO_HASH | ||
| 93 | help | 95 | help |
| 94 | This option provides support for calculating Diffie-Hellman | 96 | This option provides support for calculating Diffie-Hellman |
| 95 | public keys and shared secrets using values stored as keys | 97 | public keys and shared secrets using values stored as keys |
diff --git a/security/keys/Makefile b/security/keys/Makefile index 1fd4a16e6daf..57dff0c15809 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
| @@ -15,7 +15,8 @@ obj-y := \ | |||
| 15 | request_key.o \ | 15 | request_key.o \ |
| 16 | request_key_auth.o \ | 16 | request_key_auth.o \ |
| 17 | user_defined.o | 17 | user_defined.o |
| 18 | obj-$(CONFIG_KEYS_COMPAT) += compat.o | 18 | compat-obj-$(CONFIG_KEY_DH_OPERATIONS) += compat_dh.o |
| 19 | obj-$(CONFIG_KEYS_COMPAT) += compat.o $(compat-obj-y) | ||
| 19 | obj-$(CONFIG_PROC_FS) += proc.o | 20 | obj-$(CONFIG_PROC_FS) += proc.o |
| 20 | obj-$(CONFIG_SYSCTL) += sysctl.o | 21 | obj-$(CONFIG_SYSCTL) += sysctl.o |
| 21 | obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o | 22 | obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o |
diff --git a/security/keys/compat.c b/security/keys/compat.c index 36c80bf5b89c..e87c89c0177c 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
| @@ -133,8 +133,13 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option, | |||
| 133 | return keyctl_get_persistent(arg2, arg3); | 133 | return keyctl_get_persistent(arg2, arg3); |
| 134 | 134 | ||
| 135 | case KEYCTL_DH_COMPUTE: | 135 | case KEYCTL_DH_COMPUTE: |
| 136 | return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3), | 136 | return compat_keyctl_dh_compute(compat_ptr(arg2), |
| 137 | arg4, compat_ptr(arg5)); | 137 | compat_ptr(arg3), |
| 138 | arg4, compat_ptr(arg5)); | ||
| 139 | |||
| 140 | case KEYCTL_RESTRICT_KEYRING: | ||
| 141 | return keyctl_restrict_keyring(arg2, compat_ptr(arg3), | ||
| 142 | compat_ptr(arg4)); | ||
| 138 | 143 | ||
| 139 | default: | 144 | default: |
| 140 | return -EOPNOTSUPP; | 145 | return -EOPNOTSUPP; |
diff --git a/security/keys/compat_dh.c b/security/keys/compat_dh.c new file mode 100644 index 000000000000..a6a659b6bcb6 --- /dev/null +++ b/security/keys/compat_dh.c | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* 32-bit compatibility syscall for 64-bit systems for DH operations | ||
| 2 | * | ||
| 3 | * Copyright (C) 2016 Stephan Mueller <smueller@chronox.de> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License | ||
| 7 | * as published by the Free Software Foundation; either version | ||
| 8 | * 2 of the License, or (at your option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/uaccess.h> | ||
| 12 | |||
| 13 | #include "internal.h" | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Perform the DH computation or DH based key derivation. | ||
| 17 | * | ||
| 18 | * If successful, 0 will be returned. | ||
| 19 | */ | ||
| 20 | long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params, | ||
| 21 | char __user *buffer, size_t buflen, | ||
| 22 | struct compat_keyctl_kdf_params __user *kdf) | ||
| 23 | { | ||
| 24 | struct keyctl_kdf_params kdfcopy; | ||
| 25 | struct compat_keyctl_kdf_params compat_kdfcopy; | ||
| 26 | |||
| 27 | if (!kdf) | ||
| 28 | return __keyctl_dh_compute(params, buffer, buflen, NULL); | ||
| 29 | |||
| 30 | if (copy_from_user(&compat_kdfcopy, kdf, sizeof(compat_kdfcopy)) != 0) | ||
| 31 | return -EFAULT; | ||
| 32 | |||
| 33 | kdfcopy.hashname = compat_ptr(compat_kdfcopy.hashname); | ||
| 34 | kdfcopy.otherinfo = compat_ptr(compat_kdfcopy.otherinfo); | ||
| 35 | kdfcopy.otherinfolen = compat_kdfcopy.otherinfolen; | ||
| 36 | |||
| 37 | return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy); | ||
| 38 | } | ||
diff --git a/security/keys/dh.c b/security/keys/dh.c index 893af4c45038..e603bd912e4c 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/mpi.h> | 11 | #include <linux/mpi.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/uaccess.h> | 13 | #include <linux/uaccess.h> |
| 14 | #include <linux/crypto.h> | ||
| 15 | #include <crypto/hash.h> | ||
| 14 | #include <keys/user-type.h> | 16 | #include <keys/user-type.h> |
| 15 | #include "internal.h" | 17 | #include "internal.h" |
| 16 | 18 | ||
| @@ -77,9 +79,146 @@ error: | |||
| 77 | return ret; | 79 | return ret; |
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | long keyctl_dh_compute(struct keyctl_dh_params __user *params, | 82 | struct kdf_sdesc { |
| 81 | char __user *buffer, size_t buflen, | 83 | struct shash_desc shash; |
| 82 | void __user *reserved) | 84 | char ctx[]; |
| 85 | }; | ||
| 86 | |||
| 87 | static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname) | ||
| 88 | { | ||
| 89 | struct crypto_shash *tfm; | ||
| 90 | struct kdf_sdesc *sdesc; | ||
| 91 | int size; | ||
| 92 | |||
| 93 | /* allocate synchronous hash */ | ||
| 94 | tfm = crypto_alloc_shash(hashname, 0, 0); | ||
| 95 | if (IS_ERR(tfm)) { | ||
| 96 | pr_info("could not allocate digest TFM handle %s\n", hashname); | ||
| 97 | return PTR_ERR(tfm); | ||
| 98 | } | ||
| 99 | |||
| 100 | size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm); | ||
| 101 | sdesc = kmalloc(size, GFP_KERNEL); | ||
| 102 | if (!sdesc) | ||
| 103 | return -ENOMEM; | ||
| 104 | sdesc->shash.tfm = tfm; | ||
| 105 | sdesc->shash.flags = 0x0; | ||
| 106 | |||
| 107 | *sdesc_ret = sdesc; | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void kdf_dealloc(struct kdf_sdesc *sdesc) | ||
| 113 | { | ||
| 114 | if (!sdesc) | ||
| 115 | return; | ||
| 116 | |||
| 117 | if (sdesc->shash.tfm) | ||
| 118 | crypto_free_shash(sdesc->shash.tfm); | ||
| 119 | |||
| 120 | kzfree(sdesc); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* convert 32 bit integer into its string representation */ | ||
| 124 | static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf) | ||
| 125 | { | ||
| 126 | __be32 *a = (__be32 *)buf; | ||
| 127 | |||
| 128 | *a = cpu_to_be32(val); | ||
| 129 | } | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Implementation of the KDF in counter mode according to SP800-108 section 5.1 | ||
| 133 | * as well as SP800-56A section 5.8.1 (Single-step KDF). | ||
| 134 | * | ||
| 135 | * SP800-56A: | ||
| 136 | * The src pointer is defined as Z || other info where Z is the shared secret | ||
| 137 | * from DH and other info is an arbitrary string (see SP800-56A section | ||
| 138 | * 5.8.1.2). | ||
| 139 | */ | ||
| 140 | static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, | ||
| 141 | u8 *dst, unsigned int dlen) | ||
| 142 | { | ||
| 143 | struct shash_desc *desc = &sdesc->shash; | ||
| 144 | unsigned int h = crypto_shash_digestsize(desc->tfm); | ||
| 145 | int err = 0; | ||
| 146 | u8 *dst_orig = dst; | ||
| 147 | u32 i = 1; | ||
| 148 | u8 iteration[sizeof(u32)]; | ||
| 149 | |||
| 150 | while (dlen) { | ||
| 151 | err = crypto_shash_init(desc); | ||
| 152 | if (err) | ||
| 153 | goto err; | ||
| 154 | |||
| 155 | crypto_kw_cpu_to_be32(i, iteration); | ||
| 156 | err = crypto_shash_update(desc, iteration, sizeof(u32)); | ||
| 157 | if (err) | ||
| 158 | goto err; | ||
| 159 | |||
| 160 | if (src && slen) { | ||
| 161 | err = crypto_shash_update(desc, src, slen); | ||
| 162 | if (err) | ||
| 163 | goto err; | ||
| 164 | } | ||
| 165 | |||
| 166 | if (dlen < h) { | ||
| 167 | u8 tmpbuffer[h]; | ||
| 168 | |||
| 169 | err = crypto_shash_final(desc, tmpbuffer); | ||
| 170 | if (err) | ||
| 171 | goto err; | ||
| 172 | memcpy(dst, tmpbuffer, dlen); | ||
| 173 | memzero_explicit(tmpbuffer, h); | ||
| 174 | return 0; | ||
| 175 | } else { | ||
| 176 | err = crypto_shash_final(desc, dst); | ||
| 177 | if (err) | ||
| 178 | goto err; | ||
| 179 | |||
| 180 | dlen -= h; | ||
| 181 | dst += h; | ||
| 182 | i++; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | |||
| 188 | err: | ||
| 189 | memzero_explicit(dst_orig, dlen); | ||
| 190 | return err; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, | ||
| 194 | char __user *buffer, size_t buflen, | ||
| 195 | uint8_t *kbuf, size_t kbuflen) | ||
| 196 | { | ||
| 197 | uint8_t *outbuf = NULL; | ||
| 198 | int ret; | ||
| 199 | |||
| 200 | outbuf = kmalloc(buflen, GFP_KERNEL); | ||
| 201 | if (!outbuf) { | ||
| 202 | ret = -ENOMEM; | ||
| 203 | goto err; | ||
| 204 | } | ||
| 205 | |||
| 206 | ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen); | ||
| 207 | if (ret) | ||
| 208 | goto err; | ||
| 209 | |||
| 210 | ret = buflen; | ||
| 211 | if (copy_to_user(buffer, outbuf, buflen) != 0) | ||
| 212 | ret = -EFAULT; | ||
| 213 | |||
| 214 | err: | ||
| 215 | kzfree(outbuf); | ||
| 216 | return ret; | ||
| 217 | } | ||
| 218 | |||
| 219 | long __keyctl_dh_compute(struct keyctl_dh_params __user *params, | ||
| 220 | char __user *buffer, size_t buflen, | ||
| 221 | struct keyctl_kdf_params *kdfcopy) | ||
| 83 | { | 222 | { |
| 84 | long ret; | 223 | long ret; |
| 85 | MPI base, private, prime, result; | 224 | MPI base, private, prime, result; |
| @@ -88,6 +227,7 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
| 88 | uint8_t *kbuf; | 227 | uint8_t *kbuf; |
| 89 | ssize_t keylen; | 228 | ssize_t keylen; |
| 90 | size_t resultlen; | 229 | size_t resultlen; |
| 230 | struct kdf_sdesc *sdesc = NULL; | ||
| 91 | 231 | ||
| 92 | if (!params || (!buffer && buflen)) { | 232 | if (!params || (!buffer && buflen)) { |
| 93 | ret = -EINVAL; | 233 | ret = -EINVAL; |
| @@ -98,12 +238,34 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
| 98 | goto out; | 238 | goto out; |
| 99 | } | 239 | } |
| 100 | 240 | ||
| 101 | if (reserved) { | 241 | if (kdfcopy) { |
| 102 | ret = -EINVAL; | 242 | char *hashname; |
| 103 | goto out; | 243 | |
| 244 | if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || | ||
| 245 | kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { | ||
| 246 | ret = -EMSGSIZE; | ||
| 247 | goto out; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* get KDF name string */ | ||
| 251 | hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); | ||
| 252 | if (IS_ERR(hashname)) { | ||
| 253 | ret = PTR_ERR(hashname); | ||
| 254 | goto out; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* allocate KDF from the kernel crypto API */ | ||
| 258 | ret = kdf_alloc(&sdesc, hashname); | ||
| 259 | kfree(hashname); | ||
| 260 | if (ret) | ||
| 261 | goto out; | ||
| 104 | } | 262 | } |
| 105 | 263 | ||
| 106 | keylen = mpi_from_key(pcopy.prime, buflen, &prime); | 264 | /* |
| 265 | * If the caller requests postprocessing with a KDF, allow an | ||
| 266 | * arbitrary output buffer size since the KDF ensures proper truncation. | ||
| 267 | */ | ||
| 268 | keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime); | ||
| 107 | if (keylen < 0 || !prime) { | 269 | if (keylen < 0 || !prime) { |
| 108 | /* buflen == 0 may be used to query the required buffer size, | 270 | /* buflen == 0 may be used to query the required buffer size, |
| 109 | * which is the prime key length. | 271 | * which is the prime key length. |
| @@ -133,12 +295,25 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
| 133 | goto error3; | 295 | goto error3; |
| 134 | } | 296 | } |
| 135 | 297 | ||
| 136 | kbuf = kmalloc(resultlen, GFP_KERNEL); | 298 | /* allocate space for DH shared secret and SP800-56A otherinfo */ |
| 299 | kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen, | ||
| 300 | GFP_KERNEL); | ||
| 137 | if (!kbuf) { | 301 | if (!kbuf) { |
| 138 | ret = -ENOMEM; | 302 | ret = -ENOMEM; |
| 139 | goto error4; | 303 | goto error4; |
| 140 | } | 304 | } |
| 141 | 305 | ||
| 306 | /* | ||
| 307 | * Concatenate SP800-56A otherinfo past DH shared secret -- the | ||
| 308 | * input to the KDF is (DH shared secret || otherinfo) | ||
| 309 | */ | ||
| 310 | if (kdfcopy && kdfcopy->otherinfo && | ||
| 311 | copy_from_user(kbuf + resultlen, kdfcopy->otherinfo, | ||
| 312 | kdfcopy->otherinfolen) != 0) { | ||
| 313 | ret = -EFAULT; | ||
| 314 | goto error5; | ||
| 315 | } | ||
| 316 | |||
| 142 | ret = do_dh(result, base, private, prime); | 317 | ret = do_dh(result, base, private, prime); |
| 143 | if (ret) | 318 | if (ret) |
| 144 | goto error5; | 319 | goto error5; |
| @@ -147,12 +322,17 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
| 147 | if (ret != 0) | 322 | if (ret != 0) |
| 148 | goto error5; | 323 | goto error5; |
| 149 | 324 | ||
| 150 | ret = nbytes; | 325 | if (kdfcopy) { |
| 151 | if (copy_to_user(buffer, kbuf, nbytes) != 0) | 326 | ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf, |
| 152 | ret = -EFAULT; | 327 | resultlen + kdfcopy->otherinfolen); |
| 328 | } else { | ||
| 329 | ret = nbytes; | ||
| 330 | if (copy_to_user(buffer, kbuf, nbytes) != 0) | ||
| 331 | ret = -EFAULT; | ||
| 332 | } | ||
| 153 | 333 | ||
| 154 | error5: | 334 | error5: |
| 155 | kfree(kbuf); | 335 | kzfree(kbuf); |
| 156 | error4: | 336 | error4: |
| 157 | mpi_free(result); | 337 | mpi_free(result); |
| 158 | error3: | 338 | error3: |
| @@ -162,5 +342,21 @@ error2: | |||
| 162 | error1: | 342 | error1: |
| 163 | mpi_free(prime); | 343 | mpi_free(prime); |
| 164 | out: | 344 | out: |
| 345 | kdf_dealloc(sdesc); | ||
| 165 | return ret; | 346 | return ret; |
| 166 | } | 347 | } |
| 348 | |||
| 349 | long keyctl_dh_compute(struct keyctl_dh_params __user *params, | ||
| 350 | char __user *buffer, size_t buflen, | ||
| 351 | struct keyctl_kdf_params __user *kdf) | ||
| 352 | { | ||
| 353 | struct keyctl_kdf_params kdfcopy; | ||
| 354 | |||
| 355 | if (!kdf) | ||
| 356 | return __keyctl_dh_compute(params, buffer, buflen, NULL); | ||
| 357 | |||
| 358 | if (copy_from_user(&kdfcopy, kdf, sizeof(kdfcopy)) != 0) | ||
| 359 | return -EFAULT; | ||
| 360 | |||
| 361 | return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy); | ||
| 362 | } | ||
diff --git a/security/keys/gc.c b/security/keys/gc.c index 9cb4fe4478a1..595becc6d0d2 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
| @@ -220,7 +220,7 @@ continue_scanning: | |||
| 220 | key = rb_entry(cursor, struct key, serial_node); | 220 | key = rb_entry(cursor, struct key, serial_node); |
| 221 | cursor = rb_next(cursor); | 221 | cursor = rb_next(cursor); |
| 222 | 222 | ||
| 223 | if (atomic_read(&key->usage) == 0) | 223 | if (refcount_read(&key->usage) == 0) |
| 224 | goto found_unreferenced_key; | 224 | goto found_unreferenced_key; |
| 225 | 225 | ||
| 226 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) { | 226 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) { |
| @@ -229,6 +229,9 @@ continue_scanning: | |||
| 229 | set_bit(KEY_FLAG_DEAD, &key->flags); | 229 | set_bit(KEY_FLAG_DEAD, &key->flags); |
| 230 | key->perm = 0; | 230 | key->perm = 0; |
| 231 | goto skip_dead_key; | 231 | goto skip_dead_key; |
| 232 | } else if (key->type == &key_type_keyring && | ||
| 233 | key->restrict_link) { | ||
| 234 | goto found_restricted_keyring; | ||
| 232 | } | 235 | } |
| 233 | } | 236 | } |
| 234 | 237 | ||
| @@ -334,6 +337,14 @@ found_unreferenced_key: | |||
| 334 | gc_state |= KEY_GC_REAP_AGAIN; | 337 | gc_state |= KEY_GC_REAP_AGAIN; |
| 335 | goto maybe_resched; | 338 | goto maybe_resched; |
| 336 | 339 | ||
| 340 | /* We found a restricted keyring and need to update the restriction if | ||
| 341 | * it is associated with the dead key type. | ||
| 342 | */ | ||
| 343 | found_restricted_keyring: | ||
| 344 | spin_unlock(&key_serial_lock); | ||
| 345 | keyring_restriction_gc(key, key_gc_dead_keytype); | ||
| 346 | goto maybe_resched; | ||
| 347 | |||
| 337 | /* We found a keyring and we need to check the payload for links to | 348 | /* We found a keyring and we need to check the payload for links to |
| 338 | * dead or expired keys. We don't flag another reap immediately as we | 349 | * dead or expired keys. We don't flag another reap immediately as we |
| 339 | * have to wait for the old payload to be destroyed by RCU before we | 350 | * have to wait for the old payload to be destroyed by RCU before we |
diff --git a/security/keys/internal.h b/security/keys/internal.h index a2f4c0abb8d8..c0f8682eba69 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/key-type.h> | 17 | #include <linux/key-type.h> |
| 18 | #include <linux/task_work.h> | 18 | #include <linux/task_work.h> |
| 19 | #include <linux/keyctl.h> | 19 | #include <linux/keyctl.h> |
| 20 | #include <linux/refcount.h> | ||
| 21 | #include <linux/compat.h> | ||
| 20 | 22 | ||
| 21 | struct iovec; | 23 | struct iovec; |
| 22 | 24 | ||
| @@ -53,7 +55,7 @@ struct key_user { | |||
| 53 | struct rb_node node; | 55 | struct rb_node node; |
| 54 | struct mutex cons_lock; /* construction initiation lock */ | 56 | struct mutex cons_lock; /* construction initiation lock */ |
| 55 | spinlock_t lock; | 57 | spinlock_t lock; |
| 56 | atomic_t usage; /* for accessing qnkeys & qnbytes */ | 58 | refcount_t usage; /* for accessing qnkeys & qnbytes */ |
| 57 | atomic_t nkeys; /* number of keys */ | 59 | atomic_t nkeys; /* number of keys */ |
| 58 | atomic_t nikeys; /* number of instantiated keys */ | 60 | atomic_t nikeys; /* number of instantiated keys */ |
| 59 | kuid_t uid; | 61 | kuid_t uid; |
| @@ -167,6 +169,8 @@ extern void key_change_session_keyring(struct callback_head *twork); | |||
| 167 | extern struct work_struct key_gc_work; | 169 | extern struct work_struct key_gc_work; |
| 168 | extern unsigned key_gc_delay; | 170 | extern unsigned key_gc_delay; |
| 169 | extern void keyring_gc(struct key *keyring, time_t limit); | 171 | extern void keyring_gc(struct key *keyring, time_t limit); |
| 172 | extern void keyring_restriction_gc(struct key *keyring, | ||
| 173 | struct key_type *dead_type); | ||
| 170 | extern void key_schedule_gc(time_t gc_at); | 174 | extern void key_schedule_gc(time_t gc_at); |
| 171 | extern void key_schedule_gc_links(void); | 175 | extern void key_schedule_gc_links(void); |
| 172 | extern void key_gc_keytype(struct key_type *ktype); | 176 | extern void key_gc_keytype(struct key_type *ktype); |
| @@ -249,6 +253,9 @@ struct iov_iter; | |||
| 249 | extern long keyctl_instantiate_key_common(key_serial_t, | 253 | extern long keyctl_instantiate_key_common(key_serial_t, |
| 250 | struct iov_iter *, | 254 | struct iov_iter *, |
| 251 | key_serial_t); | 255 | key_serial_t); |
| 256 | extern long keyctl_restrict_keyring(key_serial_t id, | ||
| 257 | const char __user *_type, | ||
| 258 | const char __user *_restriction); | ||
| 252 | #ifdef CONFIG_PERSISTENT_KEYRINGS | 259 | #ifdef CONFIG_PERSISTENT_KEYRINGS |
| 253 | extern long keyctl_get_persistent(uid_t, key_serial_t); | 260 | extern long keyctl_get_persistent(uid_t, key_serial_t); |
| 254 | extern unsigned persistent_keyring_expiry; | 261 | extern unsigned persistent_keyring_expiry; |
| @@ -261,15 +268,34 @@ static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring) | |||
| 261 | 268 | ||
| 262 | #ifdef CONFIG_KEY_DH_OPERATIONS | 269 | #ifdef CONFIG_KEY_DH_OPERATIONS |
| 263 | extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *, | 270 | extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *, |
| 264 | size_t, void __user *); | 271 | size_t, struct keyctl_kdf_params __user *); |
| 272 | extern long __keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *, | ||
| 273 | size_t, struct keyctl_kdf_params *); | ||
| 274 | #ifdef CONFIG_KEYS_COMPAT | ||
| 275 | extern long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params, | ||
| 276 | char __user *buffer, size_t buflen, | ||
| 277 | struct compat_keyctl_kdf_params __user *kdf); | ||
| 278 | #endif | ||
| 279 | #define KEYCTL_KDF_MAX_OUTPUT_LEN 1024 /* max length of KDF output */ | ||
| 280 | #define KEYCTL_KDF_MAX_OI_LEN 64 /* max length of otherinfo */ | ||
| 265 | #else | 281 | #else |
| 266 | static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params, | 282 | static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params, |
| 267 | char __user *buffer, size_t buflen, | 283 | char __user *buffer, size_t buflen, |
| 268 | void __user *reserved) | 284 | struct keyctl_kdf_params __user *kdf) |
| 285 | { | ||
| 286 | return -EOPNOTSUPP; | ||
| 287 | } | ||
| 288 | |||
| 289 | #ifdef CONFIG_KEYS_COMPAT | ||
| 290 | static inline long compat_keyctl_dh_compute( | ||
| 291 | struct keyctl_dh_params __user *params, | ||
| 292 | char __user *buffer, size_t buflen, | ||
| 293 | struct keyctl_kdf_params __user *kdf) | ||
| 269 | { | 294 | { |
| 270 | return -EOPNOTSUPP; | 295 | return -EOPNOTSUPP; |
| 271 | } | 296 | } |
| 272 | #endif | 297 | #endif |
| 298 | #endif | ||
| 273 | 299 | ||
| 274 | /* | 300 | /* |
| 275 | * Debugging key validation | 301 | * Debugging key validation |
diff --git a/security/keys/key.c b/security/keys/key.c index 346fbf201c22..455c04d80bbb 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
| @@ -93,7 +93,7 @@ try_again: | |||
| 93 | 93 | ||
| 94 | /* if we get here, then the user record still hadn't appeared on the | 94 | /* if we get here, then the user record still hadn't appeared on the |
| 95 | * second pass - so we use the candidate record */ | 95 | * second pass - so we use the candidate record */ |
| 96 | atomic_set(&candidate->usage, 1); | 96 | refcount_set(&candidate->usage, 1); |
| 97 | atomic_set(&candidate->nkeys, 0); | 97 | atomic_set(&candidate->nkeys, 0); |
| 98 | atomic_set(&candidate->nikeys, 0); | 98 | atomic_set(&candidate->nikeys, 0); |
| 99 | candidate->uid = uid; | 99 | candidate->uid = uid; |
| @@ -110,7 +110,7 @@ try_again: | |||
| 110 | 110 | ||
| 111 | /* okay - we found a user record for this UID */ | 111 | /* okay - we found a user record for this UID */ |
| 112 | found: | 112 | found: |
| 113 | atomic_inc(&user->usage); | 113 | refcount_inc(&user->usage); |
| 114 | spin_unlock(&key_user_lock); | 114 | spin_unlock(&key_user_lock); |
| 115 | kfree(candidate); | 115 | kfree(candidate); |
| 116 | out: | 116 | out: |
| @@ -122,7 +122,7 @@ out: | |||
| 122 | */ | 122 | */ |
| 123 | void key_user_put(struct key_user *user) | 123 | void key_user_put(struct key_user *user) |
| 124 | { | 124 | { |
| 125 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { | 125 | if (refcount_dec_and_lock(&user->usage, &key_user_lock)) { |
| 126 | rb_erase(&user->node, &key_user_tree); | 126 | rb_erase(&user->node, &key_user_tree); |
| 127 | spin_unlock(&key_user_lock); | 127 | spin_unlock(&key_user_lock); |
| 128 | 128 | ||
| @@ -201,12 +201,15 @@ serial_exists: | |||
| 201 | * @cred: The credentials specifying UID namespace. | 201 | * @cred: The credentials specifying UID namespace. |
| 202 | * @perm: The permissions mask of the new key. | 202 | * @perm: The permissions mask of the new key. |
| 203 | * @flags: Flags specifying quota properties. | 203 | * @flags: Flags specifying quota properties. |
| 204 | * @restrict_link: Optional link restriction method for new keyrings. | 204 | * @restrict_link: Optional link restriction for new keyrings. |
| 205 | * | 205 | * |
| 206 | * Allocate a key of the specified type with the attributes given. The key is | 206 | * Allocate a key of the specified type with the attributes given. The key is |
| 207 | * returned in an uninstantiated state and the caller needs to instantiate the | 207 | * returned in an uninstantiated state and the caller needs to instantiate the |
| 208 | * key before returning. | 208 | * key before returning. |
| 209 | * | 209 | * |
| 210 | * The restrict_link structure (if not NULL) will be freed when the | ||
| 211 | * keyring is destroyed, so it must be dynamically allocated. | ||
| 212 | * | ||
| 210 | * The user's key count quota is updated to reflect the creation of the key and | 213 | * The user's key count quota is updated to reflect the creation of the key and |
| 211 | * the user's key data quota has the default for the key type reserved. The | 214 | * the user's key data quota has the default for the key type reserved. The |
| 212 | * instantiation function should amend this as necessary. If insufficient | 215 | * instantiation function should amend this as necessary. If insufficient |
| @@ -225,9 +228,7 @@ serial_exists: | |||
| 225 | struct key *key_alloc(struct key_type *type, const char *desc, | 228 | struct key *key_alloc(struct key_type *type, const char *desc, |
| 226 | kuid_t uid, kgid_t gid, const struct cred *cred, | 229 | kuid_t uid, kgid_t gid, const struct cred *cred, |
| 227 | key_perm_t perm, unsigned long flags, | 230 | key_perm_t perm, unsigned long flags, |
| 228 | int (*restrict_link)(struct key *, | 231 | struct key_restriction *restrict_link) |
| 229 | const struct key_type *, | ||
| 230 | const union key_payload *)) | ||
| 231 | { | 232 | { |
| 232 | struct key_user *user = NULL; | 233 | struct key_user *user = NULL; |
| 233 | struct key *key; | 234 | struct key *key; |
| @@ -285,7 +286,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
| 285 | if (!key->index_key.description) | 286 | if (!key->index_key.description) |
| 286 | goto no_memory_3; | 287 | goto no_memory_3; |
| 287 | 288 | ||
| 288 | atomic_set(&key->usage, 1); | 289 | refcount_set(&key->usage, 1); |
| 289 | init_rwsem(&key->sem); | 290 | init_rwsem(&key->sem); |
| 290 | lockdep_set_class(&key->sem, &type->lock_class); | 291 | lockdep_set_class(&key->sem, &type->lock_class); |
| 291 | key->index_key.type = type; | 292 | key->index_key.type = type; |
| @@ -499,19 +500,23 @@ int key_instantiate_and_link(struct key *key, | |||
| 499 | } | 500 | } |
| 500 | 501 | ||
| 501 | if (keyring) { | 502 | if (keyring) { |
| 502 | if (keyring->restrict_link) { | ||
| 503 | ret = keyring->restrict_link(keyring, key->type, | ||
| 504 | &prep.payload); | ||
| 505 | if (ret < 0) | ||
| 506 | goto error; | ||
| 507 | } | ||
| 508 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 503 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
| 509 | if (ret < 0) | 504 | if (ret < 0) |
| 510 | goto error; | 505 | goto error; |
| 506 | |||
| 507 | if (keyring->restrict_link && keyring->restrict_link->check) { | ||
| 508 | struct key_restriction *keyres = keyring->restrict_link; | ||
| 509 | |||
| 510 | ret = keyres->check(keyring, key->type, &prep.payload, | ||
| 511 | keyres->key); | ||
| 512 | if (ret < 0) | ||
| 513 | goto error_link_end; | ||
| 514 | } | ||
| 511 | } | 515 | } |
| 512 | 516 | ||
| 513 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); | 517 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); |
| 514 | 518 | ||
| 519 | error_link_end: | ||
| 515 | if (keyring) | 520 | if (keyring) |
| 516 | __key_link_end(keyring, &key->index_key, edit); | 521 | __key_link_end(keyring, &key->index_key, edit); |
| 517 | 522 | ||
| @@ -621,7 +626,7 @@ void key_put(struct key *key) | |||
| 621 | if (key) { | 626 | if (key) { |
| 622 | key_check(key); | 627 | key_check(key); |
| 623 | 628 | ||
| 624 | if (atomic_dec_and_test(&key->usage)) | 629 | if (refcount_dec_and_test(&key->usage)) |
| 625 | schedule_work(&key_gc_work); | 630 | schedule_work(&key_gc_work); |
| 626 | } | 631 | } |
| 627 | } | 632 | } |
| @@ -656,7 +661,7 @@ not_found: | |||
| 656 | 661 | ||
| 657 | found: | 662 | found: |
| 658 | /* pretend it doesn't exist if it is awaiting deletion */ | 663 | /* pretend it doesn't exist if it is awaiting deletion */ |
| 659 | if (atomic_read(&key->usage) == 0) | 664 | if (refcount_read(&key->usage) == 0) |
| 660 | goto not_found; | 665 | goto not_found; |
| 661 | 666 | ||
| 662 | /* this races with key_put(), but that doesn't matter since key_put() | 667 | /* this races with key_put(), but that doesn't matter since key_put() |
| @@ -806,9 +811,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 806 | struct key *keyring, *key = NULL; | 811 | struct key *keyring, *key = NULL; |
| 807 | key_ref_t key_ref; | 812 | key_ref_t key_ref; |
| 808 | int ret; | 813 | int ret; |
| 809 | int (*restrict_link)(struct key *, | 814 | struct key_restriction *restrict_link = NULL; |
| 810 | const struct key_type *, | ||
| 811 | const union key_payload *) = NULL; | ||
| 812 | 815 | ||
| 813 | /* look up the key type to see if it's one of the registered kernel | 816 | /* look up the key type to see if it's one of the registered kernel |
| 814 | * types */ | 817 | * types */ |
| @@ -854,20 +857,21 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 854 | } | 857 | } |
| 855 | index_key.desc_len = strlen(index_key.description); | 858 | index_key.desc_len = strlen(index_key.description); |
| 856 | 859 | ||
| 857 | if (restrict_link) { | ||
| 858 | ret = restrict_link(keyring, index_key.type, &prep.payload); | ||
| 859 | if (ret < 0) { | ||
| 860 | key_ref = ERR_PTR(ret); | ||
| 861 | goto error_free_prep; | ||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 865 | ret = __key_link_begin(keyring, &index_key, &edit); | 860 | ret = __key_link_begin(keyring, &index_key, &edit); |
| 866 | if (ret < 0) { | 861 | if (ret < 0) { |
| 867 | key_ref = ERR_PTR(ret); | 862 | key_ref = ERR_PTR(ret); |
| 868 | goto error_free_prep; | 863 | goto error_free_prep; |
| 869 | } | 864 | } |
| 870 | 865 | ||
| 866 | if (restrict_link && restrict_link->check) { | ||
| 867 | ret = restrict_link->check(keyring, index_key.type, | ||
| 868 | &prep.payload, restrict_link->key); | ||
| 869 | if (ret < 0) { | ||
| 870 | key_ref = ERR_PTR(ret); | ||
| 871 | goto error_link_end; | ||
| 872 | } | ||
| 873 | } | ||
| 874 | |||
| 871 | /* if we're going to allocate a new key, we're going to have | 875 | /* if we're going to allocate a new key, we're going to have |
| 872 | * to modify the keyring */ | 876 | * to modify the keyring */ |
| 873 | ret = key_permission(keyring_ref, KEY_NEED_WRITE); | 877 | ret = key_permission(keyring_ref, KEY_NEED_WRITE); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4ad3212adebe..82a9e1851108 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -1585,6 +1585,59 @@ error_keyring: | |||
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | /* | 1587 | /* |
| 1588 | * Apply a restriction to a given keyring. | ||
| 1589 | * | ||
| 1590 | * The caller must have Setattr permission to change keyring restrictions. | ||
| 1591 | * | ||
| 1592 | * The requested type name may be a NULL pointer to reject all attempts | ||
| 1593 | * to link to the keyring. If _type is non-NULL, _restriction can be | ||
| 1594 | * NULL or a pointer to a string describing the restriction. If _type is | ||
| 1595 | * NULL, _restriction must also be NULL. | ||
| 1596 | * | ||
| 1597 | * Returns 0 if successful. | ||
| 1598 | */ | ||
| 1599 | long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, | ||
| 1600 | const char __user *_restriction) | ||
| 1601 | { | ||
| 1602 | key_ref_t key_ref; | ||
| 1603 | bool link_reject = !_type; | ||
| 1604 | char type[32]; | ||
| 1605 | char *restriction = NULL; | ||
| 1606 | long ret; | ||
| 1607 | |||
| 1608 | key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR); | ||
| 1609 | if (IS_ERR(key_ref)) | ||
| 1610 | return PTR_ERR(key_ref); | ||
| 1611 | |||
| 1612 | if (_type) { | ||
| 1613 | ret = key_get_type_from_user(type, _type, sizeof(type)); | ||
| 1614 | if (ret < 0) | ||
| 1615 | goto error; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | if (_restriction) { | ||
| 1619 | if (!_type) { | ||
| 1620 | ret = -EINVAL; | ||
| 1621 | goto error; | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | restriction = strndup_user(_restriction, PAGE_SIZE); | ||
| 1625 | if (IS_ERR(restriction)) { | ||
| 1626 | ret = PTR_ERR(restriction); | ||
| 1627 | goto error; | ||
| 1628 | } | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction); | ||
| 1632 | kfree(restriction); | ||
| 1633 | |||
| 1634 | error: | ||
| 1635 | key_ref_put(key_ref); | ||
| 1636 | |||
| 1637 | return ret; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | /* | ||
| 1588 | * The key control system call | 1641 | * The key control system call |
| 1589 | */ | 1642 | */ |
| 1590 | SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | 1643 | SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, |
| @@ -1693,7 +1746,12 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 1693 | case KEYCTL_DH_COMPUTE: | 1746 | case KEYCTL_DH_COMPUTE: |
| 1694 | return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2, | 1747 | return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2, |
| 1695 | (char __user *) arg3, (size_t) arg4, | 1748 | (char __user *) arg3, (size_t) arg4, |
| 1696 | (void __user *) arg5); | 1749 | (struct keyctl_kdf_params __user *) arg5); |
| 1750 | |||
| 1751 | case KEYCTL_RESTRICT_KEYRING: | ||
| 1752 | return keyctl_restrict_keyring((key_serial_t) arg2, | ||
| 1753 | (const char __user *) arg3, | ||
| 1754 | (const char __user *) arg4); | ||
| 1697 | 1755 | ||
| 1698 | default: | 1756 | default: |
| 1699 | return -EOPNOTSUPP; | 1757 | return -EOPNOTSUPP; |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index c91e4e0cea08..4d1678e4586f 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
| @@ -394,6 +394,13 @@ static void keyring_destroy(struct key *keyring) | |||
| 394 | write_unlock(&keyring_name_lock); | 394 | write_unlock(&keyring_name_lock); |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | if (keyring->restrict_link) { | ||
| 398 | struct key_restriction *keyres = keyring->restrict_link; | ||
| 399 | |||
| 400 | key_put(keyres->key); | ||
| 401 | kfree(keyres); | ||
| 402 | } | ||
| 403 | |||
| 397 | assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops); | 404 | assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops); |
| 398 | } | 405 | } |
| 399 | 406 | ||
| @@ -492,9 +499,7 @@ static long keyring_read(const struct key *keyring, | |||
| 492 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | 499 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, |
| 493 | const struct cred *cred, key_perm_t perm, | 500 | const struct cred *cred, key_perm_t perm, |
| 494 | unsigned long flags, | 501 | unsigned long flags, |
| 495 | int (*restrict_link)(struct key *, | 502 | struct key_restriction *restrict_link, |
| 496 | const struct key_type *, | ||
| 497 | const union key_payload *), | ||
| 498 | struct key *dest) | 503 | struct key *dest) |
| 499 | { | 504 | { |
| 500 | struct key *keyring; | 505 | struct key *keyring; |
| @@ -519,17 +524,19 @@ EXPORT_SYMBOL(keyring_alloc); | |||
| 519 | * @keyring: The keyring being added to. | 524 | * @keyring: The keyring being added to. |
| 520 | * @type: The type of key being added. | 525 | * @type: The type of key being added. |
| 521 | * @payload: The payload of the key intended to be added. | 526 | * @payload: The payload of the key intended to be added. |
| 527 | * @data: Additional data for evaluating restriction. | ||
| 522 | * | 528 | * |
| 523 | * Reject the addition of any links to a keyring. It can be overridden by | 529 | * Reject the addition of any links to a keyring. It can be overridden by |
| 524 | * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when | 530 | * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when |
| 525 | * adding a key to a keyring. | 531 | * adding a key to a keyring. |
| 526 | * | 532 | * |
| 527 | * This is meant to be passed as the restrict_link parameter to | 533 | * This is meant to be stored in a key_restriction structure which is passed |
| 528 | * keyring_alloc(). | 534 | * in the restrict_link parameter to keyring_alloc(). |
| 529 | */ | 535 | */ |
| 530 | int restrict_link_reject(struct key *keyring, | 536 | int restrict_link_reject(struct key *keyring, |
| 531 | const struct key_type *type, | 537 | const struct key_type *type, |
| 532 | const union key_payload *payload) | 538 | const union key_payload *payload, |
| 539 | struct key *restriction_key) | ||
| 533 | { | 540 | { |
| 534 | return -EPERM; | 541 | return -EPERM; |
| 535 | } | 542 | } |
| @@ -940,6 +947,111 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
| 940 | } | 947 | } |
| 941 | EXPORT_SYMBOL(keyring_search); | 948 | EXPORT_SYMBOL(keyring_search); |
| 942 | 949 | ||
| 950 | static struct key_restriction *keyring_restriction_alloc( | ||
| 951 | key_restrict_link_func_t check) | ||
| 952 | { | ||
| 953 | struct key_restriction *keyres = | ||
| 954 | kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | ||
| 955 | |||
| 956 | if (!keyres) | ||
| 957 | return ERR_PTR(-ENOMEM); | ||
| 958 | |||
| 959 | keyres->check = check; | ||
| 960 | |||
| 961 | return keyres; | ||
| 962 | } | ||
| 963 | |||
| 964 | /* | ||
| 965 | * Semaphore to serialise restriction setup to prevent reference count | ||
| 966 | * cycles through restriction key pointers. | ||
| 967 | */ | ||
| 968 | static DECLARE_RWSEM(keyring_serialise_restrict_sem); | ||
| 969 | |||
| 970 | /* | ||
| 971 | * Check for restriction cycles that would prevent keyring garbage collection. | ||
| 972 | * keyring_serialise_restrict_sem must be held. | ||
| 973 | */ | ||
| 974 | static bool keyring_detect_restriction_cycle(const struct key *dest_keyring, | ||
| 975 | struct key_restriction *keyres) | ||
| 976 | { | ||
| 977 | while (keyres && keyres->key && | ||
| 978 | keyres->key->type == &key_type_keyring) { | ||
| 979 | if (keyres->key == dest_keyring) | ||
| 980 | return true; | ||
| 981 | |||
| 982 | keyres = keyres->key->restrict_link; | ||
| 983 | } | ||
| 984 | |||
| 985 | return false; | ||
| 986 | } | ||
| 987 | |||
| 988 | /** | ||
| 989 | * keyring_restrict - Look up and apply a restriction to a keyring | ||
| 990 | * | ||
| 991 | * @keyring: The keyring to be restricted | ||
| 992 | * @restriction: The restriction options to apply to the keyring | ||
| 993 | */ | ||
| 994 | int keyring_restrict(key_ref_t keyring_ref, const char *type, | ||
| 995 | const char *restriction) | ||
| 996 | { | ||
| 997 | struct key *keyring; | ||
| 998 | struct key_type *restrict_type = NULL; | ||
| 999 | struct key_restriction *restrict_link; | ||
| 1000 | int ret = 0; | ||
| 1001 | |||
| 1002 | keyring = key_ref_to_ptr(keyring_ref); | ||
| 1003 | key_check(keyring); | ||
| 1004 | |||
| 1005 | if (keyring->type != &key_type_keyring) | ||
| 1006 | return -ENOTDIR; | ||
| 1007 | |||
| 1008 | if (!type) { | ||
| 1009 | restrict_link = keyring_restriction_alloc(restrict_link_reject); | ||
| 1010 | } else { | ||
| 1011 | restrict_type = key_type_lookup(type); | ||
| 1012 | |||
| 1013 | if (IS_ERR(restrict_type)) | ||
| 1014 | return PTR_ERR(restrict_type); | ||
| 1015 | |||
| 1016 | if (!restrict_type->lookup_restriction) { | ||
| 1017 | ret = -ENOENT; | ||
| 1018 | goto error; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | restrict_link = restrict_type->lookup_restriction(restriction); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | if (IS_ERR(restrict_link)) { | ||
| 1025 | ret = PTR_ERR(restrict_link); | ||
| 1026 | goto error; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | down_write(&keyring->sem); | ||
| 1030 | down_write(&keyring_serialise_restrict_sem); | ||
| 1031 | |||
| 1032 | if (keyring->restrict_link) | ||
| 1033 | ret = -EEXIST; | ||
| 1034 | else if (keyring_detect_restriction_cycle(keyring, restrict_link)) | ||
| 1035 | ret = -EDEADLK; | ||
| 1036 | else | ||
| 1037 | keyring->restrict_link = restrict_link; | ||
| 1038 | |||
| 1039 | up_write(&keyring_serialise_restrict_sem); | ||
| 1040 | up_write(&keyring->sem); | ||
| 1041 | |||
| 1042 | if (ret < 0) { | ||
| 1043 | key_put(restrict_link->key); | ||
| 1044 | kfree(restrict_link); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | error: | ||
| 1048 | if (restrict_type) | ||
| 1049 | key_type_put(restrict_type); | ||
| 1050 | |||
| 1051 | return ret; | ||
| 1052 | } | ||
| 1053 | EXPORT_SYMBOL(keyring_restrict); | ||
| 1054 | |||
| 943 | /* | 1055 | /* |
| 944 | * Search the given keyring for a key that might be updated. | 1056 | * Search the given keyring for a key that might be updated. |
| 945 | * | 1057 | * |
| @@ -1033,7 +1145,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
| 1033 | /* we've got a match but we might end up racing with | 1145 | /* we've got a match but we might end up racing with |
| 1034 | * key_cleanup() if the keyring is currently 'dead' | 1146 | * key_cleanup() if the keyring is currently 'dead' |
| 1035 | * (ie. it has a zero usage count) */ | 1147 | * (ie. it has a zero usage count) */ |
| 1036 | if (!atomic_inc_not_zero(&keyring->usage)) | 1148 | if (!refcount_inc_not_zero(&keyring->usage)) |
| 1037 | continue; | 1149 | continue; |
| 1038 | keyring->last_used_at = current_kernel_time().tv_sec; | 1150 | keyring->last_used_at = current_kernel_time().tv_sec; |
| 1039 | goto out; | 1151 | goto out; |
| @@ -1220,9 +1332,10 @@ void __key_link_end(struct key *keyring, | |||
| 1220 | */ | 1332 | */ |
| 1221 | static int __key_link_check_restriction(struct key *keyring, struct key *key) | 1333 | static int __key_link_check_restriction(struct key *keyring, struct key *key) |
| 1222 | { | 1334 | { |
| 1223 | if (!keyring->restrict_link) | 1335 | if (!keyring->restrict_link || !keyring->restrict_link->check) |
| 1224 | return 0; | 1336 | return 0; |
| 1225 | return keyring->restrict_link(keyring, key->type, &key->payload); | 1337 | return keyring->restrict_link->check(keyring, key->type, &key->payload, |
| 1338 | keyring->restrict_link->key); | ||
| 1226 | } | 1339 | } |
| 1227 | 1340 | ||
| 1228 | /** | 1341 | /** |
| @@ -1250,14 +1363,14 @@ int key_link(struct key *keyring, struct key *key) | |||
| 1250 | struct assoc_array_edit *edit; | 1363 | struct assoc_array_edit *edit; |
| 1251 | int ret; | 1364 | int ret; |
| 1252 | 1365 | ||
| 1253 | kenter("{%d,%d}", keyring->serial, atomic_read(&keyring->usage)); | 1366 | kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage)); |
| 1254 | 1367 | ||
| 1255 | key_check(keyring); | 1368 | key_check(keyring); |
| 1256 | key_check(key); | 1369 | key_check(key); |
| 1257 | 1370 | ||
| 1258 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 1371 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
| 1259 | if (ret == 0) { | 1372 | if (ret == 0) { |
| 1260 | kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); | 1373 | kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage)); |
| 1261 | ret = __key_link_check_restriction(keyring, key); | 1374 | ret = __key_link_check_restriction(keyring, key); |
| 1262 | if (ret == 0) | 1375 | if (ret == 0) |
| 1263 | ret = __key_link_check_live_key(keyring, key); | 1376 | ret = __key_link_check_live_key(keyring, key); |
| @@ -1266,7 +1379,7 @@ int key_link(struct key *keyring, struct key *key) | |||
| 1266 | __key_link_end(keyring, &key->index_key, edit); | 1379 | __key_link_end(keyring, &key->index_key, edit); |
| 1267 | } | 1380 | } |
| 1268 | 1381 | ||
| 1269 | kleave(" = %d {%d,%d}", ret, keyring->serial, atomic_read(&keyring->usage)); | 1382 | kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage)); |
| 1270 | return ret; | 1383 | return ret; |
| 1271 | } | 1384 | } |
| 1272 | EXPORT_SYMBOL(key_link); | 1385 | EXPORT_SYMBOL(key_link); |
| @@ -1426,3 +1539,53 @@ do_gc: | |||
| 1426 | up_write(&keyring->sem); | 1539 | up_write(&keyring->sem); |
| 1427 | kleave(" [gc]"); | 1540 | kleave(" [gc]"); |
| 1428 | } | 1541 | } |
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Garbage collect restriction pointers from a keyring. | ||
| 1545 | * | ||
| 1546 | * Keyring restrictions are associated with a key type, and must be cleaned | ||
| 1547 | * up if the key type is unregistered. The restriction is altered to always | ||
| 1548 | * reject additional keys so a keyring cannot be opened up by unregistering | ||
| 1549 | * a key type. | ||
| 1550 | * | ||
| 1551 | * Not called with any keyring locks held. The keyring's key struct will not | ||
| 1552 | * be deallocated under us as only our caller may deallocate it. | ||
| 1553 | * | ||
| 1554 | * The caller is required to hold key_types_sem and dead_type->sem. This is | ||
| 1555 | * fulfilled by key_gc_keytype() holding the locks on behalf of | ||
| 1556 | * key_garbage_collector(), which it invokes on a workqueue. | ||
| 1557 | */ | ||
| 1558 | void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type) | ||
| 1559 | { | ||
| 1560 | struct key_restriction *keyres; | ||
| 1561 | |||
| 1562 | kenter("%x{%s}", keyring->serial, keyring->description ?: ""); | ||
| 1563 | |||
| 1564 | /* | ||
| 1565 | * keyring->restrict_link is only assigned at key allocation time | ||
| 1566 | * or with the key type locked, so the only values that could be | ||
| 1567 | * concurrently assigned to keyring->restrict_link are for key | ||
| 1568 | * types other than dead_type. Given this, it's ok to check | ||
| 1569 | * the key type before acquiring keyring->sem. | ||
| 1570 | */ | ||
| 1571 | if (!dead_type || !keyring->restrict_link || | ||
| 1572 | keyring->restrict_link->keytype != dead_type) { | ||
| 1573 | kleave(" [no restriction gc]"); | ||
| 1574 | return; | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | /* Lock the keyring to ensure that a link is not in progress */ | ||
| 1578 | down_write(&keyring->sem); | ||
| 1579 | |||
| 1580 | keyres = keyring->restrict_link; | ||
| 1581 | |||
| 1582 | keyres->check = restrict_link_reject; | ||
| 1583 | |||
| 1584 | key_put(keyres->key); | ||
| 1585 | keyres->key = NULL; | ||
| 1586 | keyres->keytype = NULL; | ||
| 1587 | |||
| 1588 | up_write(&keyring->sem); | ||
| 1589 | |||
| 1590 | kleave(" [restriction gc]"); | ||
| 1591 | } | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index b9f531c9e4fa..bf08d02b6646 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
| @@ -252,7 +252,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
| 252 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), | 252 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), |
| 253 | showflag(key, 'N', KEY_FLAG_NEGATIVE), | 253 | showflag(key, 'N', KEY_FLAG_NEGATIVE), |
| 254 | showflag(key, 'i', KEY_FLAG_INVALIDATED), | 254 | showflag(key, 'i', KEY_FLAG_INVALIDATED), |
| 255 | atomic_read(&key->usage), | 255 | refcount_read(&key->usage), |
| 256 | xbuf, | 256 | xbuf, |
| 257 | key->perm, | 257 | key->perm, |
| 258 | from_kuid_munged(seq_user_ns(m), key->uid), | 258 | from_kuid_munged(seq_user_ns(m), key->uid), |
| @@ -340,7 +340,7 @@ static int proc_key_users_show(struct seq_file *m, void *v) | |||
| 340 | 340 | ||
| 341 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", | 341 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", |
| 342 | from_kuid_munged(seq_user_ns(m), user->uid), | 342 | from_kuid_munged(seq_user_ns(m), user->uid), |
| 343 | atomic_read(&user->usage), | 343 | refcount_read(&user->usage), |
| 344 | atomic_read(&user->nkeys), | 344 | atomic_read(&user->nkeys), |
| 345 | atomic_read(&user->nikeys), | 345 | atomic_read(&user->nikeys), |
| 346 | user->qnkeys, | 346 | user->qnkeys, |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 9139b18fc863..2217dfec7996 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -30,7 +30,7 @@ static DEFINE_MUTEX(key_user_keyring_mutex); | |||
| 30 | 30 | ||
| 31 | /* The root user's tracking struct */ | 31 | /* The root user's tracking struct */ |
| 32 | struct key_user root_key_user = { | 32 | struct key_user root_key_user = { |
| 33 | .usage = ATOMIC_INIT(3), | 33 | .usage = REFCOUNT_INIT(3), |
| 34 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), | 34 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), |
| 35 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), | 35 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
| 36 | .nkeys = ATOMIC_INIT(2), | 36 | .nkeys = ATOMIC_INIT(2), |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 6bbe2f535f08..0f062156dfb2 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
| @@ -213,7 +213,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
| 213 | if (ret < 0) | 213 | if (ret < 0) |
| 214 | goto error_inst; | 214 | goto error_inst; |
| 215 | 215 | ||
| 216 | kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage)); | 216 | kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage)); |
| 217 | return authkey; | 217 | return authkey; |
| 218 | 218 | ||
| 219 | auth_key_revoked: | 219 | auth_key_revoked: |
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 1d82eae3a5b8..dbe6efde77a0 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c | |||
| @@ -174,7 +174,7 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id) | |||
| 174 | return 0; | 174 | return 0; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static struct security_hook_list loadpin_hooks[] = { | 177 | static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { |
| 178 | LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), | 178 | LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), |
| 179 | LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), | 179 | LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), |
| 180 | }; | 180 | }; |
diff --git a/security/security.c b/security/security.c index 23555c5504f6..b9fea3999cf8 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | /* Maximum number of letters for an LSM name string */ | 32 | /* Maximum number of letters for an LSM name string */ |
| 33 | #define SECURITY_NAME_MAX 10 | 33 | #define SECURITY_NAME_MAX 10 |
| 34 | 34 | ||
| 35 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; | ||
| 35 | char *lsm_names; | 36 | char *lsm_names; |
| 36 | /* Boot-time LSM user choice */ | 37 | /* Boot-time LSM user choice */ |
| 37 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | 38 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = |
| @@ -54,6 +55,12 @@ static void __init do_security_initcalls(void) | |||
| 54 | */ | 55 | */ |
| 55 | int __init security_init(void) | 56 | int __init security_init(void) |
| 56 | { | 57 | { |
| 58 | int i; | ||
| 59 | struct list_head *list = (struct list_head *) &security_hook_heads; | ||
| 60 | |||
| 61 | for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct list_head); | ||
| 62 | i++) | ||
| 63 | INIT_LIST_HEAD(&list[i]); | ||
| 57 | pr_info("Security Framework initialized\n"); | 64 | pr_info("Security Framework initialized\n"); |
| 58 | 65 | ||
| 59 | /* | 66 | /* |
| @@ -934,6 +941,11 @@ int security_task_create(unsigned long clone_flags) | |||
| 934 | return call_int_hook(task_create, 0, clone_flags); | 941 | return call_int_hook(task_create, 0, clone_flags); |
| 935 | } | 942 | } |
| 936 | 943 | ||
| 944 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) | ||
| 945 | { | ||
| 946 | return call_int_hook(task_alloc, 0, task, clone_flags); | ||
| 947 | } | ||
| 948 | |||
| 937 | void security_task_free(struct task_struct *task) | 949 | void security_task_free(struct task_struct *task) |
| 938 | { | 950 | { |
| 939 | call_void_hook(task_free, task); | 951 | call_void_hook(task_free, task); |
| @@ -1040,6 +1052,12 @@ int security_task_getioprio(struct task_struct *p) | |||
| 1040 | return call_int_hook(task_getioprio, 0, p); | 1052 | return call_int_hook(task_getioprio, 0, p); |
| 1041 | } | 1053 | } |
| 1042 | 1054 | ||
| 1055 | int security_task_prlimit(const struct cred *cred, const struct cred *tcred, | ||
| 1056 | unsigned int flags) | ||
| 1057 | { | ||
| 1058 | return call_int_hook(task_prlimit, 0, cred, tcred, flags); | ||
| 1059 | } | ||
| 1060 | |||
| 1043 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, | 1061 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, |
| 1044 | struct rlimit *new_rlim) | 1062 | struct rlimit *new_rlim) |
| 1045 | { | 1063 | { |
| @@ -1625,355 +1643,3 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, | |||
| 1625 | actx); | 1643 | actx); |
| 1626 | } | 1644 | } |
| 1627 | #endif /* CONFIG_AUDIT */ | 1645 | #endif /* CONFIG_AUDIT */ |
| 1628 | |||
| 1629 | struct security_hook_heads security_hook_heads = { | ||
| 1630 | .binder_set_context_mgr = | ||
| 1631 | LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr), | ||
| 1632 | .binder_transaction = | ||
| 1633 | LIST_HEAD_INIT(security_hook_heads.binder_transaction), | ||
| 1634 | .binder_transfer_binder = | ||
| 1635 | LIST_HEAD_INIT(security_hook_heads.binder_transfer_binder), | ||
| 1636 | .binder_transfer_file = | ||
| 1637 | LIST_HEAD_INIT(security_hook_heads.binder_transfer_file), | ||
| 1638 | |||
| 1639 | .ptrace_access_check = | ||
| 1640 | LIST_HEAD_INIT(security_hook_heads.ptrace_access_check), | ||
| 1641 | .ptrace_traceme = | ||
| 1642 | LIST_HEAD_INIT(security_hook_heads.ptrace_traceme), | ||
| 1643 | .capget = LIST_HEAD_INIT(security_hook_heads.capget), | ||
| 1644 | .capset = LIST_HEAD_INIT(security_hook_heads.capset), | ||
| 1645 | .capable = LIST_HEAD_INIT(security_hook_heads.capable), | ||
| 1646 | .quotactl = LIST_HEAD_INIT(security_hook_heads.quotactl), | ||
| 1647 | .quota_on = LIST_HEAD_INIT(security_hook_heads.quota_on), | ||
| 1648 | .syslog = LIST_HEAD_INIT(security_hook_heads.syslog), | ||
| 1649 | .settime = LIST_HEAD_INIT(security_hook_heads.settime), | ||
| 1650 | .vm_enough_memory = | ||
| 1651 | LIST_HEAD_INIT(security_hook_heads.vm_enough_memory), | ||
| 1652 | .bprm_set_creds = | ||
| 1653 | LIST_HEAD_INIT(security_hook_heads.bprm_set_creds), | ||
| 1654 | .bprm_check_security = | ||
| 1655 | LIST_HEAD_INIT(security_hook_heads.bprm_check_security), | ||
| 1656 | .bprm_secureexec = | ||
| 1657 | LIST_HEAD_INIT(security_hook_heads.bprm_secureexec), | ||
| 1658 | .bprm_committing_creds = | ||
| 1659 | LIST_HEAD_INIT(security_hook_heads.bprm_committing_creds), | ||
| 1660 | .bprm_committed_creds = | ||
| 1661 | LIST_HEAD_INIT(security_hook_heads.bprm_committed_creds), | ||
| 1662 | .sb_alloc_security = | ||
| 1663 | LIST_HEAD_INIT(security_hook_heads.sb_alloc_security), | ||
| 1664 | .sb_free_security = | ||
| 1665 | LIST_HEAD_INIT(security_hook_heads.sb_free_security), | ||
| 1666 | .sb_copy_data = LIST_HEAD_INIT(security_hook_heads.sb_copy_data), | ||
| 1667 | .sb_remount = LIST_HEAD_INIT(security_hook_heads.sb_remount), | ||
| 1668 | .sb_kern_mount = | ||
| 1669 | LIST_HEAD_INIT(security_hook_heads.sb_kern_mount), | ||
| 1670 | .sb_show_options = | ||
| 1671 | LIST_HEAD_INIT(security_hook_heads.sb_show_options), | ||
| 1672 | .sb_statfs = LIST_HEAD_INIT(security_hook_heads.sb_statfs), | ||
| 1673 | .sb_mount = LIST_HEAD_INIT(security_hook_heads.sb_mount), | ||
| 1674 | .sb_umount = LIST_HEAD_INIT(security_hook_heads.sb_umount), | ||
| 1675 | .sb_pivotroot = LIST_HEAD_INIT(security_hook_heads.sb_pivotroot), | ||
| 1676 | .sb_set_mnt_opts = | ||
| 1677 | LIST_HEAD_INIT(security_hook_heads.sb_set_mnt_opts), | ||
| 1678 | .sb_clone_mnt_opts = | ||
| 1679 | LIST_HEAD_INIT(security_hook_heads.sb_clone_mnt_opts), | ||
| 1680 | .sb_parse_opts_str = | ||
| 1681 | LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str), | ||
| 1682 | .dentry_init_security = | ||
| 1683 | LIST_HEAD_INIT(security_hook_heads.dentry_init_security), | ||
| 1684 | .dentry_create_files_as = | ||
| 1685 | LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as), | ||
| 1686 | #ifdef CONFIG_SECURITY_PATH | ||
| 1687 | .path_unlink = LIST_HEAD_INIT(security_hook_heads.path_unlink), | ||
| 1688 | .path_mkdir = LIST_HEAD_INIT(security_hook_heads.path_mkdir), | ||
| 1689 | .path_rmdir = LIST_HEAD_INIT(security_hook_heads.path_rmdir), | ||
| 1690 | .path_mknod = LIST_HEAD_INIT(security_hook_heads.path_mknod), | ||
| 1691 | .path_truncate = | ||
| 1692 | LIST_HEAD_INIT(security_hook_heads.path_truncate), | ||
| 1693 | .path_symlink = LIST_HEAD_INIT(security_hook_heads.path_symlink), | ||
| 1694 | .path_link = LIST_HEAD_INIT(security_hook_heads.path_link), | ||
| 1695 | .path_rename = LIST_HEAD_INIT(security_hook_heads.path_rename), | ||
| 1696 | .path_chmod = LIST_HEAD_INIT(security_hook_heads.path_chmod), | ||
| 1697 | .path_chown = LIST_HEAD_INIT(security_hook_heads.path_chown), | ||
| 1698 | .path_chroot = LIST_HEAD_INIT(security_hook_heads.path_chroot), | ||
| 1699 | #endif | ||
| 1700 | .inode_alloc_security = | ||
| 1701 | LIST_HEAD_INIT(security_hook_heads.inode_alloc_security), | ||
| 1702 | .inode_free_security = | ||
| 1703 | LIST_HEAD_INIT(security_hook_heads.inode_free_security), | ||
| 1704 | .inode_init_security = | ||
| 1705 | LIST_HEAD_INIT(security_hook_heads.inode_init_security), | ||
| 1706 | .inode_create = LIST_HEAD_INIT(security_hook_heads.inode_create), | ||
| 1707 | .inode_link = LIST_HEAD_INIT(security_hook_heads.inode_link), | ||
| 1708 | .inode_unlink = LIST_HEAD_INIT(security_hook_heads.inode_unlink), | ||
| 1709 | .inode_symlink = | ||
| 1710 | LIST_HEAD_INIT(security_hook_heads.inode_symlink), | ||
| 1711 | .inode_mkdir = LIST_HEAD_INIT(security_hook_heads.inode_mkdir), | ||
| 1712 | .inode_rmdir = LIST_HEAD_INIT(security_hook_heads.inode_rmdir), | ||
| 1713 | .inode_mknod = LIST_HEAD_INIT(security_hook_heads.inode_mknod), | ||
| 1714 | .inode_rename = LIST_HEAD_INIT(security_hook_heads.inode_rename), | ||
| 1715 | .inode_readlink = | ||
| 1716 | LIST_HEAD_INIT(security_hook_heads.inode_readlink), | ||
| 1717 | .inode_follow_link = | ||
| 1718 | LIST_HEAD_INIT(security_hook_heads.inode_follow_link), | ||
| 1719 | .inode_permission = | ||
| 1720 | LIST_HEAD_INIT(security_hook_heads.inode_permission), | ||
| 1721 | .inode_setattr = | ||
| 1722 | LIST_HEAD_INIT(security_hook_heads.inode_setattr), | ||
| 1723 | .inode_getattr = | ||
| 1724 | LIST_HEAD_INIT(security_hook_heads.inode_getattr), | ||
| 1725 | .inode_setxattr = | ||
| 1726 | LIST_HEAD_INIT(security_hook_heads.inode_setxattr), | ||
| 1727 | .inode_post_setxattr = | ||
| 1728 | LIST_HEAD_INIT(security_hook_heads.inode_post_setxattr), | ||
| 1729 | .inode_getxattr = | ||
| 1730 | LIST_HEAD_INIT(security_hook_heads.inode_getxattr), | ||
| 1731 | .inode_listxattr = | ||
| 1732 | LIST_HEAD_INIT(security_hook_heads.inode_listxattr), | ||
| 1733 | .inode_removexattr = | ||
| 1734 | LIST_HEAD_INIT(security_hook_heads.inode_removexattr), | ||
| 1735 | .inode_need_killpriv = | ||
| 1736 | LIST_HEAD_INIT(security_hook_heads.inode_need_killpriv), | ||
| 1737 | .inode_killpriv = | ||
| 1738 | LIST_HEAD_INIT(security_hook_heads.inode_killpriv), | ||
| 1739 | .inode_getsecurity = | ||
| 1740 | LIST_HEAD_INIT(security_hook_heads.inode_getsecurity), | ||
| 1741 | .inode_setsecurity = | ||
| 1742 | LIST_HEAD_INIT(security_hook_heads.inode_setsecurity), | ||
| 1743 | .inode_listsecurity = | ||
| 1744 | LIST_HEAD_INIT(security_hook_heads.inode_listsecurity), | ||
| 1745 | .inode_getsecid = | ||
| 1746 | LIST_HEAD_INIT(security_hook_heads.inode_getsecid), | ||
| 1747 | .inode_copy_up = | ||
| 1748 | LIST_HEAD_INIT(security_hook_heads.inode_copy_up), | ||
| 1749 | .inode_copy_up_xattr = | ||
| 1750 | LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr), | ||
| 1751 | .file_permission = | ||
| 1752 | LIST_HEAD_INIT(security_hook_heads.file_permission), | ||
| 1753 | .file_alloc_security = | ||
| 1754 | LIST_HEAD_INIT(security_hook_heads.file_alloc_security), | ||
| 1755 | .file_free_security = | ||
| 1756 | LIST_HEAD_INIT(security_hook_heads.file_free_security), | ||
| 1757 | .file_ioctl = LIST_HEAD_INIT(security_hook_heads.file_ioctl), | ||
| 1758 | .mmap_addr = LIST_HEAD_INIT(security_hook_heads.mmap_addr), | ||
| 1759 | .mmap_file = LIST_HEAD_INIT(security_hook_heads.mmap_file), | ||
| 1760 | .file_mprotect = | ||
| 1761 | LIST_HEAD_INIT(security_hook_heads.file_mprotect), | ||
| 1762 | .file_lock = LIST_HEAD_INIT(security_hook_heads.file_lock), | ||
| 1763 | .file_fcntl = LIST_HEAD_INIT(security_hook_heads.file_fcntl), | ||
| 1764 | .file_set_fowner = | ||
| 1765 | LIST_HEAD_INIT(security_hook_heads.file_set_fowner), | ||
| 1766 | .file_send_sigiotask = | ||
| 1767 | LIST_HEAD_INIT(security_hook_heads.file_send_sigiotask), | ||
| 1768 | .file_receive = LIST_HEAD_INIT(security_hook_heads.file_receive), | ||
| 1769 | .file_open = LIST_HEAD_INIT(security_hook_heads.file_open), | ||
| 1770 | .task_create = LIST_HEAD_INIT(security_hook_heads.task_create), | ||
| 1771 | .task_free = LIST_HEAD_INIT(security_hook_heads.task_free), | ||
| 1772 | .cred_alloc_blank = | ||
| 1773 | LIST_HEAD_INIT(security_hook_heads.cred_alloc_blank), | ||
| 1774 | .cred_free = LIST_HEAD_INIT(security_hook_heads.cred_free), | ||
| 1775 | .cred_prepare = LIST_HEAD_INIT(security_hook_heads.cred_prepare), | ||
| 1776 | .cred_transfer = | ||
| 1777 | LIST_HEAD_INIT(security_hook_heads.cred_transfer), | ||
| 1778 | .kernel_act_as = | ||
| 1779 | LIST_HEAD_INIT(security_hook_heads.kernel_act_as), | ||
| 1780 | .kernel_create_files_as = | ||
| 1781 | LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as), | ||
| 1782 | .kernel_module_request = | ||
| 1783 | LIST_HEAD_INIT(security_hook_heads.kernel_module_request), | ||
| 1784 | .kernel_read_file = | ||
| 1785 | LIST_HEAD_INIT(security_hook_heads.kernel_read_file), | ||
| 1786 | .kernel_post_read_file = | ||
| 1787 | LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file), | ||
| 1788 | .task_fix_setuid = | ||
| 1789 | LIST_HEAD_INIT(security_hook_heads.task_fix_setuid), | ||
| 1790 | .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid), | ||
| 1791 | .task_getpgid = LIST_HEAD_INIT(security_hook_heads.task_getpgid), | ||
| 1792 | .task_getsid = LIST_HEAD_INIT(security_hook_heads.task_getsid), | ||
| 1793 | .task_getsecid = | ||
| 1794 | LIST_HEAD_INIT(security_hook_heads.task_getsecid), | ||
| 1795 | .task_setnice = LIST_HEAD_INIT(security_hook_heads.task_setnice), | ||
| 1796 | .task_setioprio = | ||
| 1797 | LIST_HEAD_INIT(security_hook_heads.task_setioprio), | ||
| 1798 | .task_getioprio = | ||
| 1799 | LIST_HEAD_INIT(security_hook_heads.task_getioprio), | ||
| 1800 | .task_setrlimit = | ||
| 1801 | LIST_HEAD_INIT(security_hook_heads.task_setrlimit), | ||
| 1802 | .task_setscheduler = | ||
| 1803 | LIST_HEAD_INIT(security_hook_heads.task_setscheduler), | ||
| 1804 | .task_getscheduler = | ||
| 1805 | LIST_HEAD_INIT(security_hook_heads.task_getscheduler), | ||
| 1806 | .task_movememory = | ||
| 1807 | LIST_HEAD_INIT(security_hook_heads.task_movememory), | ||
| 1808 | .task_kill = LIST_HEAD_INIT(security_hook_heads.task_kill), | ||
| 1809 | .task_prctl = LIST_HEAD_INIT(security_hook_heads.task_prctl), | ||
| 1810 | .task_to_inode = | ||
| 1811 | LIST_HEAD_INIT(security_hook_heads.task_to_inode), | ||
| 1812 | .ipc_permission = | ||
| 1813 | LIST_HEAD_INIT(security_hook_heads.ipc_permission), | ||
| 1814 | .ipc_getsecid = LIST_HEAD_INIT(security_hook_heads.ipc_getsecid), | ||
| 1815 | .msg_msg_alloc_security = | ||
| 1816 | LIST_HEAD_INIT(security_hook_heads.msg_msg_alloc_security), | ||
| 1817 | .msg_msg_free_security = | ||
| 1818 | LIST_HEAD_INIT(security_hook_heads.msg_msg_free_security), | ||
| 1819 | .msg_queue_alloc_security = | ||
| 1820 | LIST_HEAD_INIT(security_hook_heads.msg_queue_alloc_security), | ||
| 1821 | .msg_queue_free_security = | ||
| 1822 | LIST_HEAD_INIT(security_hook_heads.msg_queue_free_security), | ||
| 1823 | .msg_queue_associate = | ||
| 1824 | LIST_HEAD_INIT(security_hook_heads.msg_queue_associate), | ||
| 1825 | .msg_queue_msgctl = | ||
| 1826 | LIST_HEAD_INIT(security_hook_heads.msg_queue_msgctl), | ||
| 1827 | .msg_queue_msgsnd = | ||
| 1828 | LIST_HEAD_INIT(security_hook_heads.msg_queue_msgsnd), | ||
| 1829 | .msg_queue_msgrcv = | ||
| 1830 | LIST_HEAD_INIT(security_hook_heads.msg_queue_msgrcv), | ||
| 1831 | .shm_alloc_security = | ||
| 1832 | LIST_HEAD_INIT(security_hook_heads.shm_alloc_security), | ||
| 1833 | .shm_free_security = | ||
| 1834 | LIST_HEAD_INIT(security_hook_heads.shm_free_security), | ||
| 1835 | .shm_associate = | ||
| 1836 | LIST_HEAD_INIT(security_hook_heads.shm_associate), | ||
| 1837 | .shm_shmctl = LIST_HEAD_INIT(security_hook_heads.shm_shmctl), | ||
| 1838 | .shm_shmat = LIST_HEAD_INIT(security_hook_heads.shm_shmat), | ||
| 1839 | .sem_alloc_security = | ||
| 1840 | LIST_HEAD_INIT(security_hook_heads.sem_alloc_security), | ||
| 1841 | .sem_free_security = | ||
| 1842 | LIST_HEAD_INIT(security_hook_heads.sem_free_security), | ||
| 1843 | .sem_associate = | ||
| 1844 | LIST_HEAD_INIT(security_hook_heads.sem_associate), | ||
| 1845 | .sem_semctl = LIST_HEAD_INIT(security_hook_heads.sem_semctl), | ||
| 1846 | .sem_semop = LIST_HEAD_INIT(security_hook_heads.sem_semop), | ||
| 1847 | .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send), | ||
| 1848 | .d_instantiate = | ||
| 1849 | LIST_HEAD_INIT(security_hook_heads.d_instantiate), | ||
| 1850 | .getprocattr = LIST_HEAD_INIT(security_hook_heads.getprocattr), | ||
| 1851 | .setprocattr = LIST_HEAD_INIT(security_hook_heads.setprocattr), | ||
| 1852 | .ismaclabel = LIST_HEAD_INIT(security_hook_heads.ismaclabel), | ||
| 1853 | .secid_to_secctx = | ||
| 1854 | LIST_HEAD_INIT(security_hook_heads.secid_to_secctx), | ||
| 1855 | .secctx_to_secid = | ||
| 1856 | LIST_HEAD_INIT(security_hook_heads.secctx_to_secid), | ||
| 1857 | .release_secctx = | ||
| 1858 | LIST_HEAD_INIT(security_hook_heads.release_secctx), | ||
| 1859 | .inode_invalidate_secctx = | ||
| 1860 | LIST_HEAD_INIT(security_hook_heads.inode_invalidate_secctx), | ||
| 1861 | .inode_notifysecctx = | ||
| 1862 | LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx), | ||
| 1863 | .inode_setsecctx = | ||
| 1864 | LIST_HEAD_INIT(security_hook_heads.inode_setsecctx), | ||
| 1865 | .inode_getsecctx = | ||
| 1866 | LIST_HEAD_INIT(security_hook_heads.inode_getsecctx), | ||
| 1867 | #ifdef CONFIG_SECURITY_NETWORK | ||
| 1868 | .unix_stream_connect = | ||
| 1869 | LIST_HEAD_INIT(security_hook_heads.unix_stream_connect), | ||
| 1870 | .unix_may_send = | ||
| 1871 | LIST_HEAD_INIT(security_hook_heads.unix_may_send), | ||
| 1872 | .socket_create = | ||
| 1873 | LIST_HEAD_INIT(security_hook_heads.socket_create), | ||
| 1874 | .socket_post_create = | ||
| 1875 | LIST_HEAD_INIT(security_hook_heads.socket_post_create), | ||
| 1876 | .socket_bind = LIST_HEAD_INIT(security_hook_heads.socket_bind), | ||
| 1877 | .socket_connect = | ||
| 1878 | LIST_HEAD_INIT(security_hook_heads.socket_connect), | ||
| 1879 | .socket_listen = | ||
| 1880 | LIST_HEAD_INIT(security_hook_heads.socket_listen), | ||
| 1881 | .socket_accept = | ||
| 1882 | LIST_HEAD_INIT(security_hook_heads.socket_accept), | ||
| 1883 | .socket_sendmsg = | ||
| 1884 | LIST_HEAD_INIT(security_hook_heads.socket_sendmsg), | ||
| 1885 | .socket_recvmsg = | ||
| 1886 | LIST_HEAD_INIT(security_hook_heads.socket_recvmsg), | ||
| 1887 | .socket_getsockname = | ||
| 1888 | LIST_HEAD_INIT(security_hook_heads.socket_getsockname), | ||
| 1889 | .socket_getpeername = | ||
| 1890 | LIST_HEAD_INIT(security_hook_heads.socket_getpeername), | ||
| 1891 | .socket_getsockopt = | ||
| 1892 | LIST_HEAD_INIT(security_hook_heads.socket_getsockopt), | ||
| 1893 | .socket_setsockopt = | ||
| 1894 | LIST_HEAD_INIT(security_hook_heads.socket_setsockopt), | ||
| 1895 | .socket_shutdown = | ||
| 1896 | LIST_HEAD_INIT(security_hook_heads.socket_shutdown), | ||
| 1897 | .socket_sock_rcv_skb = | ||
| 1898 | LIST_HEAD_INIT(security_hook_heads.socket_sock_rcv_skb), | ||
| 1899 | .socket_getpeersec_stream = | ||
| 1900 | LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_stream), | ||
| 1901 | .socket_getpeersec_dgram = | ||
| 1902 | LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_dgram), | ||
| 1903 | .sk_alloc_security = | ||
| 1904 | LIST_HEAD_INIT(security_hook_heads.sk_alloc_security), | ||
| 1905 | .sk_free_security = | ||
| 1906 | LIST_HEAD_INIT(security_hook_heads.sk_free_security), | ||
| 1907 | .sk_clone_security = | ||
| 1908 | LIST_HEAD_INIT(security_hook_heads.sk_clone_security), | ||
| 1909 | .sk_getsecid = LIST_HEAD_INIT(security_hook_heads.sk_getsecid), | ||
| 1910 | .sock_graft = LIST_HEAD_INIT(security_hook_heads.sock_graft), | ||
| 1911 | .inet_conn_request = | ||
| 1912 | LIST_HEAD_INIT(security_hook_heads.inet_conn_request), | ||
| 1913 | .inet_csk_clone = | ||
| 1914 | LIST_HEAD_INIT(security_hook_heads.inet_csk_clone), | ||
| 1915 | .inet_conn_established = | ||
| 1916 | LIST_HEAD_INIT(security_hook_heads.inet_conn_established), | ||
| 1917 | .secmark_relabel_packet = | ||
| 1918 | LIST_HEAD_INIT(security_hook_heads.secmark_relabel_packet), | ||
| 1919 | .secmark_refcount_inc = | ||
| 1920 | LIST_HEAD_INIT(security_hook_heads.secmark_refcount_inc), | ||
| 1921 | .secmark_refcount_dec = | ||
| 1922 | LIST_HEAD_INIT(security_hook_heads.secmark_refcount_dec), | ||
| 1923 | .req_classify_flow = | ||
| 1924 | LIST_HEAD_INIT(security_hook_heads.req_classify_flow), | ||
| 1925 | .tun_dev_alloc_security = | ||
| 1926 | LIST_HEAD_INIT(security_hook_heads.tun_dev_alloc_security), | ||
| 1927 | .tun_dev_free_security = | ||
| 1928 | LIST_HEAD_INIT(security_hook_heads.tun_dev_free_security), | ||
| 1929 | .tun_dev_create = | ||
| 1930 | LIST_HEAD_INIT(security_hook_heads.tun_dev_create), | ||
| 1931 | .tun_dev_attach_queue = | ||
| 1932 | LIST_HEAD_INIT(security_hook_heads.tun_dev_attach_queue), | ||
| 1933 | .tun_dev_attach = | ||
| 1934 | LIST_HEAD_INIT(security_hook_heads.tun_dev_attach), | ||
| 1935 | .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open), | ||
| 1936 | #endif /* CONFIG_SECURITY_NETWORK */ | ||
| 1937 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | ||
| 1938 | .xfrm_policy_alloc_security = | ||
| 1939 | LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security), | ||
| 1940 | .xfrm_policy_clone_security = | ||
| 1941 | LIST_HEAD_INIT(security_hook_heads.xfrm_policy_clone_security), | ||
| 1942 | .xfrm_policy_free_security = | ||
| 1943 | LIST_HEAD_INIT(security_hook_heads.xfrm_policy_free_security), | ||
| 1944 | .xfrm_policy_delete_security = | ||
| 1945 | LIST_HEAD_INIT(security_hook_heads.xfrm_policy_delete_security), | ||
| 1946 | .xfrm_state_alloc = | ||
| 1947 | LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc), | ||
| 1948 | .xfrm_state_alloc_acquire = | ||
| 1949 | LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc_acquire), | ||
| 1950 | .xfrm_state_free_security = | ||
| 1951 | LIST_HEAD_INIT(security_hook_heads.xfrm_state_free_security), | ||
| 1952 | .xfrm_state_delete_security = | ||
| 1953 | LIST_HEAD_INIT(security_hook_heads.xfrm_state_delete_security), | ||
| 1954 | .xfrm_policy_lookup = | ||
| 1955 | LIST_HEAD_INIT(security_hook_heads.xfrm_policy_lookup), | ||
| 1956 | .xfrm_state_pol_flow_match = | ||
| 1957 | LIST_HEAD_INIT(security_hook_heads.xfrm_state_pol_flow_match), | ||
| 1958 | .xfrm_decode_session = | ||
| 1959 | LIST_HEAD_INIT(security_hook_heads.xfrm_decode_session), | ||
| 1960 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | ||
| 1961 | #ifdef CONFIG_KEYS | ||
| 1962 | .key_alloc = LIST_HEAD_INIT(security_hook_heads.key_alloc), | ||
| 1963 | .key_free = LIST_HEAD_INIT(security_hook_heads.key_free), | ||
| 1964 | .key_permission = | ||
| 1965 | LIST_HEAD_INIT(security_hook_heads.key_permission), | ||
| 1966 | .key_getsecurity = | ||
| 1967 | LIST_HEAD_INIT(security_hook_heads.key_getsecurity), | ||
| 1968 | #endif /* CONFIG_KEYS */ | ||
| 1969 | #ifdef CONFIG_AUDIT | ||
| 1970 | .audit_rule_init = | ||
| 1971 | LIST_HEAD_INIT(security_hook_heads.audit_rule_init), | ||
| 1972 | .audit_rule_known = | ||
| 1973 | LIST_HEAD_INIT(security_hook_heads.audit_rule_known), | ||
| 1974 | .audit_rule_match = | ||
| 1975 | LIST_HEAD_INIT(security_hook_heads.audit_rule_match), | ||
| 1976 | .audit_rule_free = | ||
| 1977 | LIST_HEAD_INIT(security_hook_heads.audit_rule_free), | ||
| 1978 | #endif /* CONFIG_AUDIT */ | ||
| 1979 | }; | ||
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index ea7e3efbe0f7..8af7a690eb40 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig | |||
| @@ -40,6 +40,7 @@ config SECURITY_SELINUX_BOOTPARAM_VALUE | |||
| 40 | config SECURITY_SELINUX_DISABLE | 40 | config SECURITY_SELINUX_DISABLE |
| 41 | bool "NSA SELinux runtime disable" | 41 | bool "NSA SELinux runtime disable" |
| 42 | depends on SECURITY_SELINUX | 42 | depends on SECURITY_SELINUX |
| 43 | select SECURITY_WRITABLE_HOOKS | ||
| 43 | default n | 44 | default n |
| 44 | help | 45 | help |
| 45 | This option enables writing to a selinuxfs node 'disable', which | 46 | This option enables writing to a selinuxfs node 'disable', which |
| @@ -50,6 +51,11 @@ config SECURITY_SELINUX_DISABLE | |||
| 50 | portability across platforms where boot parameters are difficult | 51 | portability across platforms where boot parameters are difficult |
| 51 | to employ. | 52 | to employ. |
| 52 | 53 | ||
| 54 | NOTE: selecting this option will disable the '__ro_after_init' | ||
| 55 | kernel hardening feature for security hooks. Please consider | ||
| 56 | using the selinux=0 boot parameter instead of enabling this | ||
| 57 | option. | ||
| 58 | |||
| 53 | If you are unsure how to answer this question, answer N. | 59 | If you are unsure how to answer this question, answer N. |
| 54 | 60 | ||
| 55 | config SECURITY_SELINUX_DEVELOP | 61 | config SECURITY_SELINUX_DEVELOP |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0c2ac318aa7f..e67a526d1f30 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -3920,6 +3920,21 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
| 3920 | PROCESS__GETSCHED, NULL); | 3920 | PROCESS__GETSCHED, NULL); |
| 3921 | } | 3921 | } |
| 3922 | 3922 | ||
| 3923 | int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, | ||
| 3924 | unsigned int flags) | ||
| 3925 | { | ||
| 3926 | u32 av = 0; | ||
| 3927 | |||
| 3928 | if (!flags) | ||
| 3929 | return 0; | ||
| 3930 | if (flags & LSM_PRLIMIT_WRITE) | ||
| 3931 | av |= PROCESS__SETRLIMIT; | ||
| 3932 | if (flags & LSM_PRLIMIT_READ) | ||
| 3933 | av |= PROCESS__GETRLIMIT; | ||
| 3934 | return avc_has_perm(cred_sid(cred), cred_sid(tcred), | ||
| 3935 | SECCLASS_PROCESS, av, NULL); | ||
| 3936 | } | ||
| 3937 | |||
| 3923 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | 3938 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
| 3924 | struct rlimit *new_rlim) | 3939 | struct rlimit *new_rlim) |
| 3925 | { | 3940 | { |
| @@ -4352,10 +4367,18 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4352 | u32 sid, node_perm; | 4367 | u32 sid, node_perm; |
| 4353 | 4368 | ||
| 4354 | if (family == PF_INET) { | 4369 | if (family == PF_INET) { |
| 4370 | if (addrlen < sizeof(struct sockaddr_in)) { | ||
| 4371 | err = -EINVAL; | ||
| 4372 | goto out; | ||
| 4373 | } | ||
| 4355 | addr4 = (struct sockaddr_in *)address; | 4374 | addr4 = (struct sockaddr_in *)address; |
| 4356 | snum = ntohs(addr4->sin_port); | 4375 | snum = ntohs(addr4->sin_port); |
| 4357 | addrp = (char *)&addr4->sin_addr.s_addr; | 4376 | addrp = (char *)&addr4->sin_addr.s_addr; |
| 4358 | } else { | 4377 | } else { |
| 4378 | if (addrlen < SIN6_LEN_RFC2133) { | ||
| 4379 | err = -EINVAL; | ||
| 4380 | goto out; | ||
| 4381 | } | ||
| 4359 | addr6 = (struct sockaddr_in6 *)address; | 4382 | addr6 = (struct sockaddr_in6 *)address; |
| 4360 | snum = ntohs(addr6->sin6_port); | 4383 | snum = ntohs(addr6->sin6_port); |
| 4361 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 4384 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
| @@ -6108,7 +6131,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
| 6108 | 6131 | ||
| 6109 | #endif | 6132 | #endif |
| 6110 | 6133 | ||
| 6111 | static struct security_hook_list selinux_hooks[] = { | 6134 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { |
| 6112 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), | 6135 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), |
| 6113 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), | 6136 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), |
| 6114 | LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder), | 6137 | LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder), |
| @@ -6206,6 +6229,7 @@ static struct security_hook_list selinux_hooks[] = { | |||
| 6206 | LSM_HOOK_INIT(task_setnice, selinux_task_setnice), | 6229 | LSM_HOOK_INIT(task_setnice, selinux_task_setnice), |
| 6207 | LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio), | 6230 | LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio), |
| 6208 | LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio), | 6231 | LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio), |
| 6232 | LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit), | ||
| 6209 | LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit), | 6233 | LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit), |
| 6210 | LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler), | 6234 | LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler), |
| 6211 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), | 6235 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), |
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index d429c4a1c551..1e0cc9b5de20 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
| @@ -47,7 +47,7 @@ struct security_class_mapping secclass_map[] = { | |||
| 47 | "getattr", "setexec", "setfscreate", "noatsecure", "siginh", | 47 | "getattr", "setexec", "setfscreate", "noatsecure", "siginh", |
| 48 | "setrlimit", "rlimitinh", "dyntransition", "setcurrent", | 48 | "setrlimit", "rlimitinh", "dyntransition", "setcurrent", |
| 49 | "execmem", "execstack", "execheap", "setkeycreate", | 49 | "execmem", "execstack", "execheap", "setkeycreate", |
| 50 | "setsockcreate", NULL } }, | 50 | "setsockcreate", "getrlimit", NULL } }, |
| 51 | { "system", | 51 | { "system", |
| 52 | { "ipc_info", "syslog_read", "syslog_mod", | 52 | { "ipc_info", "syslog_read", "syslog_mod", |
| 53 | "syslog_console", "module_request", "module_load", NULL } }, | 53 | "syslog_console", "module_request", "module_load", NULL } }, |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 8e67bb4c9cab..5aeaf30b7a13 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
| @@ -28,7 +28,7 @@ struct nlmsg_perm { | |||
| 28 | u32 perm; | 28 | u32 perm; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static struct nlmsg_perm nlmsg_route_perms[] = | 31 | static const struct nlmsg_perm nlmsg_route_perms[] = |
| 32 | { | 32 | { |
| 33 | { RTM_NEWLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 33 | { RTM_NEWLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
| 34 | { RTM_DELLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 34 | { RTM_DELLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
| @@ -81,7 +81,7 @@ static struct nlmsg_perm nlmsg_route_perms[] = | |||
| 81 | { RTM_GETSTATS, NETLINK_ROUTE_SOCKET__NLMSG_READ }, | 81 | { RTM_GETSTATS, NETLINK_ROUTE_SOCKET__NLMSG_READ }, |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | 84 | static const struct nlmsg_perm nlmsg_tcpdiag_perms[] = |
| 85 | { | 85 | { |
| 86 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 86 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
| 87 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 87 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
| @@ -89,7 +89,7 @@ static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | |||
| 89 | { SOCK_DESTROY, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE }, | 89 | { SOCK_DESTROY, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE }, |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | static struct nlmsg_perm nlmsg_xfrm_perms[] = | 92 | static const struct nlmsg_perm nlmsg_xfrm_perms[] = |
| 93 | { | 93 | { |
| 94 | { XFRM_MSG_NEWSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, | 94 | { XFRM_MSG_NEWSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, |
| 95 | { XFRM_MSG_DELSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, | 95 | { XFRM_MSG_DELSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, |
| @@ -116,7 +116,7 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] = | |||
| 116 | { XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ }, | 116 | { XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ }, |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | static struct nlmsg_perm nlmsg_audit_perms[] = | 119 | static const struct nlmsg_perm nlmsg_audit_perms[] = |
| 120 | { | 120 | { |
| 121 | { AUDIT_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | 121 | { AUDIT_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, |
| 122 | { AUDIT_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | 122 | { AUDIT_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, |
| @@ -137,7 +137,7 @@ static struct nlmsg_perm nlmsg_audit_perms[] = | |||
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | 139 | ||
| 140 | static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize) | 140 | static int nlmsg_perm(u16 nlmsg_type, u32 *perm, const struct nlmsg_perm *tab, size_t tabsize) |
| 141 | { | 141 | { |
| 142 | int i, err = -EINVAL; | 142 | int i, err = -EINVAL; |
| 143 | 143 | ||
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cb3fd98fb05a..ce7171884223 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1456,10 +1456,10 @@ static int sel_avc_stats_seq_show(struct seq_file *seq, void *v) | |||
| 1456 | { | 1456 | { |
| 1457 | struct avc_cache_stats *st = v; | 1457 | struct avc_cache_stats *st = v; |
| 1458 | 1458 | ||
| 1459 | if (v == SEQ_START_TOKEN) | 1459 | if (v == SEQ_START_TOKEN) { |
| 1460 | seq_printf(seq, "lookups hits misses allocations reclaims " | 1460 | seq_puts(seq, |
| 1461 | "frees\n"); | 1461 | "lookups hits misses allocations reclaims frees\n"); |
| 1462 | else { | 1462 | } else { |
| 1463 | unsigned int lookups = st->lookups; | 1463 | unsigned int lookups = st->lookups; |
| 1464 | unsigned int misses = st->misses; | 1464 | unsigned int misses = st->misses; |
| 1465 | unsigned int hits = lookups - misses; | 1465 | unsigned int hits = lookups - misses; |
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 34afeadd9e73..771c96afe1d5 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
| @@ -176,8 +176,9 @@ void cond_policydb_destroy(struct policydb *p) | |||
| 176 | int cond_init_bool_indexes(struct policydb *p) | 176 | int cond_init_bool_indexes(struct policydb *p) |
| 177 | { | 177 | { |
| 178 | kfree(p->bool_val_to_struct); | 178 | kfree(p->bool_val_to_struct); |
| 179 | p->bool_val_to_struct = | 179 | p->bool_val_to_struct = kmalloc_array(p->p_bools.nprim, |
| 180 | kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL); | 180 | sizeof(*p->bool_val_to_struct), |
| 181 | GFP_KERNEL); | ||
| 181 | if (!p->bool_val_to_struct) | 182 | if (!p->bool_val_to_struct) |
| 182 | return -ENOMEM; | 183 | return -ENOMEM; |
| 183 | return 0; | 184 | return 0; |
| @@ -226,7 +227,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
| 226 | u32 len; | 227 | u32 len; |
| 227 | int rc; | 228 | int rc; |
| 228 | 229 | ||
| 229 | booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 230 | booldatum = kzalloc(sizeof(*booldatum), GFP_KERNEL); |
| 230 | if (!booldatum) | 231 | if (!booldatum) |
| 231 | return -ENOMEM; | 232 | return -ENOMEM; |
| 232 | 233 | ||
| @@ -331,7 +332,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
| 331 | goto err; | 332 | goto err; |
| 332 | } | 333 | } |
| 333 | 334 | ||
| 334 | list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); | 335 | list = kzalloc(sizeof(*list), GFP_KERNEL); |
| 335 | if (!list) { | 336 | if (!list) { |
| 336 | rc = -ENOMEM; | 337 | rc = -ENOMEM; |
| 337 | goto err; | 338 | goto err; |
| @@ -420,7 +421,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
| 420 | goto err; | 421 | goto err; |
| 421 | 422 | ||
| 422 | rc = -ENOMEM; | 423 | rc = -ENOMEM; |
| 423 | expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); | 424 | expr = kzalloc(sizeof(*expr), GFP_KERNEL); |
| 424 | if (!expr) | 425 | if (!expr) |
| 425 | goto err; | 426 | goto err; |
| 426 | 427 | ||
| @@ -471,7 +472,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
| 471 | 472 | ||
| 472 | for (i = 0; i < len; i++) { | 473 | for (i = 0; i < len; i++) { |
| 473 | rc = -ENOMEM; | 474 | rc = -ENOMEM; |
| 474 | node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); | 475 | node = kzalloc(sizeof(*node), GFP_KERNEL); |
| 475 | if (!node) | 476 | if (!node) |
| 476 | goto err; | 477 | goto err; |
| 477 | 478 | ||
| @@ -663,5 +664,4 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, | |||
| 663 | (node->key.specified & AVTAB_XPERMS)) | 664 | (node->key.specified & AVTAB_XPERMS)) |
| 664 | services_compute_xperms_drivers(xperms, node); | 665 | services_compute_xperms_drivers(xperms, node); |
| 665 | } | 666 | } |
| 666 | return; | ||
| 667 | } | 667 | } |
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 2cc496149842..3858706a29fb 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c | |||
| @@ -17,15 +17,15 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void * | |||
| 17 | u32 i; | 17 | u32 i; |
| 18 | 18 | ||
| 19 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 19 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 20 | if (p == NULL) | 20 | if (!p) |
| 21 | return p; | 21 | return p; |
| 22 | 22 | ||
| 23 | p->size = size; | 23 | p->size = size; |
| 24 | p->nel = 0; | 24 | p->nel = 0; |
| 25 | p->hash_value = hash_value; | 25 | p->hash_value = hash_value; |
| 26 | p->keycmp = keycmp; | 26 | p->keycmp = keycmp; |
| 27 | p->htable = kmalloc(sizeof(*(p->htable)) * size, GFP_KERNEL); | 27 | p->htable = kmalloc_array(size, sizeof(*p->htable), GFP_KERNEL); |
| 28 | if (p->htable == NULL) { | 28 | if (!p->htable) { |
| 29 | kfree(p); | 29 | kfree(p); |
| 30 | return NULL; | 30 | return NULL; |
| 31 | } | 31 | } |
| @@ -58,7 +58,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum) | |||
| 58 | return -EEXIST; | 58 | return -EEXIST; |
| 59 | 59 | ||
| 60 | newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); | 60 | newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); |
| 61 | if (newnode == NULL) | 61 | if (!newnode) |
| 62 | return -ENOMEM; | 62 | return -ENOMEM; |
| 63 | newnode->key = key; | 63 | newnode->key = key; |
| 64 | newnode->datum = datum; | 64 | newnode->datum = datum; |
| @@ -87,7 +87,7 @@ void *hashtab_search(struct hashtab *h, const void *key) | |||
| 87 | while (cur && h->keycmp(h, key, cur->key) > 0) | 87 | while (cur && h->keycmp(h, key, cur->key) > 0) |
| 88 | cur = cur->next; | 88 | cur = cur->next; |
| 89 | 89 | ||
| 90 | if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) | 90 | if (!cur || (h->keycmp(h, key, cur->key) != 0)) |
| 91 | return NULL; | 91 | return NULL; |
| 92 | 92 | ||
| 93 | return cur->datum; | 93 | return cur->datum; |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 9c92f29a38ea..0080122760ad 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
| @@ -178,10 +178,9 @@ static int roles_init(struct policydb *p) | |||
| 178 | int rc; | 178 | int rc; |
| 179 | struct role_datum *role; | 179 | struct role_datum *role; |
| 180 | 180 | ||
| 181 | rc = -ENOMEM; | ||
| 182 | role = kzalloc(sizeof(*role), GFP_KERNEL); | 181 | role = kzalloc(sizeof(*role), GFP_KERNEL); |
| 183 | if (!role) | 182 | if (!role) |
| 184 | goto out; | 183 | return -ENOMEM; |
| 185 | 184 | ||
| 186 | rc = -EINVAL; | 185 | rc = -EINVAL; |
| 187 | role->value = ++p->p_roles.nprim; | 186 | role->value = ++p->p_roles.nprim; |
| @@ -540,23 +539,23 @@ static int policydb_index(struct policydb *p) | |||
| 540 | #endif | 539 | #endif |
| 541 | 540 | ||
| 542 | rc = -ENOMEM; | 541 | rc = -ENOMEM; |
| 543 | p->class_val_to_struct = | 542 | p->class_val_to_struct = kcalloc(p->p_classes.nprim, |
| 544 | kzalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), | 543 | sizeof(*p->class_val_to_struct), |
| 545 | GFP_KERNEL); | 544 | GFP_KERNEL); |
| 546 | if (!p->class_val_to_struct) | 545 | if (!p->class_val_to_struct) |
| 547 | goto out; | 546 | goto out; |
| 548 | 547 | ||
| 549 | rc = -ENOMEM; | 548 | rc = -ENOMEM; |
| 550 | p->role_val_to_struct = | 549 | p->role_val_to_struct = kcalloc(p->p_roles.nprim, |
| 551 | kzalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)), | 550 | sizeof(*p->role_val_to_struct), |
| 552 | GFP_KERNEL); | 551 | GFP_KERNEL); |
| 553 | if (!p->role_val_to_struct) | 552 | if (!p->role_val_to_struct) |
| 554 | goto out; | 553 | goto out; |
| 555 | 554 | ||
| 556 | rc = -ENOMEM; | 555 | rc = -ENOMEM; |
| 557 | p->user_val_to_struct = | 556 | p->user_val_to_struct = kcalloc(p->p_users.nprim, |
| 558 | kzalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)), | 557 | sizeof(*p->user_val_to_struct), |
| 559 | GFP_KERNEL); | 558 | GFP_KERNEL); |
| 560 | if (!p->user_val_to_struct) | 559 | if (!p->user_val_to_struct) |
| 561 | goto out; | 560 | goto out; |
| 562 | 561 | ||
| @@ -880,8 +879,6 @@ void policydb_destroy(struct policydb *p) | |||
| 880 | ebitmap_destroy(&p->filename_trans_ttypes); | 879 | ebitmap_destroy(&p->filename_trans_ttypes); |
| 881 | ebitmap_destroy(&p->policycaps); | 880 | ebitmap_destroy(&p->policycaps); |
| 882 | ebitmap_destroy(&p->permissive_map); | 881 | ebitmap_destroy(&p->permissive_map); |
| 883 | |||
| 884 | return; | ||
| 885 | } | 882 | } |
| 886 | 883 | ||
| 887 | /* | 884 | /* |
| @@ -1120,10 +1117,9 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1120 | __le32 buf[2]; | 1117 | __le32 buf[2]; |
| 1121 | u32 len; | 1118 | u32 len; |
| 1122 | 1119 | ||
| 1123 | rc = -ENOMEM; | ||
| 1124 | perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); | 1120 | perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); |
| 1125 | if (!perdatum) | 1121 | if (!perdatum) |
| 1126 | goto bad; | 1122 | return -ENOMEM; |
| 1127 | 1123 | ||
| 1128 | rc = next_entry(buf, fp, sizeof buf); | 1124 | rc = next_entry(buf, fp, sizeof buf); |
| 1129 | if (rc) | 1125 | if (rc) |
| @@ -1154,10 +1150,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1154 | u32 len, nel; | 1150 | u32 len, nel; |
| 1155 | int i, rc; | 1151 | int i, rc; |
| 1156 | 1152 | ||
| 1157 | rc = -ENOMEM; | ||
| 1158 | comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); | 1153 | comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); |
| 1159 | if (!comdatum) | 1154 | if (!comdatum) |
| 1160 | goto bad; | 1155 | return -ENOMEM; |
| 1161 | 1156 | ||
| 1162 | rc = next_entry(buf, fp, sizeof buf); | 1157 | rc = next_entry(buf, fp, sizeof buf); |
| 1163 | if (rc) | 1158 | if (rc) |
| @@ -1320,10 +1315,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1320 | u32 len, len2, ncons, nel; | 1315 | u32 len, len2, ncons, nel; |
| 1321 | int i, rc; | 1316 | int i, rc; |
| 1322 | 1317 | ||
| 1323 | rc = -ENOMEM; | ||
| 1324 | cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); | 1318 | cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); |
| 1325 | if (!cladatum) | 1319 | if (!cladatum) |
| 1326 | goto bad; | 1320 | return -ENOMEM; |
| 1327 | 1321 | ||
| 1328 | rc = next_entry(buf, fp, sizeof(u32)*6); | 1322 | rc = next_entry(buf, fp, sizeof(u32)*6); |
| 1329 | if (rc) | 1323 | if (rc) |
| @@ -1414,10 +1408,9 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1414 | __le32 buf[3]; | 1408 | __le32 buf[3]; |
| 1415 | u32 len; | 1409 | u32 len; |
| 1416 | 1410 | ||
| 1417 | rc = -ENOMEM; | ||
| 1418 | role = kzalloc(sizeof(*role), GFP_KERNEL); | 1411 | role = kzalloc(sizeof(*role), GFP_KERNEL); |
| 1419 | if (!role) | 1412 | if (!role) |
| 1420 | goto bad; | 1413 | return -ENOMEM; |
| 1421 | 1414 | ||
| 1422 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1415 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
| 1423 | to_read = 3; | 1416 | to_read = 3; |
| @@ -1471,10 +1464,9 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1471 | __le32 buf[4]; | 1464 | __le32 buf[4]; |
| 1472 | u32 len; | 1465 | u32 len; |
| 1473 | 1466 | ||
| 1474 | rc = -ENOMEM; | ||
| 1475 | typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); | 1467 | typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); |
| 1476 | if (!typdatum) | 1468 | if (!typdatum) |
| 1477 | goto bad; | 1469 | return -ENOMEM; |
| 1478 | 1470 | ||
| 1479 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1471 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
| 1480 | to_read = 4; | 1472 | to_read = 4; |
| @@ -1546,10 +1538,9 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1546 | __le32 buf[3]; | 1538 | __le32 buf[3]; |
| 1547 | u32 len; | 1539 | u32 len; |
| 1548 | 1540 | ||
| 1549 | rc = -ENOMEM; | ||
| 1550 | usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); | 1541 | usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); |
| 1551 | if (!usrdatum) | 1542 | if (!usrdatum) |
| 1552 | goto bad; | 1543 | return -ENOMEM; |
| 1553 | 1544 | ||
| 1554 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1545 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
| 1555 | to_read = 3; | 1546 | to_read = 3; |
| @@ -1597,10 +1588,9 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1597 | __le32 buf[2]; | 1588 | __le32 buf[2]; |
| 1598 | u32 len; | 1589 | u32 len; |
| 1599 | 1590 | ||
| 1600 | rc = -ENOMEM; | ||
| 1601 | levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); | 1591 | levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); |
| 1602 | if (!levdatum) | 1592 | if (!levdatum) |
| 1603 | goto bad; | 1593 | return -ENOMEM; |
| 1604 | 1594 | ||
| 1605 | rc = next_entry(buf, fp, sizeof buf); | 1595 | rc = next_entry(buf, fp, sizeof buf); |
| 1606 | if (rc) | 1596 | if (rc) |
| @@ -1614,7 +1604,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1614 | goto bad; | 1604 | goto bad; |
| 1615 | 1605 | ||
| 1616 | rc = -ENOMEM; | 1606 | rc = -ENOMEM; |
| 1617 | levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); | 1607 | levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_ATOMIC); |
| 1618 | if (!levdatum->level) | 1608 | if (!levdatum->level) |
| 1619 | goto bad; | 1609 | goto bad; |
| 1620 | 1610 | ||
| @@ -1639,10 +1629,9 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1639 | __le32 buf[3]; | 1629 | __le32 buf[3]; |
| 1640 | u32 len; | 1630 | u32 len; |
| 1641 | 1631 | ||
| 1642 | rc = -ENOMEM; | ||
| 1643 | catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); | 1632 | catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); |
| 1644 | if (!catdatum) | 1633 | if (!catdatum) |
| 1645 | goto bad; | 1634 | return -ENOMEM; |
| 1646 | 1635 | ||
| 1647 | rc = next_entry(buf, fp, sizeof buf); | 1636 | rc = next_entry(buf, fp, sizeof buf); |
| 1648 | if (rc) | 1637 | if (rc) |
| @@ -1854,7 +1843,7 @@ static int range_read(struct policydb *p, void *fp) | |||
| 1854 | 1843 | ||
| 1855 | rc = next_entry(buf, fp, sizeof(u32)); | 1844 | rc = next_entry(buf, fp, sizeof(u32)); |
| 1856 | if (rc) | 1845 | if (rc) |
| 1857 | goto out; | 1846 | return rc; |
| 1858 | 1847 | ||
| 1859 | nel = le32_to_cpu(buf[0]); | 1848 | nel = le32_to_cpu(buf[0]); |
| 1860 | for (i = 0; i < nel; i++) { | 1849 | for (i = 0; i < nel; i++) { |
| @@ -1931,7 +1920,6 @@ static int filename_trans_read(struct policydb *p, void *fp) | |||
| 1931 | nel = le32_to_cpu(buf[0]); | 1920 | nel = le32_to_cpu(buf[0]); |
| 1932 | 1921 | ||
| 1933 | for (i = 0; i < nel; i++) { | 1922 | for (i = 0; i < nel; i++) { |
| 1934 | ft = NULL; | ||
| 1935 | otype = NULL; | 1923 | otype = NULL; |
| 1936 | name = NULL; | 1924 | name = NULL; |
| 1937 | 1925 | ||
| @@ -2008,7 +1996,7 @@ static int genfs_read(struct policydb *p, void *fp) | |||
| 2008 | 1996 | ||
| 2009 | rc = next_entry(buf, fp, sizeof(u32)); | 1997 | rc = next_entry(buf, fp, sizeof(u32)); |
| 2010 | if (rc) | 1998 | if (rc) |
| 2011 | goto out; | 1999 | return rc; |
| 2012 | nel = le32_to_cpu(buf[0]); | 2000 | nel = le32_to_cpu(buf[0]); |
| 2013 | 2001 | ||
| 2014 | for (i = 0; i < nel; i++) { | 2002 | for (i = 0; i < nel; i++) { |
| @@ -2100,9 +2088,10 @@ static int genfs_read(struct policydb *p, void *fp) | |||
| 2100 | } | 2088 | } |
| 2101 | rc = 0; | 2089 | rc = 0; |
| 2102 | out: | 2090 | out: |
| 2103 | if (newgenfs) | 2091 | if (newgenfs) { |
| 2104 | kfree(newgenfs->fstype); | 2092 | kfree(newgenfs->fstype); |
| 2105 | kfree(newgenfs); | 2093 | kfree(newgenfs); |
| 2094 | } | ||
| 2106 | ocontext_destroy(newc, OCON_FSUSE); | 2095 | ocontext_destroy(newc, OCON_FSUSE); |
| 2107 | 2096 | ||
| 2108 | return rc; | 2097 | return rc; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b4aa491a0a23..60d9b0252321 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -157,7 +157,7 @@ static int selinux_set_mapping(struct policydb *pol, | |||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | k = 0; | 159 | k = 0; |
| 160 | while (p_in->perms && p_in->perms[k]) { | 160 | while (p_in->perms[k]) { |
| 161 | /* An empty permission string skips ahead */ | 161 | /* An empty permission string skips ahead */ |
| 162 | if (!*p_in->perms[k]) { | 162 | if (!*p_in->perms[k]) { |
| 163 | k++; | 163 | k++; |
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 5840a35155fc..f6915f257486 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
| @@ -18,7 +18,7 @@ int sidtab_init(struct sidtab *s) | |||
| 18 | { | 18 | { |
| 19 | int i; | 19 | int i; |
| 20 | 20 | ||
| 21 | s->htable = kmalloc(sizeof(*(s->htable)) * SIDTAB_SIZE, GFP_ATOMIC); | 21 | s->htable = kmalloc_array(SIDTAB_SIZE, sizeof(*s->htable), GFP_ATOMIC); |
| 22 | if (!s->htable) | 22 | if (!s->htable) |
| 23 | return -ENOMEM; | 23 | return -ENOMEM; |
| 24 | for (i = 0; i < SIDTAB_SIZE; i++) | 24 | for (i = 0; i < SIDTAB_SIZE; i++) |
| @@ -54,7 +54,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC); | 56 | newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC); |
| 57 | if (newnode == NULL) { | 57 | if (!newnode) { |
| 58 | rc = -ENOMEM; | 58 | rc = -ENOMEM; |
| 59 | goto out; | 59 | goto out; |
| 60 | } | 60 | } |
| @@ -98,7 +98,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) | |||
| 98 | if (force && cur && sid == cur->sid && cur->context.len) | 98 | if (force && cur && sid == cur->sid && cur->context.len) |
| 99 | return &cur->context; | 99 | return &cur->context; |
| 100 | 100 | ||
| 101 | if (cur == NULL || sid != cur->sid || cur->context.len) { | 101 | if (!cur || sid != cur->sid || cur->context.len) { |
| 102 | /* Remap invalid SIDs to the unlabeled SID. */ | 102 | /* Remap invalid SIDs to the unlabeled SID. */ |
| 103 | sid = SECINITSID_UNLABELED; | 103 | sid = SECINITSID_UNLABELED; |
| 104 | hvalue = SIDTAB_HASH(sid); | 104 | hvalue = SIDTAB_HASH(sid); |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 356e3764cad9..a4b2e6b94abd 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
| @@ -504,7 +504,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, | |||
| 504 | if ((m & *cp) == 0) | 504 | if ((m & *cp) == 0) |
| 505 | continue; | 505 | continue; |
| 506 | rc = netlbl_catmap_setbit(&sap->attr.mls.cat, | 506 | rc = netlbl_catmap_setbit(&sap->attr.mls.cat, |
| 507 | cat, GFP_ATOMIC); | 507 | cat, GFP_KERNEL); |
| 508 | if (rc < 0) { | 508 | if (rc < 0) { |
| 509 | netlbl_catmap_free(sap->attr.mls.cat); | 509 | netlbl_catmap_free(sap->attr.mls.cat); |
| 510 | return rc; | 510 | return rc; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index fc8fb31fc24f..658f5d8c7e76 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -695,10 +695,8 @@ static int smack_parse_opts_str(char *options, | |||
| 695 | 695 | ||
| 696 | opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), | 696 | opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), |
| 697 | GFP_KERNEL); | 697 | GFP_KERNEL); |
| 698 | if (!opts->mnt_opts_flags) { | 698 | if (!opts->mnt_opts_flags) |
| 699 | kfree(opts->mnt_opts); | ||
| 700 | goto out_err; | 699 | goto out_err; |
| 701 | } | ||
| 702 | 700 | ||
| 703 | if (fsdefault) { | 701 | if (fsdefault) { |
| 704 | opts->mnt_opts[num_mnt_opts] = fsdefault; | 702 | opts->mnt_opts[num_mnt_opts] = fsdefault; |
| @@ -4633,7 +4631,7 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | |||
| 4633 | return 0; | 4631 | return 0; |
| 4634 | } | 4632 | } |
| 4635 | 4633 | ||
| 4636 | static struct security_hook_list smack_hooks[] = { | 4634 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { |
| 4637 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), | 4635 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), |
| 4638 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), | 4636 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), |
| 4639 | LSM_HOOK_INIT(syslog, smack_syslog), | 4637 | LSM_HOOK_INIT(syslog, smack_syslog), |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 7041a580019e..223f21ffa632 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
| @@ -692,7 +692,7 @@ int tomoyo_path_number_perm(const u8 type, const struct path *path, | |||
| 692 | { | 692 | { |
| 693 | struct tomoyo_request_info r; | 693 | struct tomoyo_request_info r; |
| 694 | struct tomoyo_obj_info obj = { | 694 | struct tomoyo_obj_info obj = { |
| 695 | .path1 = *path, | 695 | .path1 = { .mnt = path->mnt, .dentry = path->dentry }, |
| 696 | }; | 696 | }; |
| 697 | int error = -ENOMEM; | 697 | int error = -ENOMEM; |
| 698 | struct tomoyo_path_info buf; | 698 | struct tomoyo_path_info buf; |
| @@ -740,7 +740,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
| 740 | struct tomoyo_path_info buf; | 740 | struct tomoyo_path_info buf; |
| 741 | struct tomoyo_request_info r; | 741 | struct tomoyo_request_info r; |
| 742 | struct tomoyo_obj_info obj = { | 742 | struct tomoyo_obj_info obj = { |
| 743 | .path1 = *path, | 743 | .path1 = { .mnt = path->mnt, .dentry = path->dentry }, |
| 744 | }; | 744 | }; |
| 745 | int idx; | 745 | int idx; |
| 746 | 746 | ||
| @@ -786,7 +786,7 @@ int tomoyo_path_perm(const u8 operation, const struct path *path, const char *ta | |||
| 786 | { | 786 | { |
| 787 | struct tomoyo_request_info r; | 787 | struct tomoyo_request_info r; |
| 788 | struct tomoyo_obj_info obj = { | 788 | struct tomoyo_obj_info obj = { |
| 789 | .path1 = *path, | 789 | .path1 = { .mnt = path->mnt, .dentry = path->dentry }, |
| 790 | }; | 790 | }; |
| 791 | int error; | 791 | int error; |
| 792 | struct tomoyo_path_info buf; | 792 | struct tomoyo_path_info buf; |
| @@ -843,7 +843,7 @@ int tomoyo_mkdev_perm(const u8 operation, const struct path *path, | |||
| 843 | { | 843 | { |
| 844 | struct tomoyo_request_info r; | 844 | struct tomoyo_request_info r; |
| 845 | struct tomoyo_obj_info obj = { | 845 | struct tomoyo_obj_info obj = { |
| 846 | .path1 = *path, | 846 | .path1 = { .mnt = path->mnt, .dentry = path->dentry }, |
| 847 | }; | 847 | }; |
| 848 | int error = -ENOMEM; | 848 | int error = -ENOMEM; |
| 849 | struct tomoyo_path_info buf; | 849 | struct tomoyo_path_info buf; |
| @@ -890,8 +890,8 @@ int tomoyo_path2_perm(const u8 operation, const struct path *path1, | |||
| 890 | struct tomoyo_path_info buf2; | 890 | struct tomoyo_path_info buf2; |
| 891 | struct tomoyo_request_info r; | 891 | struct tomoyo_request_info r; |
| 892 | struct tomoyo_obj_info obj = { | 892 | struct tomoyo_obj_info obj = { |
| 893 | .path1 = *path1, | 893 | .path1 = { .mnt = path1->mnt, .dentry = path1->dentry }, |
| 894 | .path2 = *path2, | 894 | .path2 = { .mnt = path2->mnt, .dentry = path2->dentry } |
| 895 | }; | 895 | }; |
| 896 | int idx; | 896 | int idx; |
| 897 | 897 | ||
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index edc52d620f29..130b4fa4f65f 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
| @@ -165,7 +165,7 @@ static int tomoyo_path_truncate(const struct path *path) | |||
| 165 | */ | 165 | */ |
| 166 | static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) | 166 | static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) |
| 167 | { | 167 | { |
| 168 | struct path path = { parent->mnt, dentry }; | 168 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 169 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); | 169 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| @@ -181,7 +181,7 @@ static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) | |||
| 181 | static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, | 181 | static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, |
| 182 | umode_t mode) | 182 | umode_t mode) |
| 183 | { | 183 | { |
| 184 | struct path path = { parent->mnt, dentry }; | 184 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 185 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, | 185 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, |
| 186 | mode & S_IALLUGO); | 186 | mode & S_IALLUGO); |
| 187 | } | 187 | } |
| @@ -196,7 +196,7 @@ static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, | |||
| 196 | */ | 196 | */ |
| 197 | static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) | 197 | static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) |
| 198 | { | 198 | { |
| 199 | struct path path = { parent->mnt, dentry }; | 199 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 200 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); | 200 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| @@ -212,7 +212,7 @@ static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) | |||
| 212 | static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, | 212 | static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, |
| 213 | const char *old_name) | 213 | const char *old_name) |
| 214 | { | 214 | { |
| 215 | struct path path = { parent->mnt, dentry }; | 215 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 216 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); | 216 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| @@ -229,7 +229,7 @@ static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, | |||
| 229 | static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, | 229 | static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, |
| 230 | umode_t mode, unsigned int dev) | 230 | umode_t mode, unsigned int dev) |
| 231 | { | 231 | { |
| 232 | struct path path = { parent->mnt, dentry }; | 232 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 233 | int type = TOMOYO_TYPE_CREATE; | 233 | int type = TOMOYO_TYPE_CREATE; |
| 234 | const unsigned int perm = mode & S_IALLUGO; | 234 | const unsigned int perm = mode & S_IALLUGO; |
| 235 | 235 | ||
| @@ -268,8 +268,8 @@ static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, | |||
| 268 | static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, | 268 | static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, |
| 269 | struct dentry *new_dentry) | 269 | struct dentry *new_dentry) |
| 270 | { | 270 | { |
| 271 | struct path path1 = { new_dir->mnt, old_dentry }; | 271 | struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; |
| 272 | struct path path2 = { new_dir->mnt, new_dentry }; | 272 | struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; |
| 273 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); | 273 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| @@ -288,8 +288,8 @@ static int tomoyo_path_rename(const struct path *old_parent, | |||
| 288 | const struct path *new_parent, | 288 | const struct path *new_parent, |
| 289 | struct dentry *new_dentry) | 289 | struct dentry *new_dentry) |
| 290 | { | 290 | { |
| 291 | struct path path1 = { old_parent->mnt, old_dentry }; | 291 | struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; |
| 292 | struct path path2 = { new_parent->mnt, new_dentry }; | 292 | struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; |
| 293 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); | 293 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| @@ -417,7 +417,7 @@ static int tomoyo_sb_mount(const char *dev_name, const struct path *path, | |||
| 417 | */ | 417 | */ |
| 418 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) | 418 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) |
| 419 | { | 419 | { |
| 420 | struct path path = { mnt, mnt->mnt_root }; | 420 | struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; |
| 421 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); | 421 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); |
| 422 | } | 422 | } |
| 423 | 423 | ||
| @@ -496,7 +496,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 496 | * tomoyo_security_ops is a "struct security_operations" which is used for | 496 | * tomoyo_security_ops is a "struct security_operations" which is used for |
| 497 | * registering TOMOYO. | 497 | * registering TOMOYO. |
| 498 | */ | 498 | */ |
| 499 | static struct security_hook_list tomoyo_hooks[] = { | 499 | static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { |
| 500 | LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), | 500 | LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), |
| 501 | LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), | 501 | LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), |
| 502 | LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), | 502 | LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), |
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 88271a3bf37f..8298e094f4f7 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c | |||
| @@ -428,7 +428,7 @@ int yama_ptrace_traceme(struct task_struct *parent) | |||
| 428 | return rc; | 428 | return rc; |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | static struct security_hook_list yama_hooks[] = { | 431 | static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { |
| 432 | LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), | 432 | LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), |
| 433 | LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), | 433 | LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), |
| 434 | LSM_HOOK_INIT(task_prctl, yama_task_prctl), | 434 | LSM_HOOK_INIT(task_prctl, yama_task_prctl), |
