diff options
author | Kees Cook <keescook@chromium.org> | 2018-04-26 22:57:28 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-05-05 02:52:53 -0400 |
commit | 4e234eed58518a8df69a5d14d303b18ed9559832 (patch) | |
tree | 3e1de3cf13e7f764b249f1a37a5a30b29550b3c3 /crypto | |
parent | e99ce921c468ab5d2ccbe17c545061916f3ca82a (diff) |
crypto: tcrypt - Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this
allocates the return code buffers before starting jiffie timers, rather
than using stack space for the array. Additionally cleans up some exit
paths and make sure that the num_mb module_param() is used only once
per execution to avoid possible races in the value changing.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/tcrypt.c | 118 |
1 files changed, 79 insertions, 39 deletions
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 51fe7c8744ae..e721faab6fc8 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c | |||
@@ -158,9 +158,9 @@ struct test_mb_aead_data { | |||
158 | }; | 158 | }; |
159 | 159 | ||
160 | static int do_mult_aead_op(struct test_mb_aead_data *data, int enc, | 160 | static int do_mult_aead_op(struct test_mb_aead_data *data, int enc, |
161 | u32 num_mb) | 161 | u32 num_mb, int *rc) |
162 | { | 162 | { |
163 | int i, rc[num_mb], err = 0; | 163 | int i, err = 0; |
164 | 164 | ||
165 | /* Fire up a bunch of concurrent requests */ | 165 | /* Fire up a bunch of concurrent requests */ |
166 | for (i = 0; i < num_mb; i++) { | 166 | for (i = 0; i < num_mb; i++) { |
@@ -188,18 +188,26 @@ static int test_mb_aead_jiffies(struct test_mb_aead_data *data, int enc, | |||
188 | { | 188 | { |
189 | unsigned long start, end; | 189 | unsigned long start, end; |
190 | int bcount; | 190 | int bcount; |
191 | int ret; | 191 | int ret = 0; |
192 | int *rc; | ||
193 | |||
194 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
195 | if (!rc) | ||
196 | return -ENOMEM; | ||
192 | 197 | ||
193 | for (start = jiffies, end = start + secs * HZ, bcount = 0; | 198 | for (start = jiffies, end = start + secs * HZ, bcount = 0; |
194 | time_before(jiffies, end); bcount++) { | 199 | time_before(jiffies, end); bcount++) { |
195 | ret = do_mult_aead_op(data, enc, num_mb); | 200 | ret = do_mult_aead_op(data, enc, num_mb, rc); |
196 | if (ret) | 201 | if (ret) |
197 | return ret; | 202 | goto out; |
198 | } | 203 | } |
199 | 204 | ||
200 | pr_cont("%d operations in %d seconds (%ld bytes)\n", | 205 | pr_cont("%d operations in %d seconds (%ld bytes)\n", |
201 | bcount * num_mb, secs, (long)bcount * blen * num_mb); | 206 | bcount * num_mb, secs, (long)bcount * blen * num_mb); |
202 | return 0; | 207 | |
208 | out: | ||
209 | kfree(rc); | ||
210 | return ret; | ||
203 | } | 211 | } |
204 | 212 | ||
205 | static int test_mb_aead_cycles(struct test_mb_aead_data *data, int enc, | 213 | static int test_mb_aead_cycles(struct test_mb_aead_data *data, int enc, |
@@ -208,10 +216,15 @@ static int test_mb_aead_cycles(struct test_mb_aead_data *data, int enc, | |||
208 | unsigned long cycles = 0; | 216 | unsigned long cycles = 0; |
209 | int ret = 0; | 217 | int ret = 0; |
210 | int i; | 218 | int i; |
219 | int *rc; | ||
220 | |||
221 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
222 | if (!rc) | ||
223 | return -ENOMEM; | ||
211 | 224 | ||
212 | /* Warm-up run. */ | 225 | /* Warm-up run. */ |
213 | for (i = 0; i < 4; i++) { | 226 | for (i = 0; i < 4; i++) { |
214 | ret = do_mult_aead_op(data, enc, num_mb); | 227 | ret = do_mult_aead_op(data, enc, num_mb, rc); |
215 | if (ret) | 228 | if (ret) |
216 | goto out; | 229 | goto out; |
217 | } | 230 | } |
@@ -221,7 +234,7 @@ static int test_mb_aead_cycles(struct test_mb_aead_data *data, int enc, | |||
221 | cycles_t start, end; | 234 | cycles_t start, end; |
222 | 235 | ||
223 | start = get_cycles(); | 236 | start = get_cycles(); |
224 | ret = do_mult_aead_op(data, enc, num_mb); | 237 | ret = do_mult_aead_op(data, enc, num_mb, rc); |
225 | end = get_cycles(); | 238 | end = get_cycles(); |
226 | 239 | ||
227 | if (ret) | 240 | if (ret) |
@@ -230,11 +243,11 @@ static int test_mb_aead_cycles(struct test_mb_aead_data *data, int enc, | |||
230 | cycles += end - start; | 243 | cycles += end - start; |
231 | } | 244 | } |
232 | 245 | ||
233 | out: | 246 | pr_cont("1 operation in %lu cycles (%d bytes)\n", |
234 | if (ret == 0) | 247 | (cycles + 4) / (8 * num_mb), blen); |
235 | pr_cont("1 operation in %lu cycles (%d bytes)\n", | ||
236 | (cycles + 4) / (8 * num_mb), blen); | ||
237 | 248 | ||
249 | out: | ||
250 | kfree(rc); | ||
238 | return ret; | 251 | return ret; |
239 | } | 252 | } |
240 | 253 | ||
@@ -705,9 +718,10 @@ struct test_mb_ahash_data { | |||
705 | char *xbuf[XBUFSIZE]; | 718 | char *xbuf[XBUFSIZE]; |
706 | }; | 719 | }; |
707 | 720 | ||
708 | static inline int do_mult_ahash_op(struct test_mb_ahash_data *data, u32 num_mb) | 721 | static inline int do_mult_ahash_op(struct test_mb_ahash_data *data, u32 num_mb, |
722 | int *rc) | ||
709 | { | 723 | { |
710 | int i, rc[num_mb], err = 0; | 724 | int i, err = 0; |
711 | 725 | ||
712 | /* Fire up a bunch of concurrent requests */ | 726 | /* Fire up a bunch of concurrent requests */ |
713 | for (i = 0; i < num_mb; i++) | 727 | for (i = 0; i < num_mb; i++) |
@@ -731,18 +745,26 @@ static int test_mb_ahash_jiffies(struct test_mb_ahash_data *data, int blen, | |||
731 | { | 745 | { |
732 | unsigned long start, end; | 746 | unsigned long start, end; |
733 | int bcount; | 747 | int bcount; |
734 | int ret; | 748 | int ret = 0; |
749 | int *rc; | ||
750 | |||
751 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
752 | if (!rc) | ||
753 | return -ENOMEM; | ||
735 | 754 | ||
736 | for (start = jiffies, end = start + secs * HZ, bcount = 0; | 755 | for (start = jiffies, end = start + secs * HZ, bcount = 0; |
737 | time_before(jiffies, end); bcount++) { | 756 | time_before(jiffies, end); bcount++) { |
738 | ret = do_mult_ahash_op(data, num_mb); | 757 | ret = do_mult_ahash_op(data, num_mb, rc); |
739 | if (ret) | 758 | if (ret) |
740 | return ret; | 759 | goto out; |
741 | } | 760 | } |
742 | 761 | ||
743 | pr_cont("%d operations in %d seconds (%ld bytes)\n", | 762 | pr_cont("%d operations in %d seconds (%ld bytes)\n", |
744 | bcount * num_mb, secs, (long)bcount * blen * num_mb); | 763 | bcount * num_mb, secs, (long)bcount * blen * num_mb); |
745 | return 0; | 764 | |
765 | out: | ||
766 | kfree(rc); | ||
767 | return ret; | ||
746 | } | 768 | } |
747 | 769 | ||
748 | static int test_mb_ahash_cycles(struct test_mb_ahash_data *data, int blen, | 770 | static int test_mb_ahash_cycles(struct test_mb_ahash_data *data, int blen, |
@@ -751,10 +773,15 @@ static int test_mb_ahash_cycles(struct test_mb_ahash_data *data, int blen, | |||
751 | unsigned long cycles = 0; | 773 | unsigned long cycles = 0; |
752 | int ret = 0; | 774 | int ret = 0; |
753 | int i; | 775 | int i; |
776 | int *rc; | ||
777 | |||
778 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
779 | if (!rc) | ||
780 | return -ENOMEM; | ||
754 | 781 | ||
755 | /* Warm-up run. */ | 782 | /* Warm-up run. */ |
756 | for (i = 0; i < 4; i++) { | 783 | for (i = 0; i < 4; i++) { |
757 | ret = do_mult_ahash_op(data, num_mb); | 784 | ret = do_mult_ahash_op(data, num_mb, rc); |
758 | if (ret) | 785 | if (ret) |
759 | goto out; | 786 | goto out; |
760 | } | 787 | } |
@@ -764,7 +791,7 @@ static int test_mb_ahash_cycles(struct test_mb_ahash_data *data, int blen, | |||
764 | cycles_t start, end; | 791 | cycles_t start, end; |
765 | 792 | ||
766 | start = get_cycles(); | 793 | start = get_cycles(); |
767 | ret = do_mult_ahash_op(data, num_mb); | 794 | ret = do_mult_ahash_op(data, num_mb, rc); |
768 | end = get_cycles(); | 795 | end = get_cycles(); |
769 | 796 | ||
770 | if (ret) | 797 | if (ret) |
@@ -773,11 +800,11 @@ static int test_mb_ahash_cycles(struct test_mb_ahash_data *data, int blen, | |||
773 | cycles += end - start; | 800 | cycles += end - start; |
774 | } | 801 | } |
775 | 802 | ||
776 | out: | 803 | pr_cont("1 operation in %lu cycles (%d bytes)\n", |
777 | if (ret == 0) | 804 | (cycles + 4) / (8 * num_mb), blen); |
778 | pr_cont("1 operation in %lu cycles (%d bytes)\n", | ||
779 | (cycles + 4) / (8 * num_mb), blen); | ||
780 | 805 | ||
806 | out: | ||
807 | kfree(rc); | ||
781 | return ret; | 808 | return ret; |
782 | } | 809 | } |
783 | 810 | ||
@@ -1118,9 +1145,9 @@ struct test_mb_skcipher_data { | |||
1118 | }; | 1145 | }; |
1119 | 1146 | ||
1120 | static int do_mult_acipher_op(struct test_mb_skcipher_data *data, int enc, | 1147 | static int do_mult_acipher_op(struct test_mb_skcipher_data *data, int enc, |
1121 | u32 num_mb) | 1148 | u32 num_mb, int *rc) |
1122 | { | 1149 | { |
1123 | int i, rc[num_mb], err = 0; | 1150 | int i, err = 0; |
1124 | 1151 | ||
1125 | /* Fire up a bunch of concurrent requests */ | 1152 | /* Fire up a bunch of concurrent requests */ |
1126 | for (i = 0; i < num_mb; i++) { | 1153 | for (i = 0; i < num_mb; i++) { |
@@ -1148,18 +1175,26 @@ static int test_mb_acipher_jiffies(struct test_mb_skcipher_data *data, int enc, | |||
1148 | { | 1175 | { |
1149 | unsigned long start, end; | 1176 | unsigned long start, end; |
1150 | int bcount; | 1177 | int bcount; |
1151 | int ret; | 1178 | int ret = 0; |
1179 | int *rc; | ||
1180 | |||
1181 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
1182 | if (!rc) | ||
1183 | return -ENOMEM; | ||
1152 | 1184 | ||
1153 | for (start = jiffies, end = start + secs * HZ, bcount = 0; | 1185 | for (start = jiffies, end = start + secs * HZ, bcount = 0; |
1154 | time_before(jiffies, end); bcount++) { | 1186 | time_before(jiffies, end); bcount++) { |
1155 | ret = do_mult_acipher_op(data, enc, num_mb); | 1187 | ret = do_mult_acipher_op(data, enc, num_mb, rc); |
1156 | if (ret) | 1188 | if (ret) |
1157 | return ret; | 1189 | goto out; |
1158 | } | 1190 | } |
1159 | 1191 | ||
1160 | pr_cont("%d operations in %d seconds (%ld bytes)\n", | 1192 | pr_cont("%d operations in %d seconds (%ld bytes)\n", |
1161 | bcount * num_mb, secs, (long)bcount * blen * num_mb); | 1193 | bcount * num_mb, secs, (long)bcount * blen * num_mb); |
1162 | return 0; | 1194 | |
1195 | out: | ||
1196 | kfree(rc); | ||
1197 | return ret; | ||
1163 | } | 1198 | } |
1164 | 1199 | ||
1165 | static int test_mb_acipher_cycles(struct test_mb_skcipher_data *data, int enc, | 1200 | static int test_mb_acipher_cycles(struct test_mb_skcipher_data *data, int enc, |
@@ -1168,10 +1203,15 @@ static int test_mb_acipher_cycles(struct test_mb_skcipher_data *data, int enc, | |||
1168 | unsigned long cycles = 0; | 1203 | unsigned long cycles = 0; |
1169 | int ret = 0; | 1204 | int ret = 0; |
1170 | int i; | 1205 | int i; |
1206 | int *rc; | ||
1207 | |||
1208 | rc = kcalloc(num_mb, sizeof(*rc), GFP_KERNEL); | ||
1209 | if (!rc) | ||
1210 | return -ENOMEM; | ||
1171 | 1211 | ||
1172 | /* Warm-up run. */ | 1212 | /* Warm-up run. */ |
1173 | for (i = 0; i < 4; i++) { | 1213 | for (i = 0; i < 4; i++) { |
1174 | ret = do_mult_acipher_op(data, enc, num_mb); | 1214 | ret = do_mult_acipher_op(data, enc, num_mb, rc); |
1175 | if (ret) | 1215 | if (ret) |
1176 | goto out; | 1216 | goto out; |
1177 | } | 1217 | } |
@@ -1181,7 +1221,7 @@ static int test_mb_acipher_cycles(struct test_mb_skcipher_data *data, int enc, | |||
1181 | cycles_t start, end; | 1221 | cycles_t start, end; |
1182 | 1222 | ||
1183 | start = get_cycles(); | 1223 | start = get_cycles(); |
1184 | ret = do_mult_acipher_op(data, enc, num_mb); | 1224 | ret = do_mult_acipher_op(data, enc, num_mb, rc); |
1185 | end = get_cycles(); | 1225 | end = get_cycles(); |
1186 | 1226 | ||
1187 | if (ret) | 1227 | if (ret) |
@@ -1190,11 +1230,11 @@ static int test_mb_acipher_cycles(struct test_mb_skcipher_data *data, int enc, | |||
1190 | cycles += end - start; | 1230 | cycles += end - start; |
1191 | } | 1231 | } |
1192 | 1232 | ||
1193 | out: | 1233 | pr_cont("1 operation in %lu cycles (%d bytes)\n", |
1194 | if (ret == 0) | 1234 | (cycles + 4) / (8 * num_mb), blen); |
1195 | pr_cont("1 operation in %lu cycles (%d bytes)\n", | ||
1196 | (cycles + 4) / (8 * num_mb), blen); | ||
1197 | 1235 | ||
1236 | out: | ||
1237 | kfree(rc); | ||
1198 | return ret; | 1238 | return ret; |
1199 | } | 1239 | } |
1200 | 1240 | ||
@@ -1606,7 +1646,7 @@ static inline int tcrypt_test(const char *alg) | |||
1606 | return ret; | 1646 | return ret; |
1607 | } | 1647 | } |
1608 | 1648 | ||
1609 | static int do_test(const char *alg, u32 type, u32 mask, int m) | 1649 | static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) |
1610 | { | 1650 | { |
1611 | int i; | 1651 | int i; |
1612 | int ret = 0; | 1652 | int ret = 0; |
@@ -1621,7 +1661,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) | |||
1621 | } | 1661 | } |
1622 | 1662 | ||
1623 | for (i = 1; i < 200; i++) | 1663 | for (i = 1; i < 200; i++) |
1624 | ret += do_test(NULL, 0, 0, i); | 1664 | ret += do_test(NULL, 0, 0, i, num_mb); |
1625 | break; | 1665 | break; |
1626 | 1666 | ||
1627 | case 1: | 1667 | case 1: |
@@ -2903,7 +2943,7 @@ static int __init tcrypt_mod_init(void) | |||
2903 | goto err_free_tv; | 2943 | goto err_free_tv; |
2904 | } | 2944 | } |
2905 | 2945 | ||
2906 | err = do_test(alg, type, mask, mode); | 2946 | err = do_test(alg, type, mask, mode, num_mb); |
2907 | 2947 | ||
2908 | if (err) { | 2948 | if (err) { |
2909 | printk(KERN_ERR "tcrypt: one or more tests failed!\n"); | 2949 | printk(KERN_ERR "tcrypt: one or more tests failed!\n"); |