diff options
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), |