diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /security/keys | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/Kconfig | 71 | ||||
-rw-r--r-- | security/keys/Makefile | 12 | ||||
-rw-r--r-- | security/keys/compat.c | 7 | ||||
-rw-r--r-- | security/keys/encrypted-keys/Makefile | 10 | ||||
-rw-r--r-- | security/keys/encrypted-keys/ecryptfs_format.c | 81 | ||||
-rw-r--r-- | security/keys/encrypted-keys/ecryptfs_format.h | 30 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 1040 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.h | 66 | ||||
-rw-r--r-- | security/keys/encrypted-keys/masterkey_trusted.c | 47 | ||||
-rw-r--r-- | security/keys/gc.c | 418 | ||||
-rw-r--r-- | security/keys/internal.h | 30 | ||||
-rw-r--r-- | security/keys/key.c | 313 | ||||
-rw-r--r-- | security/keys/keyctl.c | 209 | ||||
-rw-r--r-- | security/keys/keyring.c | 214 | ||||
-rw-r--r-- | security/keys/permission.c | 54 | ||||
-rw-r--r-- | security/keys/proc.c | 47 | ||||
-rw-r--r-- | security/keys/process_keys.c | 151 | ||||
-rw-r--r-- | security/keys/request_key.c | 42 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 8 | ||||
-rw-r--r-- | security/keys/trusted.c | 95 | ||||
-rw-r--r-- | security/keys/user_defined.c | 57 |
21 files changed, 678 insertions, 2324 deletions
diff --git a/security/keys/Kconfig b/security/keys/Kconfig deleted file mode 100644 index a90d6d300db..00000000000 --- a/security/keys/Kconfig +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | # | ||
2 | # Key management configuration | ||
3 | # | ||
4 | |||
5 | config KEYS | ||
6 | bool "Enable access key retention support" | ||
7 | help | ||
8 | This option provides support for retaining authentication tokens and | ||
9 | access keys in the kernel. | ||
10 | |||
11 | It also includes provision of methods by which such keys might be | ||
12 | associated with a process so that network filesystems, encryption | ||
13 | support and the like can find them. | ||
14 | |||
15 | Furthermore, a special type of key is available that acts as keyring: | ||
16 | a searchable sequence of keys. Each process is equipped with access | ||
17 | to five standard keyrings: UID-specific, GID-specific, session, | ||
18 | process and thread. | ||
19 | |||
20 | If you are unsure as to whether this is required, answer N. | ||
21 | |||
22 | config TRUSTED_KEYS | ||
23 | tristate "TRUSTED KEYS" | ||
24 | depends on KEYS && TCG_TPM | ||
25 | select CRYPTO | ||
26 | select CRYPTO_HMAC | ||
27 | select CRYPTO_SHA1 | ||
28 | help | ||
29 | This option provides support for creating, sealing, and unsealing | ||
30 | keys in the kernel. Trusted keys are random number symmetric keys, | ||
31 | generated and RSA-sealed by the TPM. The TPM only unseals the keys, | ||
32 | if the boot PCRs and other criteria match. Userspace will only ever | ||
33 | see encrypted blobs. | ||
34 | |||
35 | If you are unsure as to whether this is required, answer N. | ||
36 | |||
37 | config ENCRYPTED_KEYS | ||
38 | tristate "ENCRYPTED KEYS" | ||
39 | depends on KEYS | ||
40 | select CRYPTO | ||
41 | select CRYPTO_HMAC | ||
42 | select CRYPTO_AES | ||
43 | select CRYPTO_CBC | ||
44 | select CRYPTO_SHA256 | ||
45 | select CRYPTO_RNG | ||
46 | help | ||
47 | This option provides support for create/encrypting/decrypting keys | ||
48 | in the kernel. Encrypted keys are kernel generated random numbers, | ||
49 | which are encrypted/decrypted with a 'master' symmetric key. The | ||
50 | 'master' key can be either a trusted-key or user-key type. | ||
51 | Userspace only ever sees/stores encrypted blobs. | ||
52 | |||
53 | If you are unsure as to whether this is required, answer N. | ||
54 | |||
55 | config KEYS_DEBUG_PROC_KEYS | ||
56 | bool "Enable the /proc/keys file by which keys may be viewed" | ||
57 | depends on KEYS | ||
58 | help | ||
59 | This option turns on support for the /proc/keys file - through which | ||
60 | can be listed all the keys on the system that are viewable by the | ||
61 | reading process. | ||
62 | |||
63 | The only keys included in the list are those that grant View | ||
64 | permission to the reading process whether or not it possesses them. | ||
65 | Note that LSM security checks are still performed, and may further | ||
66 | filter out keys that the current process is not authorised to view. | ||
67 | |||
68 | Only key attributes are listed here; key payloads are not included in | ||
69 | the resulting table. | ||
70 | |||
71 | If you are unsure as to whether this is required, answer N. | ||
diff --git a/security/keys/Makefile b/security/keys/Makefile index 504aaa00838..b34cc6ee690 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
@@ -2,9 +2,6 @@ | |||
2 | # Makefile for key management | 2 | # Makefile for key management |
3 | # | 3 | # |
4 | 4 | ||
5 | # | ||
6 | # Core | ||
7 | # | ||
8 | obj-y := \ | 5 | obj-y := \ |
9 | gc.o \ | 6 | gc.o \ |
10 | key.o \ | 7 | key.o \ |
@@ -15,12 +12,9 @@ obj-y := \ | |||
15 | request_key.o \ | 12 | request_key.o \ |
16 | request_key_auth.o \ | 13 | request_key_auth.o \ |
17 | user_defined.o | 14 | user_defined.o |
15 | |||
16 | obj-$(CONFIG_TRUSTED_KEYS) += trusted.o | ||
17 | obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o | ||
18 | obj-$(CONFIG_KEYS_COMPAT) += compat.o | 18 | obj-$(CONFIG_KEYS_COMPAT) += compat.o |
19 | obj-$(CONFIG_PROC_FS) += proc.o | 19 | obj-$(CONFIG_PROC_FS) += proc.o |
20 | obj-$(CONFIG_SYSCTL) += sysctl.o | 20 | obj-$(CONFIG_SYSCTL) += sysctl.o |
21 | |||
22 | # | ||
23 | # Key types | ||
24 | # | ||
25 | obj-$(CONFIG_TRUSTED_KEYS) += trusted.o | ||
26 | obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ | ||
diff --git a/security/keys/compat.c b/security/keys/compat.c index 1c261763f47..338b510e902 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * | 24 | * |
25 | * If successful, 0 will be returned. | 25 | * If successful, 0 will be returned. |
26 | */ | 26 | */ |
27 | static long compat_keyctl_instantiate_key_iov( | 27 | long compat_keyctl_instantiate_key_iov( |
28 | key_serial_t id, | 28 | key_serial_t id, |
29 | const struct compat_iovec __user *_payload_iov, | 29 | const struct compat_iovec __user *_payload_iov, |
30 | unsigned ioc, | 30 | unsigned ioc, |
@@ -33,7 +33,7 @@ static long compat_keyctl_instantiate_key_iov( | |||
33 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | 33 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
34 | long ret; | 34 | long ret; |
35 | 35 | ||
36 | if (!_payload_iov || !ioc) | 36 | if (_payload_iov == 0 || ioc == 0) |
37 | goto no_payload; | 37 | goto no_payload; |
38 | 38 | ||
39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
@@ -135,9 +135,6 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
135 | return compat_keyctl_instantiate_key_iov( | 135 | return compat_keyctl_instantiate_key_iov( |
136 | arg2, compat_ptr(arg3), arg4, arg5); | 136 | arg2, compat_ptr(arg3), arg4, arg5); |
137 | 137 | ||
138 | case KEYCTL_INVALIDATE: | ||
139 | return keyctl_invalidate_key(arg2); | ||
140 | |||
141 | default: | 138 | default: |
142 | return -EOPNOTSUPP; | 139 | return -EOPNOTSUPP; |
143 | } | 140 | } |
diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile deleted file mode 100644 index d6f8433250a..00000000000 --- a/security/keys/encrypted-keys/Makefile +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for encrypted keys | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o | ||
6 | |||
7 | encrypted-keys-y := encrypted.o ecryptfs_format.o | ||
8 | masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o | ||
9 | masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o | ||
10 | encrypted-keys-y += $(masterkey-y) $(masterkey-m-m) | ||
diff --git a/security/keys/encrypted-keys/ecryptfs_format.c b/security/keys/encrypted-keys/ecryptfs_format.c deleted file mode 100644 index 6daa3b6ff9e..00000000000 --- a/security/keys/encrypted-keys/ecryptfs_format.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | * ecryptfs_format.c: helper functions for the encrypted key type | ||
3 | * | ||
4 | * Copyright (C) 2006 International Business Machines Corp. | ||
5 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
6 | * TORSEC group -- http://security.polito.it | ||
7 | * | ||
8 | * Authors: | ||
9 | * Michael A. Halcrow <mahalcro@us.ibm.com> | ||
10 | * Tyler Hicks <tyhicks@ou.edu> | ||
11 | * Roberto Sassu <roberto.sassu@polito.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation, version 2 of the License. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include "ecryptfs_format.h" | ||
20 | |||
21 | u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok) | ||
22 | { | ||
23 | return auth_tok->token.password.session_key_encryption_key; | ||
24 | } | ||
25 | EXPORT_SYMBOL(ecryptfs_get_auth_tok_key); | ||
26 | |||
27 | /* | ||
28 | * ecryptfs_get_versions() | ||
29 | * | ||
30 | * Source code taken from the software 'ecryptfs-utils' version 83. | ||
31 | * | ||
32 | */ | ||
33 | void ecryptfs_get_versions(int *major, int *minor, int *file_version) | ||
34 | { | ||
35 | *major = ECRYPTFS_VERSION_MAJOR; | ||
36 | *minor = ECRYPTFS_VERSION_MINOR; | ||
37 | if (file_version) | ||
38 | *file_version = ECRYPTFS_SUPPORTED_FILE_VERSION; | ||
39 | } | ||
40 | EXPORT_SYMBOL(ecryptfs_get_versions); | ||
41 | |||
42 | /* | ||
43 | * ecryptfs_fill_auth_tok - fill the ecryptfs_auth_tok structure | ||
44 | * | ||
45 | * Fill the ecryptfs_auth_tok structure with required ecryptfs data. | ||
46 | * The source code is inspired to the original function generate_payload() | ||
47 | * shipped with the software 'ecryptfs-utils' version 83. | ||
48 | * | ||
49 | */ | ||
50 | int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok, | ||
51 | const char *key_desc) | ||
52 | { | ||
53 | int major, minor; | ||
54 | |||
55 | ecryptfs_get_versions(&major, &minor, NULL); | ||
56 | auth_tok->version = (((uint16_t)(major << 8) & 0xFF00) | ||
57 | | ((uint16_t)minor & 0x00FF)); | ||
58 | auth_tok->token_type = ECRYPTFS_PASSWORD; | ||
59 | strncpy((char *)auth_tok->token.password.signature, key_desc, | ||
60 | ECRYPTFS_PASSWORD_SIG_SIZE); | ||
61 | auth_tok->token.password.session_key_encryption_key_bytes = | ||
62 | ECRYPTFS_MAX_KEY_BYTES; | ||
63 | /* | ||
64 | * Removed auth_tok->token.password.salt and | ||
65 | * auth_tok->token.password.session_key_encryption_key | ||
66 | * initialization from the original code | ||
67 | */ | ||
68 | /* TODO: Make the hash parameterizable via policy */ | ||
69 | auth_tok->token.password.flags |= | ||
70 | ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; | ||
71 | /* The kernel code will encrypt the session key. */ | ||
72 | auth_tok->session_key.encrypted_key[0] = 0; | ||
73 | auth_tok->session_key.encrypted_key_size = 0; | ||
74 | /* Default; subject to change by kernel eCryptfs */ | ||
75 | auth_tok->token.password.hash_algo = PGP_DIGEST_ALGO_SHA512; | ||
76 | auth_tok->token.password.flags &= ~(ECRYPTFS_PERSISTENT_PASSWORD); | ||
77 | return 0; | ||
78 | } | ||
79 | EXPORT_SYMBOL(ecryptfs_fill_auth_tok); | ||
80 | |||
81 | MODULE_LICENSE("GPL"); | ||
diff --git a/security/keys/encrypted-keys/ecryptfs_format.h b/security/keys/encrypted-keys/ecryptfs_format.h deleted file mode 100644 index 40294de238b..00000000000 --- a/security/keys/encrypted-keys/ecryptfs_format.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * ecryptfs_format.h: helper functions for the encrypted key type | ||
3 | * | ||
4 | * Copyright (C) 2006 International Business Machines Corp. | ||
5 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
6 | * TORSEC group -- http://security.polito.it | ||
7 | * | ||
8 | * Authors: | ||
9 | * Michael A. Halcrow <mahalcro@us.ibm.com> | ||
10 | * Tyler Hicks <tyhicks@ou.edu> | ||
11 | * Roberto Sassu <roberto.sassu@polito.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation, version 2 of the License. | ||
16 | */ | ||
17 | |||
18 | #ifndef __KEYS_ECRYPTFS_H | ||
19 | #define __KEYS_ECRYPTFS_H | ||
20 | |||
21 | #include <linux/ecryptfs.h> | ||
22 | |||
23 | #define PGP_DIGEST_ALGO_SHA512 10 | ||
24 | |||
25 | u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok); | ||
26 | void ecryptfs_get_versions(int *major, int *minor, int *file_version); | ||
27 | int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok, | ||
28 | const char *key_desc); | ||
29 | |||
30 | #endif /* __KEYS_ECRYPTFS_H */ | ||
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c deleted file mode 100644 index 9e1e005c759..00000000000 --- a/security/keys/encrypted-keys/encrypted.c +++ /dev/null | |||
@@ -1,1040 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 IBM Corporation | ||
3 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
4 | * TORSEC group -- http://security.polito.it | ||
5 | * | ||
6 | * Authors: | ||
7 | * Mimi Zohar <zohar@us.ibm.com> | ||
8 | * Roberto Sassu <roberto.sassu@polito.it> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation, version 2 of the License. | ||
13 | * | ||
14 | * See Documentation/security/keys-trusted-encrypted.txt | ||
15 | */ | ||
16 | |||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/parser.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <keys/user-type.h> | ||
25 | #include <keys/trusted-type.h> | ||
26 | #include <keys/encrypted-type.h> | ||
27 | #include <linux/key-type.h> | ||
28 | #include <linux/random.h> | ||
29 | #include <linux/rcupdate.h> | ||
30 | #include <linux/scatterlist.h> | ||
31 | #include <linux/crypto.h> | ||
32 | #include <linux/ctype.h> | ||
33 | #include <crypto/hash.h> | ||
34 | #include <crypto/sha.h> | ||
35 | #include <crypto/aes.h> | ||
36 | |||
37 | #include "encrypted.h" | ||
38 | #include "ecryptfs_format.h" | ||
39 | |||
40 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; | ||
41 | static const char KEY_USER_PREFIX[] = "user:"; | ||
42 | static const char hash_alg[] = "sha256"; | ||
43 | static const char hmac_alg[] = "hmac(sha256)"; | ||
44 | static const char blkcipher_alg[] = "cbc(aes)"; | ||
45 | static const char key_format_default[] = "default"; | ||
46 | static const char key_format_ecryptfs[] = "ecryptfs"; | ||
47 | static unsigned int ivsize; | ||
48 | static int blksize; | ||
49 | |||
50 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) | ||
51 | #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1) | ||
52 | #define KEY_ECRYPTFS_DESC_LEN 16 | ||
53 | #define HASH_SIZE SHA256_DIGEST_SIZE | ||
54 | #define MAX_DATA_SIZE 4096 | ||
55 | #define MIN_DATA_SIZE 20 | ||
56 | |||
57 | struct sdesc { | ||
58 | struct shash_desc shash; | ||
59 | char ctx[]; | ||
60 | }; | ||
61 | |||
62 | static struct crypto_shash *hashalg; | ||
63 | static struct crypto_shash *hmacalg; | ||
64 | |||
65 | enum { | ||
66 | Opt_err = -1, Opt_new, Opt_load, Opt_update | ||
67 | }; | ||
68 | |||
69 | enum { | ||
70 | Opt_error = -1, Opt_default, Opt_ecryptfs | ||
71 | }; | ||
72 | |||
73 | static const match_table_t key_format_tokens = { | ||
74 | {Opt_default, "default"}, | ||
75 | {Opt_ecryptfs, "ecryptfs"}, | ||
76 | {Opt_error, NULL} | ||
77 | }; | ||
78 | |||
79 | static const match_table_t key_tokens = { | ||
80 | {Opt_new, "new"}, | ||
81 | {Opt_load, "load"}, | ||
82 | {Opt_update, "update"}, | ||
83 | {Opt_err, NULL} | ||
84 | }; | ||
85 | |||
86 | static int aes_get_sizes(void) | ||
87 | { | ||
88 | struct crypto_blkcipher *tfm; | ||
89 | |||
90 | tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); | ||
91 | if (IS_ERR(tfm)) { | ||
92 | pr_err("encrypted_key: failed to alloc_cipher (%ld)\n", | ||
93 | PTR_ERR(tfm)); | ||
94 | return PTR_ERR(tfm); | ||
95 | } | ||
96 | ivsize = crypto_blkcipher_ivsize(tfm); | ||
97 | blksize = crypto_blkcipher_blocksize(tfm); | ||
98 | crypto_free_blkcipher(tfm); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * valid_ecryptfs_desc - verify the description of a new/loaded encrypted key | ||
104 | * | ||
105 | * The description of a encrypted key with format 'ecryptfs' must contain | ||
106 | * exactly 16 hexadecimal characters. | ||
107 | * | ||
108 | */ | ||
109 | static int valid_ecryptfs_desc(const char *ecryptfs_desc) | ||
110 | { | ||
111 | int i; | ||
112 | |||
113 | if (strlen(ecryptfs_desc) != KEY_ECRYPTFS_DESC_LEN) { | ||
114 | pr_err("encrypted_key: key description must be %d hexadecimal " | ||
115 | "characters long\n", KEY_ECRYPTFS_DESC_LEN); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | for (i = 0; i < KEY_ECRYPTFS_DESC_LEN; i++) { | ||
120 | if (!isxdigit(ecryptfs_desc[i])) { | ||
121 | pr_err("encrypted_key: key description must contain " | ||
122 | "only hexadecimal characters\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key | ||
132 | * | ||
133 | * key-type:= "trusted:" | "user:" | ||
134 | * desc:= master-key description | ||
135 | * | ||
136 | * Verify that 'key-type' is valid and that 'desc' exists. On key update, | ||
137 | * only the master key description is permitted to change, not the key-type. | ||
138 | * The key-type remains constant. | ||
139 | * | ||
140 | * On success returns 0, otherwise -EINVAL. | ||
141 | */ | ||
142 | static int valid_master_desc(const char *new_desc, const char *orig_desc) | ||
143 | { | ||
144 | if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { | ||
145 | if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) | ||
146 | goto out; | ||
147 | if (orig_desc) | ||
148 | if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) | ||
149 | goto out; | ||
150 | } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { | ||
151 | if (strlen(new_desc) == KEY_USER_PREFIX_LEN) | ||
152 | goto out; | ||
153 | if (orig_desc) | ||
154 | if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) | ||
155 | goto out; | ||
156 | } else | ||
157 | goto out; | ||
158 | return 0; | ||
159 | out: | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * datablob_parse - parse the keyctl data | ||
165 | * | ||
166 | * datablob format: | ||
167 | * new [<format>] <master-key name> <decrypted data length> | ||
168 | * load [<format>] <master-key name> <decrypted data length> | ||
169 | * <encrypted iv + data> | ||
170 | * update <new-master-key name> | ||
171 | * | ||
172 | * Tokenizes a copy of the keyctl data, returning a pointer to each token, | ||
173 | * which is null terminated. | ||
174 | * | ||
175 | * On success returns 0, otherwise -EINVAL. | ||
176 | */ | ||
177 | static int datablob_parse(char *datablob, const char **format, | ||
178 | char **master_desc, char **decrypted_datalen, | ||
179 | char **hex_encoded_iv) | ||
180 | { | ||
181 | substring_t args[MAX_OPT_ARGS]; | ||
182 | int ret = -EINVAL; | ||
183 | int key_cmd; | ||
184 | int key_format; | ||
185 | char *p, *keyword; | ||
186 | |||
187 | keyword = strsep(&datablob, " \t"); | ||
188 | if (!keyword) { | ||
189 | pr_info("encrypted_key: insufficient parameters specified\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | key_cmd = match_token(keyword, key_tokens, args); | ||
193 | |||
194 | /* Get optional format: default | ecryptfs */ | ||
195 | p = strsep(&datablob, " \t"); | ||
196 | if (!p) { | ||
197 | pr_err("encrypted_key: insufficient parameters specified\n"); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | key_format = match_token(p, key_format_tokens, args); | ||
202 | switch (key_format) { | ||
203 | case Opt_ecryptfs: | ||
204 | case Opt_default: | ||
205 | *format = p; | ||
206 | *master_desc = strsep(&datablob, " \t"); | ||
207 | break; | ||
208 | case Opt_error: | ||
209 | *master_desc = p; | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | if (!*master_desc) { | ||
214 | pr_info("encrypted_key: master key parameter is missing\n"); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | if (valid_master_desc(*master_desc, NULL) < 0) { | ||
219 | pr_info("encrypted_key: master key parameter \'%s\' " | ||
220 | "is invalid\n", *master_desc); | ||
221 | goto out; | ||
222 | } | ||
223 | |||
224 | if (decrypted_datalen) { | ||
225 | *decrypted_datalen = strsep(&datablob, " \t"); | ||
226 | if (!*decrypted_datalen) { | ||
227 | pr_info("encrypted_key: keylen parameter is missing\n"); | ||
228 | goto out; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | switch (key_cmd) { | ||
233 | case Opt_new: | ||
234 | if (!decrypted_datalen) { | ||
235 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
236 | "when called from .update method\n", keyword); | ||
237 | break; | ||
238 | } | ||
239 | ret = 0; | ||
240 | break; | ||
241 | case Opt_load: | ||
242 | if (!decrypted_datalen) { | ||
243 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
244 | "when called from .update method\n", keyword); | ||
245 | break; | ||
246 | } | ||
247 | *hex_encoded_iv = strsep(&datablob, " \t"); | ||
248 | if (!*hex_encoded_iv) { | ||
249 | pr_info("encrypted_key: hex blob is missing\n"); | ||
250 | break; | ||
251 | } | ||
252 | ret = 0; | ||
253 | break; | ||
254 | case Opt_update: | ||
255 | if (decrypted_datalen) { | ||
256 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
257 | "when called from .instantiate method\n", | ||
258 | keyword); | ||
259 | break; | ||
260 | } | ||
261 | ret = 0; | ||
262 | break; | ||
263 | case Opt_err: | ||
264 | pr_info("encrypted_key: keyword \'%s\' not recognized\n", | ||
265 | keyword); | ||
266 | break; | ||
267 | } | ||
268 | out: | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * datablob_format - format as an ascii string, before copying to userspace | ||
274 | */ | ||
275 | static char *datablob_format(struct encrypted_key_payload *epayload, | ||
276 | size_t asciiblob_len) | ||
277 | { | ||
278 | char *ascii_buf, *bufp; | ||
279 | u8 *iv = epayload->iv; | ||
280 | int len; | ||
281 | int i; | ||
282 | |||
283 | ascii_buf = kmalloc(asciiblob_len + 1, GFP_KERNEL); | ||
284 | if (!ascii_buf) | ||
285 | goto out; | ||
286 | |||
287 | ascii_buf[asciiblob_len] = '\0'; | ||
288 | |||
289 | /* copy datablob master_desc and datalen strings */ | ||
290 | len = sprintf(ascii_buf, "%s %s %s ", epayload->format, | ||
291 | epayload->master_desc, epayload->datalen); | ||
292 | |||
293 | /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ | ||
294 | bufp = &ascii_buf[len]; | ||
295 | for (i = 0; i < (asciiblob_len - len) / 2; i++) | ||
296 | bufp = hex_byte_pack(bufp, iv[i]); | ||
297 | out: | ||
298 | return ascii_buf; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * request_user_key - request the user key | ||
303 | * | ||
304 | * Use a user provided key to encrypt/decrypt an encrypted-key. | ||
305 | */ | ||
306 | static struct key *request_user_key(const char *master_desc, u8 **master_key, | ||
307 | size_t *master_keylen) | ||
308 | { | ||
309 | struct user_key_payload *upayload; | ||
310 | struct key *ukey; | ||
311 | |||
312 | ukey = request_key(&key_type_user, master_desc, NULL); | ||
313 | if (IS_ERR(ukey)) | ||
314 | goto error; | ||
315 | |||
316 | down_read(&ukey->sem); | ||
317 | upayload = ukey->payload.data; | ||
318 | *master_key = upayload->data; | ||
319 | *master_keylen = upayload->datalen; | ||
320 | error: | ||
321 | return ukey; | ||
322 | } | ||
323 | |||
324 | static struct sdesc *alloc_sdesc(struct crypto_shash *alg) | ||
325 | { | ||
326 | struct sdesc *sdesc; | ||
327 | int size; | ||
328 | |||
329 | size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); | ||
330 | sdesc = kmalloc(size, GFP_KERNEL); | ||
331 | if (!sdesc) | ||
332 | return ERR_PTR(-ENOMEM); | ||
333 | sdesc->shash.tfm = alg; | ||
334 | sdesc->shash.flags = 0x0; | ||
335 | return sdesc; | ||
336 | } | ||
337 | |||
338 | static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen, | ||
339 | const u8 *buf, unsigned int buflen) | ||
340 | { | ||
341 | struct sdesc *sdesc; | ||
342 | int ret; | ||
343 | |||
344 | sdesc = alloc_sdesc(hmacalg); | ||
345 | if (IS_ERR(sdesc)) { | ||
346 | pr_info("encrypted_key: can't alloc %s\n", hmac_alg); | ||
347 | return PTR_ERR(sdesc); | ||
348 | } | ||
349 | |||
350 | ret = crypto_shash_setkey(hmacalg, key, keylen); | ||
351 | if (!ret) | ||
352 | ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); | ||
353 | kfree(sdesc); | ||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | static int calc_hash(u8 *digest, const u8 *buf, unsigned int buflen) | ||
358 | { | ||
359 | struct sdesc *sdesc; | ||
360 | int ret; | ||
361 | |||
362 | sdesc = alloc_sdesc(hashalg); | ||
363 | if (IS_ERR(sdesc)) { | ||
364 | pr_info("encrypted_key: can't alloc %s\n", hash_alg); | ||
365 | return PTR_ERR(sdesc); | ||
366 | } | ||
367 | |||
368 | ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); | ||
369 | kfree(sdesc); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | enum derived_key_type { ENC_KEY, AUTH_KEY }; | ||
374 | |||
375 | /* Derive authentication/encryption key from trusted key */ | ||
376 | static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, | ||
377 | const u8 *master_key, size_t master_keylen) | ||
378 | { | ||
379 | u8 *derived_buf; | ||
380 | unsigned int derived_buf_len; | ||
381 | int ret; | ||
382 | |||
383 | derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen; | ||
384 | if (derived_buf_len < HASH_SIZE) | ||
385 | derived_buf_len = HASH_SIZE; | ||
386 | |||
387 | derived_buf = kzalloc(derived_buf_len, GFP_KERNEL); | ||
388 | if (!derived_buf) { | ||
389 | pr_err("encrypted_key: out of memory\n"); | ||
390 | return -ENOMEM; | ||
391 | } | ||
392 | if (key_type) | ||
393 | strcpy(derived_buf, "AUTH_KEY"); | ||
394 | else | ||
395 | strcpy(derived_buf, "ENC_KEY"); | ||
396 | |||
397 | memcpy(derived_buf + strlen(derived_buf) + 1, master_key, | ||
398 | master_keylen); | ||
399 | ret = calc_hash(derived_key, derived_buf, derived_buf_len); | ||
400 | kfree(derived_buf); | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key, | ||
405 | unsigned int key_len, const u8 *iv, | ||
406 | unsigned int ivsize) | ||
407 | { | ||
408 | int ret; | ||
409 | |||
410 | desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); | ||
411 | if (IS_ERR(desc->tfm)) { | ||
412 | pr_err("encrypted_key: failed to load %s transform (%ld)\n", | ||
413 | blkcipher_alg, PTR_ERR(desc->tfm)); | ||
414 | return PTR_ERR(desc->tfm); | ||
415 | } | ||
416 | desc->flags = 0; | ||
417 | |||
418 | ret = crypto_blkcipher_setkey(desc->tfm, key, key_len); | ||
419 | if (ret < 0) { | ||
420 | pr_err("encrypted_key: failed to setkey (%d)\n", ret); | ||
421 | crypto_free_blkcipher(desc->tfm); | ||
422 | return ret; | ||
423 | } | ||
424 | crypto_blkcipher_set_iv(desc->tfm, iv, ivsize); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static struct key *request_master_key(struct encrypted_key_payload *epayload, | ||
429 | u8 **master_key, size_t *master_keylen) | ||
430 | { | ||
431 | struct key *mkey = NULL; | ||
432 | |||
433 | if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX, | ||
434 | KEY_TRUSTED_PREFIX_LEN)) { | ||
435 | mkey = request_trusted_key(epayload->master_desc + | ||
436 | KEY_TRUSTED_PREFIX_LEN, | ||
437 | master_key, master_keylen); | ||
438 | } else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX, | ||
439 | KEY_USER_PREFIX_LEN)) { | ||
440 | mkey = request_user_key(epayload->master_desc + | ||
441 | KEY_USER_PREFIX_LEN, | ||
442 | master_key, master_keylen); | ||
443 | } else | ||
444 | goto out; | ||
445 | |||
446 | if (IS_ERR(mkey)) { | ||
447 | int ret = PTR_ERR(mkey); | ||
448 | |||
449 | if (ret == -ENOTSUPP) | ||
450 | pr_info("encrypted_key: key %s not supported", | ||
451 | epayload->master_desc); | ||
452 | else | ||
453 | pr_info("encrypted_key: key %s not found", | ||
454 | epayload->master_desc); | ||
455 | goto out; | ||
456 | } | ||
457 | |||
458 | dump_master_key(*master_key, *master_keylen); | ||
459 | out: | ||
460 | return mkey; | ||
461 | } | ||
462 | |||
463 | /* Before returning data to userspace, encrypt decrypted data. */ | ||
464 | static int derived_key_encrypt(struct encrypted_key_payload *epayload, | ||
465 | const u8 *derived_key, | ||
466 | unsigned int derived_keylen) | ||
467 | { | ||
468 | struct scatterlist sg_in[2]; | ||
469 | struct scatterlist sg_out[1]; | ||
470 | struct blkcipher_desc desc; | ||
471 | unsigned int encrypted_datalen; | ||
472 | unsigned int padlen; | ||
473 | char pad[16]; | ||
474 | int ret; | ||
475 | |||
476 | encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | ||
477 | padlen = encrypted_datalen - epayload->decrypted_datalen; | ||
478 | |||
479 | ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, | ||
480 | epayload->iv, ivsize); | ||
481 | if (ret < 0) | ||
482 | goto out; | ||
483 | dump_decrypted_data(epayload); | ||
484 | |||
485 | memset(pad, 0, sizeof pad); | ||
486 | sg_init_table(sg_in, 2); | ||
487 | sg_set_buf(&sg_in[0], epayload->decrypted_data, | ||
488 | epayload->decrypted_datalen); | ||
489 | sg_set_buf(&sg_in[1], pad, padlen); | ||
490 | |||
491 | sg_init_table(sg_out, 1); | ||
492 | sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen); | ||
493 | |||
494 | ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen); | ||
495 | crypto_free_blkcipher(desc.tfm); | ||
496 | if (ret < 0) | ||
497 | pr_err("encrypted_key: failed to encrypt (%d)\n", ret); | ||
498 | else | ||
499 | dump_encrypted_data(epayload, encrypted_datalen); | ||
500 | out: | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | static int datablob_hmac_append(struct encrypted_key_payload *epayload, | ||
505 | const u8 *master_key, size_t master_keylen) | ||
506 | { | ||
507 | u8 derived_key[HASH_SIZE]; | ||
508 | u8 *digest; | ||
509 | int ret; | ||
510 | |||
511 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | ||
512 | if (ret < 0) | ||
513 | goto out; | ||
514 | |||
515 | digest = epayload->format + epayload->datablob_len; | ||
516 | ret = calc_hmac(digest, derived_key, sizeof derived_key, | ||
517 | epayload->format, epayload->datablob_len); | ||
518 | if (!ret) | ||
519 | dump_hmac(NULL, digest, HASH_SIZE); | ||
520 | out: | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | /* verify HMAC before decrypting encrypted key */ | ||
525 | static int datablob_hmac_verify(struct encrypted_key_payload *epayload, | ||
526 | const u8 *format, const u8 *master_key, | ||
527 | size_t master_keylen) | ||
528 | { | ||
529 | u8 derived_key[HASH_SIZE]; | ||
530 | u8 digest[HASH_SIZE]; | ||
531 | int ret; | ||
532 | char *p; | ||
533 | unsigned short len; | ||
534 | |||
535 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | ||
536 | if (ret < 0) | ||
537 | goto out; | ||
538 | |||
539 | len = epayload->datablob_len; | ||
540 | if (!format) { | ||
541 | p = epayload->master_desc; | ||
542 | len -= strlen(epayload->format) + 1; | ||
543 | } else | ||
544 | p = epayload->format; | ||
545 | |||
546 | ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); | ||
547 | if (ret < 0) | ||
548 | goto out; | ||
549 | ret = memcmp(digest, epayload->format + epayload->datablob_len, | ||
550 | sizeof digest); | ||
551 | if (ret) { | ||
552 | ret = -EINVAL; | ||
553 | dump_hmac("datablob", | ||
554 | epayload->format + epayload->datablob_len, | ||
555 | HASH_SIZE); | ||
556 | dump_hmac("calc", digest, HASH_SIZE); | ||
557 | } | ||
558 | out: | ||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | static int derived_key_decrypt(struct encrypted_key_payload *epayload, | ||
563 | const u8 *derived_key, | ||
564 | unsigned int derived_keylen) | ||
565 | { | ||
566 | struct scatterlist sg_in[1]; | ||
567 | struct scatterlist sg_out[2]; | ||
568 | struct blkcipher_desc desc; | ||
569 | unsigned int encrypted_datalen; | ||
570 | char pad[16]; | ||
571 | int ret; | ||
572 | |||
573 | encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | ||
574 | ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, | ||
575 | epayload->iv, ivsize); | ||
576 | if (ret < 0) | ||
577 | goto out; | ||
578 | dump_encrypted_data(epayload, encrypted_datalen); | ||
579 | |||
580 | memset(pad, 0, sizeof pad); | ||
581 | sg_init_table(sg_in, 1); | ||
582 | sg_init_table(sg_out, 2); | ||
583 | sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen); | ||
584 | sg_set_buf(&sg_out[0], epayload->decrypted_data, | ||
585 | epayload->decrypted_datalen); | ||
586 | sg_set_buf(&sg_out[1], pad, sizeof pad); | ||
587 | |||
588 | ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen); | ||
589 | crypto_free_blkcipher(desc.tfm); | ||
590 | if (ret < 0) | ||
591 | goto out; | ||
592 | dump_decrypted_data(epayload); | ||
593 | out: | ||
594 | return ret; | ||
595 | } | ||
596 | |||
597 | /* Allocate memory for decrypted key and datablob. */ | ||
598 | static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | ||
599 | const char *format, | ||
600 | const char *master_desc, | ||
601 | const char *datalen) | ||
602 | { | ||
603 | struct encrypted_key_payload *epayload = NULL; | ||
604 | unsigned short datablob_len; | ||
605 | unsigned short decrypted_datalen; | ||
606 | unsigned short payload_datalen; | ||
607 | unsigned int encrypted_datalen; | ||
608 | unsigned int format_len; | ||
609 | long dlen; | ||
610 | int ret; | ||
611 | |||
612 | ret = strict_strtol(datalen, 10, &dlen); | ||
613 | if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) | ||
614 | return ERR_PTR(-EINVAL); | ||
615 | |||
616 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
617 | decrypted_datalen = dlen; | ||
618 | payload_datalen = decrypted_datalen; | ||
619 | if (format && !strcmp(format, key_format_ecryptfs)) { | ||
620 | if (dlen != ECRYPTFS_MAX_KEY_BYTES) { | ||
621 | pr_err("encrypted_key: keylen for the ecryptfs format " | ||
622 | "must be equal to %d bytes\n", | ||
623 | ECRYPTFS_MAX_KEY_BYTES); | ||
624 | return ERR_PTR(-EINVAL); | ||
625 | } | ||
626 | decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES; | ||
627 | payload_datalen = sizeof(struct ecryptfs_auth_tok); | ||
628 | } | ||
629 | |||
630 | encrypted_datalen = roundup(decrypted_datalen, blksize); | ||
631 | |||
632 | datablob_len = format_len + 1 + strlen(master_desc) + 1 | ||
633 | + strlen(datalen) + 1 + ivsize + 1 + encrypted_datalen; | ||
634 | |||
635 | ret = key_payload_reserve(key, payload_datalen + datablob_len | ||
636 | + HASH_SIZE + 1); | ||
637 | if (ret < 0) | ||
638 | return ERR_PTR(ret); | ||
639 | |||
640 | epayload = kzalloc(sizeof(*epayload) + payload_datalen + | ||
641 | datablob_len + HASH_SIZE + 1, GFP_KERNEL); | ||
642 | if (!epayload) | ||
643 | return ERR_PTR(-ENOMEM); | ||
644 | |||
645 | epayload->payload_datalen = payload_datalen; | ||
646 | epayload->decrypted_datalen = decrypted_datalen; | ||
647 | epayload->datablob_len = datablob_len; | ||
648 | return epayload; | ||
649 | } | ||
650 | |||
651 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | ||
652 | const char *format, const char *hex_encoded_iv) | ||
653 | { | ||
654 | struct key *mkey; | ||
655 | u8 derived_key[HASH_SIZE]; | ||
656 | u8 *master_key; | ||
657 | u8 *hmac; | ||
658 | const char *hex_encoded_data; | ||
659 | unsigned int encrypted_datalen; | ||
660 | size_t master_keylen; | ||
661 | size_t asciilen; | ||
662 | int ret; | ||
663 | |||
664 | encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | ||
665 | asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2; | ||
666 | if (strlen(hex_encoded_iv) != asciilen) | ||
667 | return -EINVAL; | ||
668 | |||
669 | hex_encoded_data = hex_encoded_iv + (2 * ivsize) + 2; | ||
670 | ret = hex2bin(epayload->iv, hex_encoded_iv, ivsize); | ||
671 | if (ret < 0) | ||
672 | return -EINVAL; | ||
673 | ret = hex2bin(epayload->encrypted_data, hex_encoded_data, | ||
674 | encrypted_datalen); | ||
675 | if (ret < 0) | ||
676 | return -EINVAL; | ||
677 | |||
678 | hmac = epayload->format + epayload->datablob_len; | ||
679 | ret = hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), | ||
680 | HASH_SIZE); | ||
681 | if (ret < 0) | ||
682 | return -EINVAL; | ||
683 | |||
684 | mkey = request_master_key(epayload, &master_key, &master_keylen); | ||
685 | if (IS_ERR(mkey)) | ||
686 | return PTR_ERR(mkey); | ||
687 | |||
688 | ret = datablob_hmac_verify(epayload, format, master_key, master_keylen); | ||
689 | if (ret < 0) { | ||
690 | pr_err("encrypted_key: bad hmac (%d)\n", ret); | ||
691 | goto out; | ||
692 | } | ||
693 | |||
694 | ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen); | ||
695 | if (ret < 0) | ||
696 | goto out; | ||
697 | |||
698 | ret = derived_key_decrypt(epayload, derived_key, sizeof derived_key); | ||
699 | if (ret < 0) | ||
700 | pr_err("encrypted_key: failed to decrypt key (%d)\n", ret); | ||
701 | out: | ||
702 | up_read(&mkey->sem); | ||
703 | key_put(mkey); | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static void __ekey_init(struct encrypted_key_payload *epayload, | ||
708 | const char *format, const char *master_desc, | ||
709 | const char *datalen) | ||
710 | { | ||
711 | unsigned int format_len; | ||
712 | |||
713 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
714 | epayload->format = epayload->payload_data + epayload->payload_datalen; | ||
715 | epayload->master_desc = epayload->format + format_len + 1; | ||
716 | epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; | ||
717 | epayload->iv = epayload->datalen + strlen(datalen) + 1; | ||
718 | epayload->encrypted_data = epayload->iv + ivsize + 1; | ||
719 | epayload->decrypted_data = epayload->payload_data; | ||
720 | |||
721 | if (!format) | ||
722 | memcpy(epayload->format, key_format_default, format_len); | ||
723 | else { | ||
724 | if (!strcmp(format, key_format_ecryptfs)) | ||
725 | epayload->decrypted_data = | ||
726 | ecryptfs_get_auth_tok_key((struct ecryptfs_auth_tok *)epayload->payload_data); | ||
727 | |||
728 | memcpy(epayload->format, format, format_len); | ||
729 | } | ||
730 | |||
731 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); | ||
732 | memcpy(epayload->datalen, datalen, strlen(datalen)); | ||
733 | } | ||
734 | |||
735 | /* | ||
736 | * encrypted_init - initialize an encrypted key | ||
737 | * | ||
738 | * For a new key, use a random number for both the iv and data | ||
739 | * itself. For an old key, decrypt the hex encoded data. | ||
740 | */ | ||
741 | static int encrypted_init(struct encrypted_key_payload *epayload, | ||
742 | const char *key_desc, const char *format, | ||
743 | const char *master_desc, const char *datalen, | ||
744 | const char *hex_encoded_iv) | ||
745 | { | ||
746 | int ret = 0; | ||
747 | |||
748 | if (format && !strcmp(format, key_format_ecryptfs)) { | ||
749 | ret = valid_ecryptfs_desc(key_desc); | ||
750 | if (ret < 0) | ||
751 | return ret; | ||
752 | |||
753 | ecryptfs_fill_auth_tok((struct ecryptfs_auth_tok *)epayload->payload_data, | ||
754 | key_desc); | ||
755 | } | ||
756 | |||
757 | __ekey_init(epayload, format, master_desc, datalen); | ||
758 | if (!hex_encoded_iv) { | ||
759 | get_random_bytes(epayload->iv, ivsize); | ||
760 | |||
761 | get_random_bytes(epayload->decrypted_data, | ||
762 | epayload->decrypted_datalen); | ||
763 | } else | ||
764 | ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); | ||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * encrypted_instantiate - instantiate an encrypted key | ||
770 | * | ||
771 | * Decrypt an existing encrypted datablob or create a new encrypted key | ||
772 | * based on a kernel random number. | ||
773 | * | ||
774 | * On success, return 0. Otherwise return errno. | ||
775 | */ | ||
776 | static int encrypted_instantiate(struct key *key, | ||
777 | struct key_preparsed_payload *prep) | ||
778 | { | ||
779 | struct encrypted_key_payload *epayload = NULL; | ||
780 | char *datablob = NULL; | ||
781 | const char *format = NULL; | ||
782 | char *master_desc = NULL; | ||
783 | char *decrypted_datalen = NULL; | ||
784 | char *hex_encoded_iv = NULL; | ||
785 | size_t datalen = prep->datalen; | ||
786 | int ret; | ||
787 | |||
788 | if (datalen <= 0 || datalen > 32767 || !prep->data) | ||
789 | return -EINVAL; | ||
790 | |||
791 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | ||
792 | if (!datablob) | ||
793 | return -ENOMEM; | ||
794 | datablob[datalen] = 0; | ||
795 | memcpy(datablob, prep->data, datalen); | ||
796 | ret = datablob_parse(datablob, &format, &master_desc, | ||
797 | &decrypted_datalen, &hex_encoded_iv); | ||
798 | if (ret < 0) | ||
799 | goto out; | ||
800 | |||
801 | epayload = encrypted_key_alloc(key, format, master_desc, | ||
802 | decrypted_datalen); | ||
803 | if (IS_ERR(epayload)) { | ||
804 | ret = PTR_ERR(epayload); | ||
805 | goto out; | ||
806 | } | ||
807 | ret = encrypted_init(epayload, key->description, format, master_desc, | ||
808 | decrypted_datalen, hex_encoded_iv); | ||
809 | if (ret < 0) { | ||
810 | kfree(epayload); | ||
811 | goto out; | ||
812 | } | ||
813 | |||
814 | rcu_assign_keypointer(key, epayload); | ||
815 | out: | ||
816 | kfree(datablob); | ||
817 | return ret; | ||
818 | } | ||
819 | |||
820 | static void encrypted_rcu_free(struct rcu_head *rcu) | ||
821 | { | ||
822 | struct encrypted_key_payload *epayload; | ||
823 | |||
824 | epayload = container_of(rcu, struct encrypted_key_payload, rcu); | ||
825 | memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); | ||
826 | kfree(epayload); | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * encrypted_update - update the master key description | ||
831 | * | ||
832 | * Change the master key description for an existing encrypted key. | ||
833 | * The next read will return an encrypted datablob using the new | ||
834 | * master key description. | ||
835 | * | ||
836 | * On success, return 0. Otherwise return errno. | ||
837 | */ | ||
838 | static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) | ||
839 | { | ||
840 | struct encrypted_key_payload *epayload = key->payload.data; | ||
841 | struct encrypted_key_payload *new_epayload; | ||
842 | char *buf; | ||
843 | char *new_master_desc = NULL; | ||
844 | const char *format = NULL; | ||
845 | size_t datalen = prep->datalen; | ||
846 | int ret = 0; | ||
847 | |||
848 | if (datalen <= 0 || datalen > 32767 || !prep->data) | ||
849 | return -EINVAL; | ||
850 | |||
851 | buf = kmalloc(datalen + 1, GFP_KERNEL); | ||
852 | if (!buf) | ||
853 | return -ENOMEM; | ||
854 | |||
855 | buf[datalen] = 0; | ||
856 | memcpy(buf, prep->data, datalen); | ||
857 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); | ||
858 | if (ret < 0) | ||
859 | goto out; | ||
860 | |||
861 | ret = valid_master_desc(new_master_desc, epayload->master_desc); | ||
862 | if (ret < 0) | ||
863 | goto out; | ||
864 | |||
865 | new_epayload = encrypted_key_alloc(key, epayload->format, | ||
866 | new_master_desc, epayload->datalen); | ||
867 | if (IS_ERR(new_epayload)) { | ||
868 | ret = PTR_ERR(new_epayload); | ||
869 | goto out; | ||
870 | } | ||
871 | |||
872 | __ekey_init(new_epayload, epayload->format, new_master_desc, | ||
873 | epayload->datalen); | ||
874 | |||
875 | memcpy(new_epayload->iv, epayload->iv, ivsize); | ||
876 | memcpy(new_epayload->payload_data, epayload->payload_data, | ||
877 | epayload->payload_datalen); | ||
878 | |||
879 | rcu_assign_keypointer(key, new_epayload); | ||
880 | call_rcu(&epayload->rcu, encrypted_rcu_free); | ||
881 | out: | ||
882 | kfree(buf); | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | /* | ||
887 | * encrypted_read - format and copy the encrypted data to userspace | ||
888 | * | ||
889 | * The resulting datablob format is: | ||
890 | * <master-key name> <decrypted data length> <encrypted iv> <encrypted data> | ||
891 | * | ||
892 | * On success, return to userspace the encrypted key datablob size. | ||
893 | */ | ||
894 | static long encrypted_read(const struct key *key, char __user *buffer, | ||
895 | size_t buflen) | ||
896 | { | ||
897 | struct encrypted_key_payload *epayload; | ||
898 | struct key *mkey; | ||
899 | u8 *master_key; | ||
900 | size_t master_keylen; | ||
901 | char derived_key[HASH_SIZE]; | ||
902 | char *ascii_buf; | ||
903 | size_t asciiblob_len; | ||
904 | int ret; | ||
905 | |||
906 | epayload = rcu_dereference_key(key); | ||
907 | |||
908 | /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ | ||
909 | asciiblob_len = epayload->datablob_len + ivsize + 1 | ||
910 | + roundup(epayload->decrypted_datalen, blksize) | ||
911 | + (HASH_SIZE * 2); | ||
912 | |||
913 | if (!buffer || buflen < asciiblob_len) | ||
914 | return asciiblob_len; | ||
915 | |||
916 | mkey = request_master_key(epayload, &master_key, &master_keylen); | ||
917 | if (IS_ERR(mkey)) | ||
918 | return PTR_ERR(mkey); | ||
919 | |||
920 | ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen); | ||
921 | if (ret < 0) | ||
922 | goto out; | ||
923 | |||
924 | ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key); | ||
925 | if (ret < 0) | ||
926 | goto out; | ||
927 | |||
928 | ret = datablob_hmac_append(epayload, master_key, master_keylen); | ||
929 | if (ret < 0) | ||
930 | goto out; | ||
931 | |||
932 | ascii_buf = datablob_format(epayload, asciiblob_len); | ||
933 | if (!ascii_buf) { | ||
934 | ret = -ENOMEM; | ||
935 | goto out; | ||
936 | } | ||
937 | |||
938 | up_read(&mkey->sem); | ||
939 | key_put(mkey); | ||
940 | |||
941 | if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0) | ||
942 | ret = -EFAULT; | ||
943 | kfree(ascii_buf); | ||
944 | |||
945 | return asciiblob_len; | ||
946 | out: | ||
947 | up_read(&mkey->sem); | ||
948 | key_put(mkey); | ||
949 | return ret; | ||
950 | } | ||
951 | |||
952 | /* | ||
953 | * encrypted_destroy - before freeing the key, clear the decrypted data | ||
954 | * | ||
955 | * Before freeing the key, clear the memory containing the decrypted | ||
956 | * key data. | ||
957 | */ | ||
958 | static void encrypted_destroy(struct key *key) | ||
959 | { | ||
960 | struct encrypted_key_payload *epayload = key->payload.data; | ||
961 | |||
962 | if (!epayload) | ||
963 | return; | ||
964 | |||
965 | memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); | ||
966 | kfree(key->payload.data); | ||
967 | } | ||
968 | |||
969 | struct key_type key_type_encrypted = { | ||
970 | .name = "encrypted", | ||
971 | .instantiate = encrypted_instantiate, | ||
972 | .update = encrypted_update, | ||
973 | .match = user_match, | ||
974 | .destroy = encrypted_destroy, | ||
975 | .describe = user_describe, | ||
976 | .read = encrypted_read, | ||
977 | }; | ||
978 | EXPORT_SYMBOL_GPL(key_type_encrypted); | ||
979 | |||
980 | static void encrypted_shash_release(void) | ||
981 | { | ||
982 | if (hashalg) | ||
983 | crypto_free_shash(hashalg); | ||
984 | if (hmacalg) | ||
985 | crypto_free_shash(hmacalg); | ||
986 | } | ||
987 | |||
988 | static int __init encrypted_shash_alloc(void) | ||
989 | { | ||
990 | int ret; | ||
991 | |||
992 | hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC); | ||
993 | if (IS_ERR(hmacalg)) { | ||
994 | pr_info("encrypted_key: could not allocate crypto %s\n", | ||
995 | hmac_alg); | ||
996 | return PTR_ERR(hmacalg); | ||
997 | } | ||
998 | |||
999 | hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC); | ||
1000 | if (IS_ERR(hashalg)) { | ||
1001 | pr_info("encrypted_key: could not allocate crypto %s\n", | ||
1002 | hash_alg); | ||
1003 | ret = PTR_ERR(hashalg); | ||
1004 | goto hashalg_fail; | ||
1005 | } | ||
1006 | |||
1007 | return 0; | ||
1008 | |||
1009 | hashalg_fail: | ||
1010 | crypto_free_shash(hmacalg); | ||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | static int __init init_encrypted(void) | ||
1015 | { | ||
1016 | int ret; | ||
1017 | |||
1018 | ret = encrypted_shash_alloc(); | ||
1019 | if (ret < 0) | ||
1020 | return ret; | ||
1021 | ret = register_key_type(&key_type_encrypted); | ||
1022 | if (ret < 0) | ||
1023 | goto out; | ||
1024 | return aes_get_sizes(); | ||
1025 | out: | ||
1026 | encrypted_shash_release(); | ||
1027 | return ret; | ||
1028 | |||
1029 | } | ||
1030 | |||
1031 | static void __exit cleanup_encrypted(void) | ||
1032 | { | ||
1033 | encrypted_shash_release(); | ||
1034 | unregister_key_type(&key_type_encrypted); | ||
1035 | } | ||
1036 | |||
1037 | late_initcall(init_encrypted); | ||
1038 | module_exit(cleanup_encrypted); | ||
1039 | |||
1040 | MODULE_LICENSE("GPL"); | ||
diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h deleted file mode 100644 index 8136a2d44c6..00000000000 --- a/security/keys/encrypted-keys/encrypted.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | #ifndef __ENCRYPTED_KEY_H | ||
2 | #define __ENCRYPTED_KEY_H | ||
3 | |||
4 | #define ENCRYPTED_DEBUG 0 | ||
5 | #if defined(CONFIG_TRUSTED_KEYS) || \ | ||
6 | (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE)) | ||
7 | extern struct key *request_trusted_key(const char *trusted_desc, | ||
8 | u8 **master_key, size_t *master_keylen); | ||
9 | #else | ||
10 | static inline struct key *request_trusted_key(const char *trusted_desc, | ||
11 | u8 **master_key, | ||
12 | size_t *master_keylen) | ||
13 | { | ||
14 | return ERR_PTR(-EOPNOTSUPP); | ||
15 | } | ||
16 | #endif | ||
17 | |||
18 | #if ENCRYPTED_DEBUG | ||
19 | static inline void dump_master_key(const u8 *master_key, size_t master_keylen) | ||
20 | { | ||
21 | print_hex_dump(KERN_ERR, "master key: ", DUMP_PREFIX_NONE, 32, 1, | ||
22 | master_key, master_keylen, 0); | ||
23 | } | ||
24 | |||
25 | static inline void dump_decrypted_data(struct encrypted_key_payload *epayload) | ||
26 | { | ||
27 | print_hex_dump(KERN_ERR, "decrypted data: ", DUMP_PREFIX_NONE, 32, 1, | ||
28 | epayload->decrypted_data, | ||
29 | epayload->decrypted_datalen, 0); | ||
30 | } | ||
31 | |||
32 | static inline void dump_encrypted_data(struct encrypted_key_payload *epayload, | ||
33 | unsigned int encrypted_datalen) | ||
34 | { | ||
35 | print_hex_dump(KERN_ERR, "encrypted data: ", DUMP_PREFIX_NONE, 32, 1, | ||
36 | epayload->encrypted_data, encrypted_datalen, 0); | ||
37 | } | ||
38 | |||
39 | static inline void dump_hmac(const char *str, const u8 *digest, | ||
40 | unsigned int hmac_size) | ||
41 | { | ||
42 | if (str) | ||
43 | pr_info("encrypted_key: %s", str); | ||
44 | print_hex_dump(KERN_ERR, "hmac: ", DUMP_PREFIX_NONE, 32, 1, digest, | ||
45 | hmac_size, 0); | ||
46 | } | ||
47 | #else | ||
48 | static inline void dump_master_key(const u8 *master_key, size_t master_keylen) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | static inline void dump_decrypted_data(struct encrypted_key_payload *epayload) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | static inline void dump_encrypted_data(struct encrypted_key_payload *epayload, | ||
57 | unsigned int encrypted_datalen) | ||
58 | { | ||
59 | } | ||
60 | |||
61 | static inline void dump_hmac(const char *str, const u8 *digest, | ||
62 | unsigned int hmac_size) | ||
63 | { | ||
64 | } | ||
65 | #endif | ||
66 | #endif | ||
diff --git a/security/keys/encrypted-keys/masterkey_trusted.c b/security/keys/encrypted-keys/masterkey_trusted.c deleted file mode 100644 index 013f7e5d3a2..00000000000 --- a/security/keys/encrypted-keys/masterkey_trusted.c +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 IBM Corporation | ||
3 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
4 | * TORSEC group -- http://security.polito.it | ||
5 | * | ||
6 | * Authors: | ||
7 | * Mimi Zohar <zohar@us.ibm.com> | ||
8 | * Roberto Sassu <roberto.sassu@polito.it> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation, version 2 of the License. | ||
13 | * | ||
14 | * See Documentation/security/keys-trusted-encrypted.txt | ||
15 | */ | ||
16 | |||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <keys/trusted-type.h> | ||
21 | #include <keys/encrypted-type.h> | ||
22 | #include "encrypted.h" | ||
23 | |||
24 | /* | ||
25 | * request_trusted_key - request the trusted key | ||
26 | * | ||
27 | * Trusted keys are sealed to PCRs and other metadata. Although userspace | ||
28 | * manages both trusted/encrypted key-types, like the encrypted key type | ||
29 | * data, trusted key type data is not visible decrypted from userspace. | ||
30 | */ | ||
31 | struct key *request_trusted_key(const char *trusted_desc, | ||
32 | u8 **master_key, size_t *master_keylen) | ||
33 | { | ||
34 | struct trusted_key_payload *tpayload; | ||
35 | struct key *tkey; | ||
36 | |||
37 | tkey = request_key(&key_type_trusted, trusted_desc, NULL); | ||
38 | if (IS_ERR(tkey)) | ||
39 | goto error; | ||
40 | |||
41 | down_read(&tkey->sem); | ||
42 | tpayload = tkey->payload.data; | ||
43 | *master_key = tpayload->key; | ||
44 | *master_keylen = tpayload->key_len; | ||
45 | error: | ||
46 | return tkey; | ||
47 | } | ||
diff --git a/security/keys/gc.c b/security/keys/gc.c index d67c97bb102..89df6b5f203 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Key garbage collector | 1 | /* Key garbage collector |
2 | * | 2 | * |
3 | * Copyright (C) 2009-2011 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -10,8 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/security.h> | ||
15 | #include <keys/keyring-type.h> | 13 | #include <keys/keyring-type.h> |
16 | #include "internal.h" | 14 | #include "internal.h" |
17 | 15 | ||
@@ -21,33 +19,17 @@ | |||
21 | unsigned key_gc_delay = 5 * 60; | 19 | unsigned key_gc_delay = 5 * 60; |
22 | 20 | ||
23 | /* | 21 | /* |
24 | * Reaper for unused keys. | 22 | * Reaper |
25 | */ | ||
26 | static void key_garbage_collector(struct work_struct *work); | ||
27 | DECLARE_WORK(key_gc_work, key_garbage_collector); | ||
28 | |||
29 | /* | ||
30 | * Reaper for links from keyrings to dead keys. | ||
31 | */ | 23 | */ |
32 | static void key_gc_timer_func(unsigned long); | 24 | static void key_gc_timer_func(unsigned long); |
25 | static void key_garbage_collector(struct work_struct *); | ||
33 | static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0); | 26 | static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0); |
34 | 27 | static DECLARE_WORK(key_gc_work, key_garbage_collector); | |
28 | static key_serial_t key_gc_cursor; /* the last key the gc considered */ | ||
29 | static bool key_gc_again; | ||
30 | static unsigned long key_gc_executing; | ||
35 | static time_t key_gc_next_run = LONG_MAX; | 31 | static time_t key_gc_next_run = LONG_MAX; |
36 | static struct key_type *key_gc_dead_keytype; | 32 | static time_t key_gc_new_timer; |
37 | |||
38 | static unsigned long key_gc_flags; | ||
39 | #define KEY_GC_KEY_EXPIRED 0 /* A key expired and needs unlinking */ | ||
40 | #define KEY_GC_REAP_KEYTYPE 1 /* A keytype is being unregistered */ | ||
41 | #define KEY_GC_REAPING_KEYTYPE 2 /* Cleared when keytype reaped */ | ||
42 | |||
43 | |||
44 | /* | ||
45 | * Any key whose type gets unregistered will be re-typed to this if it can't be | ||
46 | * immediately unlinked. | ||
47 | */ | ||
48 | struct key_type key_type_dead = { | ||
49 | .name = "dead", | ||
50 | }; | ||
51 | 33 | ||
52 | /* | 34 | /* |
53 | * Schedule a garbage collection run. | 35 | * Schedule a garbage collection run. |
@@ -60,91 +42,39 @@ void key_schedule_gc(time_t gc_at) | |||
60 | 42 | ||
61 | kenter("%ld", gc_at - now); | 43 | kenter("%ld", gc_at - now); |
62 | 44 | ||
63 | if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { | 45 | if (gc_at <= now) { |
64 | kdebug("IMMEDIATE"); | ||
65 | schedule_work(&key_gc_work); | 46 | schedule_work(&key_gc_work); |
66 | } else if (gc_at < key_gc_next_run) { | 47 | } else if (gc_at < key_gc_next_run) { |
67 | kdebug("DEFERRED"); | ||
68 | key_gc_next_run = gc_at; | ||
69 | expires = jiffies + (gc_at - now) * HZ; | 48 | expires = jiffies + (gc_at - now) * HZ; |
70 | mod_timer(&key_gc_timer, expires); | 49 | mod_timer(&key_gc_timer, expires); |
71 | } | 50 | } |
72 | } | 51 | } |
73 | 52 | ||
74 | /* | 53 | /* |
75 | * Schedule a dead links collection run. | 54 | * The garbage collector timer kicked off |
76 | */ | ||
77 | void key_schedule_gc_links(void) | ||
78 | { | ||
79 | set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags); | ||
80 | schedule_work(&key_gc_work); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Some key's cleanup time was met after it expired, so we need to get the | ||
85 | * reaper to go through a cycle finding expired keys. | ||
86 | */ | 55 | */ |
87 | static void key_gc_timer_func(unsigned long data) | 56 | static void key_gc_timer_func(unsigned long data) |
88 | { | 57 | { |
89 | kenter(""); | 58 | kenter(""); |
90 | key_gc_next_run = LONG_MAX; | 59 | key_gc_next_run = LONG_MAX; |
91 | key_schedule_gc_links(); | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * wait_on_bit() sleep function for uninterruptible waiting | ||
96 | */ | ||
97 | static int key_gc_wait_bit(void *flags) | ||
98 | { | ||
99 | schedule(); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Reap keys of dead type. | ||
105 | * | ||
106 | * We use three flags to make sure we see three complete cycles of the garbage | ||
107 | * collector: the first to mark keys of that type as being dead, the second to | ||
108 | * collect dead links and the third to clean up the dead keys. We have to be | ||
109 | * careful as there may already be a cycle in progress. | ||
110 | * | ||
111 | * The caller must be holding key_types_sem. | ||
112 | */ | ||
113 | void key_gc_keytype(struct key_type *ktype) | ||
114 | { | ||
115 | kenter("%s", ktype->name); | ||
116 | |||
117 | key_gc_dead_keytype = ktype; | ||
118 | set_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags); | ||
119 | smp_mb(); | ||
120 | set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags); | ||
121 | |||
122 | kdebug("schedule"); | ||
123 | schedule_work(&key_gc_work); | 60 | schedule_work(&key_gc_work); |
124 | |||
125 | kdebug("sleep"); | ||
126 | wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit, | ||
127 | TASK_UNINTERRUPTIBLE); | ||
128 | |||
129 | key_gc_dead_keytype = NULL; | ||
130 | kleave(""); | ||
131 | } | 61 | } |
132 | 62 | ||
133 | /* | 63 | /* |
134 | * Garbage collect pointers from a keyring. | 64 | * Garbage collect pointers from a keyring. |
135 | * | 65 | * |
136 | * Not called with any locks held. The keyring's key struct will not be | 66 | * Return true if we altered the keyring. |
137 | * deallocated under us as only our caller may deallocate it. | ||
138 | */ | 67 | */ |
139 | static void key_gc_keyring(struct key *keyring, time_t limit) | 68 | static bool key_gc_keyring(struct key *keyring, time_t limit) |
69 | __releases(key_serial_lock) | ||
140 | { | 70 | { |
141 | struct keyring_list *klist; | 71 | struct keyring_list *klist; |
72 | struct key *key; | ||
142 | int loop; | 73 | int loop; |
143 | 74 | ||
144 | kenter("%x", key_serial(keyring)); | 75 | kenter("%x", key_serial(keyring)); |
145 | 76 | ||
146 | if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | | 77 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
147 | (1 << KEY_FLAG_REVOKED))) | ||
148 | goto dont_gc; | 78 | goto dont_gc; |
149 | 79 | ||
150 | /* scan the keyring looking for dead keys */ | 80 | /* scan the keyring looking for dead keys */ |
@@ -153,260 +83,140 @@ static void key_gc_keyring(struct key *keyring, time_t limit) | |||
153 | if (!klist) | 83 | if (!klist) |
154 | goto unlock_dont_gc; | 84 | goto unlock_dont_gc; |
155 | 85 | ||
156 | loop = klist->nkeys; | 86 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
157 | smp_rmb(); | 87 | key = klist->keys[loop]; |
158 | for (loop--; loop >= 0; loop--) { | 88 | if (test_bit(KEY_FLAG_DEAD, &key->flags) || |
159 | struct key *key = rcu_dereference(klist->keys[loop]); | 89 | (key->expiry > 0 && key->expiry <= limit)) |
160 | if (key_is_dead(key, limit)) | ||
161 | goto do_gc; | 90 | goto do_gc; |
162 | } | 91 | } |
163 | 92 | ||
164 | unlock_dont_gc: | 93 | unlock_dont_gc: |
165 | rcu_read_unlock(); | 94 | rcu_read_unlock(); |
166 | dont_gc: | 95 | dont_gc: |
167 | kleave(" [no gc]"); | 96 | kleave(" = false"); |
168 | return; | 97 | return false; |
169 | 98 | ||
170 | do_gc: | 99 | do_gc: |
171 | rcu_read_unlock(); | 100 | rcu_read_unlock(); |
172 | 101 | key_gc_cursor = keyring->serial; | |
102 | key_get(keyring); | ||
103 | spin_unlock(&key_serial_lock); | ||
173 | keyring_gc(keyring, limit); | 104 | keyring_gc(keyring, limit); |
174 | kleave(" [gc]"); | 105 | key_put(keyring); |
106 | kleave(" = true"); | ||
107 | return true; | ||
175 | } | 108 | } |
176 | 109 | ||
177 | /* | 110 | /* |
178 | * Garbage collect a list of unreferenced, detached keys | 111 | * Garbage collector for keys. This involves scanning the keyrings for dead, |
179 | */ | 112 | * expired and revoked keys that have overstayed their welcome |
180 | static noinline void key_gc_unused_keys(struct list_head *keys) | ||
181 | { | ||
182 | while (!list_empty(keys)) { | ||
183 | struct key *key = | ||
184 | list_entry(keys->next, struct key, graveyard_link); | ||
185 | list_del(&key->graveyard_link); | ||
186 | |||
187 | kdebug("- %u", key->serial); | ||
188 | key_check(key); | ||
189 | |||
190 | security_key_free(key); | ||
191 | |||
192 | /* deal with the user's key tracking and quota */ | ||
193 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | ||
194 | spin_lock(&key->user->lock); | ||
195 | key->user->qnkeys--; | ||
196 | key->user->qnbytes -= key->quotalen; | ||
197 | spin_unlock(&key->user->lock); | ||
198 | } | ||
199 | |||
200 | atomic_dec(&key->user->nkeys); | ||
201 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | ||
202 | atomic_dec(&key->user->nikeys); | ||
203 | |||
204 | key_user_put(key->user); | ||
205 | |||
206 | /* now throw away the key memory */ | ||
207 | if (key->type->destroy) | ||
208 | key->type->destroy(key); | ||
209 | |||
210 | kfree(key->description); | ||
211 | |||
212 | #ifdef KEY_DEBUGGING | ||
213 | key->magic = KEY_DEBUG_MAGIC_X; | ||
214 | #endif | ||
215 | kmem_cache_free(key_jar, key); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Garbage collector for unused keys. | ||
221 | * | ||
222 | * This is done in process context so that we don't have to disable interrupts | ||
223 | * all over the place. key_put() schedules this rather than trying to do the | ||
224 | * cleanup itself, which means key_put() doesn't have to sleep. | ||
225 | */ | 113 | */ |
226 | static void key_garbage_collector(struct work_struct *work) | 114 | static void key_garbage_collector(struct work_struct *work) |
227 | { | 115 | { |
228 | static LIST_HEAD(graveyard); | 116 | struct rb_node *rb; |
229 | static u8 gc_state; /* Internal persistent state */ | 117 | key_serial_t cursor; |
230 | #define KEY_GC_REAP_AGAIN 0x01 /* - Need another cycle */ | 118 | struct key *key, *xkey; |
231 | #define KEY_GC_REAPING_LINKS 0x02 /* - We need to reap links */ | 119 | time_t new_timer = LONG_MAX, limit, now; |
232 | #define KEY_GC_SET_TIMER 0x04 /* - We need to restart the timer */ | 120 | |
233 | #define KEY_GC_REAPING_DEAD_1 0x10 /* - We need to mark dead keys */ | 121 | now = current_kernel_time().tv_sec; |
234 | #define KEY_GC_REAPING_DEAD_2 0x20 /* - We need to reap dead key links */ | 122 | kenter("[%x,%ld]", key_gc_cursor, key_gc_new_timer - now); |
235 | #define KEY_GC_REAPING_DEAD_3 0x40 /* - We need to reap dead keys */ | 123 | |
236 | #define KEY_GC_FOUND_DEAD_KEY 0x80 /* - We found at least one dead key */ | 124 | if (test_and_set_bit(0, &key_gc_executing)) { |
237 | 125 | key_schedule_gc(current_kernel_time().tv_sec + 1); | |
238 | struct rb_node *cursor; | 126 | kleave(" [busy; deferring]"); |
239 | struct key *key; | 127 | return; |
240 | time_t new_timer, limit; | 128 | } |
241 | |||
242 | kenter("[%lx,%x]", key_gc_flags, gc_state); | ||
243 | 129 | ||
244 | limit = current_kernel_time().tv_sec; | 130 | limit = now; |
245 | if (limit > key_gc_delay) | 131 | if (limit > key_gc_delay) |
246 | limit -= key_gc_delay; | 132 | limit -= key_gc_delay; |
247 | else | 133 | else |
248 | limit = key_gc_delay; | 134 | limit = key_gc_delay; |
249 | 135 | ||
250 | /* Work out what we're going to be doing in this pass */ | ||
251 | gc_state &= KEY_GC_REAPING_DEAD_1 | KEY_GC_REAPING_DEAD_2; | ||
252 | gc_state <<= 1; | ||
253 | if (test_and_clear_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags)) | ||
254 | gc_state |= KEY_GC_REAPING_LINKS | KEY_GC_SET_TIMER; | ||
255 | |||
256 | if (test_and_clear_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) | ||
257 | gc_state |= KEY_GC_REAPING_DEAD_1; | ||
258 | kdebug("new pass %x", gc_state); | ||
259 | |||
260 | new_timer = LONG_MAX; | ||
261 | |||
262 | /* As only this function is permitted to remove things from the key | ||
263 | * serial tree, if cursor is non-NULL then it will always point to a | ||
264 | * valid node in the tree - even if lock got dropped. | ||
265 | */ | ||
266 | spin_lock(&key_serial_lock); | 136 | spin_lock(&key_serial_lock); |
267 | cursor = rb_first(&key_serial_tree); | ||
268 | |||
269 | continue_scanning: | ||
270 | while (cursor) { | ||
271 | key = rb_entry(cursor, struct key, serial_node); | ||
272 | cursor = rb_next(cursor); | ||
273 | 137 | ||
274 | if (atomic_read(&key->usage) == 0) | 138 | if (unlikely(RB_EMPTY_ROOT(&key_serial_tree))) { |
275 | goto found_unreferenced_key; | 139 | spin_unlock(&key_serial_lock); |
276 | 140 | clear_bit(0, &key_gc_executing); | |
277 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) { | 141 | return; |
278 | if (key->type == key_gc_dead_keytype) { | 142 | } |
279 | gc_state |= KEY_GC_FOUND_DEAD_KEY; | ||
280 | set_bit(KEY_FLAG_DEAD, &key->flags); | ||
281 | key->perm = 0; | ||
282 | goto skip_dead_key; | ||
283 | } | ||
284 | } | ||
285 | 143 | ||
286 | if (gc_state & KEY_GC_SET_TIMER) { | 144 | cursor = key_gc_cursor; |
287 | if (key->expiry > limit && key->expiry < new_timer) { | 145 | if (cursor < 0) |
288 | kdebug("will expire %x in %ld", | 146 | cursor = 0; |
289 | key_serial(key), key->expiry - limit); | 147 | if (cursor > 0) |
290 | new_timer = key->expiry; | 148 | new_timer = key_gc_new_timer; |
291 | } | 149 | else |
150 | key_gc_again = false; | ||
151 | |||
152 | /* find the first key above the cursor */ | ||
153 | key = NULL; | ||
154 | rb = key_serial_tree.rb_node; | ||
155 | while (rb) { | ||
156 | xkey = rb_entry(rb, struct key, serial_node); | ||
157 | if (cursor < xkey->serial) { | ||
158 | key = xkey; | ||
159 | rb = rb->rb_left; | ||
160 | } else if (cursor > xkey->serial) { | ||
161 | rb = rb->rb_right; | ||
162 | } else { | ||
163 | rb = rb_next(rb); | ||
164 | if (!rb) | ||
165 | goto reached_the_end; | ||
166 | key = rb_entry(rb, struct key, serial_node); | ||
167 | break; | ||
292 | } | 168 | } |
169 | } | ||
293 | 170 | ||
294 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2)) | 171 | if (!key) |
295 | if (key->type == key_gc_dead_keytype) | 172 | goto reached_the_end; |
296 | gc_state |= KEY_GC_FOUND_DEAD_KEY; | ||
297 | 173 | ||
298 | if ((gc_state & KEY_GC_REAPING_LINKS) || | 174 | /* trawl through the keys looking for keyrings */ |
299 | unlikely(gc_state & KEY_GC_REAPING_DEAD_2)) { | 175 | for (;;) { |
300 | if (key->type == &key_type_keyring) | 176 | if (key->expiry > limit && key->expiry < new_timer) { |
301 | goto found_keyring; | 177 | kdebug("will expire %x in %ld", |
178 | key_serial(key), key->expiry - limit); | ||
179 | new_timer = key->expiry; | ||
302 | } | 180 | } |
303 | 181 | ||
304 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_3)) | 182 | if (key->type == &key_type_keyring && |
305 | if (key->type == key_gc_dead_keytype) | 183 | key_gc_keyring(key, limit)) |
306 | goto destroy_dead_key; | 184 | /* the gc had to release our lock so that the keyring |
185 | * could be modified, so we have to get it again */ | ||
186 | goto gc_released_our_lock; | ||
307 | 187 | ||
308 | skip_dead_key: | 188 | rb = rb_next(&key->serial_node); |
309 | if (spin_is_contended(&key_serial_lock) || need_resched()) | 189 | if (!rb) |
310 | goto contended; | 190 | goto reached_the_end; |
191 | key = rb_entry(rb, struct key, serial_node); | ||
311 | } | 192 | } |
312 | 193 | ||
313 | contended: | 194 | gc_released_our_lock: |
314 | spin_unlock(&key_serial_lock); | 195 | kdebug("gc_released_our_lock"); |
315 | 196 | key_gc_new_timer = new_timer; | |
316 | maybe_resched: | 197 | key_gc_again = true; |
317 | if (cursor) { | 198 | clear_bit(0, &key_gc_executing); |
318 | cond_resched(); | 199 | schedule_work(&key_gc_work); |
319 | spin_lock(&key_serial_lock); | 200 | kleave(" [continue]"); |
320 | goto continue_scanning; | 201 | return; |
321 | } | ||
322 | |||
323 | /* We've completed the pass. Set the timer if we need to and queue a | ||
324 | * new cycle if necessary. We keep executing cycles until we find one | ||
325 | * where we didn't reap any keys. | ||
326 | */ | ||
327 | kdebug("pass complete"); | ||
328 | 202 | ||
329 | if (gc_state & KEY_GC_SET_TIMER && new_timer != (time_t)LONG_MAX) { | 203 | /* when we reach the end of the run, we set the timer for the next one */ |
204 | reached_the_end: | ||
205 | kdebug("reached_the_end"); | ||
206 | spin_unlock(&key_serial_lock); | ||
207 | key_gc_new_timer = new_timer; | ||
208 | key_gc_cursor = 0; | ||
209 | clear_bit(0, &key_gc_executing); | ||
210 | |||
211 | if (key_gc_again) { | ||
212 | /* there may have been a key that expired whilst we were | ||
213 | * scanning, so if we discarded any links we should do another | ||
214 | * scan */ | ||
215 | new_timer = now + 1; | ||
216 | key_schedule_gc(new_timer); | ||
217 | } else if (new_timer < LONG_MAX) { | ||
330 | new_timer += key_gc_delay; | 218 | new_timer += key_gc_delay; |
331 | key_schedule_gc(new_timer); | 219 | key_schedule_gc(new_timer); |
332 | } | 220 | } |
333 | 221 | kleave(" [end]"); | |
334 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2) || | ||
335 | !list_empty(&graveyard)) { | ||
336 | /* Make sure that all pending keyring payload destructions are | ||
337 | * fulfilled and that people aren't now looking at dead or | ||
338 | * dying keys that they don't have a reference upon or a link | ||
339 | * to. | ||
340 | */ | ||
341 | kdebug("gc sync"); | ||
342 | synchronize_rcu(); | ||
343 | } | ||
344 | |||
345 | if (!list_empty(&graveyard)) { | ||
346 | kdebug("gc keys"); | ||
347 | key_gc_unused_keys(&graveyard); | ||
348 | } | ||
349 | |||
350 | if (unlikely(gc_state & (KEY_GC_REAPING_DEAD_1 | | ||
351 | KEY_GC_REAPING_DEAD_2))) { | ||
352 | if (!(gc_state & KEY_GC_FOUND_DEAD_KEY)) { | ||
353 | /* No remaining dead keys: short circuit the remaining | ||
354 | * keytype reap cycles. | ||
355 | */ | ||
356 | kdebug("dead short"); | ||
357 | gc_state &= ~(KEY_GC_REAPING_DEAD_1 | KEY_GC_REAPING_DEAD_2); | ||
358 | gc_state |= KEY_GC_REAPING_DEAD_3; | ||
359 | } else { | ||
360 | gc_state |= KEY_GC_REAP_AGAIN; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | if (unlikely(gc_state & KEY_GC_REAPING_DEAD_3)) { | ||
365 | kdebug("dead wake"); | ||
366 | smp_mb(); | ||
367 | clear_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags); | ||
368 | wake_up_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE); | ||
369 | } | ||
370 | |||
371 | if (gc_state & KEY_GC_REAP_AGAIN) | ||
372 | schedule_work(&key_gc_work); | ||
373 | kleave(" [end %x]", gc_state); | ||
374 | return; | ||
375 | |||
376 | /* We found an unreferenced key - once we've removed it from the tree, | ||
377 | * we can safely drop the lock. | ||
378 | */ | ||
379 | found_unreferenced_key: | ||
380 | kdebug("unrefd key %d", key->serial); | ||
381 | rb_erase(&key->serial_node, &key_serial_tree); | ||
382 | spin_unlock(&key_serial_lock); | ||
383 | |||
384 | list_add_tail(&key->graveyard_link, &graveyard); | ||
385 | gc_state |= KEY_GC_REAP_AGAIN; | ||
386 | goto maybe_resched; | ||
387 | |||
388 | /* We found a keyring and we need to check the payload for links to | ||
389 | * dead or expired keys. We don't flag another reap immediately as we | ||
390 | * have to wait for the old payload to be destroyed by RCU before we | ||
391 | * can reap the keys to which it refers. | ||
392 | */ | ||
393 | found_keyring: | ||
394 | spin_unlock(&key_serial_lock); | ||
395 | kdebug("scan keyring %d", key->serial); | ||
396 | key_gc_keyring(key, limit); | ||
397 | goto maybe_resched; | ||
398 | |||
399 | /* We found a dead key that is still referenced. Reset its type and | ||
400 | * destroy its payload with its semaphore held. | ||
401 | */ | ||
402 | destroy_dead_key: | ||
403 | spin_unlock(&key_serial_lock); | ||
404 | kdebug("destroy key %d", key->serial); | ||
405 | down_write(&key->sem); | ||
406 | key->type = &key_type_dead; | ||
407 | if (key_gc_dead_keytype->destroy) | ||
408 | key_gc_dead_keytype->destroy(key); | ||
409 | memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); | ||
410 | up_write(&key->sem); | ||
411 | goto maybe_resched; | ||
412 | } | 222 | } |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 8bbefc3b55d..f375152a250 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
17 | #include <linux/task_work.h> | ||
18 | 17 | ||
19 | #ifdef __KDEBUG | 18 | #ifdef __KDEBUG |
20 | #define kenter(FMT, ...) \ | 19 | #define kenter(FMT, ...) \ |
@@ -32,9 +31,7 @@ | |||
32 | no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) | 31 | no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) |
33 | #endif | 32 | #endif |
34 | 33 | ||
35 | extern struct key_type key_type_dead; | ||
36 | extern struct key_type key_type_user; | 34 | extern struct key_type key_type_user; |
37 | extern struct key_type key_type_logon; | ||
38 | 35 | ||
39 | /*****************************************************************************/ | 36 | /*****************************************************************************/ |
40 | /* | 37 | /* |
@@ -52,7 +49,8 @@ struct key_user { | |||
52 | atomic_t usage; /* for accessing qnkeys & qnbytes */ | 49 | atomic_t usage; /* for accessing qnkeys & qnbytes */ |
53 | atomic_t nkeys; /* number of keys */ | 50 | atomic_t nkeys; /* number of keys */ |
54 | atomic_t nikeys; /* number of instantiated keys */ | 51 | atomic_t nikeys; /* number of instantiated keys */ |
55 | kuid_t uid; | 52 | uid_t uid; |
53 | struct user_namespace *user_ns; | ||
56 | int qnkeys; /* number of keys allocated to this user */ | 54 | int qnkeys; /* number of keys allocated to this user */ |
57 | int qnbytes; /* number of bytes allocated to this user */ | 55 | int qnbytes; /* number of bytes allocated to this user */ |
58 | }; | 56 | }; |
@@ -61,7 +59,8 @@ extern struct rb_root key_user_tree; | |||
61 | extern spinlock_t key_user_lock; | 59 | extern spinlock_t key_user_lock; |
62 | extern struct key_user root_key_user; | 60 | extern struct key_user root_key_user; |
63 | 61 | ||
64 | extern struct key_user *key_user_lookup(kuid_t uid); | 62 | extern struct key_user *key_user_lookup(uid_t uid, |
63 | struct user_namespace *user_ns); | ||
65 | extern void key_user_put(struct key_user *user); | 64 | extern void key_user_put(struct key_user *user); |
66 | 65 | ||
67 | /* | 66 | /* |
@@ -76,7 +75,6 @@ extern unsigned key_quota_maxbytes; | |||
76 | #define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */ | 75 | #define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */ |
77 | 76 | ||
78 | 77 | ||
79 | extern struct kmem_cache *key_jar; | ||
80 | extern struct rb_root key_serial_tree; | 78 | extern struct rb_root key_serial_tree; |
81 | extern spinlock_t key_serial_lock; | 79 | extern spinlock_t key_serial_lock; |
82 | extern struct mutex key_construction_mutex; | 80 | extern struct mutex key_construction_mutex; |
@@ -147,14 +145,10 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | |||
147 | #define KEY_LOOKUP_FOR_UNLINK 0x04 | 145 | #define KEY_LOOKUP_FOR_UNLINK 0x04 |
148 | 146 | ||
149 | extern long join_session_keyring(const char *name); | 147 | extern long join_session_keyring(const char *name); |
150 | extern void key_change_session_keyring(struct callback_head *twork); | ||
151 | 148 | ||
152 | extern struct work_struct key_gc_work; | ||
153 | extern unsigned key_gc_delay; | 149 | extern unsigned key_gc_delay; |
154 | extern void keyring_gc(struct key *keyring, time_t limit); | 150 | extern void keyring_gc(struct key *keyring, time_t limit); |
155 | extern void key_schedule_gc(time_t gc_at); | 151 | extern void key_schedule_gc(time_t expiry_at); |
156 | extern void key_schedule_gc_links(void); | ||
157 | extern void key_gc_keytype(struct key_type *ktype); | ||
158 | 152 | ||
159 | extern int key_task_permission(const key_ref_t key_ref, | 153 | extern int key_task_permission(const key_ref_t key_ref, |
160 | const struct cred *cred, | 154 | const struct cred *cred, |
@@ -198,17 +192,6 @@ extern struct key *request_key_auth_new(struct key *target, | |||
198 | extern struct key *key_get_instantiation_authkey(key_serial_t target_id); | 192 | extern struct key *key_get_instantiation_authkey(key_serial_t target_id); |
199 | 193 | ||
200 | /* | 194 | /* |
201 | * Determine whether a key is dead. | ||
202 | */ | ||
203 | static inline bool key_is_dead(struct key *key, time_t limit) | ||
204 | { | ||
205 | return | ||
206 | key->flags & ((1 << KEY_FLAG_DEAD) | | ||
207 | (1 << KEY_FLAG_INVALIDATED)) || | ||
208 | (key->expiry > 0 && key->expiry <= limit); | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * keyctl() functions | 195 | * keyctl() functions |
213 | */ | 196 | */ |
214 | extern long keyctl_get_keyring_ID(key_serial_t, int); | 197 | extern long keyctl_get_keyring_ID(key_serial_t, int); |
@@ -237,10 +220,9 @@ extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t); | |||
237 | extern long keyctl_instantiate_key_iov(key_serial_t, | 220 | extern long keyctl_instantiate_key_iov(key_serial_t, |
238 | const struct iovec __user *, | 221 | const struct iovec __user *, |
239 | unsigned, key_serial_t); | 222 | unsigned, key_serial_t); |
240 | extern long keyctl_invalidate_key(key_serial_t); | ||
241 | 223 | ||
242 | extern long keyctl_instantiate_key_common(key_serial_t, | 224 | extern long keyctl_instantiate_key_common(key_serial_t, |
243 | const struct iovec *, | 225 | const struct iovec __user *, |
244 | unsigned, size_t, key_serial_t); | 226 | unsigned, size_t, key_serial_t); |
245 | 227 | ||
246 | /* | 228 | /* |
diff --git a/security/keys/key.c b/security/keys/key.c index 8fb7c7bd465..f7f9d93f08d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -18,9 +18,10 @@ | |||
18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/random.h> | 19 | #include <linux/random.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/user_namespace.h> | ||
21 | #include "internal.h" | 22 | #include "internal.h" |
22 | 23 | ||
23 | struct kmem_cache *key_jar; | 24 | static struct kmem_cache *key_jar; |
24 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ | 25 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ |
25 | DEFINE_SPINLOCK(key_serial_lock); | 26 | DEFINE_SPINLOCK(key_serial_lock); |
26 | 27 | ||
@@ -35,9 +36,17 @@ unsigned int key_quota_maxbytes = 20000; /* general key space quota */ | |||
35 | static LIST_HEAD(key_types_list); | 36 | static LIST_HEAD(key_types_list); |
36 | static DECLARE_RWSEM(key_types_sem); | 37 | static DECLARE_RWSEM(key_types_sem); |
37 | 38 | ||
39 | static void key_cleanup(struct work_struct *work); | ||
40 | static DECLARE_WORK(key_cleanup_task, key_cleanup); | ||
41 | |||
38 | /* We serialise key instantiation and link */ | 42 | /* We serialise key instantiation and link */ |
39 | DEFINE_MUTEX(key_construction_mutex); | 43 | DEFINE_MUTEX(key_construction_mutex); |
40 | 44 | ||
45 | /* Any key who's type gets unegistered will be re-typed to this */ | ||
46 | static struct key_type key_type_dead = { | ||
47 | .name = "dead", | ||
48 | }; | ||
49 | |||
41 | #ifdef KEY_DEBUGGING | 50 | #ifdef KEY_DEBUGGING |
42 | void __key_check(const struct key *key) | 51 | void __key_check(const struct key *key) |
43 | { | 52 | { |
@@ -51,7 +60,7 @@ void __key_check(const struct key *key) | |||
51 | * Get the key quota record for a user, allocating a new record if one doesn't | 60 | * Get the key quota record for a user, allocating a new record if one doesn't |
52 | * already exist. | 61 | * already exist. |
53 | */ | 62 | */ |
54 | struct key_user *key_user_lookup(kuid_t uid) | 63 | struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns) |
55 | { | 64 | { |
56 | struct key_user *candidate = NULL, *user; | 65 | struct key_user *candidate = NULL, *user; |
57 | struct rb_node *parent = NULL; | 66 | struct rb_node *parent = NULL; |
@@ -66,9 +75,13 @@ try_again: | |||
66 | parent = *p; | 75 | parent = *p; |
67 | user = rb_entry(parent, struct key_user, node); | 76 | user = rb_entry(parent, struct key_user, node); |
68 | 77 | ||
69 | if (uid_lt(uid, user->uid)) | 78 | if (uid < user->uid) |
79 | p = &(*p)->rb_left; | ||
80 | else if (uid > user->uid) | ||
81 | p = &(*p)->rb_right; | ||
82 | else if (user_ns < user->user_ns) | ||
70 | p = &(*p)->rb_left; | 83 | p = &(*p)->rb_left; |
71 | else if (uid_gt(uid, user->uid)) | 84 | else if (user_ns > user->user_ns) |
72 | p = &(*p)->rb_right; | 85 | p = &(*p)->rb_right; |
73 | else | 86 | else |
74 | goto found; | 87 | goto found; |
@@ -97,6 +110,7 @@ try_again: | |||
97 | atomic_set(&candidate->nkeys, 0); | 110 | atomic_set(&candidate->nkeys, 0); |
98 | atomic_set(&candidate->nikeys, 0); | 111 | atomic_set(&candidate->nikeys, 0); |
99 | candidate->uid = uid; | 112 | candidate->uid = uid; |
113 | candidate->user_ns = get_user_ns(user_ns); | ||
100 | candidate->qnkeys = 0; | 114 | candidate->qnkeys = 0; |
101 | candidate->qnbytes = 0; | 115 | candidate->qnbytes = 0; |
102 | spin_lock_init(&candidate->lock); | 116 | spin_lock_init(&candidate->lock); |
@@ -125,6 +139,7 @@ void key_user_put(struct key_user *user) | |||
125 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { | 139 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { |
126 | rb_erase(&user->node, &key_user_tree); | 140 | rb_erase(&user->node, &key_user_tree); |
127 | spin_unlock(&key_user_lock); | 141 | spin_unlock(&key_user_lock); |
142 | put_user_ns(user->user_ns); | ||
128 | 143 | ||
129 | kfree(user); | 144 | kfree(user); |
130 | } | 145 | } |
@@ -222,7 +237,7 @@ serial_exists: | |||
222 | * key_alloc() calls don't race with module unloading. | 237 | * key_alloc() calls don't race with module unloading. |
223 | */ | 238 | */ |
224 | struct key *key_alloc(struct key_type *type, const char *desc, | 239 | struct key *key_alloc(struct key_type *type, const char *desc, |
225 | kuid_t uid, kgid_t gid, const struct cred *cred, | 240 | uid_t uid, gid_t gid, const struct cred *cred, |
226 | key_perm_t perm, unsigned long flags) | 241 | key_perm_t perm, unsigned long flags) |
227 | { | 242 | { |
228 | struct key_user *user = NULL; | 243 | struct key_user *user = NULL; |
@@ -246,16 +261,16 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
246 | quotalen = desclen + type->def_datalen; | 261 | quotalen = desclen + type->def_datalen; |
247 | 262 | ||
248 | /* get hold of the key tracking for this user */ | 263 | /* get hold of the key tracking for this user */ |
249 | user = key_user_lookup(uid); | 264 | user = key_user_lookup(uid, cred->user->user_ns); |
250 | if (!user) | 265 | if (!user) |
251 | goto no_memory_1; | 266 | goto no_memory_1; |
252 | 267 | ||
253 | /* check that the user's quota permits allocation of another key and | 268 | /* check that the user's quota permits allocation of another key and |
254 | * its description */ | 269 | * its description */ |
255 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { | 270 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
256 | unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ? | 271 | unsigned maxkeys = (uid == 0) ? |
257 | key_quota_root_maxkeys : key_quota_maxkeys; | 272 | key_quota_root_maxkeys : key_quota_maxkeys; |
258 | unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ? | 273 | unsigned maxbytes = (uid == 0) ? |
259 | key_quota_root_maxbytes : key_quota_maxbytes; | 274 | key_quota_root_maxbytes : key_quota_maxbytes; |
260 | 275 | ||
261 | spin_lock(&user->lock); | 276 | spin_lock(&user->lock); |
@@ -284,7 +299,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
284 | 299 | ||
285 | atomic_set(&key->usage, 1); | 300 | atomic_set(&key->usage, 1); |
286 | init_rwsem(&key->sem); | 301 | init_rwsem(&key->sem); |
287 | lockdep_set_class(&key->sem, &type->lock_class); | ||
288 | key->type = type; | 302 | key->type = type; |
289 | key->user = user; | 303 | key->user = user; |
290 | key->quotalen = quotalen; | 304 | key->quotalen = quotalen; |
@@ -373,7 +387,7 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
373 | 387 | ||
374 | /* contemplate the quota adjustment */ | 388 | /* contemplate the quota adjustment */ |
375 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 389 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
376 | unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ? | 390 | unsigned maxbytes = (key->user->uid == 0) ? |
377 | key_quota_root_maxbytes : key_quota_maxbytes; | 391 | key_quota_root_maxbytes : key_quota_maxbytes; |
378 | 392 | ||
379 | spin_lock(&key->user->lock); | 393 | spin_lock(&key->user->lock); |
@@ -405,7 +419,8 @@ EXPORT_SYMBOL(key_payload_reserve); | |||
405 | * key_construction_mutex. | 419 | * key_construction_mutex. |
406 | */ | 420 | */ |
407 | static int __key_instantiate_and_link(struct key *key, | 421 | static int __key_instantiate_and_link(struct key *key, |
408 | struct key_preparsed_payload *prep, | 422 | const void *data, |
423 | size_t datalen, | ||
409 | struct key *keyring, | 424 | struct key *keyring, |
410 | struct key *authkey, | 425 | struct key *authkey, |
411 | unsigned long *_prealloc) | 426 | unsigned long *_prealloc) |
@@ -423,7 +438,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
423 | /* can't instantiate twice */ | 438 | /* can't instantiate twice */ |
424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 439 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
425 | /* instantiate the key */ | 440 | /* instantiate the key */ |
426 | ret = key->type->instantiate(key, prep); | 441 | ret = key->type->instantiate(key, data, datalen); |
427 | 442 | ||
428 | if (ret == 0) { | 443 | if (ret == 0) { |
429 | /* mark the key as being instantiated */ | 444 | /* mark the key as being instantiated */ |
@@ -474,37 +489,22 @@ int key_instantiate_and_link(struct key *key, | |||
474 | struct key *keyring, | 489 | struct key *keyring, |
475 | struct key *authkey) | 490 | struct key *authkey) |
476 | { | 491 | { |
477 | struct key_preparsed_payload prep; | ||
478 | unsigned long prealloc; | 492 | unsigned long prealloc; |
479 | int ret; | 493 | int ret; |
480 | 494 | ||
481 | memset(&prep, 0, sizeof(prep)); | ||
482 | prep.data = data; | ||
483 | prep.datalen = datalen; | ||
484 | prep.quotalen = key->type->def_datalen; | ||
485 | if (key->type->preparse) { | ||
486 | ret = key->type->preparse(&prep); | ||
487 | if (ret < 0) | ||
488 | goto error; | ||
489 | } | ||
490 | |||
491 | if (keyring) { | 495 | if (keyring) { |
492 | ret = __key_link_begin(keyring, key->type, key->description, | 496 | ret = __key_link_begin(keyring, key->type, key->description, |
493 | &prealloc); | 497 | &prealloc); |
494 | if (ret < 0) | 498 | if (ret < 0) |
495 | goto error_free_preparse; | 499 | return ret; |
496 | } | 500 | } |
497 | 501 | ||
498 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, | 502 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, |
499 | &prealloc); | 503 | &prealloc); |
500 | 504 | ||
501 | if (keyring) | 505 | if (keyring) |
502 | __key_link_end(keyring, key->type, prealloc); | 506 | __key_link_end(keyring, key->type, prealloc); |
503 | 507 | ||
504 | error_free_preparse: | ||
505 | if (key->type->preparse) | ||
506 | key->type->free_preparse(&prep); | ||
507 | error: | ||
508 | return ret; | 508 | return ret; |
509 | } | 509 | } |
510 | 510 | ||
@@ -591,6 +591,71 @@ int key_reject_and_link(struct key *key, | |||
591 | } | 591 | } |
592 | EXPORT_SYMBOL(key_reject_and_link); | 592 | EXPORT_SYMBOL(key_reject_and_link); |
593 | 593 | ||
594 | /* | ||
595 | * Garbage collect keys in process context so that we don't have to disable | ||
596 | * interrupts all over the place. | ||
597 | * | ||
598 | * key_put() schedules this rather than trying to do the cleanup itself, which | ||
599 | * means key_put() doesn't have to sleep. | ||
600 | */ | ||
601 | static void key_cleanup(struct work_struct *work) | ||
602 | { | ||
603 | struct rb_node *_n; | ||
604 | struct key *key; | ||
605 | |||
606 | go_again: | ||
607 | /* look for a dead key in the tree */ | ||
608 | spin_lock(&key_serial_lock); | ||
609 | |||
610 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | ||
611 | key = rb_entry(_n, struct key, serial_node); | ||
612 | |||
613 | if (atomic_read(&key->usage) == 0) | ||
614 | goto found_dead_key; | ||
615 | } | ||
616 | |||
617 | spin_unlock(&key_serial_lock); | ||
618 | return; | ||
619 | |||
620 | found_dead_key: | ||
621 | /* we found a dead key - once we've removed it from the tree, we can | ||
622 | * drop the lock */ | ||
623 | rb_erase(&key->serial_node, &key_serial_tree); | ||
624 | spin_unlock(&key_serial_lock); | ||
625 | |||
626 | key_check(key); | ||
627 | |||
628 | security_key_free(key); | ||
629 | |||
630 | /* deal with the user's key tracking and quota */ | ||
631 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | ||
632 | spin_lock(&key->user->lock); | ||
633 | key->user->qnkeys--; | ||
634 | key->user->qnbytes -= key->quotalen; | ||
635 | spin_unlock(&key->user->lock); | ||
636 | } | ||
637 | |||
638 | atomic_dec(&key->user->nkeys); | ||
639 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | ||
640 | atomic_dec(&key->user->nikeys); | ||
641 | |||
642 | key_user_put(key->user); | ||
643 | |||
644 | /* now throw away the key memory */ | ||
645 | if (key->type->destroy) | ||
646 | key->type->destroy(key); | ||
647 | |||
648 | kfree(key->description); | ||
649 | |||
650 | #ifdef KEY_DEBUGGING | ||
651 | key->magic = KEY_DEBUG_MAGIC_X; | ||
652 | #endif | ||
653 | kmem_cache_free(key_jar, key); | ||
654 | |||
655 | /* there may, of course, be more than one key to destroy */ | ||
656 | goto go_again; | ||
657 | } | ||
658 | |||
594 | /** | 659 | /** |
595 | * key_put - Discard a reference to a key. | 660 | * key_put - Discard a reference to a key. |
596 | * @key: The key to discard a reference from. | 661 | * @key: The key to discard a reference from. |
@@ -605,7 +670,7 @@ void key_put(struct key *key) | |||
605 | key_check(key); | 670 | key_check(key); |
606 | 671 | ||
607 | if (atomic_dec_and_test(&key->usage)) | 672 | if (atomic_dec_and_test(&key->usage)) |
608 | schedule_work(&key_gc_work); | 673 | schedule_work(&key_cleanup_task); |
609 | } | 674 | } |
610 | } | 675 | } |
611 | EXPORT_SYMBOL(key_put); | 676 | EXPORT_SYMBOL(key_put); |
@@ -678,26 +743,6 @@ found_kernel_type: | |||
678 | return ktype; | 743 | return ktype; |
679 | } | 744 | } |
680 | 745 | ||
681 | void key_set_timeout(struct key *key, unsigned timeout) | ||
682 | { | ||
683 | struct timespec now; | ||
684 | time_t expiry = 0; | ||
685 | |||
686 | /* make the changes with the locks held to prevent races */ | ||
687 | down_write(&key->sem); | ||
688 | |||
689 | if (timeout > 0) { | ||
690 | now = current_kernel_time(); | ||
691 | expiry = now.tv_sec + timeout; | ||
692 | } | ||
693 | |||
694 | key->expiry = expiry; | ||
695 | key_schedule_gc(key->expiry + key_gc_delay); | ||
696 | |||
697 | up_write(&key->sem); | ||
698 | } | ||
699 | EXPORT_SYMBOL_GPL(key_set_timeout); | ||
700 | |||
701 | /* | 746 | /* |
702 | * Unlock a key type locked by key_type_lookup(). | 747 | * Unlock a key type locked by key_type_lookup(). |
703 | */ | 748 | */ |
@@ -713,7 +758,7 @@ void key_type_put(struct key_type *ktype) | |||
713 | * if we get an error. | 758 | * if we get an error. |
714 | */ | 759 | */ |
715 | static inline key_ref_t __key_update(key_ref_t key_ref, | 760 | static inline key_ref_t __key_update(key_ref_t key_ref, |
716 | struct key_preparsed_payload *prep) | 761 | const void *payload, size_t plen) |
717 | { | 762 | { |
718 | struct key *key = key_ref_to_ptr(key_ref); | 763 | struct key *key = key_ref_to_ptr(key_ref); |
719 | int ret; | 764 | int ret; |
@@ -729,7 +774,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
729 | 774 | ||
730 | down_write(&key->sem); | 775 | down_write(&key->sem); |
731 | 776 | ||
732 | ret = key->type->update(key, prep); | 777 | ret = key->type->update(key, payload, plen); |
733 | if (ret == 0) | 778 | if (ret == 0) |
734 | /* updating a negative key instantiates it */ | 779 | /* updating a negative key instantiates it */ |
735 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 780 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
@@ -781,7 +826,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
781 | unsigned long flags) | 826 | unsigned long flags) |
782 | { | 827 | { |
783 | unsigned long prealloc; | 828 | unsigned long prealloc; |
784 | struct key_preparsed_payload prep; | ||
785 | const struct cred *cred = current_cred(); | 829 | const struct cred *cred = current_cred(); |
786 | struct key_type *ktype; | 830 | struct key_type *ktype; |
787 | struct key *keyring, *key = NULL; | 831 | struct key *keyring, *key = NULL; |
@@ -797,9 +841,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
797 | } | 841 | } |
798 | 842 | ||
799 | key_ref = ERR_PTR(-EINVAL); | 843 | key_ref = ERR_PTR(-EINVAL); |
800 | if (!ktype->match || !ktype->instantiate || | 844 | if (!ktype->match || !ktype->instantiate) |
801 | (!description && !ktype->preparse)) | 845 | goto error_2; |
802 | goto error_put_type; | ||
803 | 846 | ||
804 | keyring = key_ref_to_ptr(keyring_ref); | 847 | keyring = key_ref_to_ptr(keyring_ref); |
805 | 848 | ||
@@ -807,37 +850,18 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
807 | 850 | ||
808 | key_ref = ERR_PTR(-ENOTDIR); | 851 | key_ref = ERR_PTR(-ENOTDIR); |
809 | if (keyring->type != &key_type_keyring) | 852 | if (keyring->type != &key_type_keyring) |
810 | goto error_put_type; | 853 | goto error_2; |
811 | |||
812 | memset(&prep, 0, sizeof(prep)); | ||
813 | prep.data = payload; | ||
814 | prep.datalen = plen; | ||
815 | prep.quotalen = ktype->def_datalen; | ||
816 | if (ktype->preparse) { | ||
817 | ret = ktype->preparse(&prep); | ||
818 | if (ret < 0) { | ||
819 | key_ref = ERR_PTR(ret); | ||
820 | goto error_put_type; | ||
821 | } | ||
822 | if (!description) | ||
823 | description = prep.description; | ||
824 | key_ref = ERR_PTR(-EINVAL); | ||
825 | if (!description) | ||
826 | goto error_free_prep; | ||
827 | } | ||
828 | 854 | ||
829 | ret = __key_link_begin(keyring, ktype, description, &prealloc); | 855 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
830 | if (ret < 0) { | 856 | if (ret < 0) |
831 | key_ref = ERR_PTR(ret); | 857 | goto error_2; |
832 | goto error_free_prep; | ||
833 | } | ||
834 | 858 | ||
835 | /* if we're going to allocate a new key, we're going to have | 859 | /* if we're going to allocate a new key, we're going to have |
836 | * to modify the keyring */ | 860 | * to modify the keyring */ |
837 | ret = key_permission(keyring_ref, KEY_WRITE); | 861 | ret = key_permission(keyring_ref, KEY_WRITE); |
838 | if (ret < 0) { | 862 | if (ret < 0) { |
839 | key_ref = ERR_PTR(ret); | 863 | key_ref = ERR_PTR(ret); |
840 | goto error_link_end; | 864 | goto error_3; |
841 | } | 865 | } |
842 | 866 | ||
843 | /* if it's possible to update this type of key, search for an existing | 867 | /* if it's possible to update this type of key, search for an existing |
@@ -854,13 +878,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
854 | /* if the client doesn't provide, decide on the permissions we want */ | 878 | /* if the client doesn't provide, decide on the permissions we want */ |
855 | if (perm == KEY_PERM_UNDEF) { | 879 | if (perm == KEY_PERM_UNDEF) { |
856 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | 880 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
857 | perm |= KEY_USR_VIEW; | 881 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; |
858 | 882 | ||
859 | if (ktype->read) | 883 | if (ktype->read) |
860 | perm |= KEY_POS_READ; | 884 | perm |= KEY_POS_READ | KEY_USR_READ; |
861 | 885 | ||
862 | if (ktype == &key_type_keyring || ktype->update) | 886 | if (ktype == &key_type_keyring || ktype->update) |
863 | perm |= KEY_POS_WRITE; | 887 | perm |= KEY_USR_WRITE; |
864 | } | 888 | } |
865 | 889 | ||
866 | /* allocate a new key */ | 890 | /* allocate a new key */ |
@@ -868,27 +892,25 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
868 | perm, flags); | 892 | perm, flags); |
869 | if (IS_ERR(key)) { | 893 | if (IS_ERR(key)) { |
870 | key_ref = ERR_CAST(key); | 894 | key_ref = ERR_CAST(key); |
871 | goto error_link_end; | 895 | goto error_3; |
872 | } | 896 | } |
873 | 897 | ||
874 | /* instantiate it and link it into the target keyring */ | 898 | /* instantiate it and link it into the target keyring */ |
875 | ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); | 899 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, |
900 | &prealloc); | ||
876 | if (ret < 0) { | 901 | if (ret < 0) { |
877 | key_put(key); | 902 | key_put(key); |
878 | key_ref = ERR_PTR(ret); | 903 | key_ref = ERR_PTR(ret); |
879 | goto error_link_end; | 904 | goto error_3; |
880 | } | 905 | } |
881 | 906 | ||
882 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 907 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
883 | 908 | ||
884 | error_link_end: | 909 | error_3: |
885 | __key_link_end(keyring, ktype, prealloc); | 910 | __key_link_end(keyring, ktype, prealloc); |
886 | error_free_prep: | 911 | error_2: |
887 | if (ktype->preparse) | ||
888 | ktype->free_preparse(&prep); | ||
889 | error_put_type: | ||
890 | key_type_put(ktype); | 912 | key_type_put(ktype); |
891 | error: | 913 | error: |
892 | return key_ref; | 914 | return key_ref; |
893 | 915 | ||
894 | found_matching_key: | 916 | found_matching_key: |
@@ -896,9 +918,10 @@ error: | |||
896 | * - we can drop the locks first as we have the key pinned | 918 | * - we can drop the locks first as we have the key pinned |
897 | */ | 919 | */ |
898 | __key_link_end(keyring, ktype, prealloc); | 920 | __key_link_end(keyring, ktype, prealloc); |
921 | key_type_put(ktype); | ||
899 | 922 | ||
900 | key_ref = __key_update(key_ref, &prep); | 923 | key_ref = __key_update(key_ref, payload, plen); |
901 | goto error_free_prep; | 924 | goto error; |
902 | } | 925 | } |
903 | EXPORT_SYMBOL(key_create_or_update); | 926 | EXPORT_SYMBOL(key_create_or_update); |
904 | 927 | ||
@@ -917,7 +940,6 @@ EXPORT_SYMBOL(key_create_or_update); | |||
917 | */ | 940 | */ |
918 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) | 941 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) |
919 | { | 942 | { |
920 | struct key_preparsed_payload prep; | ||
921 | struct key *key = key_ref_to_ptr(key_ref); | 943 | struct key *key = key_ref_to_ptr(key_ref); |
922 | int ret; | 944 | int ret; |
923 | 945 | ||
@@ -930,31 +952,18 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
930 | 952 | ||
931 | /* attempt to update it if supported */ | 953 | /* attempt to update it if supported */ |
932 | ret = -EOPNOTSUPP; | 954 | ret = -EOPNOTSUPP; |
933 | if (!key->type->update) | 955 | if (key->type->update) { |
934 | goto error; | 956 | down_write(&key->sem); |
935 | 957 | ||
936 | memset(&prep, 0, sizeof(prep)); | 958 | ret = key->type->update(key, payload, plen); |
937 | prep.data = payload; | 959 | if (ret == 0) |
938 | prep.datalen = plen; | 960 | /* updating a negative key instantiates it */ |
939 | prep.quotalen = key->type->def_datalen; | 961 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
940 | if (key->type->preparse) { | ||
941 | ret = key->type->preparse(&prep); | ||
942 | if (ret < 0) | ||
943 | goto error; | ||
944 | } | ||
945 | 962 | ||
946 | down_write(&key->sem); | 963 | up_write(&key->sem); |
947 | 964 | } | |
948 | ret = key->type->update(key, &prep); | ||
949 | if (ret == 0) | ||
950 | /* updating a negative key instantiates it */ | ||
951 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
952 | |||
953 | up_write(&key->sem); | ||
954 | 965 | ||
955 | if (key->type->preparse) | 966 | error: |
956 | key->type->free_preparse(&prep); | ||
957 | error: | ||
958 | return ret; | 967 | return ret; |
959 | } | 968 | } |
960 | EXPORT_SYMBOL(key_update); | 969 | EXPORT_SYMBOL(key_update); |
@@ -998,28 +1007,6 @@ void key_revoke(struct key *key) | |||
998 | EXPORT_SYMBOL(key_revoke); | 1007 | EXPORT_SYMBOL(key_revoke); |
999 | 1008 | ||
1000 | /** | 1009 | /** |
1001 | * key_invalidate - Invalidate a key. | ||
1002 | * @key: The key to be invalidated. | ||
1003 | * | ||
1004 | * Mark a key as being invalidated and have it cleaned up immediately. The key | ||
1005 | * is ignored by all searches and other operations from this point. | ||
1006 | */ | ||
1007 | void key_invalidate(struct key *key) | ||
1008 | { | ||
1009 | kenter("%d", key_serial(key)); | ||
1010 | |||
1011 | key_check(key); | ||
1012 | |||
1013 | if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) { | ||
1014 | down_write_nested(&key->sem, 1); | ||
1015 | if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) | ||
1016 | key_schedule_gc_links(); | ||
1017 | up_write(&key->sem); | ||
1018 | } | ||
1019 | } | ||
1020 | EXPORT_SYMBOL(key_invalidate); | ||
1021 | |||
1022 | /** | ||
1023 | * register_key_type - Register a type of key. | 1010 | * register_key_type - Register a type of key. |
1024 | * @ktype: The new key type. | 1011 | * @ktype: The new key type. |
1025 | * | 1012 | * |
@@ -1032,8 +1019,6 @@ int register_key_type(struct key_type *ktype) | |||
1032 | struct key_type *p; | 1019 | struct key_type *p; |
1033 | int ret; | 1020 | int ret; |
1034 | 1021 | ||
1035 | memset(&ktype->lock_class, 0, sizeof(ktype->lock_class)); | ||
1036 | |||
1037 | ret = -EEXIST; | 1022 | ret = -EEXIST; |
1038 | down_write(&key_types_sem); | 1023 | down_write(&key_types_sem); |
1039 | 1024 | ||
@@ -1045,8 +1030,6 @@ int register_key_type(struct key_type *ktype) | |||
1045 | 1030 | ||
1046 | /* store the type */ | 1031 | /* store the type */ |
1047 | list_add(&ktype->link, &key_types_list); | 1032 | list_add(&ktype->link, &key_types_list); |
1048 | |||
1049 | pr_notice("Key type %s registered\n", ktype->name); | ||
1050 | ret = 0; | 1033 | ret = 0; |
1051 | 1034 | ||
1052 | out: | 1035 | out: |
@@ -1065,12 +1048,49 @@ EXPORT_SYMBOL(register_key_type); | |||
1065 | */ | 1048 | */ |
1066 | void unregister_key_type(struct key_type *ktype) | 1049 | void unregister_key_type(struct key_type *ktype) |
1067 | { | 1050 | { |
1051 | struct rb_node *_n; | ||
1052 | struct key *key; | ||
1053 | |||
1068 | down_write(&key_types_sem); | 1054 | down_write(&key_types_sem); |
1055 | |||
1056 | /* withdraw the key type */ | ||
1069 | list_del_init(&ktype->link); | 1057 | list_del_init(&ktype->link); |
1070 | downgrade_write(&key_types_sem); | 1058 | |
1071 | key_gc_keytype(ktype); | 1059 | /* mark all the keys of this type dead */ |
1072 | pr_notice("Key type %s unregistered\n", ktype->name); | 1060 | spin_lock(&key_serial_lock); |
1073 | up_read(&key_types_sem); | 1061 | |
1062 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | ||
1063 | key = rb_entry(_n, struct key, serial_node); | ||
1064 | |||
1065 | if (key->type == ktype) { | ||
1066 | key->type = &key_type_dead; | ||
1067 | set_bit(KEY_FLAG_DEAD, &key->flags); | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | spin_unlock(&key_serial_lock); | ||
1072 | |||
1073 | /* make sure everyone revalidates their keys */ | ||
1074 | synchronize_rcu(); | ||
1075 | |||
1076 | /* we should now be able to destroy the payloads of all the keys of | ||
1077 | * this type with impunity */ | ||
1078 | spin_lock(&key_serial_lock); | ||
1079 | |||
1080 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | ||
1081 | key = rb_entry(_n, struct key, serial_node); | ||
1082 | |||
1083 | if (key->type == ktype) { | ||
1084 | if (ktype->destroy) | ||
1085 | ktype->destroy(key); | ||
1086 | memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | spin_unlock(&key_serial_lock); | ||
1091 | up_write(&key_types_sem); | ||
1092 | |||
1093 | key_schedule_gc(0); | ||
1074 | } | 1094 | } |
1075 | EXPORT_SYMBOL(unregister_key_type); | 1095 | EXPORT_SYMBOL(unregister_key_type); |
1076 | 1096 | ||
@@ -1087,7 +1107,6 @@ void __init key_init(void) | |||
1087 | list_add_tail(&key_type_keyring.link, &key_types_list); | 1107 | list_add_tail(&key_type_keyring.link, &key_types_list); |
1088 | list_add_tail(&key_type_dead.link, &key_types_list); | 1108 | list_add_tail(&key_type_dead.link, &key_types_list); |
1089 | list_add_tail(&key_type_user.link, &key_types_list); | 1109 | list_add_tail(&key_type_user.link, &key_types_list); |
1090 | list_add_tail(&key_type_logon.link, &key_types_list); | ||
1091 | 1110 | ||
1092 | /* record the root user tracking */ | 1111 | /* record the root user tracking */ |
1093 | rb_link_node(&root_key_user.node, | 1112 | rb_link_node(&root_key_user.node, |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4b5c948eb41..eca51918c95 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/syscalls.h> | 16 | #include <linux/syscalls.h> |
17 | #include <linux/key.h> | ||
18 | #include <linux/keyctl.h> | 17 | #include <linux/keyctl.h> |
19 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
20 | #include <linux/capability.h> | 19 | #include <linux/capability.h> |
@@ -46,9 +45,6 @@ static int key_get_type_from_user(char *type, | |||
46 | * Extract the description of a new key from userspace and either add it as a | 45 | * Extract the description of a new key from userspace and either add it as a |
47 | * new key to the specified keyring or update a matching key in that keyring. | 46 | * new key to the specified keyring or update a matching key in that keyring. |
48 | * | 47 | * |
49 | * If the description is NULL or an empty string, the key type is asked to | ||
50 | * generate one from the payload. | ||
51 | * | ||
52 | * The keyring must be writable so that we can attach the key to it. | 48 | * The keyring must be writable so that we can attach the key to it. |
53 | * | 49 | * |
54 | * If successful, the new key's serial number is returned, otherwise an error | 50 | * If successful, the new key's serial number is returned, otherwise an error |
@@ -75,17 +71,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
75 | if (ret < 0) | 71 | if (ret < 0) |
76 | goto error; | 72 | goto error; |
77 | 73 | ||
78 | description = NULL; | 74 | description = strndup_user(_description, PAGE_SIZE); |
79 | if (_description) { | 75 | if (IS_ERR(description)) { |
80 | description = strndup_user(_description, PAGE_SIZE); | 76 | ret = PTR_ERR(description); |
81 | if (IS_ERR(description)) { | 77 | goto error; |
82 | ret = PTR_ERR(description); | ||
83 | goto error; | ||
84 | } | ||
85 | if (!*description) { | ||
86 | kfree(description); | ||
87 | description = NULL; | ||
88 | } | ||
89 | } | 78 | } |
90 | 79 | ||
91 | /* pull the payload in if one was supplied */ | 80 | /* pull the payload in if one was supplied */ |
@@ -94,7 +83,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
94 | vm = false; | 83 | vm = false; |
95 | if (_payload) { | 84 | if (_payload) { |
96 | ret = -ENOMEM; | 85 | ret = -ENOMEM; |
97 | payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); | 86 | payload = kmalloc(plen, GFP_KERNEL); |
98 | if (!payload) { | 87 | if (!payload) { |
99 | if (plen <= PAGE_SIZE) | 88 | if (plen <= PAGE_SIZE) |
100 | goto error2; | 89 | goto error2; |
@@ -385,37 +374,6 @@ error: | |||
385 | } | 374 | } |
386 | 375 | ||
387 | /* | 376 | /* |
388 | * Invalidate a key. | ||
389 | * | ||
390 | * The key must be grant the caller Invalidate permission for this to work. | ||
391 | * The key and any links to the key will be automatically garbage collected | ||
392 | * immediately. | ||
393 | * | ||
394 | * If successful, 0 is returned. | ||
395 | */ | ||
396 | long keyctl_invalidate_key(key_serial_t id) | ||
397 | { | ||
398 | key_ref_t key_ref; | ||
399 | long ret; | ||
400 | |||
401 | kenter("%d", id); | ||
402 | |||
403 | key_ref = lookup_user_key(id, 0, KEY_SEARCH); | ||
404 | if (IS_ERR(key_ref)) { | ||
405 | ret = PTR_ERR(key_ref); | ||
406 | goto error; | ||
407 | } | ||
408 | |||
409 | key_invalidate(key_ref_to_ptr(key_ref)); | ||
410 | ret = 0; | ||
411 | |||
412 | key_ref_put(key_ref); | ||
413 | error: | ||
414 | kleave(" = %ld", ret); | ||
415 | return ret; | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Clear the specified keyring, creating an empty process keyring if one of the | 377 | * Clear the specified keyring, creating an empty process keyring if one of the |
420 | * special keyring IDs is used. | 378 | * special keyring IDs is used. |
421 | * | 379 | * |
@@ -430,24 +388,11 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
430 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); | 388 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
431 | if (IS_ERR(keyring_ref)) { | 389 | if (IS_ERR(keyring_ref)) { |
432 | ret = PTR_ERR(keyring_ref); | 390 | ret = PTR_ERR(keyring_ref); |
433 | |||
434 | /* Root is permitted to invalidate certain special keyrings */ | ||
435 | if (capable(CAP_SYS_ADMIN)) { | ||
436 | keyring_ref = lookup_user_key(ringid, 0, 0); | ||
437 | if (IS_ERR(keyring_ref)) | ||
438 | goto error; | ||
439 | if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR, | ||
440 | &key_ref_to_ptr(keyring_ref)->flags)) | ||
441 | goto clear; | ||
442 | goto error_put; | ||
443 | } | ||
444 | |||
445 | goto error; | 391 | goto error; |
446 | } | 392 | } |
447 | 393 | ||
448 | clear: | ||
449 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); | 394 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); |
450 | error_put: | 395 | |
451 | key_ref_put(keyring_ref); | 396 | key_ref_put(keyring_ref); |
452 | error: | 397 | error: |
453 | return ret; | 398 | return ret; |
@@ -579,8 +524,8 @@ okay: | |||
579 | ret = snprintf(tmpbuf, PAGE_SIZE - 1, | 524 | ret = snprintf(tmpbuf, PAGE_SIZE - 1, |
580 | "%s;%d;%d;%08x;%s", | 525 | "%s;%d;%d;%08x;%s", |
581 | key->type->name, | 526 | key->type->name, |
582 | from_kuid_munged(current_user_ns(), key->uid), | 527 | key->uid, |
583 | from_kgid_munged(current_user_ns(), key->gid), | 528 | key->gid, |
584 | key->perm, | 529 | key->perm, |
585 | key->description ?: ""); | 530 | key->description ?: ""); |
586 | 531 | ||
@@ -776,25 +721,15 @@ error: | |||
776 | * | 721 | * |
777 | * If successful, 0 will be returned. | 722 | * If successful, 0 will be returned. |
778 | */ | 723 | */ |
779 | long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) | 724 | long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) |
780 | { | 725 | { |
781 | struct key_user *newowner, *zapowner = NULL; | 726 | struct key_user *newowner, *zapowner = NULL; |
782 | struct key *key; | 727 | struct key *key; |
783 | key_ref_t key_ref; | 728 | key_ref_t key_ref; |
784 | long ret; | 729 | long ret; |
785 | kuid_t uid; | ||
786 | kgid_t gid; | ||
787 | |||
788 | uid = make_kuid(current_user_ns(), user); | ||
789 | gid = make_kgid(current_user_ns(), group); | ||
790 | ret = -EINVAL; | ||
791 | if ((user != (uid_t) -1) && !uid_valid(uid)) | ||
792 | goto error; | ||
793 | if ((group != (gid_t) -1) && !gid_valid(gid)) | ||
794 | goto error; | ||
795 | 730 | ||
796 | ret = 0; | 731 | ret = 0; |
797 | if (user == (uid_t) -1 && group == (gid_t) -1) | 732 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
798 | goto error; | 733 | goto error; |
799 | 734 | ||
800 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, | 735 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
@@ -812,27 +747,27 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) | |||
812 | 747 | ||
813 | if (!capable(CAP_SYS_ADMIN)) { | 748 | if (!capable(CAP_SYS_ADMIN)) { |
814 | /* only the sysadmin can chown a key to some other UID */ | 749 | /* only the sysadmin can chown a key to some other UID */ |
815 | if (user != (uid_t) -1 && !uid_eq(key->uid, uid)) | 750 | if (uid != (uid_t) -1 && key->uid != uid) |
816 | goto error_put; | 751 | goto error_put; |
817 | 752 | ||
818 | /* only the sysadmin can set the key's GID to a group other | 753 | /* only the sysadmin can set the key's GID to a group other |
819 | * than one of those that the current process subscribes to */ | 754 | * than one of those that the current process subscribes to */ |
820 | if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid)) | 755 | if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) |
821 | goto error_put; | 756 | goto error_put; |
822 | } | 757 | } |
823 | 758 | ||
824 | /* change the UID */ | 759 | /* change the UID */ |
825 | if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) { | 760 | if (uid != (uid_t) -1 && uid != key->uid) { |
826 | ret = -ENOMEM; | 761 | ret = -ENOMEM; |
827 | newowner = key_user_lookup(uid); | 762 | newowner = key_user_lookup(uid, current_user_ns()); |
828 | if (!newowner) | 763 | if (!newowner) |
829 | goto error_put; | 764 | goto error_put; |
830 | 765 | ||
831 | /* transfer the quota burden to the new user */ | 766 | /* transfer the quota burden to the new user */ |
832 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 767 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
833 | unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ? | 768 | unsigned maxkeys = (uid == 0) ? |
834 | key_quota_root_maxkeys : key_quota_maxkeys; | 769 | key_quota_root_maxkeys : key_quota_maxkeys; |
835 | unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ? | 770 | unsigned maxbytes = (uid == 0) ? |
836 | key_quota_root_maxbytes : key_quota_maxbytes; | 771 | key_quota_root_maxbytes : key_quota_maxbytes; |
837 | 772 | ||
838 | spin_lock(&newowner->lock); | 773 | spin_lock(&newowner->lock); |
@@ -866,7 +801,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) | |||
866 | } | 801 | } |
867 | 802 | ||
868 | /* change the GID */ | 803 | /* change the GID */ |
869 | if (group != (gid_t) -1) | 804 | if (gid != (gid_t) -1) |
870 | key->gid = gid; | 805 | key->gid = gid; |
871 | 806 | ||
872 | ret = 0; | 807 | ret = 0; |
@@ -917,7 +852,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
917 | down_write(&key->sem); | 852 | down_write(&key->sem); |
918 | 853 | ||
919 | /* if we're not the sysadmin, we can only change a key that we own */ | 854 | /* if we're not the sysadmin, we can only change a key that we own */ |
920 | if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) { | 855 | if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) { |
921 | key->perm = perm; | 856 | key->perm = perm; |
922 | ret = 0; | 857 | ret = 0; |
923 | } | 858 | } |
@@ -1126,18 +1061,18 @@ long keyctl_instantiate_key_iov(key_serial_t id, | |||
1126 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | 1061 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
1127 | long ret; | 1062 | long ret; |
1128 | 1063 | ||
1129 | if (!_payload_iov || !ioc) | 1064 | if (_payload_iov == 0 || ioc == 0) |
1130 | goto no_payload; | 1065 | goto no_payload; |
1131 | 1066 | ||
1132 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 1067 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
1133 | ARRAY_SIZE(iovstack), iovstack, &iov); | 1068 | ARRAY_SIZE(iovstack), iovstack, &iov); |
1134 | if (ret < 0) | 1069 | if (ret < 0) |
1135 | goto err; | 1070 | return ret; |
1136 | if (ret == 0) | 1071 | if (ret == 0) |
1137 | goto no_payload_free; | 1072 | goto no_payload_free; |
1138 | 1073 | ||
1139 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | 1074 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); |
1140 | err: | 1075 | |
1141 | if (iov != iovstack) | 1076 | if (iov != iovstack) |
1142 | kfree(iov); | 1077 | kfree(iov); |
1143 | return ret; | 1078 | return ret; |
@@ -1309,8 +1244,10 @@ error: | |||
1309 | */ | 1244 | */ |
1310 | long keyctl_set_timeout(key_serial_t id, unsigned timeout) | 1245 | long keyctl_set_timeout(key_serial_t id, unsigned timeout) |
1311 | { | 1246 | { |
1247 | struct timespec now; | ||
1312 | struct key *key, *instkey; | 1248 | struct key *key, *instkey; |
1313 | key_ref_t key_ref; | 1249 | key_ref_t key_ref; |
1250 | time_t expiry; | ||
1314 | long ret; | 1251 | long ret; |
1315 | 1252 | ||
1316 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, | 1253 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
@@ -1336,7 +1273,20 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) | |||
1336 | 1273 | ||
1337 | okay: | 1274 | okay: |
1338 | key = key_ref_to_ptr(key_ref); | 1275 | key = key_ref_to_ptr(key_ref); |
1339 | key_set_timeout(key, timeout); | 1276 | |
1277 | /* make the changes with the locks held to prevent races */ | ||
1278 | down_write(&key->sem); | ||
1279 | |||
1280 | expiry = 0; | ||
1281 | if (timeout > 0) { | ||
1282 | now = current_kernel_time(); | ||
1283 | expiry = now.tv_sec + timeout; | ||
1284 | } | ||
1285 | |||
1286 | key->expiry = expiry; | ||
1287 | key_schedule_gc(key->expiry + key_gc_delay); | ||
1288 | |||
1289 | up_write(&key->sem); | ||
1340 | key_put(key); | 1290 | key_put(key); |
1341 | 1291 | ||
1342 | ret = 0; | 1292 | ret = 0; |
@@ -1474,93 +1424,103 @@ long keyctl_get_security(key_serial_t keyid, | |||
1474 | */ | 1424 | */ |
1475 | long keyctl_session_to_parent(void) | 1425 | long keyctl_session_to_parent(void) |
1476 | { | 1426 | { |
1427 | #ifdef TIF_NOTIFY_RESUME | ||
1477 | struct task_struct *me, *parent; | 1428 | struct task_struct *me, *parent; |
1478 | const struct cred *mycred, *pcred; | 1429 | const struct cred *mycred, *pcred; |
1479 | struct callback_head *newwork, *oldwork; | 1430 | struct cred *cred, *oldcred; |
1480 | key_ref_t keyring_r; | 1431 | key_ref_t keyring_r; |
1481 | struct cred *cred; | ||
1482 | int ret; | 1432 | int ret; |
1483 | 1433 | ||
1484 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); | 1434 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); |
1485 | if (IS_ERR(keyring_r)) | 1435 | if (IS_ERR(keyring_r)) |
1486 | return PTR_ERR(keyring_r); | 1436 | return PTR_ERR(keyring_r); |
1487 | 1437 | ||
1488 | ret = -ENOMEM; | ||
1489 | |||
1490 | /* our parent is going to need a new cred struct, a new tgcred struct | 1438 | /* our parent is going to need a new cred struct, a new tgcred struct |
1491 | * and new security data, so we allocate them here to prevent ENOMEM in | 1439 | * and new security data, so we allocate them here to prevent ENOMEM in |
1492 | * our parent */ | 1440 | * our parent */ |
1441 | ret = -ENOMEM; | ||
1493 | cred = cred_alloc_blank(); | 1442 | cred = cred_alloc_blank(); |
1494 | if (!cred) | 1443 | if (!cred) |
1495 | goto error_keyring; | 1444 | goto error_keyring; |
1496 | newwork = &cred->rcu; | ||
1497 | 1445 | ||
1498 | cred->session_keyring = key_ref_to_ptr(keyring_r); | 1446 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); |
1499 | keyring_r = NULL; | 1447 | keyring_r = NULL; |
1500 | init_task_work(newwork, key_change_session_keyring); | ||
1501 | 1448 | ||
1502 | me = current; | 1449 | me = current; |
1503 | rcu_read_lock(); | 1450 | rcu_read_lock(); |
1504 | write_lock_irq(&tasklist_lock); | 1451 | write_lock_irq(&tasklist_lock); |
1505 | 1452 | ||
1506 | ret = -EPERM; | ||
1507 | oldwork = NULL; | ||
1508 | parent = me->real_parent; | 1453 | parent = me->real_parent; |
1454 | ret = -EPERM; | ||
1509 | 1455 | ||
1510 | /* the parent mustn't be init and mustn't be a kernel thread */ | 1456 | /* the parent mustn't be init and mustn't be a kernel thread */ |
1511 | if (parent->pid <= 1 || !parent->mm) | 1457 | if (parent->pid <= 1 || !parent->mm) |
1512 | goto unlock; | 1458 | goto not_permitted; |
1513 | 1459 | ||
1514 | /* the parent must be single threaded */ | 1460 | /* the parent must be single threaded */ |
1515 | if (!thread_group_empty(parent)) | 1461 | if (!thread_group_empty(parent)) |
1516 | goto unlock; | 1462 | goto not_permitted; |
1517 | 1463 | ||
1518 | /* the parent and the child must have different session keyrings or | 1464 | /* the parent and the child must have different session keyrings or |
1519 | * there's no point */ | 1465 | * there's no point */ |
1520 | mycred = current_cred(); | 1466 | mycred = current_cred(); |
1521 | pcred = __task_cred(parent); | 1467 | pcred = __task_cred(parent); |
1522 | if (mycred == pcred || | 1468 | if (mycred == pcred || |
1523 | mycred->session_keyring == pcred->session_keyring) { | 1469 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) |
1524 | ret = 0; | 1470 | goto already_same; |
1525 | goto unlock; | ||
1526 | } | ||
1527 | 1471 | ||
1528 | /* the parent must have the same effective ownership and mustn't be | 1472 | /* the parent must have the same effective ownership and mustn't be |
1529 | * SUID/SGID */ | 1473 | * SUID/SGID */ |
1530 | if (!uid_eq(pcred->uid, mycred->euid) || | 1474 | if (pcred->uid != mycred->euid || |
1531 | !uid_eq(pcred->euid, mycred->euid) || | 1475 | pcred->euid != mycred->euid || |
1532 | !uid_eq(pcred->suid, mycred->euid) || | 1476 | pcred->suid != mycred->euid || |
1533 | !gid_eq(pcred->gid, mycred->egid) || | 1477 | pcred->gid != mycred->egid || |
1534 | !gid_eq(pcred->egid, mycred->egid) || | 1478 | pcred->egid != mycred->egid || |
1535 | !gid_eq(pcred->sgid, mycred->egid)) | 1479 | pcred->sgid != mycred->egid) |
1536 | goto unlock; | 1480 | goto not_permitted; |
1537 | 1481 | ||
1538 | /* the keyrings must have the same UID */ | 1482 | /* the keyrings must have the same UID */ |
1539 | if ((pcred->session_keyring && | 1483 | if ((pcred->tgcred->session_keyring && |
1540 | !uid_eq(pcred->session_keyring->uid, mycred->euid)) || | 1484 | pcred->tgcred->session_keyring->uid != mycred->euid) || |
1541 | !uid_eq(mycred->session_keyring->uid, mycred->euid)) | 1485 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1542 | goto unlock; | 1486 | goto not_permitted; |
1543 | 1487 | ||
1544 | /* cancel an already pending keyring replacement */ | 1488 | /* if there's an already pending keyring replacement, then we replace |
1545 | oldwork = task_work_cancel(parent, key_change_session_keyring); | 1489 | * that */ |
1490 | oldcred = parent->replacement_session_keyring; | ||
1546 | 1491 | ||
1547 | /* the replacement session keyring is applied just prior to userspace | 1492 | /* the replacement session keyring is applied just prior to userspace |
1548 | * restarting */ | 1493 | * restarting */ |
1549 | ret = task_work_add(parent, newwork, true); | 1494 | parent->replacement_session_keyring = cred; |
1550 | if (!ret) | 1495 | cred = NULL; |
1551 | newwork = NULL; | 1496 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); |
1552 | unlock: | 1497 | |
1553 | write_unlock_irq(&tasklist_lock); | 1498 | write_unlock_irq(&tasklist_lock); |
1554 | rcu_read_unlock(); | 1499 | rcu_read_unlock(); |
1555 | if (oldwork) | 1500 | if (oldcred) |
1556 | put_cred(container_of(oldwork, struct cred, rcu)); | 1501 | put_cred(oldcred); |
1557 | if (newwork) | 1502 | return 0; |
1558 | put_cred(cred); | 1503 | |
1504 | already_same: | ||
1505 | ret = 0; | ||
1506 | not_permitted: | ||
1507 | write_unlock_irq(&tasklist_lock); | ||
1508 | rcu_read_unlock(); | ||
1509 | put_cred(cred); | ||
1559 | return ret; | 1510 | return ret; |
1560 | 1511 | ||
1561 | error_keyring: | 1512 | error_keyring: |
1562 | key_ref_put(keyring_r); | 1513 | key_ref_put(keyring_r); |
1563 | return ret; | 1514 | return ret; |
1515 | |||
1516 | #else /* !TIF_NOTIFY_RESUME */ | ||
1517 | /* | ||
1518 | * To be removed when TIF_NOTIFY_RESUME has been implemented on | ||
1519 | * m68k/xtensa | ||
1520 | */ | ||
1521 | #warning TIF_NOTIFY_RESUME not implemented | ||
1522 | return -EOPNOTSUPP; | ||
1523 | #endif /* !TIF_NOTIFY_RESUME */ | ||
1564 | } | 1524 | } |
1565 | 1525 | ||
1566 | /* | 1526 | /* |
@@ -1663,9 +1623,6 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1663 | (unsigned) arg4, | 1623 | (unsigned) arg4, |
1664 | (key_serial_t) arg5); | 1624 | (key_serial_t) arg5); |
1665 | 1625 | ||
1666 | case KEYCTL_INVALIDATE: | ||
1667 | return keyctl_invalidate_key((key_serial_t) arg2); | ||
1668 | |||
1669 | default: | 1626 | default: |
1670 | return -EOPNOTSUPP; | 1627 | return -EOPNOTSUPP; |
1671 | } | 1628 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 6ece7f2e570..30e242f7bd0 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -25,15 +25,6 @@ | |||
25 | (keyring)->payload.subscriptions, \ | 25 | (keyring)->payload.subscriptions, \ |
26 | rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) | 26 | rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) |
27 | 27 | ||
28 | #define rcu_deref_link_locked(klist, index, keyring) \ | ||
29 | (rcu_dereference_protected( \ | ||
30 | (klist)->keys[index], \ | ||
31 | rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) | ||
32 | |||
33 | #define MAX_KEYRING_LINKS \ | ||
34 | min_t(size_t, USHRT_MAX - 1, \ | ||
35 | ((PAGE_SIZE - sizeof(struct keyring_list)) / sizeof(struct key *))) | ||
36 | |||
37 | #define KEY_LINK_FIXQUOTA 1UL | 28 | #define KEY_LINK_FIXQUOTA 1UL |
38 | 29 | ||
39 | /* | 30 | /* |
@@ -66,7 +57,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
66 | * operations. | 57 | * operations. |
67 | */ | 58 | */ |
68 | static int keyring_instantiate(struct key *keyring, | 59 | static int keyring_instantiate(struct key *keyring, |
69 | struct key_preparsed_payload *prep); | 60 | const void *data, size_t datalen); |
70 | static int keyring_match(const struct key *keyring, const void *criterion); | 61 | static int keyring_match(const struct key *keyring, const void *criterion); |
71 | static void keyring_revoke(struct key *keyring); | 62 | static void keyring_revoke(struct key *keyring); |
72 | static void keyring_destroy(struct key *keyring); | 63 | static void keyring_destroy(struct key *keyring); |
@@ -121,12 +112,12 @@ static void keyring_publish_name(struct key *keyring) | |||
121 | * Returns 0 on success, -EINVAL if given any data. | 112 | * Returns 0 on success, -EINVAL if given any data. |
122 | */ | 113 | */ |
123 | static int keyring_instantiate(struct key *keyring, | 114 | static int keyring_instantiate(struct key *keyring, |
124 | struct key_preparsed_payload *prep) | 115 | const void *data, size_t datalen) |
125 | { | 116 | { |
126 | int ret; | 117 | int ret; |
127 | 118 | ||
128 | ret = -EINVAL; | 119 | ret = -EINVAL; |
129 | if (prep->datalen == 0) { | 120 | if (datalen == 0) { |
130 | /* make the keyring available by name if it has one */ | 121 | /* make the keyring available by name if it has one */ |
131 | keyring_publish_name(keyring); | 122 | keyring_publish_name(keyring); |
132 | ret = 0; | 123 | ret = 0; |
@@ -147,11 +138,6 @@ static int keyring_match(const struct key *keyring, const void *description) | |||
147 | /* | 138 | /* |
148 | * Clean up a keyring when it is destroyed. Unpublish its name if it had one | 139 | * Clean up a keyring when it is destroyed. Unpublish its name if it had one |
149 | * and dispose of its data. | 140 | * and dispose of its data. |
150 | * | ||
151 | * The garbage collector detects the final key_put(), removes the keyring from | ||
152 | * the serial number tree and then does RCU synchronisation before coming here, | ||
153 | * so we shouldn't need to worry about code poking around here with the RCU | ||
154 | * readlock held by this time. | ||
155 | */ | 141 | */ |
156 | static void keyring_destroy(struct key *keyring) | 142 | static void keyring_destroy(struct key *keyring) |
157 | { | 143 | { |
@@ -168,10 +154,11 @@ static void keyring_destroy(struct key *keyring) | |||
168 | write_unlock(&keyring_name_lock); | 154 | write_unlock(&keyring_name_lock); |
169 | } | 155 | } |
170 | 156 | ||
171 | klist = rcu_access_pointer(keyring->payload.subscriptions); | 157 | klist = rcu_dereference_check(keyring->payload.subscriptions, |
158 | atomic_read(&keyring->usage) == 0); | ||
172 | if (klist) { | 159 | if (klist) { |
173 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 160 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
174 | key_put(rcu_access_pointer(klist->keys[loop])); | 161 | key_put(klist->keys[loop]); |
175 | kfree(klist); | 162 | kfree(klist); |
176 | } | 163 | } |
177 | } | 164 | } |
@@ -227,8 +214,7 @@ static long keyring_read(const struct key *keyring, | |||
227 | ret = -EFAULT; | 214 | ret = -EFAULT; |
228 | 215 | ||
229 | for (loop = 0; loop < klist->nkeys; loop++) { | 216 | for (loop = 0; loop < klist->nkeys; loop++) { |
230 | key = rcu_deref_link_locked(klist, loop, | 217 | key = klist->keys[loop]; |
231 | keyring); | ||
232 | 218 | ||
233 | tmp = sizeof(key_serial_t); | 219 | tmp = sizeof(key_serial_t); |
234 | if (tmp > buflen) | 220 | if (tmp > buflen) |
@@ -256,15 +242,18 @@ error: | |||
256 | /* | 242 | /* |
257 | * Allocate a keyring and link into the destination keyring. | 243 | * Allocate a keyring and link into the destination keyring. |
258 | */ | 244 | */ |
259 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | 245 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
260 | const struct cred *cred, key_perm_t perm, | 246 | const struct cred *cred, unsigned long flags, |
261 | unsigned long flags, struct key *dest) | 247 | struct key *dest) |
262 | { | 248 | { |
263 | struct key *keyring; | 249 | struct key *keyring; |
264 | int ret; | 250 | int ret; |
265 | 251 | ||
266 | keyring = key_alloc(&key_type_keyring, description, | 252 | keyring = key_alloc(&key_type_keyring, description, |
267 | uid, gid, cred, perm, flags); | 253 | uid, gid, cred, |
254 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | ||
255 | flags); | ||
256 | |||
268 | if (!IS_ERR(keyring)) { | 257 | if (!IS_ERR(keyring)) { |
269 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 258 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
270 | if (ret < 0) { | 259 | if (ret < 0) { |
@@ -275,7 +264,6 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
275 | 264 | ||
276 | return keyring; | 265 | return keyring; |
277 | } | 266 | } |
278 | EXPORT_SYMBOL(keyring_alloc); | ||
279 | 267 | ||
280 | /** | 268 | /** |
281 | * keyring_search_aux - Search a keyring tree for a key matching some criteria | 269 | * keyring_search_aux - Search a keyring tree for a key matching some criteria |
@@ -321,8 +309,6 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
321 | bool no_state_check) | 309 | bool no_state_check) |
322 | { | 310 | { |
323 | struct { | 311 | struct { |
324 | /* Need a separate keylist pointer for RCU purposes */ | ||
325 | struct key *keyring; | ||
326 | struct keyring_list *keylist; | 312 | struct keyring_list *keylist; |
327 | int kix; | 313 | int kix; |
328 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | 314 | } stack[KEYRING_SEARCH_MAX_DEPTH]; |
@@ -333,7 +319,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
333 | struct key *keyring, *key; | 319 | struct key *keyring, *key; |
334 | key_ref_t key_ref; | 320 | key_ref_t key_ref; |
335 | long err; | 321 | long err; |
336 | int sp, nkeys, kix; | 322 | int sp, kix; |
337 | 323 | ||
338 | keyring = key_ref_to_ptr(keyring_ref); | 324 | keyring = key_ref_to_ptr(keyring_ref); |
339 | possessed = is_key_possessed(keyring_ref); | 325 | possessed = is_key_possessed(keyring_ref); |
@@ -380,17 +366,13 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
380 | /* otherwise, the top keyring must not be revoked, expired, or | 366 | /* otherwise, the top keyring must not be revoked, expired, or |
381 | * negatively instantiated if we are to search it */ | 367 | * negatively instantiated if we are to search it */ |
382 | key_ref = ERR_PTR(-EAGAIN); | 368 | key_ref = ERR_PTR(-EAGAIN); |
383 | if (kflags & ((1 << KEY_FLAG_INVALIDATED) | | 369 | if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) || |
384 | (1 << KEY_FLAG_REVOKED) | | ||
385 | (1 << KEY_FLAG_NEGATIVE)) || | ||
386 | (keyring->expiry && now.tv_sec >= keyring->expiry)) | 370 | (keyring->expiry && now.tv_sec >= keyring->expiry)) |
387 | goto error_2; | 371 | goto error_2; |
388 | 372 | ||
389 | /* start processing a new keyring */ | 373 | /* start processing a new keyring */ |
390 | descend: | 374 | descend: |
391 | kflags = keyring->flags; | 375 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
392 | if (kflags & ((1 << KEY_FLAG_INVALIDATED) | | ||
393 | (1 << KEY_FLAG_REVOKED))) | ||
394 | goto not_this_keyring; | 376 | goto not_this_keyring; |
395 | 377 | ||
396 | keylist = rcu_dereference(keyring->payload.subscriptions); | 378 | keylist = rcu_dereference(keyring->payload.subscriptions); |
@@ -398,20 +380,17 @@ descend: | |||
398 | goto not_this_keyring; | 380 | goto not_this_keyring; |
399 | 381 | ||
400 | /* iterate through the keys in this keyring first */ | 382 | /* iterate through the keys in this keyring first */ |
401 | nkeys = keylist->nkeys; | 383 | for (kix = 0; kix < keylist->nkeys; kix++) { |
402 | smp_rmb(); | 384 | key = keylist->keys[kix]; |
403 | for (kix = 0; kix < nkeys; kix++) { | ||
404 | key = rcu_dereference(keylist->keys[kix]); | ||
405 | kflags = key->flags; | 385 | kflags = key->flags; |
406 | 386 | ||
407 | /* ignore keys not of this type */ | 387 | /* ignore keys not of this type */ |
408 | if (key->type != type) | 388 | if (key->type != type) |
409 | continue; | 389 | continue; |
410 | 390 | ||
411 | /* skip invalidated, revoked and expired keys */ | 391 | /* skip revoked keys and expired keys */ |
412 | if (!no_state_check) { | 392 | if (!no_state_check) { |
413 | if (kflags & ((1 << KEY_FLAG_INVALIDATED) | | 393 | if (kflags & (1 << KEY_FLAG_REVOKED)) |
414 | (1 << KEY_FLAG_REVOKED))) | ||
415 | continue; | 394 | continue; |
416 | 395 | ||
417 | if (key->expiry && now.tv_sec >= key->expiry) | 396 | if (key->expiry && now.tv_sec >= key->expiry) |
@@ -442,10 +421,8 @@ descend: | |||
442 | /* search through the keyrings nested in this one */ | 421 | /* search through the keyrings nested in this one */ |
443 | kix = 0; | 422 | kix = 0; |
444 | ascend: | 423 | ascend: |
445 | nkeys = keylist->nkeys; | 424 | for (; kix < keylist->nkeys; kix++) { |
446 | smp_rmb(); | 425 | key = keylist->keys[kix]; |
447 | for (; kix < nkeys; kix++) { | ||
448 | key = rcu_dereference(keylist->keys[kix]); | ||
449 | if (key->type != &key_type_keyring) | 426 | if (key->type != &key_type_keyring) |
450 | continue; | 427 | continue; |
451 | 428 | ||
@@ -460,7 +437,6 @@ ascend: | |||
460 | continue; | 437 | continue; |
461 | 438 | ||
462 | /* stack the current position */ | 439 | /* stack the current position */ |
463 | stack[sp].keyring = keyring; | ||
464 | stack[sp].keylist = keylist; | 440 | stack[sp].keylist = keylist; |
465 | stack[sp].kix = kix; | 441 | stack[sp].kix = kix; |
466 | sp++; | 442 | sp++; |
@@ -476,7 +452,6 @@ not_this_keyring: | |||
476 | if (sp > 0) { | 452 | if (sp > 0) { |
477 | /* resume the processing of a keyring higher up in the tree */ | 453 | /* resume the processing of a keyring higher up in the tree */ |
478 | sp--; | 454 | sp--; |
479 | keyring = stack[sp].keyring; | ||
480 | keylist = stack[sp].keylist; | 455 | keylist = stack[sp].keylist; |
481 | kix = stack[sp].kix + 1; | 456 | kix = stack[sp].kix + 1; |
482 | goto ascend; | 457 | goto ascend; |
@@ -488,10 +463,6 @@ not_this_keyring: | |||
488 | /* we found a viable match */ | 463 | /* we found a viable match */ |
489 | found: | 464 | found: |
490 | atomic_inc(&key->usage); | 465 | atomic_inc(&key->usage); |
491 | key->last_used_at = now.tv_sec; | ||
492 | keyring->last_used_at = now.tv_sec; | ||
493 | while (sp > 0) | ||
494 | stack[--sp].keyring->last_used_at = now.tv_sec; | ||
495 | key_check(key); | 466 | key_check(key); |
496 | key_ref = make_key_ref(key, possessed); | 467 | key_ref = make_key_ref(key, possessed); |
497 | error_2: | 468 | error_2: |
@@ -544,7 +515,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
544 | struct keyring_list *klist; | 515 | struct keyring_list *klist; |
545 | unsigned long possessed; | 516 | unsigned long possessed; |
546 | struct key *keyring, *key; | 517 | struct key *keyring, *key; |
547 | int nkeys, loop; | 518 | int loop; |
548 | 519 | ||
549 | keyring = key_ref_to_ptr(keyring_ref); | 520 | keyring = key_ref_to_ptr(keyring_ref); |
550 | possessed = is_key_possessed(keyring_ref); | 521 | possessed = is_key_possessed(keyring_ref); |
@@ -553,17 +524,15 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
553 | 524 | ||
554 | klist = rcu_dereference(keyring->payload.subscriptions); | 525 | klist = rcu_dereference(keyring->payload.subscriptions); |
555 | if (klist) { | 526 | if (klist) { |
556 | nkeys = klist->nkeys; | 527 | for (loop = 0; loop < klist->nkeys; loop++) { |
557 | smp_rmb(); | 528 | key = klist->keys[loop]; |
558 | for (loop = 0; loop < nkeys ; loop++) { | 529 | |
559 | key = rcu_dereference(klist->keys[loop]); | ||
560 | if (key->type == ktype && | 530 | if (key->type == ktype && |
561 | (!key->type->match || | 531 | (!key->type->match || |
562 | key->type->match(key, description)) && | 532 | key->type->match(key, description)) && |
563 | key_permission(make_key_ref(key, possessed), | 533 | key_permission(make_key_ref(key, possessed), |
564 | perm) == 0 && | 534 | perm) == 0 && |
565 | !(key->flags & ((1 << KEY_FLAG_INVALIDATED) | | 535 | !test_bit(KEY_FLAG_REVOKED, &key->flags) |
566 | (1 << KEY_FLAG_REVOKED))) | ||
567 | ) | 536 | ) |
568 | goto found; | 537 | goto found; |
569 | } | 538 | } |
@@ -574,8 +543,6 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
574 | 543 | ||
575 | found: | 544 | found: |
576 | atomic_inc(&key->usage); | 545 | atomic_inc(&key->usage); |
577 | keyring->last_used_at = key->last_used_at = | ||
578 | current_kernel_time().tv_sec; | ||
579 | rcu_read_unlock(); | 546 | rcu_read_unlock(); |
580 | return make_key_ref(key, possessed); | 547 | return make_key_ref(key, possessed); |
581 | } | 548 | } |
@@ -610,7 +577,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
610 | &keyring_name_hash[bucket], | 577 | &keyring_name_hash[bucket], |
611 | type_data.link | 578 | type_data.link |
612 | ) { | 579 | ) { |
613 | if (!kuid_has_mapping(current_user_ns(), keyring->user->uid)) | 580 | if (keyring->user->user_ns != current_user_ns()) |
614 | continue; | 581 | continue; |
615 | 582 | ||
616 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 583 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
@@ -629,7 +596,6 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
629 | * (ie. it has a zero usage count) */ | 596 | * (ie. it has a zero usage count) */ |
630 | if (!atomic_inc_not_zero(&keyring->usage)) | 597 | if (!atomic_inc_not_zero(&keyring->usage)) |
631 | continue; | 598 | continue; |
632 | keyring->last_used_at = current_kernel_time().tv_sec; | ||
633 | goto out; | 599 | goto out; |
634 | } | 600 | } |
635 | } | 601 | } |
@@ -656,7 +622,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
656 | 622 | ||
657 | struct keyring_list *keylist; | 623 | struct keyring_list *keylist; |
658 | struct key *subtree, *key; | 624 | struct key *subtree, *key; |
659 | int sp, nkeys, kix, ret; | 625 | int sp, kix, ret; |
660 | 626 | ||
661 | rcu_read_lock(); | 627 | rcu_read_lock(); |
662 | 628 | ||
@@ -679,10 +645,8 @@ descend: | |||
679 | 645 | ||
680 | ascend: | 646 | ascend: |
681 | /* iterate through the remaining keys in this keyring */ | 647 | /* iterate through the remaining keys in this keyring */ |
682 | nkeys = keylist->nkeys; | 648 | for (; kix < keylist->nkeys; kix++) { |
683 | smp_rmb(); | 649 | key = keylist->keys[kix]; |
684 | for (; kix < nkeys; kix++) { | ||
685 | key = rcu_dereference(keylist->keys[kix]); | ||
686 | 650 | ||
687 | if (key == A) | 651 | if (key == A) |
688 | goto cycle_detected; | 652 | goto cycle_detected; |
@@ -739,7 +703,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | |||
739 | container_of(rcu, struct keyring_list, rcu); | 703 | container_of(rcu, struct keyring_list, rcu); |
740 | 704 | ||
741 | if (klist->delkey != USHRT_MAX) | 705 | if (klist->delkey != USHRT_MAX) |
742 | key_put(rcu_access_pointer(klist->keys[klist->delkey])); | 706 | key_put(klist->keys[klist->delkey]); |
743 | kfree(klist); | 707 | kfree(klist); |
744 | } | 708 | } |
745 | 709 | ||
@@ -749,14 +713,12 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | |||
749 | int __key_link_begin(struct key *keyring, const struct key_type *type, | 713 | int __key_link_begin(struct key *keyring, const struct key_type *type, |
750 | const char *description, unsigned long *_prealloc) | 714 | const char *description, unsigned long *_prealloc) |
751 | __acquires(&keyring->sem) | 715 | __acquires(&keyring->sem) |
752 | __acquires(&keyring_serialise_link_sem) | ||
753 | { | 716 | { |
754 | struct keyring_list *klist, *nklist; | 717 | struct keyring_list *klist, *nklist; |
755 | unsigned long prealloc; | 718 | unsigned long prealloc; |
756 | unsigned max; | 719 | unsigned max; |
757 | time_t lowest_lru; | ||
758 | size_t size; | 720 | size_t size; |
759 | int loop, lru, ret; | 721 | int loop, ret; |
760 | 722 | ||
761 | kenter("%d,%s,%s,", key_serial(keyring), type->name, description); | 723 | kenter("%d,%s,%s,", key_serial(keyring), type->name, description); |
762 | 724 | ||
@@ -777,39 +739,31 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, | |||
777 | klist = rcu_dereference_locked_keyring(keyring); | 739 | klist = rcu_dereference_locked_keyring(keyring); |
778 | 740 | ||
779 | /* see if there's a matching key we can displace */ | 741 | /* see if there's a matching key we can displace */ |
780 | lru = -1; | ||
781 | if (klist && klist->nkeys > 0) { | 742 | if (klist && klist->nkeys > 0) { |
782 | lowest_lru = TIME_T_MAX; | ||
783 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 743 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
784 | struct key *key = rcu_deref_link_locked(klist, loop, | 744 | if (klist->keys[loop]->type == type && |
785 | keyring); | 745 | strcmp(klist->keys[loop]->description, |
786 | if (key->type == type && | 746 | description) == 0 |
787 | strcmp(key->description, description) == 0) { | 747 | ) { |
788 | /* Found a match - we'll replace the link with | 748 | /* found a match - we'll replace this one with |
789 | * one to the new key. We record the slot | 749 | * the new key */ |
790 | * position. | 750 | size = sizeof(struct key *) * klist->maxkeys; |
791 | */ | 751 | size += sizeof(*klist); |
792 | klist->delkey = loop; | 752 | BUG_ON(size > PAGE_SIZE); |
793 | prealloc = 0; | 753 | |
754 | ret = -ENOMEM; | ||
755 | nklist = kmemdup(klist, size, GFP_KERNEL); | ||
756 | if (!nklist) | ||
757 | goto error_sem; | ||
758 | |||
759 | /* note replacement slot */ | ||
760 | klist->delkey = nklist->delkey = loop; | ||
761 | prealloc = (unsigned long)nklist; | ||
794 | goto done; | 762 | goto done; |
795 | } | 763 | } |
796 | if (key->last_used_at < lowest_lru) { | ||
797 | lowest_lru = key->last_used_at; | ||
798 | lru = loop; | ||
799 | } | ||
800 | } | 764 | } |
801 | } | 765 | } |
802 | 766 | ||
803 | /* If the keyring is full then do an LRU discard */ | ||
804 | if (klist && | ||
805 | klist->nkeys == klist->maxkeys && | ||
806 | klist->maxkeys >= MAX_KEYRING_LINKS) { | ||
807 | kdebug("LRU discard %d\n", lru); | ||
808 | klist->delkey = lru; | ||
809 | prealloc = 0; | ||
810 | goto done; | ||
811 | } | ||
812 | |||
813 | /* check that we aren't going to overrun the user's quota */ | 767 | /* check that we aren't going to overrun the user's quota */ |
814 | ret = key_payload_reserve(keyring, | 768 | ret = key_payload_reserve(keyring, |
815 | keyring->datalen + KEYQUOTA_LINK_BYTES); | 769 | keyring->datalen + KEYQUOTA_LINK_BYTES); |
@@ -818,19 +772,20 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, | |||
818 | 772 | ||
819 | if (klist && klist->nkeys < klist->maxkeys) { | 773 | if (klist && klist->nkeys < klist->maxkeys) { |
820 | /* there's sufficient slack space to append directly */ | 774 | /* there's sufficient slack space to append directly */ |
821 | klist->delkey = klist->nkeys; | 775 | nklist = NULL; |
822 | prealloc = KEY_LINK_FIXQUOTA; | 776 | prealloc = KEY_LINK_FIXQUOTA; |
823 | } else { | 777 | } else { |
824 | /* grow the key list */ | 778 | /* grow the key list */ |
825 | max = 4; | 779 | max = 4; |
826 | if (klist) { | 780 | if (klist) |
827 | max += klist->maxkeys; | 781 | max += klist->maxkeys; |
828 | if (max > MAX_KEYRING_LINKS) | ||
829 | max = MAX_KEYRING_LINKS; | ||
830 | BUG_ON(max <= klist->maxkeys); | ||
831 | } | ||
832 | 782 | ||
783 | ret = -ENFILE; | ||
784 | if (max > USHRT_MAX - 1) | ||
785 | goto error_quota; | ||
833 | size = sizeof(*klist) + sizeof(struct key *) * max; | 786 | size = sizeof(*klist) + sizeof(struct key *) * max; |
787 | if (size > PAGE_SIZE) | ||
788 | goto error_quota; | ||
834 | 789 | ||
835 | ret = -ENOMEM; | 790 | ret = -ENOMEM; |
836 | nklist = kmalloc(size, GFP_KERNEL); | 791 | nklist = kmalloc(size, GFP_KERNEL); |
@@ -850,10 +805,10 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, | |||
850 | } | 805 | } |
851 | 806 | ||
852 | /* add the key into the new space */ | 807 | /* add the key into the new space */ |
853 | RCU_INIT_POINTER(nklist->keys[nklist->delkey], NULL); | 808 | nklist->keys[nklist->delkey] = NULL; |
854 | prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA; | ||
855 | } | 809 | } |
856 | 810 | ||
811 | prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA; | ||
857 | done: | 812 | done: |
858 | *_prealloc = prealloc; | 813 | *_prealloc = prealloc; |
859 | kleave(" = 0"); | 814 | kleave(" = 0"); |
@@ -899,26 +854,24 @@ void __key_link(struct key *keyring, struct key *key, | |||
899 | unsigned long *_prealloc) | 854 | unsigned long *_prealloc) |
900 | { | 855 | { |
901 | struct keyring_list *klist, *nklist; | 856 | struct keyring_list *klist, *nklist; |
902 | struct key *discard; | ||
903 | 857 | ||
904 | nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA); | 858 | nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA); |
905 | *_prealloc = 0; | 859 | *_prealloc = 0; |
906 | 860 | ||
907 | kenter("%d,%d,%p", keyring->serial, key->serial, nklist); | 861 | kenter("%d,%d,%p", keyring->serial, key->serial, nklist); |
908 | 862 | ||
909 | klist = rcu_dereference_locked_keyring(keyring); | 863 | klist = rcu_dereference_protected(keyring->payload.subscriptions, |
864 | rwsem_is_locked(&keyring->sem)); | ||
910 | 865 | ||
911 | atomic_inc(&key->usage); | 866 | atomic_inc(&key->usage); |
912 | keyring->last_used_at = key->last_used_at = | ||
913 | current_kernel_time().tv_sec; | ||
914 | 867 | ||
915 | /* there's a matching key we can displace or an empty slot in a newly | 868 | /* there's a matching key we can displace or an empty slot in a newly |
916 | * allocated list we can fill */ | 869 | * allocated list we can fill */ |
917 | if (nklist) { | 870 | if (nklist) { |
918 | kdebug("reissue %hu/%hu/%hu", | 871 | kdebug("replace %hu/%hu/%hu", |
919 | nklist->delkey, nklist->nkeys, nklist->maxkeys); | 872 | nklist->delkey, nklist->nkeys, nklist->maxkeys); |
920 | 873 | ||
921 | RCU_INIT_POINTER(nklist->keys[nklist->delkey], key); | 874 | nklist->keys[nklist->delkey] = key; |
922 | 875 | ||
923 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | 876 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); |
924 | 877 | ||
@@ -929,23 +882,9 @@ void __key_link(struct key *keyring, struct key *key, | |||
929 | klist->delkey, klist->nkeys, klist->maxkeys); | 882 | klist->delkey, klist->nkeys, klist->maxkeys); |
930 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | 883 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); |
931 | } | 884 | } |
932 | } else if (klist->delkey < klist->nkeys) { | ||
933 | kdebug("replace %hu/%hu/%hu", | ||
934 | klist->delkey, klist->nkeys, klist->maxkeys); | ||
935 | |||
936 | discard = rcu_dereference_protected( | ||
937 | klist->keys[klist->delkey], | ||
938 | rwsem_is_locked(&keyring->sem)); | ||
939 | rcu_assign_pointer(klist->keys[klist->delkey], key); | ||
940 | /* The garbage collector will take care of RCU | ||
941 | * synchronisation */ | ||
942 | key_put(discard); | ||
943 | } else { | 885 | } else { |
944 | /* there's sufficient slack space to append directly */ | 886 | /* there's sufficient slack space to append directly */ |
945 | kdebug("append %hu/%hu/%hu", | 887 | klist->keys[klist->nkeys] = key; |
946 | klist->delkey, klist->nkeys, klist->maxkeys); | ||
947 | |||
948 | RCU_INIT_POINTER(klist->keys[klist->delkey], key); | ||
949 | smp_wmb(); | 888 | smp_wmb(); |
950 | klist->nkeys++; | 889 | klist->nkeys++; |
951 | } | 890 | } |
@@ -959,7 +898,6 @@ void __key_link(struct key *keyring, struct key *key, | |||
959 | void __key_link_end(struct key *keyring, struct key_type *type, | 898 | void __key_link_end(struct key *keyring, struct key_type *type, |
960 | unsigned long prealloc) | 899 | unsigned long prealloc) |
961 | __releases(&keyring->sem) | 900 | __releases(&keyring->sem) |
962 | __releases(&keyring_serialise_link_sem) | ||
963 | { | 901 | { |
964 | BUG_ON(type == NULL); | 902 | BUG_ON(type == NULL); |
965 | BUG_ON(type->name == NULL); | 903 | BUG_ON(type->name == NULL); |
@@ -1053,7 +991,7 @@ int key_unlink(struct key *keyring, struct key *key) | |||
1053 | if (klist) { | 991 | if (klist) { |
1054 | /* search the keyring for the key */ | 992 | /* search the keyring for the key */ |
1055 | for (loop = 0; loop < klist->nkeys; loop++) | 993 | for (loop = 0; loop < klist->nkeys; loop++) |
1056 | if (rcu_access_pointer(klist->keys[loop]) == key) | 994 | if (klist->keys[loop] == key) |
1057 | goto key_is_present; | 995 | goto key_is_present; |
1058 | } | 996 | } |
1059 | 997 | ||
@@ -1116,7 +1054,7 @@ static void keyring_clear_rcu_disposal(struct rcu_head *rcu) | |||
1116 | klist = container_of(rcu, struct keyring_list, rcu); | 1054 | klist = container_of(rcu, struct keyring_list, rcu); |
1117 | 1055 | ||
1118 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 1056 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
1119 | key_put(rcu_access_pointer(klist->keys[loop])); | 1057 | key_put(klist->keys[loop]); |
1120 | 1058 | ||
1121 | kfree(klist); | 1059 | kfree(klist); |
1122 | } | 1060 | } |
@@ -1183,6 +1121,15 @@ static void keyring_revoke(struct key *keyring) | |||
1183 | } | 1121 | } |
1184 | 1122 | ||
1185 | /* | 1123 | /* |
1124 | * Determine whether a key is dead. | ||
1125 | */ | ||
1126 | static bool key_is_dead(struct key *key, time_t limit) | ||
1127 | { | ||
1128 | return test_bit(KEY_FLAG_DEAD, &key->flags) || | ||
1129 | (key->expiry > 0 && key->expiry <= limit); | ||
1130 | } | ||
1131 | |||
1132 | /* | ||
1186 | * Collect garbage from the contents of a keyring, replacing the old list with | 1133 | * Collect garbage from the contents of a keyring, replacing the old list with |
1187 | * a new one with the pointers all shuffled down. | 1134 | * a new one with the pointers all shuffled down. |
1188 | * | 1135 | * |
@@ -1207,8 +1154,7 @@ void keyring_gc(struct key *keyring, time_t limit) | |||
1207 | /* work out how many subscriptions we're keeping */ | 1154 | /* work out how many subscriptions we're keeping */ |
1208 | keep = 0; | 1155 | keep = 0; |
1209 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 1156 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
1210 | if (!key_is_dead(rcu_deref_link_locked(klist, loop, keyring), | 1157 | if (!key_is_dead(klist->keys[loop], limit)) |
1211 | limit)) | ||
1212 | keep++; | 1158 | keep++; |
1213 | 1159 | ||
1214 | if (keep == klist->nkeys) | 1160 | if (keep == klist->nkeys) |
@@ -1229,11 +1175,11 @@ void keyring_gc(struct key *keyring, time_t limit) | |||
1229 | */ | 1175 | */ |
1230 | keep = 0; | 1176 | keep = 0; |
1231 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 1177 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
1232 | key = rcu_deref_link_locked(klist, loop, keyring); | 1178 | key = klist->keys[loop]; |
1233 | if (!key_is_dead(key, limit)) { | 1179 | if (!key_is_dead(key, limit)) { |
1234 | if (keep >= max) | 1180 | if (keep >= max) |
1235 | goto discard_new; | 1181 | goto discard_new; |
1236 | RCU_INIT_POINTER(new->keys[keep++], key_get(key)); | 1182 | new->keys[keep++] = key_get(key); |
1237 | } | 1183 | } |
1238 | } | 1184 | } |
1239 | new->nkeys = keep; | 1185 | new->nkeys = keep; |
diff --git a/security/keys/permission.c b/security/keys/permission.c index efcc0c855a0..c35b5229e3c 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -36,16 +36,19 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
36 | 36 | ||
37 | key = key_ref_to_ptr(key_ref); | 37 | key = key_ref_to_ptr(key_ref); |
38 | 38 | ||
39 | if (key->user->user_ns != cred->user->user_ns) | ||
40 | goto use_other_perms; | ||
41 | |||
39 | /* use the second 8-bits of permissions for keys the caller owns */ | 42 | /* use the second 8-bits of permissions for keys the caller owns */ |
40 | if (uid_eq(key->uid, cred->fsuid)) { | 43 | if (key->uid == cred->fsuid) { |
41 | kperm = key->perm >> 16; | 44 | kperm = key->perm >> 16; |
42 | goto use_these_perms; | 45 | goto use_these_perms; |
43 | } | 46 | } |
44 | 47 | ||
45 | /* use the third 8-bits of permissions for keys the caller has a group | 48 | /* use the third 8-bits of permissions for keys the caller has a group |
46 | * membership in common with */ | 49 | * membership in common with */ |
47 | if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) { | 50 | if (key->gid != -1 && key->perm & KEY_GRP_ALL) { |
48 | if (gid_eq(key->gid, cred->fsgid)) { | 51 | if (key->gid == cred->fsgid) { |
49 | kperm = key->perm >> 8; | 52 | kperm = key->perm >> 8; |
50 | goto use_these_perms; | 53 | goto use_these_perms; |
51 | } | 54 | } |
@@ -57,6 +60,8 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
57 | } | 60 | } |
58 | } | 61 | } |
59 | 62 | ||
63 | use_other_perms: | ||
64 | |||
60 | /* otherwise use the least-significant 8-bits */ | 65 | /* otherwise use the least-significant 8-bits */ |
61 | kperm = key->perm; | 66 | kperm = key->perm; |
62 | 67 | ||
@@ -82,29 +87,32 @@ EXPORT_SYMBOL(key_task_permission); | |||
82 | * key_validate - Validate a key. | 87 | * key_validate - Validate a key. |
83 | * @key: The key to be validated. | 88 | * @key: The key to be validated. |
84 | * | 89 | * |
85 | * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the | 90 | * Check that a key is valid, returning 0 if the key is okay, -EKEYREVOKED if |
86 | * key is invalidated, -EKEYREVOKED if the key's type has been removed or if | 91 | * the key's type has been removed or if the key has been revoked or |
87 | * the key has been revoked or -EKEYEXPIRED if the key has expired. | 92 | * -EKEYEXPIRED if the key has expired. |
88 | */ | 93 | */ |
89 | int key_validate(const struct key *key) | 94 | int key_validate(struct key *key) |
90 | { | 95 | { |
91 | unsigned long flags = key->flags; | 96 | struct timespec now; |
92 | 97 | int ret = 0; | |
93 | if (flags & (1 << KEY_FLAG_INVALIDATED)) | 98 | |
94 | return -ENOKEY; | 99 | if (key) { |
95 | 100 | /* check it's still accessible */ | |
96 | /* check it's still accessible */ | 101 | ret = -EKEYREVOKED; |
97 | if (flags & ((1 << KEY_FLAG_REVOKED) | | 102 | if (test_bit(KEY_FLAG_REVOKED, &key->flags) || |
98 | (1 << KEY_FLAG_DEAD))) | 103 | test_bit(KEY_FLAG_DEAD, &key->flags)) |
99 | return -EKEYREVOKED; | 104 | goto error; |
100 | 105 | ||
101 | /* check it hasn't expired */ | 106 | /* check it hasn't expired */ |
102 | if (key->expiry) { | 107 | ret = 0; |
103 | struct timespec now = current_kernel_time(); | 108 | if (key->expiry) { |
104 | if (now.tv_sec >= key->expiry) | 109 | now = current_kernel_time(); |
105 | return -EKEYEXPIRED; | 110 | if (now.tv_sec >= key->expiry) |
111 | ret = -EKEYEXPIRED; | ||
112 | } | ||
106 | } | 113 | } |
107 | 114 | ||
108 | return 0; | 115 | error: |
116 | return ret; | ||
109 | } | 117 | } |
110 | EXPORT_SYMBOL(key_validate); | 118 | EXPORT_SYMBOL(key_validate); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index 217b6855e81..49bbc97943a 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -88,14 +88,14 @@ __initcall(key_proc_init); | |||
88 | */ | 88 | */ |
89 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | 89 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS |
90 | 90 | ||
91 | static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) | 91 | static struct rb_node *key_serial_next(struct rb_node *n) |
92 | { | 92 | { |
93 | struct user_namespace *user_ns = seq_user_ns(p); | 93 | struct user_namespace *user_ns = current_user_ns(); |
94 | 94 | ||
95 | n = rb_next(n); | 95 | n = rb_next(n); |
96 | while (n) { | 96 | while (n) { |
97 | struct key *key = rb_entry(n, struct key, serial_node); | 97 | struct key *key = rb_entry(n, struct key, serial_node); |
98 | if (kuid_has_mapping(user_ns, key->user->uid)) | 98 | if (key->user->user_ns == user_ns) |
99 | break; | 99 | break; |
100 | n = rb_next(n); | 100 | n = rb_next(n); |
101 | } | 101 | } |
@@ -107,9 +107,9 @@ static int proc_keys_open(struct inode *inode, struct file *file) | |||
107 | return seq_open(file, &proc_keys_ops); | 107 | return seq_open(file, &proc_keys_ops); |
108 | } | 108 | } |
109 | 109 | ||
110 | static struct key *find_ge_key(struct seq_file *p, key_serial_t id) | 110 | static struct key *find_ge_key(key_serial_t id) |
111 | { | 111 | { |
112 | struct user_namespace *user_ns = seq_user_ns(p); | 112 | struct user_namespace *user_ns = current_user_ns(); |
113 | struct rb_node *n = key_serial_tree.rb_node; | 113 | struct rb_node *n = key_serial_tree.rb_node; |
114 | struct key *minkey = NULL; | 114 | struct key *minkey = NULL; |
115 | 115 | ||
@@ -132,7 +132,7 @@ static struct key *find_ge_key(struct seq_file *p, key_serial_t id) | |||
132 | return NULL; | 132 | return NULL; |
133 | 133 | ||
134 | for (;;) { | 134 | for (;;) { |
135 | if (kuid_has_mapping(user_ns, minkey->user->uid)) | 135 | if (minkey->user->user_ns == user_ns) |
136 | return minkey; | 136 | return minkey; |
137 | n = rb_next(&minkey->serial_node); | 137 | n = rb_next(&minkey->serial_node); |
138 | if (!n) | 138 | if (!n) |
@@ -151,7 +151,7 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos) | |||
151 | 151 | ||
152 | if (*_pos > INT_MAX) | 152 | if (*_pos > INT_MAX) |
153 | return NULL; | 153 | return NULL; |
154 | key = find_ge_key(p, pos); | 154 | key = find_ge_key(pos); |
155 | if (!key) | 155 | if (!key) |
156 | return NULL; | 156 | return NULL; |
157 | *_pos = key->serial; | 157 | *_pos = key->serial; |
@@ -168,7 +168,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) | |||
168 | { | 168 | { |
169 | struct rb_node *n; | 169 | struct rb_node *n; |
170 | 170 | ||
171 | n = key_serial_next(p, v); | 171 | n = key_serial_next(v); |
172 | if (n) | 172 | if (n) |
173 | *_pos = key_node_serial(n); | 173 | *_pos = key_node_serial(n); |
174 | return n; | 174 | return n; |
@@ -242,7 +242,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
242 | #define showflag(KEY, LETTER, FLAG) \ | 242 | #define showflag(KEY, LETTER, FLAG) \ |
243 | (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') | 243 | (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') |
244 | 244 | ||
245 | seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", | 245 | seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", |
246 | key->serial, | 246 | key->serial, |
247 | showflag(key, 'I', KEY_FLAG_INSTANTIATED), | 247 | showflag(key, 'I', KEY_FLAG_INSTANTIATED), |
248 | showflag(key, 'R', KEY_FLAG_REVOKED), | 248 | showflag(key, 'R', KEY_FLAG_REVOKED), |
@@ -250,12 +250,11 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
250 | showflag(key, 'Q', KEY_FLAG_IN_QUOTA), | 250 | showflag(key, 'Q', KEY_FLAG_IN_QUOTA), |
251 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), | 251 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), |
252 | showflag(key, 'N', KEY_FLAG_NEGATIVE), | 252 | showflag(key, 'N', KEY_FLAG_NEGATIVE), |
253 | showflag(key, 'i', KEY_FLAG_INVALIDATED), | ||
254 | atomic_read(&key->usage), | 253 | atomic_read(&key->usage), |
255 | xbuf, | 254 | xbuf, |
256 | key->perm, | 255 | key->perm, |
257 | from_kuid_munged(seq_user_ns(m), key->uid), | 256 | key->uid, |
258 | from_kgid_munged(seq_user_ns(m), key->gid), | 257 | key->gid, |
259 | key->type->name); | 258 | key->type->name); |
260 | 259 | ||
261 | #undef showflag | 260 | #undef showflag |
@@ -270,26 +269,26 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
270 | 269 | ||
271 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ | 270 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ |
272 | 271 | ||
273 | static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n) | 272 | static struct rb_node *__key_user_next(struct rb_node *n) |
274 | { | 273 | { |
275 | while (n) { | 274 | while (n) { |
276 | struct key_user *user = rb_entry(n, struct key_user, node); | 275 | struct key_user *user = rb_entry(n, struct key_user, node); |
277 | if (kuid_has_mapping(user_ns, user->uid)) | 276 | if (user->user_ns == current_user_ns()) |
278 | break; | 277 | break; |
279 | n = rb_next(n); | 278 | n = rb_next(n); |
280 | } | 279 | } |
281 | return n; | 280 | return n; |
282 | } | 281 | } |
283 | 282 | ||
284 | static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n) | 283 | static struct rb_node *key_user_next(struct rb_node *n) |
285 | { | 284 | { |
286 | return __key_user_next(user_ns, rb_next(n)); | 285 | return __key_user_next(rb_next(n)); |
287 | } | 286 | } |
288 | 287 | ||
289 | static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r) | 288 | static struct rb_node *key_user_first(struct rb_root *r) |
290 | { | 289 | { |
291 | struct rb_node *n = rb_first(r); | 290 | struct rb_node *n = rb_first(r); |
292 | return __key_user_next(user_ns, n); | 291 | return __key_user_next(n); |
293 | } | 292 | } |
294 | 293 | ||
295 | /* | 294 | /* |
@@ -309,10 +308,10 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
309 | 308 | ||
310 | spin_lock(&key_user_lock); | 309 | spin_lock(&key_user_lock); |
311 | 310 | ||
312 | _p = key_user_first(seq_user_ns(p), &key_user_tree); | 311 | _p = key_user_first(&key_user_tree); |
313 | while (pos > 0 && _p) { | 312 | while (pos > 0 && _p) { |
314 | pos--; | 313 | pos--; |
315 | _p = key_user_next(seq_user_ns(p), _p); | 314 | _p = key_user_next(_p); |
316 | } | 315 | } |
317 | 316 | ||
318 | return _p; | 317 | return _p; |
@@ -321,7 +320,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
321 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | 320 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) |
322 | { | 321 | { |
323 | (*_pos)++; | 322 | (*_pos)++; |
324 | return key_user_next(seq_user_ns(p), (struct rb_node *)v); | 323 | return key_user_next((struct rb_node *)v); |
325 | } | 324 | } |
326 | 325 | ||
327 | static void proc_key_users_stop(struct seq_file *p, void *v) | 326 | static void proc_key_users_stop(struct seq_file *p, void *v) |
@@ -334,13 +333,13 @@ static int proc_key_users_show(struct seq_file *m, void *v) | |||
334 | { | 333 | { |
335 | struct rb_node *_p = v; | 334 | struct rb_node *_p = v; |
336 | struct key_user *user = rb_entry(_p, struct key_user, node); | 335 | struct key_user *user = rb_entry(_p, struct key_user, node); |
337 | unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ? | 336 | unsigned maxkeys = (user->uid == 0) ? |
338 | key_quota_root_maxkeys : key_quota_maxkeys; | 337 | key_quota_root_maxkeys : key_quota_maxkeys; |
339 | unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ? | 338 | unsigned maxbytes = (user->uid == 0) ? |
340 | key_quota_root_maxbytes : key_quota_maxbytes; | 339 | key_quota_root_maxbytes : key_quota_maxbytes; |
341 | 340 | ||
342 | 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", |
343 | from_kuid_munged(seq_user_ns(m), user->uid), | 342 | user->uid, |
344 | atomic_read(&user->usage), | 343 | atomic_read(&user->usage), |
345 | atomic_read(&user->nkeys), | 344 | atomic_read(&user->nkeys), |
346 | atomic_read(&user->nikeys), | 345 | atomic_read(&user->nikeys), |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 20e4bf57aec..a3063eb3dc2 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -34,7 +34,8 @@ struct key_user root_key_user = { | |||
34 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), | 34 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
35 | .nkeys = ATOMIC_INIT(2), | 35 | .nkeys = ATOMIC_INIT(2), |
36 | .nikeys = ATOMIC_INIT(2), | 36 | .nikeys = ATOMIC_INIT(2), |
37 | .uid = GLOBAL_ROOT_UID, | 37 | .uid = 0, |
38 | .user_ns = &init_user_ns, | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | /* | 41 | /* |
@@ -45,17 +46,13 @@ int install_user_keyrings(void) | |||
45 | struct user_struct *user; | 46 | struct user_struct *user; |
46 | const struct cred *cred; | 47 | const struct cred *cred; |
47 | struct key *uid_keyring, *session_keyring; | 48 | struct key *uid_keyring, *session_keyring; |
48 | key_perm_t user_keyring_perm; | ||
49 | char buf[20]; | 49 | char buf[20]; |
50 | int ret; | 50 | int ret; |
51 | uid_t uid; | ||
52 | 51 | ||
53 | user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; | ||
54 | cred = current_cred(); | 52 | cred = current_cred(); |
55 | user = cred->user; | 53 | user = cred->user; |
56 | uid = from_kuid(cred->user_ns, user->uid); | ||
57 | 54 | ||
58 | kenter("%p{%u}", user, uid); | 55 | kenter("%p{%u}", user, user->uid); |
59 | 56 | ||
60 | if (user->uid_keyring) { | 57 | if (user->uid_keyring) { |
61 | kleave(" = 0 [exist]"); | 58 | kleave(" = 0 [exist]"); |
@@ -70,13 +67,13 @@ int install_user_keyrings(void) | |||
70 | * - there may be one in existence already as it may have been | 67 | * - there may be one in existence already as it may have been |
71 | * pinned by a session, but the user_struct pointing to it | 68 | * pinned by a session, but the user_struct pointing to it |
72 | * may have been destroyed by setuid */ | 69 | * may have been destroyed by setuid */ |
73 | sprintf(buf, "_uid.%u", uid); | 70 | sprintf(buf, "_uid.%u", user->uid); |
74 | 71 | ||
75 | uid_keyring = find_keyring_by_name(buf, true); | 72 | uid_keyring = find_keyring_by_name(buf, true); |
76 | if (IS_ERR(uid_keyring)) { | 73 | if (IS_ERR(uid_keyring)) { |
77 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, | 74 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, |
78 | cred, user_keyring_perm, | 75 | cred, KEY_ALLOC_IN_QUOTA, |
79 | KEY_ALLOC_IN_QUOTA, NULL); | 76 | NULL); |
80 | if (IS_ERR(uid_keyring)) { | 77 | if (IS_ERR(uid_keyring)) { |
81 | ret = PTR_ERR(uid_keyring); | 78 | ret = PTR_ERR(uid_keyring); |
82 | goto error; | 79 | goto error; |
@@ -85,14 +82,13 @@ int install_user_keyrings(void) | |||
85 | 82 | ||
86 | /* get a default session keyring (which might also exist | 83 | /* get a default session keyring (which might also exist |
87 | * already) */ | 84 | * already) */ |
88 | sprintf(buf, "_uid_ses.%u", uid); | 85 | sprintf(buf, "_uid_ses.%u", user->uid); |
89 | 86 | ||
90 | session_keyring = find_keyring_by_name(buf, true); | 87 | session_keyring = find_keyring_by_name(buf, true); |
91 | if (IS_ERR(session_keyring)) { | 88 | if (IS_ERR(session_keyring)) { |
92 | session_keyring = | 89 | session_keyring = |
93 | keyring_alloc(buf, user->uid, INVALID_GID, | 90 | keyring_alloc(buf, user->uid, (gid_t) -1, |
94 | cred, user_keyring_perm, | 91 | cred, KEY_ALLOC_IN_QUOTA, NULL); |
95 | KEY_ALLOC_IN_QUOTA, NULL); | ||
96 | if (IS_ERR(session_keyring)) { | 92 | if (IS_ERR(session_keyring)) { |
97 | ret = PTR_ERR(session_keyring); | 93 | ret = PTR_ERR(session_keyring); |
98 | goto error_release; | 94 | goto error_release; |
@@ -133,7 +129,6 @@ int install_thread_keyring_to_cred(struct cred *new) | |||
133 | struct key *keyring; | 129 | struct key *keyring; |
134 | 130 | ||
135 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, | 131 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
136 | KEY_POS_ALL | KEY_USR_VIEW, | ||
137 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 132 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
138 | if (IS_ERR(keyring)) | 133 | if (IS_ERR(keyring)) |
139 | return PTR_ERR(keyring); | 134 | return PTR_ERR(keyring); |
@@ -174,18 +169,27 @@ static int install_thread_keyring(void) | |||
174 | int install_process_keyring_to_cred(struct cred *new) | 169 | int install_process_keyring_to_cred(struct cred *new) |
175 | { | 170 | { |
176 | struct key *keyring; | 171 | struct key *keyring; |
172 | int ret; | ||
177 | 173 | ||
178 | if (new->process_keyring) | 174 | if (new->tgcred->process_keyring) |
179 | return -EEXIST; | 175 | return -EEXIST; |
180 | 176 | ||
181 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, | 177 | keyring = keyring_alloc("_pid", new->uid, new->gid, |
182 | KEY_POS_ALL | KEY_USR_VIEW, | 178 | new, KEY_ALLOC_QUOTA_OVERRUN, NULL); |
183 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
184 | if (IS_ERR(keyring)) | 179 | if (IS_ERR(keyring)) |
185 | return PTR_ERR(keyring); | 180 | return PTR_ERR(keyring); |
186 | 181 | ||
187 | new->process_keyring = keyring; | 182 | spin_lock_irq(&new->tgcred->lock); |
188 | return 0; | 183 | if (!new->tgcred->process_keyring) { |
184 | new->tgcred->process_keyring = keyring; | ||
185 | keyring = NULL; | ||
186 | ret = 0; | ||
187 | } else { | ||
188 | ret = -EEXIST; | ||
189 | } | ||
190 | spin_unlock_irq(&new->tgcred->lock); | ||
191 | key_put(keyring); | ||
192 | return ret; | ||
189 | } | 193 | } |
190 | 194 | ||
191 | /* | 195 | /* |
@@ -226,12 +230,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
226 | /* create an empty session keyring */ | 230 | /* create an empty session keyring */ |
227 | if (!keyring) { | 231 | if (!keyring) { |
228 | flags = KEY_ALLOC_QUOTA_OVERRUN; | 232 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
229 | if (cred->session_keyring) | 233 | if (cred->tgcred->session_keyring) |
230 | flags = KEY_ALLOC_IN_QUOTA; | 234 | flags = KEY_ALLOC_IN_QUOTA; |
231 | 235 | ||
232 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, | 236 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, |
233 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | 237 | cred, flags, NULL); |
234 | flags, NULL); | ||
235 | if (IS_ERR(keyring)) | 238 | if (IS_ERR(keyring)) |
236 | return PTR_ERR(keyring); | 239 | return PTR_ERR(keyring); |
237 | } else { | 240 | } else { |
@@ -239,11 +242,17 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
239 | } | 242 | } |
240 | 243 | ||
241 | /* install the keyring */ | 244 | /* install the keyring */ |
242 | old = cred->session_keyring; | 245 | spin_lock_irq(&cred->tgcred->lock); |
243 | rcu_assign_pointer(cred->session_keyring, keyring); | 246 | old = cred->tgcred->session_keyring; |
244 | 247 | rcu_assign_pointer(cred->tgcred->session_keyring, keyring); | |
245 | if (old) | 248 | spin_unlock_irq(&cred->tgcred->lock); |
249 | |||
250 | /* we're using RCU on the pointer, but there's no point synchronising | ||
251 | * on it if it didn't previously point to anything */ | ||
252 | if (old) { | ||
253 | synchronize_rcu(); | ||
246 | key_put(old); | 254 | key_put(old); |
255 | } | ||
247 | 256 | ||
248 | return 0; | 257 | return 0; |
249 | } | 258 | } |
@@ -261,7 +270,7 @@ static int install_session_keyring(struct key *keyring) | |||
261 | if (!new) | 270 | if (!new) |
262 | return -ENOMEM; | 271 | return -ENOMEM; |
263 | 272 | ||
264 | ret = install_session_keyring_to_cred(new, keyring); | 273 | ret = install_session_keyring_to_cred(new, NULL); |
265 | if (ret < 0) { | 274 | if (ret < 0) { |
266 | abort_creds(new); | 275 | abort_creds(new); |
267 | return ret; | 276 | return ret; |
@@ -348,6 +357,8 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
348 | 357 | ||
349 | switch (PTR_ERR(key_ref)) { | 358 | switch (PTR_ERR(key_ref)) { |
350 | case -EAGAIN: /* no key */ | 359 | case -EAGAIN: /* no key */ |
360 | if (ret) | ||
361 | break; | ||
351 | case -ENOKEY: /* negative key */ | 362 | case -ENOKEY: /* negative key */ |
352 | ret = key_ref; | 363 | ret = key_ref; |
353 | break; | 364 | break; |
@@ -358,15 +369,17 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
358 | } | 369 | } |
359 | 370 | ||
360 | /* search the process keyring second */ | 371 | /* search the process keyring second */ |
361 | if (cred->process_keyring) { | 372 | if (cred->tgcred->process_keyring) { |
362 | key_ref = keyring_search_aux( | 373 | key_ref = keyring_search_aux( |
363 | make_key_ref(cred->process_keyring, 1), | 374 | make_key_ref(cred->tgcred->process_keyring, 1), |
364 | cred, type, description, match, no_state_check); | 375 | cred, type, description, match, no_state_check); |
365 | if (!IS_ERR(key_ref)) | 376 | if (!IS_ERR(key_ref)) |
366 | goto found; | 377 | goto found; |
367 | 378 | ||
368 | switch (PTR_ERR(key_ref)) { | 379 | switch (PTR_ERR(key_ref)) { |
369 | case -EAGAIN: /* no key */ | 380 | case -EAGAIN: /* no key */ |
381 | if (ret) | ||
382 | break; | ||
370 | case -ENOKEY: /* negative key */ | 383 | case -ENOKEY: /* negative key */ |
371 | ret = key_ref; | 384 | ret = key_ref; |
372 | break; | 385 | break; |
@@ -377,10 +390,12 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
377 | } | 390 | } |
378 | 391 | ||
379 | /* search the session keyring */ | 392 | /* search the session keyring */ |
380 | if (cred->session_keyring) { | 393 | if (cred->tgcred->session_keyring) { |
381 | rcu_read_lock(); | 394 | rcu_read_lock(); |
382 | key_ref = keyring_search_aux( | 395 | key_ref = keyring_search_aux( |
383 | make_key_ref(rcu_dereference(cred->session_keyring), 1), | 396 | make_key_ref(rcu_dereference( |
397 | cred->tgcred->session_keyring), | ||
398 | 1), | ||
384 | cred, type, description, match, no_state_check); | 399 | cred, type, description, match, no_state_check); |
385 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
386 | 401 | ||
@@ -550,7 +565,7 @@ try_again: | |||
550 | break; | 565 | break; |
551 | 566 | ||
552 | case KEY_SPEC_PROCESS_KEYRING: | 567 | case KEY_SPEC_PROCESS_KEYRING: |
553 | if (!cred->process_keyring) { | 568 | if (!cred->tgcred->process_keyring) { |
554 | if (!(lflags & KEY_LOOKUP_CREATE)) | 569 | if (!(lflags & KEY_LOOKUP_CREATE)) |
555 | goto error; | 570 | goto error; |
556 | 571 | ||
@@ -562,38 +577,28 @@ try_again: | |||
562 | goto reget_creds; | 577 | goto reget_creds; |
563 | } | 578 | } |
564 | 579 | ||
565 | key = cred->process_keyring; | 580 | key = cred->tgcred->process_keyring; |
566 | atomic_inc(&key->usage); | 581 | atomic_inc(&key->usage); |
567 | key_ref = make_key_ref(key, 1); | 582 | key_ref = make_key_ref(key, 1); |
568 | break; | 583 | break; |
569 | 584 | ||
570 | case KEY_SPEC_SESSION_KEYRING: | 585 | case KEY_SPEC_SESSION_KEYRING: |
571 | if (!cred->session_keyring) { | 586 | if (!cred->tgcred->session_keyring) { |
572 | /* always install a session keyring upon access if one | 587 | /* always install a session keyring upon access if one |
573 | * doesn't exist yet */ | 588 | * doesn't exist yet */ |
574 | ret = install_user_keyrings(); | 589 | ret = install_user_keyrings(); |
575 | if (ret < 0) | 590 | if (ret < 0) |
576 | goto error; | 591 | goto error; |
577 | if (lflags & KEY_LOOKUP_CREATE) | 592 | ret = install_session_keyring( |
578 | ret = join_session_keyring(NULL); | 593 | cred->user->session_keyring); |
579 | else | ||
580 | ret = install_session_keyring( | ||
581 | cred->user->session_keyring); | ||
582 | 594 | ||
583 | if (ret < 0) | 595 | if (ret < 0) |
584 | goto error; | 596 | goto error; |
585 | goto reget_creds; | 597 | goto reget_creds; |
586 | } else if (cred->session_keyring == | ||
587 | cred->user->session_keyring && | ||
588 | lflags & KEY_LOOKUP_CREATE) { | ||
589 | ret = join_session_keyring(NULL); | ||
590 | if (ret < 0) | ||
591 | goto error; | ||
592 | goto reget_creds; | ||
593 | } | 598 | } |
594 | 599 | ||
595 | rcu_read_lock(); | 600 | rcu_read_lock(); |
596 | key = rcu_dereference(cred->session_keyring); | 601 | key = rcu_dereference(cred->tgcred->session_keyring); |
597 | atomic_inc(&key->usage); | 602 | atomic_inc(&key->usage); |
598 | rcu_read_unlock(); | 603 | rcu_read_unlock(); |
599 | key_ref = make_key_ref(key, 1); | 604 | key_ref = make_key_ref(key, 1); |
@@ -642,8 +647,7 @@ try_again: | |||
642 | goto error; | 647 | goto error; |
643 | 648 | ||
644 | down_read(&cred->request_key_auth->sem); | 649 | down_read(&cred->request_key_auth->sem); |
645 | if (test_bit(KEY_FLAG_REVOKED, | 650 | if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) { |
646 | &cred->request_key_auth->flags)) { | ||
647 | key_ref = ERR_PTR(-EKEYREVOKED); | 651 | key_ref = ERR_PTR(-EKEYREVOKED); |
648 | key = NULL; | 652 | key = NULL; |
649 | } else { | 653 | } else { |
@@ -717,8 +721,6 @@ try_again: | |||
717 | if (ret < 0) | 721 | if (ret < 0) |
718 | goto invalid_key; | 722 | goto invalid_key; |
719 | 723 | ||
720 | key->last_used_at = current_kernel_time().tv_sec; | ||
721 | |||
722 | error: | 724 | error: |
723 | put_cred(cred); | 725 | put_cred(cred); |
724 | return key_ref; | 726 | return key_ref; |
@@ -753,6 +755,12 @@ long join_session_keyring(const char *name) | |||
753 | struct key *keyring; | 755 | struct key *keyring; |
754 | long ret, serial; | 756 | long ret, serial; |
755 | 757 | ||
758 | /* only permit this if there's a single thread in the thread group - | ||
759 | * this avoids us having to adjust the creds on all threads and risking | ||
760 | * ENOMEM */ | ||
761 | if (!current_is_single_threaded()) | ||
762 | return -EMLINK; | ||
763 | |||
756 | new = prepare_creds(); | 764 | new = prepare_creds(); |
757 | if (!new) | 765 | if (!new) |
758 | return -ENOMEM; | 766 | return -ENOMEM; |
@@ -764,7 +772,7 @@ long join_session_keyring(const char *name) | |||
764 | if (ret < 0) | 772 | if (ret < 0) |
765 | goto error; | 773 | goto error; |
766 | 774 | ||
767 | serial = new->session_keyring->serial; | 775 | serial = new->tgcred->session_keyring->serial; |
768 | ret = commit_creds(new); | 776 | ret = commit_creds(new); |
769 | if (ret == 0) | 777 | if (ret == 0) |
770 | ret = serial; | 778 | ret = serial; |
@@ -778,10 +786,8 @@ long join_session_keyring(const char *name) | |||
778 | keyring = find_keyring_by_name(name, false); | 786 | keyring = find_keyring_by_name(name, false); |
779 | if (PTR_ERR(keyring) == -ENOKEY) { | 787 | if (PTR_ERR(keyring) == -ENOKEY) { |
780 | /* not found - try and create a new one */ | 788 | /* not found - try and create a new one */ |
781 | keyring = keyring_alloc( | 789 | keyring = keyring_alloc(name, old->uid, old->gid, old, |
782 | name, old->uid, old->gid, old, | 790 | KEY_ALLOC_IN_QUOTA, NULL); |
783 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, | ||
784 | KEY_ALLOC_IN_QUOTA, NULL); | ||
785 | if (IS_ERR(keyring)) { | 791 | if (IS_ERR(keyring)) { |
786 | ret = PTR_ERR(keyring); | 792 | ret = PTR_ERR(keyring); |
787 | goto error2; | 793 | goto error2; |
@@ -789,9 +795,6 @@ long join_session_keyring(const char *name) | |||
789 | } else if (IS_ERR(keyring)) { | 795 | } else if (IS_ERR(keyring)) { |
790 | ret = PTR_ERR(keyring); | 796 | ret = PTR_ERR(keyring); |
791 | goto error2; | 797 | goto error2; |
792 | } else if (keyring == new->session_keyring) { | ||
793 | ret = 0; | ||
794 | goto error2; | ||
795 | } | 798 | } |
796 | 799 | ||
797 | /* we've got a keyring - now to install it */ | 800 | /* we've got a keyring - now to install it */ |
@@ -818,16 +821,23 @@ error: | |||
818 | * Replace a process's session keyring on behalf of one of its children when | 821 | * Replace a process's session keyring on behalf of one of its children when |
819 | * the target process is about to resume userspace execution. | 822 | * the target process is about to resume userspace execution. |
820 | */ | 823 | */ |
821 | void key_change_session_keyring(struct callback_head *twork) | 824 | void key_replace_session_keyring(void) |
822 | { | 825 | { |
823 | const struct cred *old = current_cred(); | 826 | const struct cred *old; |
824 | struct cred *new = container_of(twork, struct cred, rcu); | 827 | struct cred *new; |
825 | 828 | ||
826 | if (unlikely(current->flags & PF_EXITING)) { | 829 | if (!current->replacement_session_keyring) |
827 | put_cred(new); | ||
828 | return; | 830 | return; |
829 | } | ||
830 | 831 | ||
832 | write_lock_irq(&tasklist_lock); | ||
833 | new = current->replacement_session_keyring; | ||
834 | current->replacement_session_keyring = NULL; | ||
835 | write_unlock_irq(&tasklist_lock); | ||
836 | |||
837 | if (!new) | ||
838 | return; | ||
839 | |||
840 | old = current_cred(); | ||
831 | new-> uid = old-> uid; | 841 | new-> uid = old-> uid; |
832 | new-> euid = old-> euid; | 842 | new-> euid = old-> euid; |
833 | new-> suid = old-> suid; | 843 | new-> suid = old-> suid; |
@@ -837,7 +847,7 @@ void key_change_session_keyring(struct callback_head *twork) | |||
837 | new-> sgid = old-> sgid; | 847 | new-> sgid = old-> sgid; |
838 | new->fsgid = old->fsgid; | 848 | new->fsgid = old->fsgid; |
839 | new->user = get_uid(old->user); | 849 | new->user = get_uid(old->user); |
840 | new->user_ns = get_user_ns(new->user_ns); | 850 | new->user_ns = new->user->user_ns; |
841 | new->group_info = get_group_info(old->group_info); | 851 | new->group_info = get_group_info(old->group_info); |
842 | 852 | ||
843 | new->securebits = old->securebits; | 853 | new->securebits = old->securebits; |
@@ -848,7 +858,8 @@ void key_change_session_keyring(struct callback_head *twork) | |||
848 | 858 | ||
849 | new->jit_keyring = old->jit_keyring; | 859 | new->jit_keyring = old->jit_keyring; |
850 | new->thread_keyring = key_get(old->thread_keyring); | 860 | new->thread_keyring = key_get(old->thread_keyring); |
851 | new->process_keyring = key_get(old->process_keyring); | 861 | new->tgcred->tgid = old->tgcred->tgid; |
862 | new->tgcred->process_keyring = key_get(old->tgcred->process_keyring); | ||
852 | 863 | ||
853 | security_transfer_creds(new, old); | 864 | security_transfer_creds(new, old); |
854 | 865 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 4bd6bdb7419..82465328c39 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -91,11 +91,18 @@ static void umh_keys_cleanup(struct subprocess_info *info) | |||
91 | * Call a usermode helper with a specific session keyring. | 91 | * Call a usermode helper with a specific session keyring. |
92 | */ | 92 | */ |
93 | static int call_usermodehelper_keys(char *path, char **argv, char **envp, | 93 | static int call_usermodehelper_keys(char *path, char **argv, char **envp, |
94 | struct key *session_keyring, int wait) | 94 | struct key *session_keyring, enum umh_wait wait) |
95 | { | 95 | { |
96 | return call_usermodehelper_fns(path, argv, envp, wait, | 96 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; |
97 | umh_keys_init, umh_keys_cleanup, | 97 | struct subprocess_info *info = |
98 | key_get(session_keyring)); | 98 | call_usermodehelper_setup(path, argv, envp, gfp_mask); |
99 | |||
100 | if (!info) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | call_usermodehelper_setfns(info, umh_keys_init, umh_keys_cleanup, | ||
104 | key_get(session_keyring)); | ||
105 | return call_usermodehelper_exec(info, wait); | ||
99 | } | 106 | } |
100 | 107 | ||
101 | /* | 108 | /* |
@@ -126,7 +133,6 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
126 | 133 | ||
127 | cred = get_current_cred(); | 134 | cred = get_current_cred(); |
128 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | 135 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, |
129 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | ||
130 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 136 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
131 | put_cred(cred); | 137 | put_cred(cred); |
132 | if (IS_ERR(keyring)) { | 138 | if (IS_ERR(keyring)) { |
@@ -140,8 +146,8 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
140 | goto error_link; | 146 | goto error_link; |
141 | 147 | ||
142 | /* record the UID and GID */ | 148 | /* record the UID and GID */ |
143 | sprintf(uid_str, "%d", from_kuid(&init_user_ns, cred->fsuid)); | 149 | sprintf(uid_str, "%d", cred->fsuid); |
144 | sprintf(gid_str, "%d", from_kgid(&init_user_ns, cred->fsgid)); | 150 | sprintf(gid_str, "%d", cred->fsgid); |
145 | 151 | ||
146 | /* we say which key is under construction */ | 152 | /* we say which key is under construction */ |
147 | sprintf(key_str, "%d", key->serial); | 153 | sprintf(key_str, "%d", key->serial); |
@@ -151,12 +157,12 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
151 | cred->thread_keyring ? cred->thread_keyring->serial : 0); | 157 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
152 | 158 | ||
153 | prkey = 0; | 159 | prkey = 0; |
154 | if (cred->process_keyring) | 160 | if (cred->tgcred->process_keyring) |
155 | prkey = cred->process_keyring->serial; | 161 | prkey = cred->tgcred->process_keyring->serial; |
156 | sprintf(keyring_str[1], "%d", prkey); | 162 | sprintf(keyring_str[1], "%d", prkey); |
157 | 163 | ||
158 | rcu_read_lock(); | 164 | rcu_read_lock(); |
159 | session = rcu_dereference(cred->session_keyring); | 165 | session = rcu_dereference(cred->tgcred->session_keyring); |
160 | if (!session) | 166 | if (!session) |
161 | session = cred->user->session_keyring; | 167 | session = cred->user->session_keyring; |
162 | sskey = session->serial; | 168 | sskey = session->serial; |
@@ -298,14 +304,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) | |||
298 | break; | 304 | break; |
299 | 305 | ||
300 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 306 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
301 | dest_keyring = key_get(cred->process_keyring); | 307 | dest_keyring = key_get(cred->tgcred->process_keyring); |
302 | if (dest_keyring) | 308 | if (dest_keyring) |
303 | break; | 309 | break; |
304 | 310 | ||
305 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 311 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
306 | rcu_read_lock(); | 312 | rcu_read_lock(); |
307 | dest_keyring = key_get( | 313 | dest_keyring = key_get( |
308 | rcu_dereference(cred->session_keyring)); | 314 | rcu_dereference(cred->tgcred->session_keyring)); |
309 | rcu_read_unlock(); | 315 | rcu_read_unlock(); |
310 | 316 | ||
311 | if (dest_keyring) | 317 | if (dest_keyring) |
@@ -348,7 +354,6 @@ static int construct_alloc_key(struct key_type *type, | |||
348 | const struct cred *cred = current_cred(); | 354 | const struct cred *cred = current_cred(); |
349 | unsigned long prealloc; | 355 | unsigned long prealloc; |
350 | struct key *key; | 356 | struct key *key; |
351 | key_perm_t perm; | ||
352 | key_ref_t key_ref; | 357 | key_ref_t key_ref; |
353 | int ret; | 358 | int ret; |
354 | 359 | ||
@@ -357,15 +362,8 @@ static int construct_alloc_key(struct key_type *type, | |||
357 | *_key = NULL; | 362 | *_key = NULL; |
358 | mutex_lock(&user->cons_lock); | 363 | mutex_lock(&user->cons_lock); |
359 | 364 | ||
360 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | ||
361 | perm |= KEY_USR_VIEW; | ||
362 | if (type->read) | ||
363 | perm |= KEY_POS_READ; | ||
364 | if (type == &key_type_keyring || type->update) | ||
365 | perm |= KEY_POS_WRITE; | ||
366 | |||
367 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 365 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
368 | perm, flags); | 366 | KEY_POS_ALL, flags); |
369 | if (IS_ERR(key)) | 367 | if (IS_ERR(key)) |
370 | goto alloc_failed; | 368 | goto alloc_failed; |
371 | 369 | ||
@@ -451,7 +449,7 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
451 | 449 | ||
452 | kenter(""); | 450 | kenter(""); |
453 | 451 | ||
454 | user = key_user_lookup(current_fsuid()); | 452 | user = key_user_lookup(current_fsuid(), current_user_ns()); |
455 | if (!user) | 453 | if (!user) |
456 | return ERR_PTR(-ENOMEM); | 454 | return ERR_PTR(-ENOMEM); |
457 | 455 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 85730d5a5a5..60d4e3f5e4b 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -19,8 +19,7 @@ | |||
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static int request_key_auth_instantiate(struct key *, | 22 | static int request_key_auth_instantiate(struct key *, const void *, size_t); |
23 | struct key_preparsed_payload *); | ||
24 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 23 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
25 | static void request_key_auth_revoke(struct key *); | 24 | static void request_key_auth_revoke(struct key *); |
26 | static void request_key_auth_destroy(struct key *); | 25 | static void request_key_auth_destroy(struct key *); |
@@ -43,9 +42,10 @@ struct key_type key_type_request_key_auth = { | |||
43 | * Instantiate a request-key authorisation key. | 42 | * Instantiate a request-key authorisation key. |
44 | */ | 43 | */ |
45 | static int request_key_auth_instantiate(struct key *key, | 44 | static int request_key_auth_instantiate(struct key *key, |
46 | struct key_preparsed_payload *prep) | 45 | const void *data, |
46 | size_t datalen) | ||
47 | { | 47 | { |
48 | key->payload.data = (struct request_key_auth *)prep->data; | 48 | key->payload.data = (struct request_key_auth *) data; |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index e13fcf7636f..0c33e2ea1f3 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -369,6 +369,38 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd, | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /* | 371 | /* |
372 | * get a random value from TPM | ||
373 | */ | ||
374 | static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len) | ||
375 | { | ||
376 | int ret; | ||
377 | |||
378 | INIT_BUF(tb); | ||
379 | store16(tb, TPM_TAG_RQU_COMMAND); | ||
380 | store32(tb, TPM_GETRANDOM_SIZE); | ||
381 | store32(tb, TPM_ORD_GETRANDOM); | ||
382 | store32(tb, len); | ||
383 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); | ||
384 | if (!ret) | ||
385 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | static int my_get_random(unsigned char *buf, int len) | ||
390 | { | ||
391 | struct tpm_buf *tb; | ||
392 | int ret; | ||
393 | |||
394 | tb = kmalloc(sizeof *tb, GFP_KERNEL); | ||
395 | if (!tb) | ||
396 | return -ENOMEM; | ||
397 | ret = tpm_get_random(tb, buf, len); | ||
398 | |||
399 | kfree(tb); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | /* | ||
372 | * Lock a trusted key, by extending a selected PCR. | 404 | * Lock a trusted key, by extending a selected PCR. |
373 | * | 405 | * |
374 | * Prevents a trusted key that is sealed to PCRs from being accessed. | 406 | * Prevents a trusted key that is sealed to PCRs from being accessed. |
@@ -381,8 +413,8 @@ static int pcrlock(const int pcrnum) | |||
381 | 413 | ||
382 | if (!capable(CAP_SYS_ADMIN)) | 414 | if (!capable(CAP_SYS_ADMIN)) |
383 | return -EPERM; | 415 | return -EPERM; |
384 | ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE); | 416 | ret = my_get_random(hash, SHA1_DIGEST_SIZE); |
385 | if (ret != SHA1_DIGEST_SIZE) | 417 | if (ret < 0) |
386 | return ret; | 418 | return ret; |
387 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; | 419 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; |
388 | } | 420 | } |
@@ -397,8 +429,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
397 | unsigned char ononce[TPM_NONCE_SIZE]; | 429 | unsigned char ononce[TPM_NONCE_SIZE]; |
398 | int ret; | 430 | int ret; |
399 | 431 | ||
400 | ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE); | 432 | ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE); |
401 | if (ret != TPM_NONCE_SIZE) | 433 | if (ret < 0) |
402 | return ret; | 434 | return ret; |
403 | 435 | ||
404 | INIT_BUF(tb); | 436 | INIT_BUF(tb); |
@@ -492,8 +524,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
492 | if (ret < 0) | 524 | if (ret < 0) |
493 | goto out; | 525 | goto out; |
494 | 526 | ||
495 | ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE); | 527 | ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE); |
496 | if (ret != TPM_NONCE_SIZE) | 528 | if (ret < 0) |
497 | goto out; | 529 | goto out; |
498 | ordinal = htonl(TPM_ORD_SEAL); | 530 | ordinal = htonl(TPM_ORD_SEAL); |
499 | datsize = htonl(datalen); | 531 | datsize = htonl(datalen); |
@@ -602,8 +634,8 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
602 | 634 | ||
603 | ordinal = htonl(TPM_ORD_UNSEAL); | 635 | ordinal = htonl(TPM_ORD_UNSEAL); |
604 | keyhndl = htonl(SRKHANDLE); | 636 | keyhndl = htonl(SRKHANDLE); |
605 | ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE); | 637 | ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE); |
606 | if (ret != TPM_NONCE_SIZE) { | 638 | if (ret < 0) { |
607 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 639 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
608 | return ret; | 640 | return ret; |
609 | } | 641 | } |
@@ -747,10 +779,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
747 | opt->pcrinfo_len = strlen(args[0].from) / 2; | 779 | opt->pcrinfo_len = strlen(args[0].from) / 2; |
748 | if (opt->pcrinfo_len > MAX_PCRINFO_SIZE) | 780 | if (opt->pcrinfo_len > MAX_PCRINFO_SIZE) |
749 | return -EINVAL; | 781 | return -EINVAL; |
750 | res = hex2bin(opt->pcrinfo, args[0].from, | 782 | hex2bin(opt->pcrinfo, args[0].from, opt->pcrinfo_len); |
751 | opt->pcrinfo_len); | ||
752 | if (res < 0) | ||
753 | return -EINVAL; | ||
754 | break; | 783 | break; |
755 | case Opt_keyhandle: | 784 | case Opt_keyhandle: |
756 | res = strict_strtoul(args[0].from, 16, &handle); | 785 | res = strict_strtoul(args[0].from, 16, &handle); |
@@ -762,18 +791,12 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
762 | case Opt_keyauth: | 791 | case Opt_keyauth: |
763 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) | 792 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) |
764 | return -EINVAL; | 793 | return -EINVAL; |
765 | res = hex2bin(opt->keyauth, args[0].from, | 794 | hex2bin(opt->keyauth, args[0].from, SHA1_DIGEST_SIZE); |
766 | SHA1_DIGEST_SIZE); | ||
767 | if (res < 0) | ||
768 | return -EINVAL; | ||
769 | break; | 795 | break; |
770 | case Opt_blobauth: | 796 | case Opt_blobauth: |
771 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) | 797 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) |
772 | return -EINVAL; | 798 | return -EINVAL; |
773 | res = hex2bin(opt->blobauth, args[0].from, | 799 | hex2bin(opt->blobauth, args[0].from, SHA1_DIGEST_SIZE); |
774 | SHA1_DIGEST_SIZE); | ||
775 | if (res < 0) | ||
776 | return -EINVAL; | ||
777 | break; | 800 | break; |
778 | case Opt_migratable: | 801 | case Opt_migratable: |
779 | if (*args[0].from == '0') | 802 | if (*args[0].from == '0') |
@@ -837,9 +860,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p, | |||
837 | p->blob_len = strlen(c) / 2; | 860 | p->blob_len = strlen(c) / 2; |
838 | if (p->blob_len > MAX_BLOB_SIZE) | 861 | if (p->blob_len > MAX_BLOB_SIZE) |
839 | return -EINVAL; | 862 | return -EINVAL; |
840 | ret = hex2bin(p->blob, c, p->blob_len); | 863 | hex2bin(p->blob, c, p->blob_len); |
841 | if (ret < 0) | ||
842 | return -EINVAL; | ||
843 | ret = getoptions(datablob, p, o); | 864 | ret = getoptions(datablob, p, o); |
844 | if (ret < 0) | 865 | if (ret < 0) |
845 | return ret; | 866 | return ret; |
@@ -895,24 +916,22 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
895 | * | 916 | * |
896 | * On success, return 0. Otherwise return errno. | 917 | * On success, return 0. Otherwise return errno. |
897 | */ | 918 | */ |
898 | static int trusted_instantiate(struct key *key, | 919 | static int trusted_instantiate(struct key *key, const void *data, |
899 | struct key_preparsed_payload *prep) | 920 | size_t datalen) |
900 | { | 921 | { |
901 | struct trusted_key_payload *payload = NULL; | 922 | struct trusted_key_payload *payload = NULL; |
902 | struct trusted_key_options *options = NULL; | 923 | struct trusted_key_options *options = NULL; |
903 | size_t datalen = prep->datalen; | ||
904 | char *datablob; | 924 | char *datablob; |
905 | int ret = 0; | 925 | int ret = 0; |
906 | int key_cmd; | 926 | int key_cmd; |
907 | size_t key_len; | ||
908 | 927 | ||
909 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 928 | if (datalen <= 0 || datalen > 32767 || !data) |
910 | return -EINVAL; | 929 | return -EINVAL; |
911 | 930 | ||
912 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 931 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
913 | if (!datablob) | 932 | if (!datablob) |
914 | return -ENOMEM; | 933 | return -ENOMEM; |
915 | memcpy(datablob, prep->data, datalen); | 934 | memcpy(datablob, data, datalen); |
916 | datablob[datalen] = '\0'; | 935 | datablob[datalen] = '\0'; |
917 | 936 | ||
918 | options = trusted_options_alloc(); | 937 | options = trusted_options_alloc(); |
@@ -944,9 +963,8 @@ static int trusted_instantiate(struct key *key, | |||
944 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); | 963 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); |
945 | break; | 964 | break; |
946 | case Opt_new: | 965 | case Opt_new: |
947 | key_len = payload->key_len; | 966 | ret = my_get_random(payload->key, payload->key_len); |
948 | ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len); | 967 | if (ret < 0) { |
949 | if (ret != key_len) { | ||
950 | pr_info("trusted_key: key_create failed (%d)\n", ret); | 968 | pr_info("trusted_key: key_create failed (%d)\n", ret); |
951 | goto out; | 969 | goto out; |
952 | } | 970 | } |
@@ -964,7 +982,7 @@ out: | |||
964 | kfree(datablob); | 982 | kfree(datablob); |
965 | kfree(options); | 983 | kfree(options); |
966 | if (!ret) | 984 | if (!ret) |
967 | rcu_assign_keypointer(key, payload); | 985 | rcu_assign_pointer(key->payload.data, payload); |
968 | else | 986 | else |
969 | kfree(payload); | 987 | kfree(payload); |
970 | return ret; | 988 | return ret; |
@@ -982,18 +1000,17 @@ static void trusted_rcu_free(struct rcu_head *rcu) | |||
982 | /* | 1000 | /* |
983 | * trusted_update - reseal an existing key with new PCR values | 1001 | * trusted_update - reseal an existing key with new PCR values |
984 | */ | 1002 | */ |
985 | static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | 1003 | static int trusted_update(struct key *key, const void *data, size_t datalen) |
986 | { | 1004 | { |
987 | struct trusted_key_payload *p = key->payload.data; | 1005 | struct trusted_key_payload *p = key->payload.data; |
988 | struct trusted_key_payload *new_p; | 1006 | struct trusted_key_payload *new_p; |
989 | struct trusted_key_options *new_o; | 1007 | struct trusted_key_options *new_o; |
990 | size_t datalen = prep->datalen; | ||
991 | char *datablob; | 1008 | char *datablob; |
992 | int ret = 0; | 1009 | int ret = 0; |
993 | 1010 | ||
994 | if (!p->migratable) | 1011 | if (!p->migratable) |
995 | return -EPERM; | 1012 | return -EPERM; |
996 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 1013 | if (datalen <= 0 || datalen > 32767 || !data) |
997 | return -EINVAL; | 1014 | return -EINVAL; |
998 | 1015 | ||
999 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 1016 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -1010,7 +1027,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | |||
1010 | goto out; | 1027 | goto out; |
1011 | } | 1028 | } |
1012 | 1029 | ||
1013 | memcpy(datablob, prep->data, datalen); | 1030 | memcpy(datablob, data, datalen); |
1014 | datablob[datalen] = '\0'; | 1031 | datablob[datalen] = '\0'; |
1015 | ret = datablob_parse(datablob, new_p, new_o); | 1032 | ret = datablob_parse(datablob, new_p, new_o); |
1016 | if (ret != Opt_update) { | 1033 | if (ret != Opt_update) { |
@@ -1039,7 +1056,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | |||
1039 | goto out; | 1056 | goto out; |
1040 | } | 1057 | } |
1041 | } | 1058 | } |
1042 | rcu_assign_keypointer(key, new_p); | 1059 | rcu_assign_pointer(key->payload.data, new_p); |
1043 | call_rcu(&p->rcu, trusted_rcu_free); | 1060 | call_rcu(&p->rcu, trusted_rcu_free); |
1044 | out: | 1061 | out: |
1045 | kfree(datablob); | 1062 | kfree(datablob); |
@@ -1070,7 +1087,7 @@ static long trusted_read(const struct key *key, char __user *buffer, | |||
1070 | 1087 | ||
1071 | bufp = ascii_buf; | 1088 | bufp = ascii_buf; |
1072 | for (i = 0; i < p->blob_len; i++) | 1089 | for (i = 0; i < p->blob_len; i++) |
1073 | bufp = hex_byte_pack(bufp, p->blob[i]); | 1090 | bufp = pack_hex_byte(bufp, p->blob[i]); |
1074 | if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { | 1091 | if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { |
1075 | kfree(ascii_buf); | 1092 | kfree(ascii_buf); |
1076 | return -EFAULT; | 1093 | return -EFAULT; |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 55dc8893918..69ff52c08e9 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -18,8 +18,6 @@ | |||
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include "internal.h" | 19 | #include "internal.h" |
20 | 20 | ||
21 | static int logon_vet_description(const char *desc); | ||
22 | |||
23 | /* | 21 | /* |
24 | * user defined keys take an arbitrary string as the description and an | 22 | * user defined keys take an arbitrary string as the description and an |
25 | * arbitrary blob of data as the payload | 23 | * arbitrary blob of data as the payload |
@@ -38,34 +36,15 @@ struct key_type key_type_user = { | |||
38 | EXPORT_SYMBOL_GPL(key_type_user); | 36 | EXPORT_SYMBOL_GPL(key_type_user); |
39 | 37 | ||
40 | /* | 38 | /* |
41 | * This key type is essentially the same as key_type_user, but it does | ||
42 | * not define a .read op. This is suitable for storing username and | ||
43 | * password pairs in the keyring that you do not want to be readable | ||
44 | * from userspace. | ||
45 | */ | ||
46 | struct key_type key_type_logon = { | ||
47 | .name = "logon", | ||
48 | .instantiate = user_instantiate, | ||
49 | .update = user_update, | ||
50 | .match = user_match, | ||
51 | .revoke = user_revoke, | ||
52 | .destroy = user_destroy, | ||
53 | .describe = user_describe, | ||
54 | .vet_description = logon_vet_description, | ||
55 | }; | ||
56 | EXPORT_SYMBOL_GPL(key_type_logon); | ||
57 | |||
58 | /* | ||
59 | * instantiate a user defined key | 39 | * instantiate a user defined key |
60 | */ | 40 | */ |
61 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) | 41 | int user_instantiate(struct key *key, const void *data, size_t datalen) |
62 | { | 42 | { |
63 | struct user_key_payload *upayload; | 43 | struct user_key_payload *upayload; |
64 | size_t datalen = prep->datalen; | ||
65 | int ret; | 44 | int ret; |
66 | 45 | ||
67 | ret = -EINVAL; | 46 | ret = -EINVAL; |
68 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 47 | if (datalen <= 0 || datalen > 32767 || !data) |
69 | goto error; | 48 | goto error; |
70 | 49 | ||
71 | ret = key_payload_reserve(key, datalen); | 50 | ret = key_payload_reserve(key, datalen); |
@@ -79,8 +58,8 @@ int user_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
79 | 58 | ||
80 | /* attach the data */ | 59 | /* attach the data */ |
81 | upayload->datalen = datalen; | 60 | upayload->datalen = datalen; |
82 | memcpy(upayload->data, prep->data, datalen); | 61 | memcpy(upayload->data, data, datalen); |
83 | rcu_assign_keypointer(key, upayload); | 62 | rcu_assign_pointer(key->payload.data, upayload); |
84 | ret = 0; | 63 | ret = 0; |
85 | 64 | ||
86 | error: | 65 | error: |
@@ -93,14 +72,13 @@ EXPORT_SYMBOL_GPL(user_instantiate); | |||
93 | * update a user defined key | 72 | * update a user defined key |
94 | * - the key's semaphore is write-locked | 73 | * - the key's semaphore is write-locked |
95 | */ | 74 | */ |
96 | int user_update(struct key *key, struct key_preparsed_payload *prep) | 75 | int user_update(struct key *key, const void *data, size_t datalen) |
97 | { | 76 | { |
98 | struct user_key_payload *upayload, *zap; | 77 | struct user_key_payload *upayload, *zap; |
99 | size_t datalen = prep->datalen; | ||
100 | int ret; | 78 | int ret; |
101 | 79 | ||
102 | ret = -EINVAL; | 80 | ret = -EINVAL; |
103 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 81 | if (datalen <= 0 || datalen > 32767 || !data) |
104 | goto error; | 82 | goto error; |
105 | 83 | ||
106 | /* construct a replacement payload */ | 84 | /* construct a replacement payload */ |
@@ -110,7 +88,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) | |||
110 | goto error; | 88 | goto error; |
111 | 89 | ||
112 | upayload->datalen = datalen; | 90 | upayload->datalen = datalen; |
113 | memcpy(upayload->data, prep->data, datalen); | 91 | memcpy(upayload->data, data, datalen); |
114 | 92 | ||
115 | /* check the quota and attach the new data */ | 93 | /* check the quota and attach the new data */ |
116 | zap = upayload; | 94 | zap = upayload; |
@@ -120,7 +98,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) | |||
120 | if (ret == 0) { | 98 | if (ret == 0) { |
121 | /* attach the new data, displacing the old */ | 99 | /* attach the new data, displacing the old */ |
122 | zap = key->payload.data; | 100 | zap = key->payload.data; |
123 | rcu_assign_keypointer(key, upayload); | 101 | rcu_assign_pointer(key->payload.data, upayload); |
124 | key->expiry = 0; | 102 | key->expiry = 0; |
125 | } | 103 | } |
126 | 104 | ||
@@ -155,7 +133,7 @@ void user_revoke(struct key *key) | |||
155 | key_payload_reserve(key, 0); | 133 | key_payload_reserve(key, 0); |
156 | 134 | ||
157 | if (upayload) { | 135 | if (upayload) { |
158 | rcu_assign_keypointer(key, NULL); | 136 | rcu_assign_pointer(key->payload.data, NULL); |
159 | kfree_rcu(upayload, rcu); | 137 | kfree_rcu(upayload, rcu); |
160 | } | 138 | } |
161 | } | 139 | } |
@@ -211,20 +189,3 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) | |||
211 | } | 189 | } |
212 | 190 | ||
213 | EXPORT_SYMBOL_GPL(user_read); | 191 | EXPORT_SYMBOL_GPL(user_read); |
214 | |||
215 | /* Vet the description for a "logon" key */ | ||
216 | static int logon_vet_description(const char *desc) | ||
217 | { | ||
218 | char *p; | ||
219 | |||
220 | /* require a "qualified" description string */ | ||
221 | p = strchr(desc, ':'); | ||
222 | if (!p) | ||
223 | return -EINVAL; | ||
224 | |||
225 | /* also reject description with ':' as first char */ | ||
226 | if (p == desc) | ||
227 | return -EINVAL; | ||
228 | |||
229 | return 0; | ||
230 | } | ||